From be1b13a724b0194bd62fae3c5945e0782bef5df8 Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado Date: Mon, 5 Feb 2024 22:27:03 -0800 Subject: [PATCH 01/50] Update TypeSpec --- audio/main.tsp | 1 - audio/models.tsp | 154 +- audio/operations.tsp | 67 +- {edits => chat}/main.tsp | 0 completions/chat-meta.tsp => chat/meta.tsp | 15 +- chat/models.tsp | 593 ++ chat/operations.tsp | 22 + common/models.tsp | 55 +- completions/models.tsp | 454 +- completions/operations.tsp | 16 +- edits/models.tsp | 69 - edits/operations.tsp | 19 - embeddings/models.tsp | 81 +- embeddings/operations.tsp | 4 +- files/models.tsp | 97 +- files/operations.tsp | 46 +- fine-tuning/models.tsp | 5 +- fine-tuning/operations.tsp | 39 +- images/models.tsp | 149 +- images/operations.tsp | 4 +- main.tsp | 5 +- models/main.tsp | 1 + models/models.tsp | 38 + models/operations.tsp | 47 + {moderation => moderations}/main.tsp | 0 {moderation => moderations}/models.tsp | 24 +- {moderation => moderations}/operations.tsp | 1 + openapi.yaml | 9334 +++++++++++++++----- package-lock.json | 632 +- package.json | 13 +- 30 files changed, 8745 insertions(+), 3240 deletions(-) rename {edits => chat}/main.tsp (100%) rename completions/chat-meta.tsp => chat/meta.tsp (94%) create mode 100644 chat/models.tsp create mode 100644 chat/operations.tsp delete mode 100644 edits/models.tsp delete mode 100644 edits/operations.tsp create mode 100644 models/main.tsp create mode 100644 models/models.tsp create mode 100644 models/operations.tsp rename {moderation => moderations}/main.tsp (100%) rename {moderation => moderations}/models.tsp (89%) rename {moderation => moderations}/operations.tsp (98%) diff --git a/audio/main.tsp b/audio/main.tsp index c6458821f..144c4aeaf 100644 --- a/audio/main.tsp +++ b/audio/main.tsp @@ -1,2 +1 @@ import "./operations.tsp"; -import "./models.tsp"; diff --git a/audio/models.tsp b/audio/models.tsp index a2a440a90..ba931af7e 100644 --- a/audio/models.tsp +++ b/audio/models.tsp @@ -1,6 +1,42 @@ -namespace OpenAI; +import "../common/models.tsp"; + +using TypeSpec.Http; using TypeSpec.OpenAPI; +namespace OpenAI; + +model CreateSpeechRequest { + /** One of the available [TTS models](/docs/models/tts): `tts-1` or `tts-1-hd` */ + @extension("x-oaiTypeLabel", "string") + `model`: string | TEXT_TO_SPEECH_MODELS; + + /** + * The text to generate audio for. The maximum length is 4096 characters. + */ + @maxLength(4096) + input: string; + + /** + * The voice to use when generating the audio. Supported voices are `alloy`, `echo`, `fable`, + * `onyx`, `nova`, and `shimmer`. Previews of the voices are available in the + * [Text to speech guide](/docs/guides/text-to-speech/voice-options). + */ + voice: "alloy" | "echo" | "fable" | "onyx" | "nova" | "shimmer"; + + /** + * The format of the transcript output, in one of these options: json, text, srt, verbose_json, or + * vtt. + */ + response_format?: "json" | "text" | "srt" | "verbose_json" | "vtt" = "json"; + + /** + * The speed of the generated audio. Select a value from `0.25` to `4.0`. `1.0` is the default. + */ + @minValue(0.25) + @maxValue(4.0) + speed?: float64 = 1.0; +} + model CreateTranscriptionRequest { /** * The audio file object (not file name) to transcribe, in one of these formats: flac, mp3, mp4, @@ -12,7 +48,14 @@ model CreateTranscriptionRequest { /** ID of the model to use. Only `whisper-1` is currently available. */ @extension("x-oaiTypeLabel", "string") - `model`: string | "whisper-1"; + `model`: string | SPEECH_TO_TEXT_MODELS; + + /** + * The language of the input audio. Supplying the input language in + * [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) format will improve accuracy + * and latency. + */ + language?: string; /** * An optional text to guide the model's style or continue a previous audio segment. The @@ -35,18 +78,6 @@ model CreateTranscriptionRequest { @minValue(0) @maxValue(1) temperature?: float64 = 0; - - /** - * The language of the input audio. Supplying the input language in - * [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) format will improve accuracy - * and latency. - */ - language?: string; -} - -// Note: This does not currently support the non-default response format types. -model CreateTranscriptionResponse { - text: string; } model CreateTranslationRequest { @@ -60,7 +91,7 @@ model CreateTranslationRequest { /** ID of the model to use. Only `whisper-1` is currently available. */ @extension("x-oaiTypeLabel", "string") - `model`: string | "whisper-1"; + `model`: string | SPEECH_TO_TEXT_MODELS; /** * An optional text to guide the model's style or continue a previous audio segment. The @@ -86,7 +117,98 @@ model CreateTranslationRequest { temperature?: float64 = 0; } -// Note: This does not currently support the non-default response format types. +// TODO: This model is not defined in the OpenAI API spec. +model CreateTranscriptionResponse { + /** The transcribed text for the provided audio data. */ + text: string; + + /** The label that describes which operation type generated the accompanying response data. */ + task?: "transcribe"; + + /** The spoken language that was detected in the audio data. */ + language?: string; + + /** + * The total duration of the audio processed to produce accompanying transcription information. + */ + @encode("seconds", float64) + duration?: duration; + + /** + * A collection of information about the timing, probabilities, and other detail of each processed + * audio segment. + */ + segments?: AudioSegment[]; +} + +// TODO: This model is not defined in the OpenAI API spec. model CreateTranslationResponse { + /** The translated text for the provided audio data. */ text: string; + + /** The label that describes which operation type generated the accompanying response data. */ + task?: "translate"; + + /** The spoken language that was detected in the audio data. */ + language?: string; + + /** The total duration of the audio processed to produce accompanying translation information. */ + @encode("seconds", float64) + duration?: duration; + + /** + * A collection of information about the timing, probabilities, and other detail of each processed + * audio segment. + */ + segments?: AudioSegment[]; } + +alias TEXT_TO_SPEECH_MODELS = + | "tts-1" + | "tts-1-hd"; + +alias SPEECH_TO_TEXT_MODELS = + | "whisper-1"; + +// TODO: This model is not defined in the OpenAI API spec. +model AudioSegment { + /** The zero-based index of this segment. */ + id: safeint; + + /** + * The seek position associated with the processing of this audio segment. Seek positions are + * expressed as hundredths of seconds. The model may process several segments from a single seek + * position, so while the seek position will never represent a later time than the segment's + * start, the segment's start may represent a significantly later time than the segment's + * associated seek position. + */ + seek: safeint; + + /** The time at which this segment started relative to the beginning of the audio. */ + @encode("seconds", float64) + start: duration; + + /** The time at which this segment ended relative to the beginning of the audio. */ + @encode("seconds", float64) + end: duration; + + /** The text that was part of this audio segment. */ + text: string; + + /** The token IDs matching the text in this audio segment. */ + tokens: TokenArray; + + /** The temperature score associated with this audio segment. */ + @minValue(0) + @maxValue(1) + temperature: float64; + + /** The average log probability associated with this audio segment. */ + avg_logprob: float64; + + /** The compression ratio of this audio segment. */ + compression_ratio: float64; + + /** The probability of no speech detection within this audio segment. */ + no_speech_prob: float64; +} \ No newline at end of file diff --git a/audio/operations.tsp b/audio/operations.tsp index 636fb941a..a598297bf 100644 --- a/audio/operations.tsp +++ b/audio/operations.tsp @@ -2,34 +2,57 @@ import "@typespec/http"; import "@typespec/openapi"; import "../common/errors.tsp"; +import "./models.tsp"; using TypeSpec.Http; using TypeSpec.OpenAPI; namespace OpenAI; + @route("/audio") -namespace Audio { +interface Audio { + @route("speech") + @post + @operationId("createSpeech") + @tag("OpenAI") + @summary("Generates audio from the input text.") + createSpeech( + @body speech: CreateSpeechRequest, + ): { + @header contentType: "application/octet-stream"; + @header("Transfer-Encoding") transferEncoding: "chunked"; + @body @encode("binary") audio: bytes; + }; + @route("transcriptions") - interface Transcriptions { - @post - @operationId("createTranscription") - @tag("OpenAI") - @summary("Transcribes audio into the input language.") - createTranscription( - @header contentType: "multipart/form-data", - @body audio: CreateTranscriptionRequest, - ): CreateTranscriptionResponse | ErrorResponse; - } + @post + @operationId("createTranscription") + @tag("OpenAI") + @summary("Transcribes audio into the input language.") + createTranscription( + @header contentType: "multipart/form-data", + @body audio: CreateTranscriptionRequest, + ): + | CreateTranscriptionResponse + | { + @header contentType: "text/plain"; + @body text: string; + } + | ErrorResponse; @route("translations") - interface Translations { - @post - @operationId("createTranslation") - @tag("OpenAI") - @summary("Transcribes audio into the input language.") - createTranslation( - @header contentType: "multipart/form-data", - @body audio: CreateTranslationRequest, - ): CreateTranslationResponse | ErrorResponse; - } -} + @post + @operationId("createTranslation") + @tag("OpenAI") + @summary("Transcribes audio into the input language.") + createTranslation( + @header contentType: "multipart/form-data", + @body audio: CreateTranslationRequest, + ): + | CreateTranslationResponse + | { + @header contentType: "text/plain"; + @body text: string; + } + | ErrorResponse; +} \ No newline at end of file diff --git a/edits/main.tsp b/chat/main.tsp similarity index 100% rename from edits/main.tsp rename to chat/main.tsp diff --git a/completions/chat-meta.tsp b/chat/meta.tsp similarity index 94% rename from completions/chat-meta.tsp rename to chat/meta.tsp index 7823da41d..3296a6c42 100644 --- a/completions/chat-meta.tsp +++ b/chat/meta.tsp @@ -1,6 +1,9 @@ +import "./operations.tsp"; + +namespace OpenAI; using TypeSpec.OpenAPI; -@@extension(OpenAI.Completions.createCompletion, +@@extension(OpenAI.Chat.createChatCompletion, "x-oaiMeta", { name: "Create chat completion", @@ -166,3 +169,13 @@ using TypeSpec.OpenAPI; ], } ); + +// TODO: Fill in example here. +@@extension(OpenAI.CreateChatCompletionResponse, + "x-oaiMeta", + { + name: "The chat completion object", + group: "chat", + example: "", + } +); \ No newline at end of file diff --git a/chat/models.tsp b/chat/models.tsp new file mode 100644 index 000000000..a80178e99 --- /dev/null +++ b/chat/models.tsp @@ -0,0 +1,593 @@ +import "../common/models.tsp"; + +using TypeSpec.OpenAPI; + +namespace OpenAI; + +model CreateChatCompletionRequest { + /** + * A list of messages comprising the conversation so far. + * [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb). + */ + @minItems(1) + messages: ChatCompletionRequestMessage[]; + + /** + * ID of the model to use. See the [model endpoint compatibility](/docs/models/model-endpoint-compatibility) + * table for details on which models work with the Chat API. + */ + @extension("x-oaiTypeLabel", "string") + `model`: string | CHAT_COMPLETION_MODELS; + + /** + * Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing + * frequency in the text so far, decreasing the model's likelihood to repeat the same line + * verbatim. + * + * [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) + */ + frequency_penalty?: Penalty | null = 0; + + /** + * Modify the likelihood of specified tokens appearing in the completion. + * + * Accepts a JSON object that maps tokens (specified by their token ID in the tokenizer) to an + * associated bias value from -100 to 100. Mathematically, the bias is added to the logits + * generated by the model prior to sampling. The exact effect will vary per model, but values + * between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 + * should result in a ban or exclusive selection of the relevant token. + */ + @extension("x-oaiTypeLabel", "map") + logit_bias?: Record | null = null; + + /** + * Whether to return log probabilities of the output tokens or not. If true, returns the log + * probabilities of each output token returned in the `content` of `message`. This option is + * currently not available on the `gpt-4-vision-preview` model. + */ + logprobs?: boolean | null = false; + + /** + * An integer between 0 and 5 specifying the number of most likely tokens to return at each token + * position, each with an associated log probability. `logprobs` must be set to `true` if this + * parameter is used. + */ + top_logprobs?: TopLogprobs | null; + + /** + * The maximum number of [tokens](/tokenizer) that can be generated in the chat completion. + * + * The total length of input tokens and generated tokens is limited by the model's context length. + * [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) + * for counting tokens. + */ + max_tokens?: MaxTokens | null = 16; + + /** + * How many chat completion choices to generate for each input message. Note that you will be + * charged based on the number of generated tokens across all of the choices. Keep `n` as `1` to + * minimize costs. + */ + n?: N | null = 1; + + /** + * Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear + * in the text so far, increasing the model's likelihood to talk about new topics. + * + * [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) + */ + presence_penalty?: Penalty | null = 0; + + /** + * An object specifying the format that the model must output. Compatible with + * [GPT-4 Turbo](/docs/models/gpt-4-and-gpt-4-turbo) and `gpt-3.5-turbo-1106`. + * + * 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. + */ + response_format?: { + /** Must be one of `text` or `json_object`. */ + type?: "text" | "json_object" = "text"; + }; + + /** + * This feature is in Beta. + * + * If specified, our system will make a best effort to sample deterministically, such that + * repeated requests with the same `seed` and parameters should return the same result. + * + * Determinism is not guaranteed, and you should refer to the `system_fingerprint` response + * parameter to monitor changes in the backend. + */ + @extension( + "x-oaiMeta", + { + beta: true + } + ) + seed?: Seed | null; + + // TODO: Consider inlining when https://github.com/microsoft/typespec/issues/2356 is resolved + // https://github.com/microsoft/typespec/issues/2355 + /** Up to 4 sequences where the API will stop generating further tokens. */ + stop?: Stop | null = null; + + /** + * If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only + * [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) + * as they become available, with the stream terminated by a `data: [DONE]` message. + * [Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions). + */ + stream?: boolean | null = false; + + /** + * What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output + * more random, while lower values like 0.2 will make it more focused and deterministic. + * + * We generally recommend altering this or `top_p` but not both. + */ + temperature?: Temperature | null = 1; + + /** + * An alternative to sampling with temperature, called nucleus sampling, where the model considers + * the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising + * the top 10% probability mass are considered. + * + * We generally recommend altering this or `temperature` but not both. + */ + top_p?: TopP | null = 1; + + /** + * A list of tools the model may call. Currently, only functions are supported as a tool. Use this + * to provide a list of functions the model may generate JSON inputs for. */ + tools?: ChatCompletionTool[]; + + tool_choice?: ChatCompletionToolChoiceOption; + + /** + * A unique identifier representing your end-user, which can help OpenAI to monitor and detect + * abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + */ + user?: User; + + /** + * Deprecated in favor of `tool_choice`. + * + * Controls which (if any) function is called by the model. `none` means the model will not call a + * function and instead generates a message. `auto` means the model can pick between generating a + * message or calling a function. Specifying a particular function via `{"name": "my_function"}` + * forces the model to call that function. + * + * `none` is the default when no functions are present. `auto` is the default if functions are + * present. + */ + #deprecated "deprecated" + @extension("x-oaiExpandable", true) + function_call?: "none" | "auto" | ChatCompletionFunctionCallOption; + + /** + * Deprecated in favor of `tools`. + * + * A list of functions the model may generate JSON inputs for. + */ + #deprecated "deprecated" + @minItems(1) + @maxItems(128) + functions?: ChatCompletionFunctions[]; +} + +/** Represents a chat completion response returned by model, based on the provided input. */ +model CreateChatCompletionResponse { + /** A unique identifier for the chat completion. */ + id: string; + + /** A list of chat completion choices. Can be more than one if `n` is greater than 1. */ + choices: { + /** + * The reason the model stopped generating tokens. This will be `stop` if the model hit a + * natural stop point or a provided stop sequence, `length` if the maximum number of tokens + * specified in the request was reached, `content_filter` if content was omitted due to a flag + * from our content filters, `tool_calls` if the model called a tool, or `function_call` + * (deprecated) if the model called a function. + */ + finish_reason: "stop" | "length" | "tool_calls" | "content_filter" | "function_call"; + + /** The index of the choice in the list of choices. */ + index: safeint; + + message: ChatCompletionResponseMessage; + + /** Log probability information for the choice. */ + logprobs: { + content: ChatCompletionTokenLogprob[] | null; + } | null; + }[]; + + /** The Unix timestamp (in seconds) of when the chat completion was created. */ + @encode("unixTimestamp", int32) + created: utcDateTime; + + /** The model used for the chat completion. */ + `model`: string; + + /** + * 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. + */ + system_fingerprint?: string; + + /** The object type, which is always `chat.completion`. */ + object: "chat.completion"; + + usage?: CompletionUsage; +} + +alias CHAT_COMPLETION_MODELS = + | "gpt-4-0125-preview" + | "gpt-4-turbo-preview" + | "gpt-4-1106-preview" + | "gpt-4-vision-preview" + | "gpt-4" + | "gpt-4-0314" + | "gpt-4-0613" + | "gpt-4-32k" + | "gpt-4-32k-0314" + | "gpt-4-32k-0613" + | "gpt-3.5-turbo" + | "gpt-3.5-turbo-16k" + | "gpt-3.5-turbo-0301" + | "gpt-3.5-turbo-0613" + | "gpt-3.5-turbo-1106" + | "gpt-3.5-turbo-16k-0613"; + +@minValue(-2) +@maxValue(2) +scalar Penalty extends float64; + +@minValue(0) +@maxValue(2) +scalar Temperature extends float64; + +@minValue(0) +@maxValue(1) +scalar TopP extends float64; + +@minValue(0) +@maxValue(5) +scalar TopLogprobs extends safeint; + +@minValue(1) +@maxValue(128) +scalar N extends safeint; + +@minValue(0) +scalar MaxTokens extends safeint; + +// TODO: Min and max exceed the limits of safeint. +@minValue(-9223372036854775808) +@maxValue(9223372036854775807) +scalar Seed extends safeint; + +@oneOf +union Stop { + string, + StopSequences, +} + +@minItems(1) +@maxItems(4) +model StopSequences is string[]; + +/** Usage statistics for the completion request. */ +model CompletionUsage { + /** Number of tokens in the prompt. */ + prompt_tokens: safeint; + + /** Number of tokens in the generated completion */ + completion_tokens: safeint; + + /** Total number of tokens used in the request (prompt + completion). */ + total_tokens: safeint; +} + +model ChatCompletionTool { + /** The type of the tool. Currently, only `function` is supported. */ + type: "function"; + + function: FunctionObject; +} + +/** + * Controls which (if any) function is called by the model. `none` means the model will not call a + * function and instead generates a message. `auto` means the model can pick between generating a + * message or calling a function. Specifying a particular function via + * `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that + * function. + * + * `none` is the default when no functions are present. `auto` is the default if functions are + * present. + */ +@oneOf +@extension("x-oaiExpandable", true) +union ChatCompletionToolChoiceOption { + "none", + "auto", + ChatCompletionNamedToolChoice, +} + +/** Specifies a tool the model should use. Use to force the model to call a specific function. */ +model ChatCompletionNamedToolChoice { + /** The type of the tool. Currently, only `function` is supported. */ + type: "function"; + + function: { + /** The name of the function to call. */ + name: string; + } +} + +@oneOf +union ChatCompletionRequestUserMessageContent { + /** The text contents of the message. */ + 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. + */ + ChatCompletionRequestMessageContentParts, +}; + +@minItems(1) +model ChatCompletionRequestMessageContentParts is ChatCompletionRequestMessageContentPart[]; + +@oneOf +@extension("x-oaiExpandable", true) +union ChatCompletionRequestMessageContentPart { + ChatCompletionRequestMessageContentPartText, + ChatCompletionRequestMessageContentPartImage, +} + +model ChatCompletionRequestMessageContentPartText { + /** The type of the content part. */ + type: "text"; + + /** The text content. */ + text: string; +} + +model ChatCompletionRequestMessageContentPartImage { + /** The type of the content part. */ + type: "image_url"; + + image_url: { + /** Either a URL of the image or the base64 encoded image data. */ + url: url | string; + + /** + * Specifies the detail level of the image. Learn more in the + * [Vision guide](/docs/guides/vision/low-or-high-fidelity-image-understanding). + */ + detail?: "auto" | "low" | "high" = "auto"; + } +} + +/** The tool calls generated by the model, such as function calls. */ +model ChatCompletionMessageToolCalls is ChatCompletionMessageToolCall[]; + +model ChatCompletionMessageToolCall { + // TODO: index included when streaming + /** The ID of the tool call. */ + id: string; + + /** The type of the tool. Currently, only `function` is supported. */ + type: "function"; + + /** The function that the model called. */ + function: { + /** The name of the function to call. */ + name: string; + + /** + * The arguments to call the function with, as generated by the model in JSON format. Note that + * the model does not always generate valid JSON, and may hallucinate parameters not defined by + * your function schema. Validate the arguments in your code before calling your function. + */ + arguments: string; + } +}; + +@oneOf +@extension("x-oaiExpandable", true) +union ChatCompletionRequestMessage { + ChatCompletionRequestSystemMessage, + ChatCompletionRequestUserMessage, + ChatCompletionRequestAssistantMessage, + ChatCompletionRequestToolMessage, + ChatCompletionRequestFunctionMessage, +} + +model ChatCompletionRequestSystemMessage { + /** The contents of the system message. */ + @extension("x-oaiExpandable", true) + content: string , + + /** The role of the messages author, in this case `system`. */ + role: "system", + + /** + * An optional name for the participant. Provides the model information to differentiate between + * participants of the same role. + */ + name?: string; +} + +model ChatCompletionRequestUserMessage { + /** The contents of the system message. */ + @extension("x-oaiExpandable", true) + content: ChatCompletionRequestUserMessageContent, + + /** The role of the messages author, in this case `user`. */ + role: "user", + + /** + * An optional name for the participant. Provides the model information to differentiate between + * participants of the same role. + */ + name?: string; +} + +model ChatCompletionRequestAssistantMessage { + /** + * The contents of the assistant message. Required unless `tool_calls` or `function_call` is' + * specified. + */ + content?: string | null, + + /** The role of the messages author, in this case `assistant`. */ + role: "assistant", + + /** + * An optional name for the participant. Provides the model information to differentiate between + * participants of the same role. + */ + name?: string; + + tool_calls?: ChatCompletionMessageToolCalls; + + /** + * Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be + * called, as generated by the model. + */ + #deprecated "deprecated" + function_call?: { + /** + * The arguments to call the function with, as generated by the model in JSON format. Note that + * the model does not always generate valid JSON, and may hallucinate parameters not defined by + * your function schema. Validate the arguments in your code before calling your function. + */ + arguments: string; + + /** The name of the function to call. */ + name: string; + + } +} + +model ChatCompletionRequestToolMessage { + /** The role of the messages author, in this case `tool`. */ + role: "tool", + + /** The contents of the tool message. */ + content: string; + + /** Tool call that this message is responding to. */ + tool_call_id: string; +} + +model ChatCompletionRequestFunctionMessage { + /** The role of the messages author, in this case `function`. */ + role: "function", + + /** The contents of the function message. */ + content: string | null; + + /** The name of the function to call. */ + name: string; +} + +model ChatCompletionResponseMessage { + /** The contents of the message. */ + content: string | null; + + tool_calls?: ChatCompletionMessageToolCalls; + + /** The role of the author of this message. */ + role: "assistant"; + + /** Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model. */ + #deprecated "deprecated" + function_call?: { + /** + * The arguments to call the function with, as generated by the model in JSON format. Note that + * the model does not always generate valid JSON, and may hallucinate parameters not defined by + * your function schema. Validate the arguments in your code before calling your function. + */ + arguments: string; + + /** The name of the function to call. */ + name: string; + }; +} + +model ChatCompletionTokenLogprob { + /** The token. */ + token: string; + + /** The log probability of this token. */ + logprob: float64; + + /** + * A list of integers representing the UTF-8 bytes representation of the token. Useful in + * instances where characters are represented by multiple tokens and their byte representations + * must be combined to generate the correct text representation. Can be `null` if there is no + * bytes representation for the token. + */ + bytes: safeint[] | null; + + /** + * List of the most likely tokens and their log probability, at this token position. In rare + * cases, there may be fewer than the number of requested `top_logprobs` returned. + */ + top_logprobs: { + /** The token. */ + token: string; + + /** The log probability of this token. */ + logprob: float64; + + /** + * A list of integers representing the UTF-8 bytes representation of the token. Useful in + * instances where characters are represented by multiple tokens and their byte representations + * must be combined to generate the correct text representation. Can be `null` if there is no + * bytes representation for the token. + */ + bytes: safeint[] | null; + }[]; +} + +/** + * Specifying a particular function via `{"name": "my_function"}` forces the model to call that + * function. + */ +model ChatCompletionFunctionCallOption { + /** The name of the function to call. */ + name: string; +} + +#deprecated "deprecated" +model ChatCompletionFunctions { + /** + * A description of what the function does, used by the model to choose when and how to call the + * function. + */ + description?: string; + + /** + * The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and + * dashes, with a maximum length of 64. + */ + name: string; + + parameters?: FunctionParameters; +} \ No newline at end of file diff --git a/chat/operations.tsp b/chat/operations.tsp new file mode 100644 index 000000000..c2c5aa364 --- /dev/null +++ b/chat/operations.tsp @@ -0,0 +1,22 @@ +import "@typespec/http"; +import "@typespec/openapi"; + +import "../common/errors.tsp"; +import "./models.tsp"; + +using TypeSpec.Http; +using TypeSpec.OpenAPI; + +namespace OpenAI; + +@route("/chat") +interface Chat { + @route("completions") + @post + @operationId("createChatCompletion") + @tag("OpenAI") + @summary("Creates a model response for the given chat conversation.") + createChatCompletion( + ...CreateChatCompletionRequest, + ): CreateChatCompletionResponse | ErrorResponse; +} \ No newline at end of file diff --git a/common/models.tsp b/common/models.tsp index d6d0d4f91..b5bfcc9b3 100644 --- a/common/models.tsp +++ b/common/models.tsp @@ -1,34 +1,6 @@ -namespace OpenAI; using TypeSpec.OpenAPI; -model ListModelsResponse { - object: string; - data: Model[]; -} - -/** Describes an OpenAI model offering that can be used with the API. */ -model Model { - /** The model identifier, which can be referenced in the API endpoints. */ - id: string; - - /** The object type, which is always "model". */ - object: "model"; - - /** The Unix timestamp (in seconds) when the model was created. */ - @encode("unixTimestamp", int32) - created: utcDateTime; - - /** The organization that owns the model. */ - owned_by: string; -} - -model DeleteModelResponse { - id: string; - object: string; - deleted: boolean; -} - -// this is using yaml refs instead of a def in the openapi, not sure if that's required? +namespace OpenAI; scalar User extends string; @@ -37,3 +9,28 @@ model TokenArray is safeint[]; @minItems(1) model TokenArrayArray is TokenArray[]; + +model FunctionObject { + /** + * A description of what the function does, used by the model to choose when and how to call the + * function. + */ + description?: string; + + /** + * The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and + * dashes, with a maximum length of 64. + */ + name: string; + + parameters?: FunctionParameters; +} + +/** + * The parameters the functions accepts, described as a JSON Schema object. See the + * [guide](/docs/guides/gpt/function-calling) for examples, and the + * [JSON Schema reference](https://json-schema.org/understanding-json-schema/) for documentation + * about the format.\n\nTo describe a function that accepts no parameters, provide the value + * `{\"type\": \"object\", \"properties\": {}}`. + */ +model FunctionParameters is Record; \ No newline at end of file diff --git a/completions/models.tsp b/completions/models.tsp index 5aa332b32..bfe7bf03c 100644 --- a/completions/models.tsp +++ b/completions/models.tsp @@ -1,80 +1,46 @@ -namespace OpenAI; -using TypeSpec.OpenAPI; +import "../common/models.tsp"; +import "../chat/models.tsp"; -alias CHAT_COMPLETION_MODELS = - | "gpt4" - | "gpt-4-0314" - | "gpt-4-0613" - | "gpt-4-32k" - | "gpt-4-32k-0314" - | "gpt-4-32k-0613" - | "gpt-3.5-turbo" - | "gpt-3.5-turbo-16k" - | "gpt-3.5-turbo-0301" - | "gpt-3.5-turbo-0613" - | "gpt-3.5-turbo-16k-0613"; +using TypeSpec.OpenAPI; -alias COMPLETION_MODELS = - | "babbage-002" - | "davinci-002" - | "text-davinci-003" - | "text-davinci-002" - | "text-davinci-001" - | "code-davinci-002" - | "text-curie-001" - | "text-babbage-001" - | "text-ada-001"; +namespace OpenAI; -alias SharedCompletionProperties = { +model CreateCompletionRequest { /** - * What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output - * more random, while lower values like 0.2 will make it more focused and deterministic. - * - * We generally recommend altering this or `top_p` but not both. + * ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + * see all of your available models, or see our [Model overview](/docs/models/overview) for + * descriptions of them. */ - temperature?: Temperature | null = 1; + @extension("x-oaiTypeLabel", "string") + `model`: string | COMPLETION_MODELS; /** - * An alternative to sampling with temperature, called nucleus sampling, where the model considers - * the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising - * the top 10% probability mass are considered. + * The prompt(s) to generate completions for, encoded as a string, array of strings, array of + * tokens, or array of token arrays. * - * We generally recommend altering this or `temperature` but not both. + * Note that <|endoftext|> is the document separator that the model sees during training, so if a + * prompt is not specified the model will generate as if from the beginning of a new document. */ - top_p?: TopP | null = 1; + // TODO: consider inlining when https://github.com/microsoft/typespec/issues/2356 fixed + prompt: Prompt = "<|endoftext|>"; /** - * How many completions to generate for each prompt. + * Generates `best_of` completions server-side and returns the "best" (the one with the highest + * log probability per token). Results cannot be streamed. + * + * When used with `n`, `best_of` controls the number of candidate completions and `n` specifies + * how many to return – `best_of` must be greater than `n`. + * * **Note:** Because this parameter generates many completions, it can quickly consume your token * quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. */ - n?: N | null = 1; - - /** - * The maximum number of [tokens](/tokenizer) to generate in the completion. - * - * The token count of your prompt plus `max_tokens` cannot exceed the model's context length. - * [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) - * for counting tokens. - */ - max_tokens?: MaxTokens | null = 16; - - // todo: consider inlining when https://github.com/microsoft/typespec/issues/2356 is resolved - // https://github.com/microsoft/typespec/issues/2355 - /** Up to 4 sequences where the API will stop generating further tokens. */ - stop?: Stop = null; + @minValue(0) + @maxValue(20) + best_of?: safeint | null = 1; - // needs default - // https://github.com/microsoft/typespec/issues/1646 - /** - * Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear - * in the text so far, increasing the model's likelihood to talk about new topics. - * - * [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) - */ - presence_penalty?: Penalty | null; + /** Echo back the prompt in addition to the completion */ + echo?: boolean | null = false; - // needs default /** * Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing * frequency in the text so far, decreasing the model's likelihood to repeat the same line @@ -82,293 +48,116 @@ alias SharedCompletionProperties = { * * [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) */ - frequency_penalty?: Penalty | null; + frequency_penalty?: Penalty | null = 0; - // needs default of null /** * Modify the likelihood of specified tokens appearing in the completion. - * Accepts a json object that maps tokens (specified by their token ID in the tokenizer) to an - * associated bias value from -100 to 100. Mathematically, the bias is added to the logits - * generated by the model prior to sampling. The exact effect will vary per model, but values - * between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 - * should result in a ban or exclusive selection of the relevant token. + * + * Accepts a JSON object that maps tokens (specified by their token ID in the GPT tokenizer) to an + * associated bias value from -100 to 100. You can use this [tokenizer tool](/tokenizer?view=bpe) + * to convert text to token IDs. Mathematically, the bias is added to the logits generated by the + * model prior to sampling. The exact effect will vary per model, but values between -1 and 1 + * should decrease or increase likelihood of selection; values like -100 or 100 should result in a + * ban or exclusive selection of the relevant token. + * + * As an example, you can pass `{"50256": -100}` to prevent the <|endoftext|> token from being + * generated. */ @extension("x-oaiTypeLabel", "map") - logit_bias?: Record | null; - - /** - * A unique identifier representing your end-user, which can help OpenAI to monitor and detect - * abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). - */ - user?: User; + logit_bias?: Record | null = null; /** - * If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only - * [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) - * as they become available, with the stream terminated by a `data: [DONE]` message. - * [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_stream_completions.ipynb). - */ - stream?: boolean | null = true; -}; - -@oneOf -union Stop { - string, - StopSequences, - null, -} - -@minValue(-2) -@maxValue(2) -scalar Penalty extends float64; - -@minItems(1) -@maxItems(4) -model StopSequences is string[]; - -@minValue(0) -@maxValue(2) -scalar Temperature extends float64; - -@minValue(0) -@maxValue(1) -scalar TopP extends float64; - -@minValue(1) -@maxValue(128) -scalar N extends safeint; - -@minValue(0) -scalar MaxTokens extends safeint; - -model CreateChatCompletionRequest { - /** - * ID of the model to use. See the [model endpoint compatibility](/docs/models/model-endpoint-compatibility) - * table for details on which models work with the Chat API. - */ - @extension("x-oaiTypeLabel", "string") - `model`: string | CHAT_COMPLETION_MODELS; - - /** - * A list of messages comprising the conversation so far. - * [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb). + * Include the log probabilities on the `logprobs` most likely tokens, as well the chosen tokens. + * For example, if `logprobs` is 5, the API will return a list of the 5 most likely tokens. The + * API will always return the `logprob` of the sampled token, so there may be up to `logprobs+1` + * elements in the response. + * + * The maximum value for `logprobs` is 5. */ - @minItems(1) - messages: ChatCompletionRequestMessage[]; - - /** A list of functions the model may generate JSON inputs for. */ - @minItems(1) - @maxItems(128) - functions?: ChatCompletionFunctions[]; + @minValue(0) + @maxValue(5) + logprobs?: safeint | null = null; /** - * Controls how the model responds to function calls. `none` means the model does not call a - * function, and responds to the end-user. `auto` means the model can pick between an end-user or - * calling a function. Specifying a particular function via `{\"name":\ \"my_function\"}` forces the - * model to call that function. `none` is the default when no functions are present. `auto` is the - * default if functions are present. + * The maximum number of [tokens](/tokenizer) to generate in the completion. + * + * The token count of your prompt plus `max_tokens` cannot exceed the model's context length. + * [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) + * for counting tokens. */ - function_call?: "none" | "auto" | ChatCompletionFunctionCallOption; - - ...SharedCompletionProperties; -} - -model ChatCompletionFunctionCallOption { - /** The name of the function to call. */ - name: string; -} + max_tokens?: MaxTokens | null = 16; -model ChatCompletionFunctions { /** - * The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and - * dashes, with a maximum length of 64. + * How many completions to generate for each prompt. + * + * **Note:** Because this parameter generates many completions, it can quickly consume your token + * quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. */ - name: string; + n?: N | null = 1; /** - * A description of what the function does, used by the model to choose when and how to call the - * function. + * Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear + * in the text so far, increasing the model's likelihood to talk about new topics. + * + * [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) */ - description?: string; + presence_penalty?: Penalty | null = 0; - /** - * The parameters the functions accepts, described as a JSON Schema object. See the - * [guide](/docs/guides/gpt/function-calling) for examples, and the - * [JSON Schema reference](https://json-schema.org/understanding-json-schema/) for documentation - * about the format.\n\nTo describe a function that accepts no parameters, provide the value - * `{\"type\": \"object\", \"properties\": {}}`. + /** + * If specified, our system will make a best effort to sample deterministically, such that + * repeated requests with the same `seed` and parameters should return the same result. + * + * Determinism is not guaranteed, and you should refer to the `system_fingerprint` response + * parameter to monitor changes in the backend. */ - parameters: ChatCompletionFunctionParameters; -} - -model ChatCompletionFunctionParameters is Record; - -model ChatCompletionRequestMessage { - /** The role of the messages author. One of `system`, `user`, `assistant`, or `function`. */ - role: "system" | "user" | "assistant" | "function"; + @extension( + "x-oaiMeta", + { + beta: true + } + ) + seed?: Seed | null; - /** - * The contents of the message. `content` is required for all messages, and may be null for - * assistant messages with function calls. - */ - content: string | null; + // todo: consider inlining when https://github.com/microsoft/typespec/issues/2356 is resolved + // https://github.com/microsoft/typespec/issues/2355 + /** Up to 4 sequences where the API will stop generating further tokens. */ + stop?: Stop | null = null; - // TODO: the constraints are not specified in the API /** - * The name of the author of this message. `name` is required if role is `function`, and it - * should be the name of the function whose response is in the `content`. May contain a-z, - * A-Z, 0-9, and underscores, with a maximum length of 64 characters. + * If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only + * [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) + * as they become available, with the stream terminated by a `data: [DONE]` message. + * [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_stream_completions.ipynb). */ - name?: string; - - /** The name and arguments of a function that should be called, as generated by the model. */ - function_call?: { - /** The name of the function to call. */ - name: string; + stream?: boolean | null = false; - /** - * The arguments to call the function with, as generated by the model in JSON format. Note that - * the model does not always generate valid JSON, and may hallucinate parameters not defined by - * your function schema. Validate the arguments in your code before calling your function. - */ - arguments: string; - }; -} - -/** Represents a chat completion response returned by model, based on the provided input. */ -// TODO: Fill in example here. -@extension( - "x-oaiMeta", - { - name: "The chat completion object", - group: "chat", - example: "", - } -) -model CreateChatCompletionResponse { - /** A unique identifier for the chat completion. */ - id: string; - - /** The object type, which is always `chat.completion`. */ - object: string; - - /** The Unix timestamp (in seconds) of when the chat completion was created. */ - @encode("unixTimestamp", int32) - created: utcDateTime; - - /** The model used for the chat completion. */ - `model`: string; - - /** A list of chat completion choices. Can be more than one if `n` is greater than 1. */ - choices: { - /** The index of the choice in the list of choices. */ - index: safeint; - - message: ChatCompletionResponseMessage; - - /** - * The reason the model stopped generating tokens. This will be `stop` if the model hit a - * natural stop point or a provided stop sequence, `length` if the maximum number of tokens - * specified in the request was reached, `content_filter` if the content was omitted due to - * a flag from our content filters, or `function_call` if the model called a function. - */ - finish_reason: "stop" | "length" | "function_call" | "content_filter"; - }[]; - - usage?: CompletionUsage; -} - -/** Usage statistics for the completion request. */ -model CompletionUsage { - /** Number of tokens in the prompt. */ - prompt_tokens: safeint; - - /** Number of tokens in the generated completion */ - completion_tokens: safeint; - - /** Total number of tokens used in the request (prompt + completion). */ - total_tokens: safeint; -} - -model ChatCompletionResponseMessage { - /** The role of the author of this message. */ - role: "system" | "user" | "assistant" | "function"; - - /** The contents of the message. */ - content: string | null; - - /** The name and arguments of a function that should be called, as generated by the model. */ - function_call?: { - /** The name of the function to call. */ - name: string; - - /** - * The arguments to call the function with, as generated by the model in JSON format. Note that - * the model does not always generate valid JSON, and may hallucinate parameters not defined by - * your function schema. Validate the arguments in your code before calling your function. - */ - arguments: string; - }; -} - -model CreateCompletionRequest { - /** - * ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to - * see all of your available models, or see our [Model overview](/docs/models/overview) for - * descriptions of them. - */ - @extension("x-oaiTypeLabel", "string") - `model`: string | COMPLETION_MODELS; + /** The suffix that comes after a completion of inserted text. */ + suffix?: string | null = null; /** - * The prompt(s) to generate completions for, encoded as a string, array of strings, array of - * tokens, or array of token arrays. + * What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output + * more random, while lower values like 0.2 will make it more focused and deterministic. * - * Note that <|endoftext|> is the document separator that the model sees during training, so if a - * prompt is not specified the model will generate as if from the beginning of a new document. + * We generally recommend altering this or `top_p` but not both. */ - // TODO: consider inlining when https://github.com/microsoft/typespec/issues/2356 fixed - prompt: Prompt = "<|endoftext|>"; - - /** The suffix that comes after a completion of inserted text. */ - suffix?: string | null = null; - - ...SharedCompletionProperties; + temperature?: Temperature | null = 1; /** - * Include the log probabilities on the `logprobs` most likely tokens, as well the chosen tokens. - * For example, if `logprobs` is 5, the API will return a list of the 5 most likely tokens. The - * API will always return the `logprob` of the sampled token, so there may be up to `logprobs+1` - * elements in the response. + * An alternative to sampling with temperature, called nucleus sampling, where the model considers + * the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising + * the top 10% probability mass are considered. * - * The maximum value for `logprobs` is 5. + * We generally recommend altering this or `temperature` but not both. */ - logprobs?: safeint | null = null; - - /** Echo back the prompt in addition to the completion */ - echo?: boolean | null = false; + top_p?: TopP | null = 1; /** - * Generates `best_of` completions server-side and returns the "best" (the one with the highest - * log probability per token). Results cannot be streamed. - * - * When used with `n`, `best_of` controls the number of candidate completions and `n` specifies - * how many to return – `best_of` must be greater than `n`. - * - * **Note:** Because this parameter generates many completions, it can quickly consume your token - * quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. + * A unique identifier representing your end-user, which can help OpenAI to monitor and detect + * abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). */ - best_of?: safeint | null = 1; + user?: User; } -@oneOf -union Prompt { - string, - string[], - TokenArray, - TokenArrayArray, - null, -} /** * Represents a completion response from the API. Note: both the streamed and non-streamed response * objects share the same shape (unlike the chat endpoint). @@ -385,16 +174,6 @@ model CreateCompletionResponse { /** A unique identifier for the completion. */ id: string; - /** The object type, which is always `text_completion`. */ - object: string; - - /** The Unix timestamp (in seconds) of when the completion was created. */ - @encode("unixTimestamp", int32) - created: utcDateTime; - - /** The model used for the completion. */ - `model`: string; - /** The list of completion choices the model generated for the input. */ choices: { index: safeint; @@ -416,5 +195,38 @@ model CreateCompletionResponse { finish_reason: "stop" | "length" | "content_filter"; }[]; + /** The Unix timestamp (in seconds) of when the completion was created. */ + @encode("unixTimestamp", int32) + created: utcDateTime; + + /** The model used for the completion. */ + `model`: string; + + /** + * 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. + */ + system_fingerprint?: string; + + /** The object type, which is always `text_completion`. */ + object: "text_completion"; + + /** Usage statistics for the completion request. */ usage?: CompletionUsage; } + +alias COMPLETION_MODELS = + | "gpt-3.5-turbo-instruct" + | "davinci-002" + | "babbage-002"; + +@oneOf +union Prompt { + string, + string[], + TokenArray, + TokenArrayArray, + null, +} \ No newline at end of file diff --git a/completions/operations.tsp b/completions/operations.tsp index d53245f7c..e84d3d44c 100644 --- a/completions/operations.tsp +++ b/completions/operations.tsp @@ -3,30 +3,18 @@ import "@typespec/openapi"; import "../common/errors.tsp"; import "./models.tsp"; -import "./chat-meta.tsp"; using TypeSpec.Http; using TypeSpec.OpenAPI; namespace OpenAI; -@route("/chat") -namespace Chat { - @route("/completions") - interface Completions { - @tag("OpenAI") - @post - @operationId("createChatCompletion") - createChatCompletion( - ...CreateChatCompletionRequest, - ): CreateChatCompletionResponse | ErrorResponse; - } -} @route("/completions") interface Completions { - @tag("OpenAI") @post @operationId("createCompletion") + @tag("OpenAI") + @summary("Creates a completion for the provided prompt and parameters.") createCompletion( ...CreateCompletionRequest, ): CreateCompletionResponse | ErrorResponse; diff --git a/edits/models.tsp b/edits/models.tsp deleted file mode 100644 index d76372649..000000000 --- a/edits/models.tsp +++ /dev/null @@ -1,69 +0,0 @@ -namespace OpenAI; -using TypeSpec.OpenAPI; - -model CreateEditRequest { - /** - * ID of the model to use. You can use the `text-davinci-edit-001` or `code-davinci-edit-001` - * model with this endpoint. - */ - @extension("x-oaiTypeLabel", "string") - `model`: string | "text-davinci-edit-001" | "code-davinci-edit-001"; - - /** The input text to use as a starting point for the edit. */ - input?: string | null = ""; - - /** The instruction that tells the model how to edit the prompt. */ - instruction: string; - - /** How many edits to generate for the input and instruction. */ - n?: EditN | null = 1; - - /** - * What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output - * more random, while lower values like 0.2 will make it more focused and deterministic. - * - * We generally recommend altering this or `top_p` but not both. - */ - temperature?: Temperature | null = 1; - - /** - * An alternative to sampling with temperature, called nucleus sampling, where the model considers - * the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising - * the top 10% probability mass are considered. - * - * We generally recommend altering this or `temperature` but not both. - */ - top_p?: TopP | null = 1; -} - -#deprecated "deprecated" -model CreateEditResponse { - /** The object type, which is always `edit`. */ - object: "edit"; - - /** The Unix timestamp (in seconds) of when the edit was created. */ - @encode("unixTimestamp", int32) - created: utcDateTime; - - /** description: A list of edit choices. Can be more than one if `n` is greater than 1. */ - choices: { - /** The edited result. */ - text: string; - - /** The index of the choice in the list of choices. */ - index: safeint; - - /** - * The reason the model stopped generating tokens. This will be `stop` if the model hit a - * natural stop point or a provided stop sequence, or `length` if the maximum number of tokens - * specified in the request was reached. - */ - finish_reason: "stop" | "length"; - }[]; - - usage: CompletionUsage; -} - -@minValue(0) -@maxValue(20) -scalar EditN extends safeint; diff --git a/edits/operations.tsp b/edits/operations.tsp deleted file mode 100644 index 08497364e..000000000 --- a/edits/operations.tsp +++ /dev/null @@ -1,19 +0,0 @@ -import "@typespec/http"; -import "@typespec/openapi"; - -import "../common/errors.tsp"; -import "./models.tsp"; - -using TypeSpec.Http; -using TypeSpec.OpenAPI; - -namespace OpenAI; - -@route("/edits") -interface Edits { - #deprecated "deprecated" - @post - @tag("OpenAI") - @operationId("createEdit") - createEdit(@body edit: CreateEditRequest): CreateEditResponse | ErrorResponse; -} diff --git a/embeddings/models.tsp b/embeddings/models.tsp index ab46275b2..fa80cac4b 100644 --- a/embeddings/models.tsp +++ b/embeddings/models.tsp @@ -1,33 +1,57 @@ import "../common/models.tsp"; -namespace OpenAI; using TypeSpec.OpenAPI; -model CreateEmbeddingRequest { - /** ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](/docs/models/overview) for descriptions of them. */ - @extension("x-oaiTypeLabel", "string") - `model`: string | "text-embedding-ada-002"; +namespace OpenAI; +model CreateEmbeddingRequest { /** * Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a * single request, pass an array of strings or array of token arrays. Each input must not exceed - * the max input tokens for the model (8191 tokens for `text-embedding-ada-002`) and cannot be an empty string. + * the max input tokens for the model (8191 tokens for `text-embedding-ada-002`) and cannot be an + * empty string. * [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) * for counting tokens. */ + @extension("x-oaiExpandable", true) input: string | string[] | TokenArray | TokenArrayArray; + /** + * ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + * see all of your available models, or see our [Model overview](/docs/models/overview) for + * descriptions of them. + */ + @extension("x-oaiTypeLabel", "string") + `model`: string | EMBEDDINGS_MODELS; + + /** + * The format to return the embeddings in. Can be either `float` or + * [`base64`](https://pypi.org/project/pybase64/). + */ + encoding_format?: "float" | "base64" | null = "float"; + + /** + * The number of dimensions the resulting output embeddings should have. Only supported in + * `text-embedding-3` and later models. + */ + dimensions?: safeint; + + /** + * A unique identifier representing your end-user, which can help OpenAI to monitor and detect + * abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + */ user?: User; } -model CreateEmbeddingResponse { - /** The object type, which is always "embedding". */ - object: "embedding"; - - /** The name of the model used to generate the embedding. */ - `model`: string; +model CreateEmbeddingResponse { /** The list of embeddings generated by the model. */ data: Embedding[]; + + /** The name of the model used to generate the embedding. */ + `model`: string; + + /** The object type, which is always "embedding". */ + object: "list"; /** The usage information for the request. */ usage: { @@ -39,17 +63,40 @@ model CreateEmbeddingResponse { }; } +alias EMBEDDINGS_MODELS = + | "text-embedding-ada-002" + | "text-embedding-3-small" + | "text-embedding-3-large"; + /** Represents an embedding vector returned by embedding endpoint. */ +@extension( + "x-oaiMeta", + { + name: "The embedding object", + example: | """ + { + "object": "embedding", + "embedding": [ + 0.0023064255, + -0.009327292, + .... (1536 floats total for ada-002) + -0.0028842222, + ], + "index": 0 + } + """ + } +) model Embedding { /** The index of the embedding in the list of embeddings. */ index: safeint; - /** The object type, which is always "embedding". */ - object: "embedding"; - /** - * The embedding vector, which is a list of floats. The length of vector depends on the model as\ + * The embedding vector, which is a list of floats. The length of vector depends on the model as * listed in the [embedding guide](/docs/guides/embeddings). */ - embedding: float64[]; + embedding: float64[] | string; + + /** The object type, which is always "embedding". */ + object: "embedding"; } diff --git a/embeddings/operations.tsp b/embeddings/operations.tsp index 012d97c58..c53347e6f 100644 --- a/embeddings/operations.tsp +++ b/embeddings/operations.tsp @@ -11,10 +11,10 @@ namespace OpenAI; @route("/embeddings") interface Embeddings { - @tag("OpenAI") - @summary("Creates an embedding vector representing the input text.") @post @operationId("createEmbedding") + @tag("OpenAI") + @summary("Creates an embedding vector representing the input text.") createEmbedding( @body embedding: CreateEmbeddingRequest, ): CreateEmbeddingResponse | ErrorResponse; diff --git a/files/models.tsp b/files/models.tsp index 990c1ea11..72a263413 100644 --- a/files/models.tsp +++ b/files/models.tsp @@ -1,70 +1,91 @@ -namespace OpenAI; using TypeSpec.OpenAPI; -model ListFilesResponse { - object: string; // presumably this is always some constant, but not defined. - data: OpenAIFile[]; -} +namespace OpenAI; model CreateFileRequest { /** - * Name of the [JSON Lines](https://jsonlines.readthedocs.io/en/latest/) file to be uploaded. - * - * If the `purpose` is set to "fine-tune", the file will be used for fine-tuning. + * The file object (not file name) to be uploaded. */ @encode("binary") file: bytes; /** - * The intended purpose of the uploaded documents. Use "fine-tune" for - * [fine-tuning](/docs/api-reference/fine-tuning). This allows us to validate the format of the - * uploaded file. + * The intended purpose of the uploaded file. Use "fine-tune" for + * [Fine-tuning](/docs/api-reference/fine-tuning) and "assistants" for + * [Assistants](/docs/api-reference/assistants) and [Messages](/docs/api-reference/messages). This + * allows us to validate the format of the uploaded file is correct for fine-tuning. */ - purpose: string; + purpose: "fine-tune" | "assistants"; +} + +model ListFilesResponse { + data: OpenAIFile[]; + object: "list"; +} + +model DeleteFileResponse { + id: string; + object: "file"; + deleted: boolean; } +alias FILE_PURPOSE = + | "fine-tune" + | "fine-tune-results" + | "assistants" + | "assistants_output"; + /** The `File` object represents a document that has been uploaded to OpenAI. */ +@extension( + "x-oaiMeta", + { + name: "The file object", + example: | """ + { + "id": "file-abc123", + "object": "file", + "bytes": 120000, + "created_at": 1677610602, + "filename": "salesOverview.pdf", + "purpose": "assistants", + } + """ + } +) model OpenAIFile { /** The file identifier, which can be referenced in the API endpoints. */ id: string; - /** The object type, which is always "file". */ - object: "file"; - - /** The size of the file in bytes. */ + /** The size of the file, in bytes. */ bytes: safeint; /** The Unix timestamp (in seconds) for when the file was created. */ @encode("unixTimestamp", int32) - createdAt: utcDateTime; + created_at: utcDateTime; /** The name of the file. */ filename: string; - /** The intended purpose of the file. Currently, only "fine-tune" is supported. */ - purpose: string; + /** The object type, which is always "file". */ + object: "file"; - /** - * The current status of the file, which can be either `uploaded`, `processed`, `pending`, - * `error`, `deleting` or `deleted`. + /** + * The intended purpose of the file. Supported values are `fine-tune`, `fine-tune-results`, + * `assistants`, and `assistants_output`. */ - status: - | "uploaded" - | "processed" - | "pending" - | "error" - | "deleting" - | "deleted"; + purpose: FILE_PURPOSE; /** - * Additional details about the status of the file. If the file is in the `error` state, this will - * include a message describing the error. + * Deprecated. The current status of the file, which can be either `uploaded`, `processed`, or + * `error`. */ - status_details?: string | null; -} + #deprecated "deprecated" + status: "uploaded" | "processed" | "error"; -model DeleteFileResponse { - id: string; - object: string; - deleted: boolean; -} + /** + * Deprecated. For details on why a fine-tuning training file failed validation, see the `error` + * field on `fine_tuning.job`. + */ + #deprecated "deprecated" + status_details?: string; +} \ No newline at end of file diff --git a/files/operations.tsp b/files/operations.tsp index 2e601ae03..eec58470a 100644 --- a/files/operations.tsp +++ b/files/operations.tsp @@ -11,46 +11,58 @@ namespace OpenAI; @route("/files") interface Files { - @tag("OpenAI") - @get - @summary("Returns a list of files that belong to the user's organization.") - @operationId("listFiles") - listFiles(): ListFilesResponse | ErrorResponse; - - @tag("OpenAI") @post - @summary("Returns a list of files that belong to the user's organization.") @operationId("createFile") + @tag("OpenAI") + @summary(""" + Upload a file that can be used across various endpoints. The size of all the files uploaded by + one organization can be up to 100 GB. + + The size of individual files can be a maximum of 512 MB or 2 million tokens for Assistants. See + the [Assistants Tools guide](/docs/assistants/tools) to learn more about the types of files + supported. The Fine-tuning API only supports `.jsonl` files. + + Please [contact us](https://help.openai.com/) if you need to increase these storage limits. + """) createFile( @header contentType: "multipart/form-data", @body file: CreateFileRequest, ): OpenAIFile | ErrorResponse; + @get + @operationId("listFiles") @tag("OpenAI") - @post - @summary("Returns information about a specific file.") + @summary("Returns a list of files that belong to the user's organization.") + listFiles( + /** Only return files with the given purpose. */ + @query purpose?: FILE_PURPOSE, + ): ListFilesResponse | ErrorResponse; + + @route("{file_id}") + @get @operationId("retrieveFile") - @route("/files/{file_id}") + @tag("OpenAI") + @summary("Returns information about a specific file.") retrieveFile( /** The ID of the file to use for this request. */ @path file_id: string, ): OpenAIFile | ErrorResponse; - @tag("OpenAI") + @route("{file_id}") @delete - @summary("Delete a file") @operationId("deleteFile") - @route("/files/{file_id}") + @tag("OpenAI") + @summary("Delete a file") deleteFile( /** The ID of the file to use for this request. */ @path file_id: string, ): DeleteFileResponse | ErrorResponse; - @route("/files/{file_id}/content") - @tag("OpenAI") + @route("{file_id}/content") @get - @summary("Returns the contents of the specified file.") @operationId("downloadFile") + @tag("OpenAI") + @summary("Returns the contents of the specified file.") downloadFile( /** The ID of the file to use for this request. */ @path file_id: string, diff --git a/fine-tuning/models.tsp b/fine-tuning/models.tsp index bf846072b..9afce6d02 100644 --- a/fine-tuning/models.tsp +++ b/fine-tuning/models.tsp @@ -1,6 +1,9 @@ -namespace OpenAI; +import "../files/models.tsp"; + using TypeSpec.OpenAPI; +namespace OpenAI; + model FineTuningJob { /** The object identifier, which can be referenced in the API endpoints. */ id: string; diff --git a/fine-tuning/operations.tsp b/fine-tuning/operations.tsp index 15491f62e..258382397 100644 --- a/fine-tuning/operations.tsp +++ b/fine-tuning/operations.tsp @@ -151,41 +151,4 @@ interface FineTunes { /** The ID of the fine-tune job to cancel */ @path fine_tune_id: string, ): FineTune | ErrorResponse; -} - -@route("/models") -interface Models { - @get - @tag("OpenAI") - @summary(""" - Lists the currently available models, and provides basic information about each one such as the - owner and availability. - """) - @operationId("listModels") - listModels(): ListModelsResponse | ErrorResponse; - - @get - @route("{model}") - @operationId("retrieveModel") - @tag("OpenAI") - @summary(""" - Retrieves a model instance, providing basic information about the model such as the owner and - permissioning. - """) - retrieve( - /** The ID of the model to use for this request. */ - @path `model`: string, - ): Model | ErrorResponse; - - @delete - @route("{model}") - @operationId("deleteModel") - @tag("OpenAI") - @summary(""" - Delete a fine-tuned model. You must have the Owner role in your organization to delete a model. - """) - delete( - /** The model to delete */ - @path `model`: string, - ): DeleteModelResponse | ErrorResponse; -} +} \ No newline at end of file diff --git a/images/models.tsp b/images/models.tsp index 3d7020b51..42f14f067 100644 --- a/images/models.tsp +++ b/images/models.tsp @@ -1,51 +1,58 @@ import "../common/models.tsp"; -namespace OpenAI; using TypeSpec.OpenAPI; -alias SharedImageProperties = { - /** The number of images to generate. Must be between 1 and 10. */ - n?: ImagesN | null = 1; - - /** The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`. */ - size?: IMAGE_SIZES | null = "1024x1024"; - - /** The format in which the generated images are returned. Must be one of `url` or `b64_json`. */ - response_format?: "url" | "b64_json" | null = "url"; - - user?: User; -}; +namespace OpenAI; model CreateImageRequest { - /** A text description of the desired image(s). The maximum length is 1000 characters. */ + /** + * A text description of the desired image(s). The maximum length is 1000 characters for + * `dall-e-2` and 4000 characters for `dall-e-3`. + */ prompt: string; - ...SharedImageProperties; -} + /** The model to use for image generation. */ + @extension("x-oaiTypeLabel", "string") + `model`?: string | "dall-e-2" | "dall-e-3" = "dall-e-2"; -model ImagesResponse { - @encode("unixTimestamp", int32) - created: utcDateTime; + /** + * The number of images to generate. Must be between 1 and 10. For `dall-e-3`, only `n=1` is + * supported. + */ + n?: ImagesN | null = 1; - data: Image[]; -} + /** + * The quality of the image that will be generated. `hd` creates images with finer details and + * greater consistency across the image. This param is only supported for `dall-e-3`. + * + * TODO: Confirm that this is actually nullable. + */ + quality?: "standard" | "hd" | null = "standard"; -alias IMAGE_SIZES = "256x256" | "512x512" | "1024x1024"; + /** The format in which the generated images are returned. Must be one of `url` or `b64_json`. */ + response_format?: "url" | "b64_json" | null = "url"; -/** Represents the url or the content of an image generated by the OpenAI API. */ -model Image { - /** The URL of the generated image, if `response_format` is `url` (default). */ - url?: url; + /** + * 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. + */ + size?: "256x256" | "512x512" | "1024x1024" | "1792x1024" | "1024x1792" | null = "1024x1024"; - /** The base64-encoded JSON of the generated image, if `response_format` is `b64_json`. */ - @encode("base64", string) - b64_json?: bytes; + /** + * The style of the generated images. Must be one of `vivid` or `natural`. Vivid causes the model + * to lean towards generating hyper-real and dramatic images. Natural causes the model to produce + * more natural, less hyper-real looking images. This param is only supported for `dall-e-3`. + */ + style?: "vivid" | "natural" | null = "vivid"; + + /** + * A unique identifier representing your end-user, which can help OpenAI to monitor and detect + * abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + */ + user?: User; } model CreateImageEditRequest { - /** A text description of the desired image(s). The maximum length is 1000 characters. */ - prompt: string; - /** * The image to edit. Must be a valid PNG file, less than 4MB, and square. If mask is not * provided, image must have transparency, which will be used as the mask. @@ -53,6 +60,9 @@ model CreateImageEditRequest { @encode("binary") image: bytes; + /** A text description of the desired image(s). The maximum length is 1000 characters. */ + prompt: string; + /** * An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where * `image` should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions @@ -61,7 +71,26 @@ model CreateImageEditRequest { @encode("binary") mask?: bytes; - ...SharedImageProperties; + /** The model to use for image generation. Only `dall-e-2` is supported at this time. */ + @extension("x-oaiTypeLabel", "string") + `model`?: string | "dall-e-2" = "dall-e-2"; + + /** + * The number of images to generate. Must be between 1 and 10. + */ + n?: ImagesN | null = 1; + + /** The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`. */ + size?: "256x256" | "512x512" | "1024x1024" | null = "1024x1024"; + + /** The format in which the generated images are returned. Must be one of `url` or `b64_json`. */ + response_format?: "url" | "b64_json" | null = "url"; + + /** + * A unique identifier representing your end-user, which can help OpenAI to monitor and detect + * abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + */ + user?: User; } model CreateImageVariationRequest { @@ -72,9 +101,61 @@ model CreateImageVariationRequest { @encode("binary") image: bytes; - ...SharedImageProperties; + /** The model to use for image generation. Only `dall-e-2` is supported at this time. */ + @extension("x-oaiTypeLabel", "string") + `model`?: string | "dall-e-2" = "dall-e-2"; + + /** + * The number of images to generate. Must be between 1 and 10. + */ + n?: ImagesN | null = 1; + + /** The format in which the generated images are returned. Must be one of `url` or `b64_json`. */ + response_format?: "url" | "b64_json" | null = "url"; + + /** The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`. */ + size?: "256x256" | "512x512" | "1024x1024" | null = "1024x1024"; + + /** + * A unique identifier representing your end-user, which can help OpenAI to monitor and detect + * abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + */ + user?: User; +} + +model ImagesResponse { + @encode("unixTimestamp", int32) + created: utcDateTime; + + data: Image[]; } @minValue(1) @maxValue(10) scalar ImagesN extends safeint; + +/** Represents the url or the content of an image generated by the OpenAI API. */ +@extension( + "x-oaiMeta", + { + name: "The image object", + example: | """ + { + "url": "...", + "revised_prompt": "..." + } + """ + } +) +model Image { + /** The base64-encoded JSON of the generated image, if `response_format` is `b64_json`. */ + @encode("base64", string) + b64_json?: bytes; + + /** The URL of the generated image, if `response_format` is `url` (default). */ + url?: url; + + /** The prompt that was used to generate the image, if there was any revision to the prompt. */ + revised_prompt?: string; +} + diff --git a/images/operations.tsp b/images/operations.tsp index 09203262b..59928894f 100644 --- a/images/operations.tsp +++ b/images/operations.tsp @@ -16,7 +16,9 @@ interface Images { @operationId("createImage") @tag("OpenAI") @summary("Creates an image given a prompt") - createImage(@body image: CreateImageRequest): ImagesResponse | ErrorResponse; + createImage( + @body image: CreateImageRequest + ): ImagesResponse | ErrorResponse; @route("edits") @post diff --git a/main.tsp b/main.tsp index 2ea8cbbc3..fe7b08d3a 100644 --- a/main.tsp +++ b/main.tsp @@ -3,13 +3,14 @@ import "@typespec/openapi3"; import "@typespec/openapi"; import "./audio"; +import "./chat"; import "./completions"; -import "./edits"; import "./embeddings"; import "./files"; import "./fine-tuning"; import "./images"; -import "./moderation"; +import "./models"; +import "./moderations"; using TypeSpec.Http; diff --git a/models/main.tsp b/models/main.tsp new file mode 100644 index 000000000..6a754bcb5 --- /dev/null +++ b/models/main.tsp @@ -0,0 +1 @@ +import "./operations.tsp"; \ No newline at end of file diff --git a/models/models.tsp b/models/models.tsp new file mode 100644 index 000000000..68774d259 --- /dev/null +++ b/models/models.tsp @@ -0,0 +1,38 @@ +using TypeSpec.OpenAPI; + +namespace OpenAI; + +model ListModelsResponse { + object: "list"; + data: Model[]; +} + +model DeleteModelResponse { + id: string; + deleted: boolean; + object: "model"; +} + +/** Describes an OpenAI model offering that can be used with the API. */ +// TODO: Fill in example here. +@extension( + "x-oaiMeta", + { + name: "The model object", + example: "*retrieve_model_response" + } +) +model Model { + /** The model identifier, which can be referenced in the API endpoints. */ + id: string; + + /** The Unix timestamp (in seconds) when the model was created. */ + @encode("unixTimestamp", int32) + created: utcDateTime; + + /** The object type, which is always "model". */ + object: "model"; + + /** The organization that owns the model. */ + owned_by: string; +} \ No newline at end of file diff --git a/models/operations.tsp b/models/operations.tsp new file mode 100644 index 000000000..f017e1585 --- /dev/null +++ b/models/operations.tsp @@ -0,0 +1,47 @@ +import "@typespec/http"; +import "@typespec/openapi"; + +import "../common/errors.tsp"; +import "./models.tsp"; + +using TypeSpec.Http; +using TypeSpec.OpenAPI; + +namespace OpenAI; + +@route("/models") +interface Models { + @get + @operationId("listModels") + @tag("OpenAI") + @summary(""" + Lists the currently available models, and provides basic information about each one such as the + owner and availability. + """) + listModels(): ListModelsResponse | ErrorResponse; + + @route("{model}") + @get + @operationId("retrieveModel") + @tag("OpenAI") + @summary(""" + Retrieves a model instance, providing basic information about the model such as the owner and + permissioning. + """) + retrieve( + /** The ID of the model to use for this request. */ + @path `model`: string, + ): Model | ErrorResponse; + + @route("{model}") + @delete + @operationId("deleteModel") + @tag("OpenAI") + @summary(""" + Delete a fine-tuned model. You must have the Owner role in your organization to delete a model. + """) + delete( + /** The model to delete */ + @path `model`: string, + ): DeleteModelResponse | ErrorResponse; +} diff --git a/moderation/main.tsp b/moderations/main.tsp similarity index 100% rename from moderation/main.tsp rename to moderations/main.tsp diff --git a/moderation/models.tsp b/moderations/models.tsp similarity index 89% rename from moderation/models.tsp rename to moderations/models.tsp index f47b21be1..a572a6f2e 100644 --- a/moderation/models.tsp +++ b/moderations/models.tsp @@ -1,6 +1,7 @@ -namespace OpenAI; using TypeSpec.OpenAPI; +namespace OpenAI; + model CreateModerationRequest { /** The input text to classify */ input: string | string[]; @@ -13,9 +14,20 @@ model CreateModerationRequest { * of `text-moderation-stable` may be slightly lower than for `text-moderation-latest`. */ @extension("x-oaiTypeLabel", "string") - `model`?: string | "text-moderation-latest" | "text-moderation-stable" = "text-moderation-latest"; + `model`?: string | MODERATION_MODELS = "text-moderation-latest"; } +/** + * Represents policy compliance report by OpenAI's content moderation model against a given input. + */ +// TODO: Fill in example here. +@extension( + "x-oaiMeta", + { + name: "The moderation object", + example: "*moderation_example" + } +) model CreateModerationResponse { /** The unique identifier for the moderation request. */ id: string; @@ -66,7 +78,7 @@ model CreateModerationResponse { * Content that encourages performing acts of self-harm, such as suicide, cutting, and eating * disorders, or that gives instructions or advice on how to commit such acts. */ - `self-harm/instructive`: boolean; + `self-harm/instructions`: boolean; /** * Content meant to arouse sexual excitement, such as the description of sexual activity, or @@ -105,7 +117,7 @@ model CreateModerationResponse { `self-harm/intent`: float64; /** The score for the category 'self-harm/instructive'. */ - `self-harm/instructive`: float64; + `self-harm/instructions`: float64; /** The score for the category 'sexual'. */ sexual: float64; @@ -121,3 +133,7 @@ model CreateModerationResponse { }; }[]; } + +alias MODERATION_MODELS = + | "text-moderation-latest" + | "text-moderation-stable"; \ No newline at end of file diff --git a/moderation/operations.tsp b/moderations/operations.tsp similarity index 98% rename from moderation/operations.tsp rename to moderations/operations.tsp index 5f29bc3be..8efad4cdb 100644 --- a/moderation/operations.tsp +++ b/moderations/operations.tsp @@ -11,6 +11,7 @@ namespace OpenAI; @route("/moderations") interface Moderations { + @post @operationId("createModeration") @tag("OpenAI") @summary("Classifies if text violates OpenAI's Content Policy") diff --git a/openapi.yaml b/openapi.yaml index 011ccf375..a6e16ee12 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -13,8 +13,26 @@ info: servers: - url: https://api.openai.com/v1 tags: - - name: OpenAI - description: The OpenAI REST API + - name: Assistants + description: Build Assistants that can call models and use tools. + - name: Audio + description: Learn how to turn audio into text or text into audio. + - name: Chat + description: Given a list of messages comprising a conversation, the model will return a response. + - name: Completions + description: Given a prompt, the model will return one or more predicted completions, and can also return the probabilities of alternative tokens at each position. + - name: Embeddings + description: Get a vector representation of a given input that can be easily consumed by machine learning models and algorithms. + - name: Fine-tuning + description: Manage fine-tuning jobs to tailor a model to your specific training data. + - name: Files + description: Files are used to upload documents that can be used with features like Assistants and Fine-tuning. + - name: Images + description: Given a prompt and/or an input image, the model will generate a new image. + - name: Models + description: List and describe the various models available in the API. + - name: Moderations + description: Given a input text, outputs if the model classifies it as violating OpenAI's content policy. paths: # Note: When adding an endpoint, make sure you also add it in the `groups` section, in the end of this file, # under the appropriate group @@ -22,7 +40,7 @@ paths: post: operationId: createChatCompletion tags: - - OpenAI + - Chat summary: Creates a model response for the given chat conversation. requestBody: required: true @@ -45,7 +63,7 @@ paths: Returns a [chat completion](/docs/api-reference/chat/object) object, or a streamed sequence of [chat completion chunk](/docs/api-reference/chat/streaming) objects if the request is streamed. path: create examples: - - title: No Streaming + - title: Default request: curl: | curl https://api.openai.com/v1/chat/completions \ @@ -65,11 +83,10 @@ paths: ] }' python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") + from openai import OpenAI + client = OpenAI() - completion = openai.ChatCompletion.create( + completion = client.chat.completions.create( model="VAR_model_id", messages=[ {"role": "system", "content": "You are a helpful assistant."}, @@ -99,12 +116,111 @@ paths: "object": "chat.completion", "created": 1677652288, "model": "gpt-3.5-turbo-0613", + "system_fingerprint": "fp_44709d6fcb", "choices": [{ "index": 0, "message": { "role": "assistant", "content": "\n\nHello there, how may I assist you today?", }, + "logprobs": null, + "finish_reason": "stop" + }], + "usage": { + "prompt_tokens": 9, + "completion_tokens": 12, + "total_tokens": 21 + } + } + - title: Image input + request: + curl: | + curl https://api.openai.com/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -d '{ + "model": "gpt-4-vision-preview", + "messages": [ + { + "role": "user", + "content": [ + { + "type": "text", + "text": "What’s in this image?" + }, + { + "type": "image_url", + "image_url": { + "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg" + } + } + ] + } + ], + "max_tokens": 300 + }' + python: | + from openai import OpenAI + + client = OpenAI() + + response = client.chat.completions.create( + model="gpt-4-vision-preview", + messages=[ + { + "role": "user", + "content": [ + {"type": "text", "text": "What’s in this image?"}, + { + "type": "image_url", + "image_url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg", + }, + ], + } + ], + max_tokens=300, + ) + + print(response.choices[0]) + node.js: |- + import OpenAI from "openai"; + + const openai = new OpenAI(); + + async function main() { + const response = await openai.chat.completions.create({ + model: "gpt-4-vision-preview", + messages: [ + { + role: "user", + content: [ + { type: "text", text: "What’s in this image?" }, + { + type: "image_url", + image_url: + "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg", + }, + ], + }, + ], + }); + console.log(response.choices[0]); + } + main(); + response: &chat_completion_image_example | + { + "id": "chatcmpl-123", + "object": "chat.completion", + "created": 1677652288, + "model": "gpt-3.5-turbo-0613", + "system_fingerprint": "fp_44709d6fcb", + "choices": [{ + "index": 0, + "message": { + "role": "assistant", + "content": "\n\nHello there, how may I assist you today?", + }, + "logprobs": null, "finish_reason": "stop" }], "usage": { @@ -134,11 +250,10 @@ paths: "stream": true }' python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") + from openai import OpenAI + client = OpenAI() - completion = openai.ChatCompletion.create( + completion = client.chat.completions.create( model="VAR_model_id", messages=[ {"role": "system", "content": "You are a helpful assistant."}, @@ -172,24 +287,403 @@ paths: main(); response: &chat_completion_chunk_example | + {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1694268190,"model":"gpt-3.5-turbo-0613", "system_fingerprint": "fp_44709d6fcb", "choices":[{"index":0,"delta":{"role":"assistant","content":""},"logprobs":null,"finish_reason":null}]} + + {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1694268190,"model":"gpt-3.5-turbo-0613", "system_fingerprint": "fp_44709d6fcb", "choices":[{"index":0,"delta":{"content":"Hello"},"logprobs":null,"finish_reason":null}]} + + {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1694268190,"model":"gpt-3.5-turbo-0613", "system_fingerprint": "fp_44709d6fcb", "choices":[{"index":0,"delta":{"content":"!"},"logprobs":null,"finish_reason":null}]} + + .... + + {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1694268190,"model":"gpt-3.5-turbo-0613", "system_fingerprint": "fp_44709d6fcb", "choices":[{"index":0,"delta":{"content":" today"},"logprobs":null,"finish_reason":null}]} + + {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1694268190,"model":"gpt-3.5-turbo-0613", "system_fingerprint": "fp_44709d6fcb", "choices":[{"index":0,"delta":{"content":"?"},"logprobs":null,"finish_reason":null}]} + + {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1694268190,"model":"gpt-3.5-turbo-0613", "system_fingerprint": "fp_44709d6fcb", "choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}]} + - title: Functions + request: + curl: | + curl https://api.openai.com/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -d '{ + "model": "gpt-3.5-turbo", + "messages": [ + { + "role": "user", + "content": "What is the weather like in Boston?" + } + ], + "tools": [ + { + "type": "function", + "function": { + "name": "get_current_weather", + "description": "Get the current weather in a given location", + "parameters": { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state, e.g. San Francisco, CA" + }, + "unit": { + "type": "string", + "enum": ["celsius", "fahrenheit"] + } + }, + "required": ["location"] + } + } + } + ], + "tool_choice": "auto" + }' + python: | + from openai import OpenAI + client = OpenAI() + + tools = [ + { + "type": "function", + "function": { + "name": "get_current_weather", + "description": "Get the current weather in a given location", + "parameters": { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state, e.g. San Francisco, CA", + }, + "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}, + }, + "required": ["location"], + }, + } + } + ] + messages = [{"role": "user", "content": "What's the weather like in Boston today?"}] + completion = client.chat.completions.create( + model="VAR_model_id", + messages=messages, + tools=tools, + tool_choice="auto" + ) + + print(completion) + node.js: |- + import OpenAI from "openai"; + + const openai = new OpenAI(); + + async function main() { + const messages = [{"role": "user", "content": "What's the weather like in Boston today?"}]; + const tools = [ + { + "type": "function", + "function": { + "name": "get_current_weather", + "description": "Get the current weather in a given location", + "parameters": { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state, e.g. San Francisco, CA", + }, + "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}, + }, + "required": ["location"], + }, + } + } + ]; + + const response = await openai.chat.completions.create({ + model: "gpt-3.5-turbo", + messages: messages, + tools: tools, + tool_choice: "auto", + }); + + console.log(response); + } + + main(); + response: &chat_completion_function_example | + { + "id": "chatcmpl-abc123", + "object": "chat.completion", + "created": 1699896916, + "model": "gpt-3.5-turbo-0613", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": null, + "tool_calls": [ + { + "id": "call_abc123", + "type": "function", + "function": { + "name": "get_current_weather", + "arguments": "{\n\"location\": \"Boston, MA\"\n}" + } + } + ] + }, + "logprobs": null, + "finish_reason": "tool_calls" + } + ], + "usage": { + "prompt_tokens": 82, + "completion_tokens": 17, + "total_tokens": 99 + } + } + - title: Logprobs + request: + curl: | + curl https://api.openai.com/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -d '{ + "model": "VAR_model_id", + "messages": [ + { + "role": "user", + "content": "Hello!" + } + ], + "logprobs": true, + "top_logprobs": 2 + }' + python: | + from openai import OpenAI + client = OpenAI() + + completion = client.chat.completions.create( + model="VAR_model_id", + messages=[ + {"role": "user", "content": "Hello!"} + ], + logprobs=True, + top_logprobs=2 + ) + + print(completion.choices[0].message) + print(completion.choices[0].logprobs) + node.js: |- + import OpenAI from "openai"; + + const openai = new OpenAI(); + + async function main() { + const completion = await openai.chat.completions.create({ + messages: [{ role: "user", content: "Hello!" }], + model: "VAR_model_id", + logprobs: true, + top_logprobs: 2, + }); + + console.log(completion.choices[0]); + } + + main(); + response: | { "id": "chatcmpl-123", - "object": "chat.completion.chunk", - "created": 1677652288, - "model": "gpt-3.5-turbo", - "choices": [{ - "index": 0, - "delta": { - "content": "Hello", - }, - "finish_reason": "stop" - }] + "object": "chat.completion", + "created": 1702685778, + "model": "gpt-3.5-turbo-0613", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": "Hello! How can I assist you today?" + }, + "logprobs": { + "content": [ + { + "token": "Hello", + "logprob": -0.31725305, + "bytes": [72, 101, 108, 108, 111], + "top_logprobs": [ + { + "token": "Hello", + "logprob": -0.31725305, + "bytes": [72, 101, 108, 108, 111] + }, + { + "token": "Hi", + "logprob": -1.3190403, + "bytes": [72, 105] + } + ] + }, + { + "token": "!", + "logprob": -0.02380986, + "bytes": [ + 33 + ], + "top_logprobs": [ + { + "token": "!", + "logprob": -0.02380986, + "bytes": [33] + }, + { + "token": " there", + "logprob": -3.787621, + "bytes": [32, 116, 104, 101, 114, 101] + } + ] + }, + { + "token": " How", + "logprob": -0.000054669687, + "bytes": [32, 72, 111, 119], + "top_logprobs": [ + { + "token": " How", + "logprob": -0.000054669687, + "bytes": [32, 72, 111, 119] + }, + { + "token": "<|end|>", + "logprob": -10.953937, + "bytes": null + } + ] + }, + { + "token": " can", + "logprob": -0.015801601, + "bytes": [32, 99, 97, 110], + "top_logprobs": [ + { + "token": " can", + "logprob": -0.015801601, + "bytes": [32, 99, 97, 110] + }, + { + "token": " may", + "logprob": -4.161023, + "bytes": [32, 109, 97, 121] + } + ] + }, + { + "token": " I", + "logprob": -3.7697225e-6, + "bytes": [ + 32, + 73 + ], + "top_logprobs": [ + { + "token": " I", + "logprob": -3.7697225e-6, + "bytes": [32, 73] + }, + { + "token": " assist", + "logprob": -13.596657, + "bytes": [32, 97, 115, 115, 105, 115, 116] + } + ] + }, + { + "token": " assist", + "logprob": -0.04571125, + "bytes": [32, 97, 115, 115, 105, 115, 116], + "top_logprobs": [ + { + "token": " assist", + "logprob": -0.04571125, + "bytes": [32, 97, 115, 115, 105, 115, 116] + }, + { + "token": " help", + "logprob": -3.1089056, + "bytes": [32, 104, 101, 108, 112] + } + ] + }, + { + "token": " you", + "logprob": -5.4385737e-6, + "bytes": [32, 121, 111, 117], + "top_logprobs": [ + { + "token": " you", + "logprob": -5.4385737e-6, + "bytes": [32, 121, 111, 117] + }, + { + "token": " today", + "logprob": -12.807695, + "bytes": [32, 116, 111, 100, 97, 121] + } + ] + }, + { + "token": " today", + "logprob": -0.0040071653, + "bytes": [32, 116, 111, 100, 97, 121], + "top_logprobs": [ + { + "token": " today", + "logprob": -0.0040071653, + "bytes": [32, 116, 111, 100, 97, 121] + }, + { + "token": "?", + "logprob": -5.5247097, + "bytes": [63] + } + ] + }, + { + "token": "?", + "logprob": -0.0008108172, + "bytes": [63], + "top_logprobs": [ + { + "token": "?", + "logprob": -0.0008108172, + "bytes": [63] + }, + { + "token": "?\n", + "logprob": -7.184561, + "bytes": [63, 10] + } + ] + } + ] + }, + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 9, + "completion_tokens": 9, + "total_tokens": 18 + }, + "system_fingerprint": null } + /completions: post: operationId: createCompletion tags: - - OpenAI + - Completions summary: Creates a completion for the provided prompt and parameters. requestBody: required: true @@ -206,6 +700,7 @@ paths: $ref: "#/components/schemas/CreateCompletionResponse" x-oaiMeta: name: Create completion + group: completions returns: | Returns a [completion](/docs/api-reference/completions/object) object, or a sequence of completion objects if the request is streamed. legacy: true @@ -223,10 +718,10 @@ paths: "temperature": 0 }' python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - openai.Completion.create( + from openai import OpenAI + client = OpenAI() + + client.completions.create( model="VAR_model_id", prompt="Say this is a test", max_tokens=7, @@ -254,6 +749,7 @@ paths: "object": "text_completion", "created": 1589478378, "model": "VAR_model_id", + "system_fingerprint": "fp_44709d6fcb", "choices": [ { "text": "\n\nThis is indeed a test", @@ -282,17 +778,17 @@ paths: "stream": true }' python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - for chunk in openai.Completion.create( + from openai import OpenAI + client = OpenAI() + + for chunk in client.completions.create( model="VAR_model_id", prompt="Say this is a test", max_tokens=7, temperature=0, stream=True ): - print(chunk['choices'][0]['text']) + print(chunk.choices[0].text) node.js: |- import OpenAI from "openai"; @@ -324,90 +820,14 @@ paths: } ], "model": "gpt-3.5-turbo-instruct" + "system_fingerprint": "fp_44709d6fcb", } - /edits: - post: - operationId: createEdit - deprecated: true - tags: - - OpenAI - summary: Creates a new edit for the provided input, instruction, and parameters. - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/CreateEditRequest" - responses: - "200": - description: OK - content: - application/json: - schema: - $ref: "#/components/schemas/CreateEditResponse" - x-oaiMeta: - name: Create edit - returns: | - Returns an [edit](/docs/api-reference/edits/object) object. - group: edits - examples: - request: - curl: | - curl https://api.openai.com/v1/edits \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer $OPENAI_API_KEY" \ - -d '{ - "model": "VAR_model_id", - "input": "What day of the wek is it?", - "instruction": "Fix the spelling mistakes" - }' - python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - openai.Edit.create( - model="VAR_model_id", - input="What day of the wek is it?", - instruction="Fix the spelling mistakes" - ) - node.js: |- - import OpenAI from "openai"; - - const openai = new OpenAI(); - - async function main() { - const edit = await openai.edits.create({ - model: "VAR_model_id", - input: "What day of the wek is it?", - instruction: "Fix the spelling mistakes.", - }); - - console.log(edit); - } - - main(); - response: &edit_example | - { - "object": "edit", - "created": 1589478378, - "choices": [ - { - "text": "What day of the week is it?", - "index": 0, - } - ], - "usage": { - "prompt_tokens": 25, - "completion_tokens": 32, - "total_tokens": 57 - } - } /images/generations: post: operationId: createImage tags: - - OpenAI + - Images summary: Creates an image given a prompt. requestBody: required: true @@ -424,6 +844,7 @@ paths: $ref: "#/components/schemas/ImagesResponse" x-oaiMeta: name: Create image + group: images returns: Returns a list of [image](/docs/api-reference/images/object) objects. examples: request: @@ -432,17 +853,19 @@ paths: -H "Content-Type: application/json" \ -H "Authorization: Bearer $OPENAI_API_KEY" \ -d '{ + "model": "dall-e-3", "prompt": "A cute baby sea otter", - "n": 2, + "n": 1, "size": "1024x1024" }' python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - openai.Image.create( + from openai import OpenAI + client = OpenAI() + + client.images.generate( + model="dall-e-3", prompt="A cute baby sea otter", - n=2, + n=1, size="1024x1024" ) node.js: |- @@ -451,7 +874,7 @@ paths: const openai = new OpenAI(); async function main() { - const image = await openai.images.generate({ prompt: "A cute baby sea otter" }); + const image = await openai.images.generate({ model: "dall-e-3", prompt: "A cute baby sea otter" }); console.log(image.data); } @@ -468,12 +891,11 @@ paths: } ] } - /images/edits: post: operationId: createImageEdit tags: - - OpenAI + - Images summary: Creates an edited or extended image given an original image and a prompt. requestBody: required: true @@ -490,6 +912,7 @@ paths: $ref: "#/components/schemas/ImagesResponse" x-oaiMeta: name: Create image edit + group: images returns: Returns a list of [image](/docs/api-reference/images/object) objects. examples: request: @@ -502,10 +925,10 @@ paths: -F n=2 \ -F size="1024x1024" python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - openai.Image.create_edit( + from openai import OpenAI + client = OpenAI() + + client.images.edit( image=open("otter.png", "rb"), mask=open("mask.png", "rb"), prompt="A cute baby sea otter wearing a beret", @@ -540,12 +963,11 @@ paths: } ] } - /images/variations: post: operationId: createImageVariation tags: - - OpenAI + - Images summary: Creates a variation of a given image. requestBody: required: true @@ -562,6 +984,7 @@ paths: $ref: "#/components/schemas/ImagesResponse" x-oaiMeta: name: Create image variation + group: images returns: Returns a list of [image](/docs/api-reference/images/object) objects. examples: request: @@ -572,11 +995,11 @@ paths: -F n=2 \ -F size="1024x1024" python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - openai.Image.create_variation( - image=open("otter.png", "rb"), + from openai import OpenAI + client = OpenAI() + + response = client.images.create_variation( + image=open("image_edit_original.png", "rb"), n=2, size="1024x1024" ) @@ -611,7 +1034,7 @@ paths: post: operationId: createEmbedding tags: - - OpenAI + - Embeddings summary: Creates an embedding vector representing the input text. requestBody: required: true @@ -628,6 +1051,7 @@ paths: $ref: "#/components/schemas/CreateEmbeddingResponse" x-oaiMeta: name: Create embeddings + group: embeddings returns: A list of [embedding](/docs/api-reference/embeddings/object) objects. examples: request: @@ -637,15 +1061,17 @@ paths: -H "Content-Type: application/json" \ -d '{ "input": "The food was delicious and the waiter...", - "model": "text-embedding-ada-002" + "model": "text-embedding-ada-002", + "encoding_format": "float" }' python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - openai.Embedding.create( + from openai import OpenAI + client = OpenAI() + + client.embeddings.create( model="text-embedding-ada-002", - input="The food was delicious and the waiter..." + input="The food was delicious and the waiter...", + encoding_format="float" ) node.js: |- import OpenAI from "openai"; @@ -656,6 +1082,7 @@ paths: const embedding = await openai.embeddings.create({ model: "text-embedding-ada-002", input: "The quick brown fox jumped over the lazy dog", + encoding_format: "float", }); console.log(embedding); @@ -684,74 +1111,149 @@ paths: } } - /audio/transcriptions: + /audio/speech: post: - operationId: createTranscription + operationId: createSpeech tags: - - OpenAI - summary: Transcribes audio into the input language. + - Audio + summary: Generates audio from the input text. requestBody: required: true content: - multipart/form-data: + application/json: schema: - $ref: "#/components/schemas/CreateTranscriptionRequest" + $ref: "#/components/schemas/CreateSpeechRequest" responses: "200": description: OK + headers: + Transfer-Encoding: + schema: + type: string + description: chunked content: - application/json: + application/octet-stream: schema: - $ref: "#/components/schemas/CreateTranscriptionResponse" + type: string + format: binary x-oaiMeta: - name: Create transcription - returns: The transcriped text. + name: Create speech + group: audio + returns: The audio file content. examples: request: curl: | - curl https://api.openai.com/v1/audio/transcriptions \ + curl https://api.openai.com/v1/audio/speech \ -H "Authorization: Bearer $OPENAI_API_KEY" \ - -H "Content-Type: multipart/form-data" \ - -F file="@/path/to/file/audio.mp3" \ - -F model="whisper-1" + -H "Content-Type: application/json" \ + -d '{ + "model": "tts-1", + "input": "The quick brown fox jumped over the lazy dog.", + "voice": "alloy" + }' \ + --output speech.mp3 python: | - import os + from pathlib import Path import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - audio_file = open("audio.mp3", "rb") - transcript = openai.Audio.transcribe("whisper-1", audio_file) - node: |- + + speech_file_path = Path(__file__).parent / "speech.mp3" + response = openai.audio.speech.create( + model="tts-1", + voice="alloy", + input="The quick brown fox jumped over the lazy dog." + ) + response.stream_to_file(speech_file_path) + node: | import fs from "fs"; + import path from "path"; import OpenAI from "openai"; const openai = new OpenAI(); + const speechFile = path.resolve("./speech.mp3"); + async function main() { - const transcription = await openai.audio.transcriptions.create({ - file: fs.createReadStream("audio.mp3"), - model: "whisper-1", + const mp3 = await openai.audio.speech.create({ + model: "tts-1", + voice: "alloy", + input: "Today is a wonderful day to build something people love!", }); - - console.log(transcription.text); + console.log(speechFile); + const buffer = Buffer.from(await mp3.arrayBuffer()); + await fs.promises.writeFile(speechFile, buffer); } main(); - response: | - { - "text": "Imagine the wildest idea that you've ever had, and you're curious about how it might scale to something that's a 100, a 1,000 times bigger. This is a place where you can get to do that." - } - - /audio/translations: + /audio/transcriptions: post: - operationId: createTranslation + operationId: createTranscription tags: - - OpenAI - summary: Translates audio into English. + - Audio + summary: Transcribes audio into the input language. requestBody: required: true content: multipart/form-data: schema: - $ref: "#/components/schemas/CreateTranslationRequest" + $ref: "#/components/schemas/CreateTranscriptionRequest" + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/CreateTranscriptionResponse" + x-oaiMeta: + name: Create transcription + group: audio + returns: The transcribed text. + examples: + request: + curl: | + curl https://api.openai.com/v1/audio/transcriptions \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "Content-Type: multipart/form-data" \ + -F file="@/path/to/file/audio.mp3" \ + -F model="whisper-1" + python: | + from openai import OpenAI + client = OpenAI() + + audio_file = open("speech.mp3", "rb") + transcript = client.audio.transcriptions.create( + model="whisper-1", + file=audio_file + ) + node: | + import fs from "fs"; + import OpenAI from "openai"; + + const openai = new OpenAI(); + + async function main() { + const transcription = await openai.audio.transcriptions.create({ + file: fs.createReadStream("audio.mp3"), + model: "whisper-1", + }); + + console.log(transcription.text); + } + main(); + response: | + { + "text": "Imagine the wildest idea that you've ever had, and you're curious about how it might scale to something that's a 100, a 1,000 times bigger. This is a place where you can get to do that." + } + /audio/translations: + post: + operationId: createTranslation + tags: + - Audio + summary: Translates audio into English. + requestBody: + required: true + content: + multipart/form-data: + schema: + $ref: "#/components/schemas/CreateTranslationRequest" responses: "200": description: OK @@ -761,6 +1263,7 @@ paths: $ref: "#/components/schemas/CreateTranslationResponse" x-oaiMeta: name: Create translation + group: audio returns: The translated text. examples: request: @@ -771,21 +1274,29 @@ paths: -F file="@/path/to/file/german.m4a" \ -F model="whisper-1" python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - audio_file = open("german.m4a", "rb") - transcript = openai.Audio.translate("whisper-1", audio_file) + from openai import OpenAI + client = OpenAI() + + audio_file = open("speech.mp3", "rb") + transcript = client.audio.translations.create( + model="whisper-1", + file=audio_file + ) node: | - const { Configuration, OpenAIApi } = require("openai"); - const configuration = new Configuration({ - apiKey: process.env.OPENAI_API_KEY, - }); - const openai = new OpenAIApi(configuration); - const resp = await openai.createTranslation( - fs.createReadStream("audio.mp3"), - "whisper-1" - ); + import fs from "fs"; + import OpenAI from "openai"; + + const openai = new OpenAI(); + + async function main() { + const translation = await openai.audio.translations.create({ + file: fs.createReadStream("speech.mp3"), + model: "whisper-1", + }); + + console.log(translation.text); + } + main(); response: | { "text": "Hello, my name is Wolfgang and I come from Germany. Where are you heading today?" @@ -795,8 +1306,15 @@ paths: get: operationId: listFiles tags: - - OpenAI + - Files summary: Returns a list of files that belong to the user's organization. + parameters: + - in: query + name: purpose + required: false + schema: + type: string + description: Only return files with the given purpose. responses: "200": description: OK @@ -806,17 +1324,18 @@ paths: $ref: "#/components/schemas/ListFilesResponse" x-oaiMeta: name: List files - returns: A list of [file](/docs/api-reference/files/object) objects. + group: files + returns: A list of [File](/docs/api-reference/files/object) objects. examples: request: curl: | curl https://api.openai.com/v1/files \ -H "Authorization: Bearer $OPENAI_API_KEY" python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - openai.File.list() + from openai import OpenAI + client = OpenAI() + + client.files.list() node.js: |- import OpenAI from "openai"; @@ -839,8 +1358,8 @@ paths: "object": "file", "bytes": 175, "created_at": 1613677385, - "filename": "train.jsonl", - "purpose": "search" + "filename": "salesOverview.pdf", + "purpose": "assistants", }, { "id": "file-abc123", @@ -848,7 +1367,7 @@ paths: "bytes": 140, "created_at": 1613779121, "filename": "puppy.jsonl", - "purpose": "search" + "purpose": "fine-tune", } ], "object": "list" @@ -856,10 +1375,13 @@ paths: post: operationId: createFile tags: - - OpenAI + - Files summary: | - Upload a file that contains document(s) to be used across various endpoints/features. Currently, the size of all the files uploaded by one organization can be up to 1 GB. Please contact us if you need to increase the storage limit. + Upload a file that can be used across various endpoints. The size of all the files uploaded by one organization can be up to 100 GB. + + The size of individual files can be a maximum of 512 MB or 2 million tokens for Assistants. See the [Assistants Tools guide](/docs/assistants/tools) to learn more about the types of files supported. The Fine-tuning API only supports `.jsonl` files. + Please [contact us](https://help.openai.com/) if you need to increase these storage limits. requestBody: required: true content: @@ -875,7 +1397,8 @@ paths: $ref: "#/components/schemas/OpenAIFile" x-oaiMeta: name: Upload file - returns: The uploaded [file](/docs/api-reference/files/object) object. + group: files + returns: The uploaded [File](/docs/api-reference/files/object) object. examples: request: curl: | @@ -884,12 +1407,12 @@ paths: -F purpose="fine-tune" \ -F file="@mydata.jsonl" python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - openai.File.create( + from openai import OpenAI + client = OpenAI() + + client.files.create( file=open("mydata.jsonl", "rb"), - purpose='fine-tune' + purpose="fine-tune" ) node.js: |- import fs from "fs"; @@ -911,18 +1434,16 @@ paths: { "id": "file-abc123", "object": "file", - "bytes": 140, - "created_at": 1613779121, + "bytes": 120000, + "created_at": 1677610602, "filename": "mydata.jsonl", "purpose": "fine-tune", - "status": "uploaded" | "processed" | "pending" | "error" } - /files/{file_id}: delete: operationId: deleteFile tags: - - OpenAI + - Files summary: Delete a file. parameters: - in: path @@ -940,6 +1461,7 @@ paths: $ref: "#/components/schemas/DeleteFileResponse" x-oaiMeta: name: Delete file + group: files returns: Deletion status. examples: request: @@ -948,10 +1470,10 @@ paths: -X DELETE \ -H "Authorization: Bearer $OPENAI_API_KEY" python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - openai.File.delete("file-abc123") + from openai import OpenAI + client = OpenAI() + + client.files.delete("file-abc123") node.js: |- import OpenAI from "openai"; @@ -973,7 +1495,7 @@ paths: get: operationId: retrieveFile tags: - - OpenAI + - Files summary: Returns information about a specific file. parameters: - in: path @@ -991,17 +1513,18 @@ paths: $ref: "#/components/schemas/OpenAIFile" x-oaiMeta: name: Retrieve file - returns: The [file](/docs/api-reference/files/object) object matching the specified ID. + group: files + returns: The [File](/docs/api-reference/files/object) object matching the specified ID. examples: request: curl: | curl https://api.openai.com/v1/files/file-abc123 \ -H "Authorization: Bearer $OPENAI_API_KEY" python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - openai.File.retrieve("file-abc123") + from openai import OpenAI + client = OpenAI() + + client.files.retrieve("file-abc123") node.js: |- import OpenAI from "openai"; @@ -1018,17 +1541,16 @@ paths: { "id": "file-abc123", "object": "file", - "bytes": 140, - "created_at": 1613779657, + "bytes": 120000, + "created_at": 1677610602, "filename": "mydata.jsonl", - "purpose": "fine-tune" + "purpose": "fine-tune", } - /files/{file_id}/content: get: operationId: downloadFile tags: - - OpenAI + - Files summary: Returns the contents of the specified file. parameters: - in: path @@ -1046,6 +1568,7 @@ paths: type: string x-oaiMeta: name: Retrieve file content + group: files returns: The file content. examples: request: @@ -1053,10 +1576,10 @@ paths: curl https://api.openai.com/v1/files/file-abc123/content \ -H "Authorization: Bearer $OPENAI_API_KEY" > file.jsonl python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - content = openai.File.download("file-abc123") + from openai import OpenAI + client = OpenAI() + + content = client.files.retrieve_content("file-abc123") node.js: | import OpenAI from "openai"; @@ -1074,9 +1597,9 @@ paths: post: operationId: createFineTuningJob tags: - - OpenAI + - Fine-tuning summary: | - Creates a job that fine-tunes a specified model from a given dataset. + Creates a fine-tuning job which begins the process of creating a new model from a given dataset. Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete. @@ -1096,23 +1619,27 @@ paths: $ref: "#/components/schemas/FineTuningJob" x-oaiMeta: name: Create fine-tuning job + group: fine-tuning returns: A [fine-tuning.job](/docs/api-reference/fine-tuning/object) object. examples: - - title: No hyperparameters + - title: Default request: curl: | curl https://api.openai.com/v1/fine_tuning/jobs \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $OPENAI_API_KEY" \ -d '{ - "training_file": "file-abc123" - "model": "gpt-3.5-turbo", + "training_file": "file-BK7bzQj3FfZFXr7DbL6xJwfo", + "model": "gpt-3.5-turbo" }' python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - openai.FineTuningJob.create(training_file="file-abc123", model="gpt-3.5-turbo") + from openai import OpenAI + client = OpenAI() + + client.fine_tuning.jobs.create( + training_file="file-abc123", + model="gpt-3.5-turbo" + ) node.js: | import OpenAI from "openai"; @@ -1130,7 +1657,7 @@ paths: response: | { "object": "fine_tuning.job", - "id": "ft-AF1WoRqd3aJAHsqc9NY7iL8F", + "id": "ftjob-abc123", "model": "gpt-3.5-turbo-0613", "created_at": 1614807352, "fine_tuned_model": null, @@ -1140,24 +1667,30 @@ paths: "validation_file": null, "training_file": "file-abc123", } - - title: Hyperparameters + - title: Epochs request: curl: | curl https://api.openai.com/v1/fine_tuning/jobs \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $OPENAI_API_KEY" \ -d '{ - "training_file": "file-abc123" + "training_file": "file-abc123", "model": "gpt-3.5-turbo", "hyperparameters": { "n_epochs": 2 } }' python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - openai.FineTuningJob.create(training_file="file-abc123", model="gpt-3.5-turbo", hyperparameters={"n_epochs":2}) + from openai import OpenAI + client = OpenAI() + + client.fine_tuning.jobs.create( + training_file="file-abc123", + model="gpt-3.5-turbo", + hyperparameters={ + "n_epochs":2 + } + ) node.js: | import OpenAI from "openai"; @@ -1167,7 +1700,7 @@ paths: const fineTune = await openai.fineTuning.jobs.create({ training_file: "file-abc123", model: "gpt-3.5-turbo", - hyperparameters: { n_epochs: 2 }, + hyperparameters: { n_epochs: 2 } }); console.log(fineTune); @@ -1177,7 +1710,7 @@ paths: response: | { "object": "fine_tuning.job", - "id": "ft-AF1WoRqd3aJAHsqc9NY7iL8F", + "id": "ftjob-abc123", "model": "gpt-3.5-turbo-0613", "created_at": 1614807352, "fine_tuned_model": null, @@ -1186,12 +1719,60 @@ paths: "status": "queued", "validation_file": null, "training_file": "file-abc123", - "hyperparameters":{"n_epochs":2}, + "hyperparameters": {"n_epochs": 2}, + } + - title: Validation file + request: + curl: | + curl https://api.openai.com/v1/fine_tuning/jobs \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -d '{ + "training_file": "file-abc123", + "validation_file": "file-abc123", + "model": "gpt-3.5-turbo" + }' + python: | + from openai import OpenAI + client = OpenAI() + + client.fine_tuning.jobs.create( + training_file="file-abc123", + validation_file="file-def456", + model="gpt-3.5-turbo" + ) + node.js: | + import OpenAI from "openai"; + + const openai = new OpenAI(); + + async function main() { + const fineTune = await openai.fineTuning.jobs.create({ + training_file: "file-abc123", + validation_file: "file-abc123" + }); + + console.log(fineTune); + } + + main(); + response: | + { + "object": "fine_tuning.job", + "id": "ftjob-abc123", + "model": "gpt-3.5-turbo-0613", + "created_at": 1614807352, + "fine_tuned_model": null, + "organization_id": "org-123", + "result_files": [], + "status": "queued", + "validation_file": "file-abc123", + "training_file": "file-abc123", } get: operationId: listPaginatedFineTuningJobs tags: - - OpenAI + - Fine-tuning summary: | List your organization's fine-tuning jobs parameters: @@ -1217,6 +1798,7 @@ paths: $ref: "#/components/schemas/ListPaginatedFineTuningJobsResponse" x-oaiMeta: name: List fine-tuning jobs + group: fine-tuning returns: A list of paginated [fine-tuning job](/docs/api-reference/fine-tuning/object) objects. examples: request: @@ -1224,10 +1806,10 @@ paths: curl https://api.openai.com/v1/fine_tuning/jobs?limit=2 \ -H "Authorization: Bearer $OPENAI_API_KEY" python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - openai.FineTuningJob.list() + from openai import OpenAI + client = OpenAI() + + client.fine_tuning.jobs.list() node.js: |- import OpenAI from "openai"; @@ -1263,7 +1845,7 @@ paths: get: operationId: retrieveFineTuningJob tags: - - OpenAI + - Fine-tuning summary: | Get info about a fine-tuning job. @@ -1286,25 +1868,26 @@ paths: $ref: "#/components/schemas/FineTuningJob" x-oaiMeta: name: Retrieve fine-tuning job - returns: The [fine-tuning](/docs/api-reference/fine-tunes/object) object with the given ID. + group: fine-tuning + returns: The [fine-tuning](/docs/api-reference/fine-tuning/object) object with the given ID. examples: request: curl: | curl https://api.openai.com/v1/fine_tuning/jobs/ft-AF1WoRqd3aJAHsqc9NY7iL8F \ -H "Authorization: Bearer $OPENAI_API_KEY" python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - openai.FineTuningJob.retrieve("ft-anaKUAgnnBkNGB3QcSr4pImR") + from openai import OpenAI + client = OpenAI() + + client.fine_tuning.jobs.retrieve("ftjob-abc123") node.js: | import OpenAI from "openai"; const openai = new OpenAI(); async function main() { - const fineTune = await openai.fineTuning.jobs.retrieve("ft-AF1WoRqd3aJAHsqc9NY7iL8F"); - + const fineTune = await openai.fineTuning.jobs.retrieve("ftjob-abc123"); + console.log(fineTune); } @@ -1312,7 +1895,7 @@ paths: response: &fine_tuning_example | { "object": "fine_tuning.job", - "id": "ft-zRdUkP4QeZqeYjDcQL0wwam1", + "id": "ftjob-abc123", "model": "davinci-002", "created_at": 1692661014, "finished_at": 1692661190, @@ -1329,12 +1912,11 @@ paths: }, "trained_tokens": 5768 } - /fine_tuning/jobs/{fine_tuning_job_id}/events: get: operationId: listFineTuningEvents tags: - - OpenAI + - Fine-tuning summary: | Get status updates for a fine-tuning job. parameters: @@ -1368,24 +1950,28 @@ paths: $ref: "#/components/schemas/ListFineTuningJobEventsResponse" x-oaiMeta: name: List fine-tuning events + group: fine-tuning returns: A list of fine-tuning event objects. examples: request: curl: | - curl https://api.openai.com/v1/fine_tuning/jobs/ft-AF1WoRqd3aJAHsqc9NY7iL8F/events \ + curl https://api.openai.com/v1/fine_tuning/jobs/ftjob-abc123/events \ -H "Authorization: Bearer $OPENAI_API_KEY" python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - openai.FineTuningJob.list_events(id="ft-w9WJrnTe9vcVopaTy9LrlGQv", limit=2) + from openai import OpenAI + client = OpenAI() + + client.fine_tuning.jobs.list_events( + fine_tuning_job_id="ftjob-abc123", + limit=2 + ) node.js: |- import OpenAI from "openai"; const openai = new OpenAI(); async function main() { - const list = await openai.fineTuning.list_events(id="ft-w9WJrnTe9vcVopaTy9LrlGQv", limit=2); + const list = await openai.fineTuning.list_events(id="ftjob-abc123", limit=2); for await (const fineTune of list) { console.log(fineTune); @@ -1418,12 +2004,11 @@ paths: ], "has_more": true } - /fine_tuning/jobs/{fine_tuning_job_id}/cancel: post: operationId: cancelFineTuningJob tags: - - OpenAI + - Fine-tuning summary: | Immediately cancel a fine-tune job. parameters: @@ -1444,24 +2029,25 @@ paths: $ref: "#/components/schemas/FineTuningJob" x-oaiMeta: name: Cancel fine-tuning + group: fine-tuning returns: The cancelled [fine-tuning](/docs/api-reference/fine-tuning/object) object. examples: request: curl: | - curl -X POST https://api.openai.com/v1/fine_tuning/jobs/ft-AF1WoRqd3aJAHsqc9NY7iL8F/cancel \ + curl -X POST https://api.openai.com/v1/fine_tuning/jobs/ftjob-abc123/cancel \ -H "Authorization: Bearer $OPENAI_API_KEY" python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - openai.FineTuningJob.cancel("ft-anaKUAgnnBkNGB3QcSr4pImR") + from openai import OpenAI + client = OpenAI() + + client.fine_tuning.jobs.cancel("ftjob-abc123") node.js: |- import OpenAI from "openai"; const openai = new OpenAI(); async function main() { - const fineTune = await openai.fineTuning.jobs.cancel("ft-AF1WoRqd3aJAHsqc9NY7iL8F"); + const fineTune = await openai.fineTuning.jobs.cancel("ftjob-abc123"); console.log(fineTune); } @@ -1469,7 +2055,7 @@ paths: response: | { "object": "fine_tuning.job", - "id": "ft-gleYLJhWh1YFufiy29AahVpj", + "id": "ftjob-abc123", "model": "gpt-3.5-turbo-0613", "created_at": 1689376978, "fine_tuned_model": null, @@ -1483,2690 +2069,6608 @@ paths: "training_file": "file-abc123" } - /fine-tunes: - post: - operationId: createFineTune - deprecated: true + /models: + get: + operationId: listModels tags: - - OpenAI - summary: | - Creates a job that fine-tunes a specified model from a given dataset. - - Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete. - - [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) - requestBody: - required: true - content: - application/json: - schema: - $ref: "#/components/schemas/CreateFineTuneRequest" + - Models + summary: Lists the currently available models, and provides basic information about each one such as the owner and availability. responses: "200": description: OK content: application/json: schema: - $ref: "#/components/schemas/FineTune" + $ref: "#/components/schemas/ListModelsResponse" x-oaiMeta: - name: Create fine-tune - returns: A [fine-tune](/docs/api-reference/fine-tunes/object) object. + name: List models + group: models + returns: A list of [model](/docs/api-reference/models/object) objects. examples: request: curl: | - curl https://api.openai.com/v1/fine-tunes \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer $OPENAI_API_KEY" \ - -d '{ - "training_file": "file-abc123" - }' + curl https://api.openai.com/v1/models \ + -H "Authorization: Bearer $OPENAI_API_KEY" python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - openai.FineTune.create(training_file="file-abc123") - node.js: | + from openai import OpenAI + client = OpenAI() + + client.models.list() + node.js: |- import OpenAI from "openai"; const openai = new OpenAI(); async function main() { - const fineTune = await openai.fineTunes.create({ - training_file: "file-abc123" - }); + const list = await openai.models.list(); - console.log(fineTune); + for await (const model of list) { + console.log(model); + } } - main(); response: | { - "id": "ft-AF1WoRqd3aJAHsqc9NY7iL8F", - "object": "fine-tune", - "model": "curie", - "created_at": 1614807352, - "events": [ + "object": "list", + "data": [ { - "object": "fine-tune-event", - "created_at": 1614807352, - "level": "info", - "message": "Job enqueued. Waiting for jobs ahead to complete. Queue number: 0." - } - ], - "fine_tuned_model": null, - "hyperparams": { - "batch_size": 4, - "learning_rate_multiplier": 0.1, - "n_epochs": 4, - "prompt_loss_weight": 0.1, - }, - "organization_id": "org-123", - "result_files": [], - "status": "pending", - "validation_files": [], - "training_files": [ + "id": "model-id-0", + "object": "model", + "created": 1686935002, + "owned_by": "organization-owner" + }, { - "id": "file-abc123", - "object": "file", - "bytes": 1547276, - "created_at": 1610062281, - "filename": "my-data-train.jsonl", - "purpose": "fine-tune-train" - } + "id": "model-id-1", + "object": "model", + "created": 1686935002, + "owned_by": "organization-owner", + }, + { + "id": "model-id-2", + "object": "model", + "created": 1686935002, + "owned_by": "openai" + }, ], - "updated_at": 1614807352, + "object": "list" } + /models/{model}: get: - operationId: listFineTunes - deprecated: true + operationId: retrieveModel tags: - - OpenAI - summary: | - List your organization's fine-tuning jobs + - Models + summary: Retrieves a model instance, providing basic information about the model such as the owner and permissioning. + parameters: + - in: path + name: model + required: true + schema: + type: string + # ideally this will be an actual ID, so this will always work from browser + example: gpt-3.5-turbo + description: The ID of the model to use for this request responses: "200": description: OK content: application/json: schema: - $ref: "#/components/schemas/ListFineTunesResponse" + $ref: "#/components/schemas/Model" x-oaiMeta: - name: List fine-tunes - returns: A list of [fine-tune](/docs/api-reference/fine-tunes/object) objects. + name: Retrieve model + group: models + returns: The [model](/docs/api-reference/models/object) object matching the specified ID. examples: request: curl: | - curl https://api.openai.com/v1/fine-tunes \ + curl https://api.openai.com/v1/models/VAR_model_id \ -H "Authorization: Bearer $OPENAI_API_KEY" python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - openai.FineTune.list() + from openai import OpenAI + client = OpenAI() + + client.models.retrieve("VAR_model_id") node.js: |- import OpenAI from "openai"; const openai = new OpenAI(); async function main() { - const list = await openai.fineTunes.list(); + const model = await openai.models.retrieve("gpt-3.5-turbo"); - for await (const fineTune of list) { - console.log(fineTune); - } + console.log(model); } main(); - response: | + response: &retrieve_model_response | { - "object": "list", - "data": [ - { - "id": "ft-AF1WoRqd3aJAHsqc9NY7iL8F", - "object": "fine-tune", - "model": "curie", - "created_at": 1614807352, - "fine_tuned_model": null, - "hyperparams": { ... }, - "organization_id": "org-123", - "result_files": [], - "status": "pending", - "validation_files": [], - "training_files": [ { ... } ], - "updated_at": 1614807352, - }, - { ... }, - { ... } - ] + "id": "VAR_model_id", + "object": "model", + "created": 1686935002, + "owned_by": "openai" } - - /fine-tunes/{fine_tune_id}: - get: - operationId: retrieveFineTune - deprecated: true + delete: + operationId: deleteModel tags: - - OpenAI - summary: | - Gets info about the fine-tune job. - - [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) + - Models + summary: Delete a fine-tuned model. You must have the Owner role in your organization to delete a model. parameters: - in: path - name: fine_tune_id + name: model required: true schema: type: string - example: ft-AF1WoRqd3aJAHsqc9NY7iL8F - description: | - The ID of the fine-tune job + example: ft:gpt-3.5-turbo:acemeco:suffix:abc123 + description: The model to delete responses: "200": description: OK content: application/json: schema: - $ref: "#/components/schemas/FineTune" + $ref: "#/components/schemas/DeleteModelResponse" x-oaiMeta: - name: Retrieve fine-tune - returns: The [fine-tune](/docs/api-reference/fine-tunes/object) object with the given ID. + name: Delete a fine-tuned model + group: models + returns: Deletion status. examples: request: curl: | - curl https://api.openai.com/v1/fine-tunes/ft-AF1WoRqd3aJAHsqc9NY7iL8F \ + curl https://api.openai.com/v1/models/ft:gpt-3.5-turbo:acemeco:suffix:abc123 \ + -X DELETE \ -H "Authorization: Bearer $OPENAI_API_KEY" python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - openai.FineTune.retrieve(id="ft-AF1WoRqd3aJAHsqc9NY7iL8F") + from openai import OpenAI + client = OpenAI() + + client.models.delete("ft:gpt-3.5-turbo:acemeco:suffix:abc123") node.js: |- import OpenAI from "openai"; const openai = new OpenAI(); async function main() { - const fineTune = await openai.fineTunes.retrieve("ft-AF1WoRqd3aJAHsqc9NY7iL8F"); + const model = await openai.models.del("ft:gpt-3.5-turbo:acemeco:suffix:abc123"); - console.log(fineTune); + console.log(model); } - main(); - response: &fine_tune_example | + response: | { - "id": "ft-AF1WoRqd3aJAHsqc9NY7iL8F", - "object": "fine-tune", - "model": "curie", - "created_at": 1614807352, - "events": [ - { - "object": "fine-tune-event", - "created_at": 1614807352, - "level": "info", - "message": "Job enqueued. Waiting for jobs ahead to complete. Queue number: 0." - }, - { - "object": "fine-tune-event", - "created_at": 1614807356, - "level": "info", - "message": "Job started." - }, - { - "object": "fine-tune-event", - "created_at": 1614807861, - "level": "info", - "message": "Uploaded snapshot: curie:ft-acmeco-2021-03-03-21-44-20." - }, - { - "object": "fine-tune-event", - "created_at": 1614807864, - "level": "info", - "message": "Uploaded result files: file-abc123." - }, - { - "object": "fine-tune-event", - "created_at": 1614807864, - "level": "info", - "message": "Job succeeded." - } - ], - "fine_tuned_model": "curie:ft-acmeco-2021-03-03-21-44-20", - "hyperparams": { - "batch_size": 4, - "learning_rate_multiplier": 0.1, - "n_epochs": 4, - "prompt_loss_weight": 0.1, - }, - "organization_id": "org-123", - "result_files": [ - { - "id": "file-abc123", - "object": "file", - "bytes": 81509, - "created_at": 1614807863, - "filename": "compiled_results.csv", - "purpose": "fine-tune-results" - } - ], - "status": "succeeded", - "validation_files": [], - "training_files": [ - { - "id": "file-abc123", - "object": "file", - "bytes": 1547276, - "created_at": 1610062281, - "filename": "my-data-train.jsonl", - "purpose": "fine-tune-train" - } - ], - "updated_at": 1614807865, + "id": "ft:gpt-3.5-turbo:acemeco:suffix:abc123", + "object": "model", + "deleted": true } - /fine-tunes/{fine_tune_id}/cancel: + /moderations: post: - operationId: cancelFineTune - deprecated: true + operationId: createModeration tags: - - OpenAI - summary: | - Immediately cancel a fine-tune job. - parameters: - - in: path - name: fine_tune_id - required: true - schema: - type: string - example: ft-AF1WoRqd3aJAHsqc9NY7iL8F - description: | - The ID of the fine-tune job to cancel + - Moderations + summary: Classifies if text violates OpenAI's Content Policy + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/CreateModerationRequest" responses: "200": description: OK content: application/json: schema: - $ref: "#/components/schemas/FineTune" + $ref: "#/components/schemas/CreateModerationResponse" x-oaiMeta: - name: Cancel fine-tune - returns: The cancelled [fine-tune](/docs/api-reference/fine-tunes/object) object. + name: Create moderation + group: moderations + returns: A [moderation](/docs/api-reference/moderations/object) object. examples: request: curl: | - curl https://api.openai.com/v1/fine-tunes/ft-AF1WoRqd3aJAHsqc9NY7iL8F/cancel \ - -H "Authorization: Bearer $OPENAI_API_KEY" + curl https://api.openai.com/v1/moderations \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -d '{ + "input": "I want to kill them." + }' python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - openai.FineTune.cancel(id="ft-AF1WoRqd3aJAHsqc9NY7iL8F") - node.js: |- + from openai import OpenAI + client = OpenAI() + + client.moderations.create(input="I want to kill them.") + node.js: | import OpenAI from "openai"; const openai = new OpenAI(); async function main() { - const fineTune = await openai.fineTunes.cancel("ft-AF1WoRqd3aJAHsqc9NY7iL8F"); + const moderation = await openai.moderations.create({ input: "I want to kill them." }); - console.log(fineTune); + console.log(moderation); } main(); - response: | + response: &moderation_example | { - "id": "ft-xhrpBbvVUzYGo8oUO1FY4nI7", - "object": "fine-tune", - "model": "curie", - "created_at": 1614807770, - "events": [ { ... } ], - "fine_tuned_model": null, - "hyperparams": { ... }, - "organization_id": "org-123", - "result_files": [], - "status": "cancelled", - "validation_files": [], - "training_files": [ + "id": "modr-XXXXX", + "model": "text-moderation-005", + "results": [ { - "id": "file-abc123", - "object": "file", - "bytes": 1547276, - "created_at": 1610062281, - "filename": "my-data-train.jsonl", - "purpose": "fine-tune-train" + "flagged": true, + "categories": { + "sexual": false, + "hate": false, + "harassment": false, + "self-harm": false, + "sexual/minors": false, + "hate/threatening": false, + "violence/graphic": false, + "self-harm/intent": false, + "self-harm/instructions": false, + "harassment/threatening": true, + "violence": true, + }, + "category_scores": { + "sexual": 1.2282071e-06, + "hate": 0.010696256, + "harassment": 0.29842457, + "self-harm": 1.5236925e-08, + "sexual/minors": 5.7246268e-08, + "hate/threatening": 0.0060676364, + "violence/graphic": 4.435014e-06, + "self-harm/intent": 8.098441e-10, + "self-harm/instructions": 2.8498655e-11, + "harassment/threatening": 0.63055265, + "violence": 0.99011886, + } } - ], - "updated_at": 1614807789, + ] } - /fine-tunes/{fine_tune_id}/events: + /assistants: get: - operationId: listFineTuneEvents - deprecated: true + operationId: listAssistants tags: - - OpenAI - summary: | - Get fine-grained status updates for a fine-tune job. + - Assistants + summary: Returns a list of assistants. parameters: - - in: path - name: fine_tune_id - required: true + - name: limit + in: query + description: &pagination_limit_param_description | + A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 20. + required: false + schema: + type: integer + default: 20 + - name: order + in: query + description: &pagination_order_param_description | + Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and `desc` for descending order. schema: type: string - example: ft-AF1WoRqd3aJAHsqc9NY7iL8F - description: | - The ID of the fine-tune job to get events for. - - in: query - name: stream - required: false + default: desc + enum: ["asc", "desc"] + - name: after + in: query + description: &pagination_after_param_description | + A cursor for use in pagination. `after` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page of the list. schema: - type: boolean - default: false - description: | - Whether to stream events for the fine-tune job. If set to true, - events will be sent as data-only - [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) - as they become available. The stream will terminate with a - `data: [DONE]` message when the job is finished (succeeded, cancelled, - or failed). - - If set to false, only events generated so far will be returned. + type: string + - name: before + in: query + description: &pagination_before_param_description | + A cursor for use in pagination. `before` is an object ID that defines your place in the list. For instance, if you make a list request and receive 100 objects, ending with obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous page of the list. + schema: + type: string responses: "200": description: OK content: application/json: schema: - $ref: "#/components/schemas/ListFineTuneEventsResponse" + $ref: "#/components/schemas/ListAssistantsResponse" x-oaiMeta: - name: List fine-tune events - returns: A list of fine-tune event objects. + name: List assistants + group: assistants + beta: true + returns: A list of [assistant](/docs/api-reference/assistants/object) objects. examples: request: curl: | - curl https://api.openai.com/v1/fine-tunes/ft-AF1WoRqd3aJAHsqc9NY7iL8F/events \ - -H "Authorization: Bearer $OPENAI_API_KEY" + curl "https://api.openai.com/v1/assistants?order=desc&limit=20" \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "OpenAI-Beta: assistants=v1" python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - openai.FineTune.list_events(id="ft-AF1WoRqd3aJAHsqc9NY7iL8F") + from openai import OpenAI + client = OpenAI() + + my_assistants = client.beta.assistants.list( + order="desc", + limit="20", + ) + print(my_assistants.data) node.js: |- import OpenAI from "openai"; const openai = new OpenAI(); async function main() { - const fineTune = await openai.fineTunes.listEvents("ft-AF1WoRqd3aJAHsqc9NY7iL8F"); + const myAssistants = await openai.beta.assistants.list({ + order: "desc", + limit: "20", + }); - console.log(fineTune); + console.log(myAssistants.data); } + main(); - response: | + response: &list_assistants_example | { "object": "list", "data": [ { - "object": "fine-tune-event", - "created_at": 1614807352, - "level": "info", - "message": "Job enqueued. Waiting for jobs ahead to complete. Queue number: 0." - }, - { - "object": "fine-tune-event", - "created_at": 1614807356, - "level": "info", - "message": "Job started." - }, - { - "object": "fine-tune-event", - "created_at": 1614807861, - "level": "info", - "message": "Uploaded snapshot: curie:ft-acmeco-2021-03-03-21-44-20." + "id": "asst_abc123", + "object": "assistant", + "created_at": 1698982736, + "name": "Coding Tutor", + "description": null, + "model": "gpt-4", + "instructions": "You are a helpful assistant designed to make me better at coding!", + "tools": [], + "file_ids": [], + "metadata": {} }, { - "object": "fine-tune-event", - "created_at": 1614807864, - "level": "info", - "message": "Uploaded result files: file-abc123" + "id": "asst_abc456", + "object": "assistant", + "created_at": 1698982718, + "name": "My Assistant", + "description": null, + "model": "gpt-4", + "instructions": "You are a helpful assistant designed to make me better at coding!", + "tools": [], + "file_ids": [], + "metadata": {} }, { - "object": "fine-tune-event", - "created_at": 1614807864, - "level": "info", - "message": "Job succeeded." + "id": "asst_abc789", + "object": "assistant", + "created_at": 1698982643, + "name": null, + "description": null, + "model": "gpt-4", + "instructions": null, + "tools": [], + "file_ids": [], + "metadata": {} } - ] + ], + "first_id": "asst_abc123", + "last_id": "asst_abc789", + "has_more": false } + post: + operationId: createAssistant + tags: + - Assistants + summary: Create an assistant with a model and instructions. + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/CreateAssistantRequest" + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/AssistantObject" + x-oaiMeta: + name: Create assistant + group: assistants + beta: true + returns: An [assistant](/docs/api-reference/assistants/object) object. + examples: + - title: Code Interpreter + request: + curl: | + curl "https://api.openai.com/v1/assistants" \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "OpenAI-Beta: assistants=v1" \ + -d '{ + "instructions": "You are a personal math tutor. When asked a question, write and run Python code to answer the question.", + "name": "Math Tutor", + "tools": [{"type": "code_interpreter"}], + "model": "gpt-4" + }' - /models: + python: | + from openai import OpenAI + client = OpenAI() + + my_assistant = client.beta.assistants.create( + instructions="You are a personal math tutor. When asked a question, write and run Python code to answer the question.", + name="Math Tutor", + tools=[{"type": "code_interpreter"}], + model="gpt-4", + ) + print(my_assistant) + node.js: |- + import OpenAI from "openai"; + + const openai = new OpenAI(); + + async function main() { + const myAssistant = await openai.beta.assistants.create({ + instructions: + "You are a personal math tutor. When asked a question, write and run Python code to answer the question.", + name: "Math Tutor", + tools: [{ type: "code_interpreter" }], + model: "gpt-4", + }); + + console.log(myAssistant); + } + + main(); + response: &create_assistants_example | + { + "id": "asst_abc123", + "object": "assistant", + "created_at": 1698984975, + "name": "Math Tutor", + "description": null, + "model": "gpt-4", + "instructions": "You are a personal math tutor. When asked a question, write and run Python code to answer the question.", + "tools": [ + { + "type": "code_interpreter" + } + ], + "file_ids": [], + "metadata": {} + } + - title: Files + request: + curl: | + curl https://api.openai.com/v1/assistants \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "OpenAI-Beta: assistants=v1" \ + -d '{ + "instructions": "You are an HR bot, and you have access to files to answer employee questions about company policies.", + "tools": [{"type": "retrieval"}], + "model": "gpt-4", + "file_ids": ["file-abc123"] + }' + python: | + from openai import OpenAI + client = OpenAI() + + my_assistant = client.beta.assistants.create( + instructions="You are an HR bot, and you have access to files to answer employee questions about company policies.", + name="HR Helper", + tools=[{"type": "retrieval"}], + model="gpt-4", + file_ids=["file-abc123"], + ) + print(my_assistant) + node.js: |- + import OpenAI from "openai"; + + const openai = new OpenAI(); + + async function main() { + const myAssistant = await openai.beta.assistants.create({ + instructions: + "You are an HR bot, and you have access to files to answer employee questions about company policies.", + name: "HR Helper", + tools: [{ type: "retrieval" }], + model: "gpt-4", + file_ids: ["file-abc123"], + }); + + console.log(myAssistant); + } + + main(); + response: | + { + "id": "asst_abc123", + "object": "assistant", + "created_at": 1699009403, + "name": "HR Helper", + "description": null, + "model": "gpt-4", + "instructions": "You are an HR bot, and you have access to files to answer employee questions about company policies.", + "tools": [ + { + "type": "retrieval" + } + ], + "file_ids": [ + "file-abc123" + ], + "metadata": {} + } + + /assistants/{assistant_id}: get: - operationId: listModels + operationId: getAssistant tags: - - OpenAI - summary: Lists the currently available models, and provides basic information about each one such as the owner and availability. + - Assistants + summary: Retrieves an assistant. + parameters: + - in: path + name: assistant_id + required: true + schema: + type: string + description: The ID of the assistant to retrieve. responses: "200": description: OK content: application/json: schema: - $ref: "#/components/schemas/ListModelsResponse" + $ref: "#/components/schemas/AssistantObject" x-oaiMeta: - name: List models - returns: A list of [model](/docs/api-reference/models/object) objects. + name: Retrieve assistant + group: assistants + beta: true + returns: The [assistant](/docs/api-reference/assistants/object) object matching the specified ID. examples: request: curl: | - curl https://api.openai.com/v1/models \ - -H "Authorization: Bearer $OPENAI_API_KEY" + curl https://api.openai.com/v1/assistants/asst_abc123 \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "OpenAI-Beta: assistants=v1" python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - openai.Model.list() + from openai import OpenAI + client = OpenAI() + + my_assistant = client.beta.assistants.retrieve("asst_abc123") + print(my_assistant) node.js: |- import OpenAI from "openai"; const openai = new OpenAI(); async function main() { - const list = await openai.models.list(); + const myAssistant = await openai.beta.assistants.retrieve( + "asst_abc123" + ); - for await (const model of list) { - console.log(model); - } + console.log(myAssistant); } + main(); response: | { - "object": "list", - "data": [ - { - "id": "model-id-0", - "object": "model", - "created": 1686935002, - "owned_by": "organization-owner" - }, + "id": "asst_abc123", + "object": "assistant", + "created_at": 1699009709, + "name": "HR Helper", + "description": null, + "model": "gpt-4", + "instructions": "You are an HR bot, and you have access to files to answer employee questions about company policies.", + "tools": [ { - "id": "model-id-1", - "object": "model", - "created": 1686935002, - "owned_by": "organization-owner", - }, - { - "id": "model-id-2", - "object": "model", - "created": 1686935002, - "owned_by": "openai" - }, + "type": "retrieval" + } ], - "object": "list" + "file_ids": [ + "file-abc123" + ], + "metadata": {} } - - /models/{model}: - get: - operationId: retrieveModel + post: + operationId: modifyAssistant tags: - - OpenAI - summary: Retrieves a model instance, providing basic information about the model such as the owner and permissioning. + - Assistants + summary: Modifies an assistant. parameters: - in: path - name: model + name: assistant_id required: true schema: type: string - # ideally this will be an actual ID, so this will always work from browser - example: gpt-3.5-turbo - description: The ID of the model to use for this request + description: The ID of the assistant to modify. + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/ModifyAssistantRequest" responses: "200": description: OK content: application/json: schema: - $ref: "#/components/schemas/Model" + $ref: "#/components/schemas/AssistantObject" x-oaiMeta: - name: Retrieve model - returns: The [model](/docs/api-reference/models/object) object matching the specified ID. + name: Modify assistant + group: assistants + beta: true + returns: The modified [assistant](/docs/api-reference/assistants/object) object. examples: request: curl: | - curl https://api.openai.com/v1/models/VAR_model_id \ - -H "Authorization: Bearer $OPENAI_API_KEY" + curl https://api.openai.com/v1/assistants/asst_abc123 \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "OpenAI-Beta: assistants=v1" \ + -d '{ + "instructions": "You are an HR bot, and you have access to files to answer employee questions about company policies. Always response with info from either of the files.", + "tools": [{"type": "retrieval"}], + "model": "gpt-4", + "file_ids": ["file-abc123", "file-abc456"] + }' python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - openai.Model.retrieve("VAR_model_id") + from openai import OpenAI + client = OpenAI() + + my_updated_assistant = client.beta.assistants.update( + "asst_abc123", + instructions="You are an HR bot, and you have access to files to answer employee questions about company policies. Always response with info from either of the files.", + name="HR Helper", + tools=[{"type": "retrieval"}], + model="gpt-4", + file_ids=["file-abc123", "file-abc456"], + ) + + print(my_updated_assistant) node.js: |- import OpenAI from "openai"; const openai = new OpenAI(); async function main() { - const model = await openai.models.retrieve("gpt-3.5-turbo"); + const myUpdatedAssistant = await openai.beta.assistants.update( + "asst_abc123", + { + instructions: + "You are an HR bot, and you have access to files to answer employee questions about company policies. Always response with info from either of the files.", + name: "HR Helper", + tools: [{ type: "retrieval" }], + model: "gpt-4", + file_ids: [ + "file-abc123", + "file-abc456", + ], + } + ); - console.log(model); + console.log(myUpdatedAssistant); } main(); - response: &retrieve_model_response | + response: | { - "id": "VAR_model_id", - "object": "model", - "created": 1686935002, - "owned_by": "openai" + "id": "asst_abc123", + "object": "assistant", + "created_at": 1699009709, + "name": "HR Helper", + "description": null, + "model": "gpt-4", + "instructions": "You are an HR bot, and you have access to files to answer employee questions about company policies. Always response with info from either of the files.", + "tools": [ + { + "type": "retrieval" + } + ], + "file_ids": [ + "file-abc123", + "file-abc456" + ], + "metadata": {} } delete: - operationId: deleteModel + operationId: deleteAssistant tags: - - OpenAI - summary: Delete a fine-tuned model. You must have the Owner role in your organization to delete a model. + - Assistants + summary: Delete an assistant. parameters: - in: path - name: model + name: assistant_id required: true schema: type: string - example: ft:gpt-3.5-turbo:acemeco:suffix:abc123 - description: The model to delete + description: The ID of the assistant to delete. responses: "200": description: OK content: application/json: schema: - $ref: "#/components/schemas/DeleteModelResponse" + $ref: "#/components/schemas/DeleteAssistantResponse" x-oaiMeta: - name: Delete fine-tune model - returns: Deletion status. + name: Delete assistant + group: assistants + beta: true + returns: Deletion status examples: request: curl: | - curl https://api.openai.com/v1/models/ft:gpt-3.5-turbo:acemeco:suffix:abc123 \ - -X DELETE \ - -H "Authorization: Bearer $OPENAI_API_KEY" + curl https://api.openai.com/v1/assistants/asst_abc123 \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "OpenAI-Beta: assistants=v1" \ + -X DELETE python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - openai.Model.delete("ft:gpt-3.5-turbo:acemeco:suffix:abc123") + from openai import OpenAI + client = OpenAI() + + response = client.beta.assistants.delete("asst_abc123") + print(response) node.js: |- import OpenAI from "openai"; const openai = new OpenAI(); async function main() { - const model = await openai.models.del("ft:gpt-3.5-turbo:acemeco:suffix:abc123"); + const response = await openai.beta.assistants.del("asst_abc123"); - console.log(model); + console.log(response); } main(); response: | { - "id": "ft:gpt-3.5-turbo:acemeco:suffix:abc123", - "object": "model", + "id": "asst_abc123", + "object": "assistant.deleted", "deleted": true } - /moderations: + /threads: post: - operationId: createModeration + operationId: createThread tags: - - OpenAI - summary: Classifies if text violates OpenAI's Content Policy + - Assistants + summary: Create a thread. + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/CreateThreadRequest" + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/ThreadObject" + x-oaiMeta: + name: Create thread + group: threads + beta: true + returns: A [thread](/docs/api-reference/threads) object. + examples: + - title: Empty + request: + curl: | + curl https://api.openai.com/v1/threads \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "OpenAI-Beta: assistants=v1" \ + -d '' + python: | + from openai import OpenAI + client = OpenAI() + + empty_thread = client.beta.threads.create() + print(empty_thread) + node.js: |- + import OpenAI from "openai"; + + const openai = new OpenAI(); + + async function main() { + const emptyThread = await openai.beta.threads.create(); + + console.log(emptyThread); + } + + main(); + response: | + { + "id": "thread_abc123", + "object": "thread", + "created_at": 1699012949, + "metadata": {} + } + - title: Messages + request: + curl: | + curl https://api.openai.com/v1/threads \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "OpenAI-Beta: assistants=v1" \ + -d '{ + "messages": [{ + "role": "user", + "content": "Hello, what is AI?", + "file_ids": ["file-abc123"] + }, { + "role": "user", + "content": "How does AI work? Explain it in simple terms." + }] + }' + python: | + from openai import OpenAI + client = OpenAI() + + message_thread = client.beta.threads.create( + messages=[ + { + "role": "user", + "content": "Hello, what is AI?", + "file_ids": ["file-abc123"], + }, + { + "role": "user", + "content": "How does AI work? Explain it in simple terms." + }, + ] + ) + + print(message_thread) + node.js: |- + import OpenAI from "openai"; + + const openai = new OpenAI(); + + async function main() { + const messageThread = await openai.beta.threads.create({ + messages: [ + { + role: "user", + content: "Hello, what is AI?", + file_ids: ["file-abc123"], + }, + { + role: "user", + content: "How does AI work? Explain it in simple terms.", + }, + ], + }); + + console.log(messageThread); + } + + main(); + response: | + { + id: 'thread_abc123', + object: 'thread', + created_at: 1699014083, + metadata: {} + } + + /threads/{thread_id}: + get: + operationId: getThread + tags: + - Assistants + summary: Retrieves a thread. + parameters: + - in: path + name: thread_id + required: true + schema: + type: string + description: The ID of the thread to retrieve. + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/ThreadObject" + x-oaiMeta: + name: Retrieve thread + group: threads + beta: true + returns: The [thread](/docs/api-reference/threads/object) object matching the specified ID. + examples: + request: + curl: | + curl https://api.openai.com/v1/threads/thread_abc123 \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "OpenAI-Beta: assistants=v1" + python: | + from openai import OpenAI + client = OpenAI() + + my_thread = client.beta.threads.retrieve("thread_abc123") + print(my_thread) + node.js: |- + import OpenAI from "openai"; + + const openai = new OpenAI(); + + async function main() { + const myThread = await openai.beta.threads.retrieve( + "thread_abc123" + ); + + console.log(myThread); + } + + main(); + response: | + { + "id": "thread_abc123", + "object": "thread", + "created_at": 1699014083, + "metadata": {} + } + post: + operationId: modifyThread + tags: + - Assistants + summary: Modifies a thread. + parameters: + - in: path + name: thread_id + required: true + schema: + type: string + description: The ID of the thread to modify. Only the `metadata` can be modified. requestBody: required: true content: application/json: schema: - $ref: "#/components/schemas/CreateModerationRequest" + $ref: "#/components/schemas/ModifyThreadRequest" responses: "200": description: OK content: application/json: schema: - $ref: "#/components/schemas/CreateModerationResponse" + $ref: "#/components/schemas/ThreadObject" x-oaiMeta: - name: Create moderation - returns: A [moderation](/docs/api-reference/moderations/object) object. + name: Modify thread + group: threads + beta: true + returns: The modified [thread](/docs/api-reference/threads/object) object matching the specified ID. examples: request: curl: | - curl https://api.openai.com/v1/moderations \ + curl https://api.openai.com/v1/threads/thread_abc123 \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "OpenAI-Beta: assistants=v1" \ -d '{ - "input": "I want to kill them." - }' + "metadata": { + "modified": "true", + "user": "abc123" + } + }' python: | - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - openai.Moderation.create( - input="I want to kill them.", + from openai import OpenAI + client = OpenAI() + + my_updated_thread = client.beta.threads.update( + "thread_abc123", + metadata={ + "modified": "true", + "user": "abc123" + } ) - node.js: | + print(my_updated_thread) + node.js: |- import OpenAI from "openai"; const openai = new OpenAI(); async function main() { - const moderation = await openai.moderations.create({ input: "I want to kill them." }); + const updatedThread = await openai.beta.threads.update( + "thread_abc123", + { + metadata: { modified: "true", user: "abc123" }, + } + ); - console.log(moderation); + console.log(updatedThread); } + main(); - response: &moderation_example | + response: | { - "id": "modr-XXXXX", - "model": "text-moderation-005", - "results": [ - { - "flagged": true, - "categories": { - "sexual": false, - "hate": false, - "harassment": false, - "self-harm": false, - "sexual/minors": false, - "hate/threatening": false, - "violence/graphic": false, - "self-harm/intent": false, - "self-harm/instructions": false, - "harassment/threatening": true, - "violence": true, - }, - "category_scores": { - "sexual": 1.2282071e-06, - "hate": 0.010696256, - "harassment": 0.29842457, - "self-harm": 1.5236925e-08, - "sexual/minors": 5.7246268e-08, - "hate/threatening": 0.0060676364, - "violence/graphic": 4.435014e-06, - "self-harm/intent": 8.098441e-10, - "self-harm/instructions": 2.8498655e-11, - "harassment/threatening": 0.63055265, - "violence": 0.99011886, - } - } - ] + "id": "thread_abc123", + "object": "thread", + "created_at": 1699014083, + "metadata": { + "modified": "true", + "user": "abc123" + } } + delete: + operationId: deleteThread + tags: + - Assistants + summary: Delete a thread. + parameters: + - in: path + name: thread_id + required: true + schema: + type: string + description: The ID of the thread to delete. + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/DeleteThreadResponse" + x-oaiMeta: + name: Delete thread + group: threads + beta: true + returns: Deletion status + examples: + request: + curl: | + curl https://api.openai.com/v1/threads/thread_abc123 \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "OpenAI-Beta: assistants=v1" \ + -X DELETE + python: | + from openai import OpenAI + client = OpenAI() -components: + response = client.beta.threads.delete("thread_abc123") + print(response) + node.js: |- + import OpenAI from "openai"; + + const openai = new OpenAI(); + + async function main() { + const response = await openai.beta.threads.del("thread_abc123"); + + console.log(response); + } + main(); + response: | + { + "id": "thread_abc123", + "object": "thread.deleted", + "deleted": true + } + + /threads/{thread_id}/messages: + get: + operationId: listMessages + tags: + - Assistants + summary: Returns a list of messages for a given thread. + parameters: + - in: path + name: thread_id + required: true + schema: + type: string + description: The ID of the [thread](/docs/api-reference/threads) the messages belong to. + - name: limit + in: query + description: *pagination_limit_param_description + required: false + schema: + type: integer + default: 20 + - name: order + in: query + description: *pagination_order_param_description + schema: + type: string + default: desc + enum: ["asc", "desc"] + - name: after + in: query + description: *pagination_after_param_description + schema: + type: string + - name: before + in: query + description: *pagination_before_param_description + schema: + type: string + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/ListMessagesResponse" + x-oaiMeta: + name: List messages + group: threads + beta: true + returns: A list of [message](/docs/api-reference/messages) objects. + examples: + request: + curl: | + curl https://api.openai.com/v1/threads/thread_abc123/messages \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "OpenAI-Beta: assistants=v1" + python: | + from openai import OpenAI + client = OpenAI() + + thread_messages = client.beta.threads.messages.list("thread_abc123") + print(thread_messages.data) + node.js: |- + import OpenAI from "openai"; + + const openai = new OpenAI(); + + async function main() { + const threadMessages = await openai.beta.threads.messages.list( + "thread_abc123" + ); + + console.log(threadMessages.data); + } + + main(); + response: | + { + "object": "list", + "data": [ + { + "id": "msg_abc123", + "object": "thread.message", + "created_at": 1699016383, + "thread_id": "thread_abc123", + "role": "user", + "content": [ + { + "type": "text", + "text": { + "value": "How does AI work? Explain it in simple terms.", + "annotations": [] + } + } + ], + "file_ids": [], + "assistant_id": null, + "run_id": null, + "metadata": {} + }, + { + "id": "msg_abc456", + "object": "thread.message", + "created_at": 1699016383, + "thread_id": "thread_abc123", + "role": "user", + "content": [ + { + "type": "text", + "text": { + "value": "Hello, what is AI?", + "annotations": [] + } + } + ], + "file_ids": [ + "file-abc123" + ], + "assistant_id": null, + "run_id": null, + "metadata": {} + } + ], + "first_id": "msg_abc123", + "last_id": "msg_abc456", + "has_more": false + } + post: + operationId: createMessage + tags: + - Assistants + summary: Create a message. + parameters: + - in: path + name: thread_id + required: true + schema: + type: string + description: The ID of the [thread](/docs/api-reference/threads) to create a message for. + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/CreateMessageRequest" + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/MessageObject" + x-oaiMeta: + name: Create message + group: threads + beta: true + returns: A [message](/docs/api-reference/messages/object) object. + examples: + request: + curl: | + curl https://api.openai.com/v1/threads/thread_abc123/messages \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "OpenAI-Beta: assistants=v1" \ + -d '{ + "role": "user", + "content": "How does AI work? Explain it in simple terms." + }' + python: | + from openai import OpenAI + client = OpenAI() + + thread_message = client.beta.threads.messages.create( + "thread_abc123", + role="user", + content="How does AI work? Explain it in simple terms.", + ) + print(thread_message) + node.js: |- + import OpenAI from "openai"; + + const openai = new OpenAI(); + + async function main() { + const threadMessages = await openai.beta.threads.messages.create( + "thread_abc123", + { role: "user", content: "How does AI work? Explain it in simple terms." } + ); + + console.log(threadMessages); + } + + main(); + response: | + { + "id": "msg_abc123", + "object": "thread.message", + "created_at": 1699017614, + "thread_id": "thread_abc123", + "role": "user", + "content": [ + { + "type": "text", + "text": { + "value": "How does AI work? Explain it in simple terms.", + "annotations": [] + } + } + ], + "file_ids": [], + "assistant_id": null, + "run_id": null, + "metadata": {} + } + + /threads/{thread_id}/messages/{message_id}: + get: + operationId: getMessage + tags: + - Assistants + summary: Retrieve a message. + parameters: + - in: path + name: thread_id + required: true + schema: + type: string + description: The ID of the [thread](/docs/api-reference/threads) to which this message belongs. + - in: path + name: message_id + required: true + schema: + type: string + description: The ID of the message to retrieve. + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/MessageObject" + x-oaiMeta: + name: Retrieve message + group: threads + beta: true + returns: The [message](/docs/api-reference/threads/messages/object) object matching the specified ID. + examples: + request: + curl: | + curl https://api.openai.com/v1/threads/thread_abc123/messages/msg_abc123 \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "OpenAI-Beta: assistants=v1" + python: | + from openai import OpenAI + client = OpenAI() + + message = client.beta.threads.messages.retrieve( + message_id="msg_abc123", + thread_id="thread_abc123", + ) + print(message) + node.js: |- + import OpenAI from "openai"; + + const openai = new OpenAI(); + + async function main() { + const message = await openai.beta.threads.messages.retrieve( + "thread_abc123", + "msg_abc123" + ); + + console.log(message); + } + + main(); + response: | + { + "id": "msg_abc123", + "object": "thread.message", + "created_at": 1699017614, + "thread_id": "thread_abc123", + "role": "user", + "content": [ + { + "type": "text", + "text": { + "value": "How does AI work? Explain it in simple terms.", + "annotations": [] + } + } + ], + "file_ids": [], + "assistant_id": null, + "run_id": null, + "metadata": {} + } + post: + operationId: modifyMessage + tags: + - Assistants + summary: Modifies a message. + parameters: + - in: path + name: thread_id + required: true + schema: + type: string + description: The ID of the thread to which this message belongs. + - in: path + name: message_id + required: true + schema: + type: string + description: The ID of the message to modify. + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/ModifyMessageRequest" + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/MessageObject" + x-oaiMeta: + name: Modify message + group: threads + beta: true + returns: The modified [message](/docs/api-reference/threads/messages/object) object. + examples: + request: + curl: | + curl https://api.openai.com/v1/threads/thread_abc123/messages/msg_abc123 \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "OpenAI-Beta: assistants=v1" \ + -d '{ + "metadata": { + "modified": "true", + "user": "abc123" + } + }' + python: | + from openai import OpenAI + client = OpenAI() + + message = client.beta.threads.messages.update( + message_id="msg_abc12", + thread_id="thread_abc123", + metadata={ + "modified": "true", + "user": "abc123", + }, + ) + print(message) + node.js: |- + import OpenAI from "openai"; + + const openai = new OpenAI(); + + async function main() { + const message = await openai.beta.threads.messages.update( + "thread_abc123", + "msg_abc123", + { + metadata: { + modified: "true", + user: "abc123", + }, + } + }' + response: | + { + "id": "msg_abc123", + "object": "thread.message", + "created_at": 1699017614, + "thread_id": "thread_abc123", + "role": "user", + "content": [ + { + "type": "text", + "text": { + "value": "How does AI work? Explain it in simple terms.", + "annotations": [] + } + } + ], + "file_ids": [], + "assistant_id": null, + "run_id": null, + "metadata": { + "modified": "true", + "user": "abc123" + } + } + + /threads/runs: + post: + operationId: createThreadAndRun + tags: + - Assistants + summary: Create a thread and run it in one request. + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/CreateThreadAndRunRequest" + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/RunObject" + x-oaiMeta: + name: Create thread and run + group: threads + beta: true + returns: A [run](/docs/api-reference/runs/object) object. + examples: + request: + curl: | + curl https://api.openai.com/v1/threads/runs \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "Content-Type: application/json" \ + -H "OpenAI-Beta: assistants=v1" \ + -d '{ + "assistant_id": "asst_abc123", + "thread": { + "messages": [ + {"role": "user", "content": "Explain deep learning to a 5 year old."} + ] + } + }' + python: | + from openai import OpenAI + client = OpenAI() + + run = client.beta.threads.create_and_run( + assistant_id="asst_abc123", + thread={ + "messages": [ + {"role": "user", "content": "Explain deep learning to a 5 year old."} + ] + } + ) + node.js: | + import OpenAI from "openai"; + + const openai = new OpenAI(); + + async function main() { + const run = await openai.beta.threads.createAndRun({ + assistant_id: "asst_abc123", + thread: { + messages: [ + { role: "user", content: "Explain deep learning to a 5 year old." }, + ], + }, + }); + + console.log(run); + } + + main(); + response: | + { + "id": "run_abc123", + "object": "thread.run", + "created_at": 1699076792, + "assistant_id": "asst_abc123", + "thread_id": "thread_abc123", + "status": "queued", + "started_at": null, + "expires_at": 1699077392, + "cancelled_at": null, + "failed_at": null, + "completed_at": null, + "last_error": null, + "model": "gpt-4", + "instructions": "You are a helpful assistant.", + "tools": [], + "file_ids": [], + "metadata": {}, + "usage": null + } + + /threads/{thread_id}/runs: + get: + operationId: listRuns + tags: + - Assistants + summary: Returns a list of runs belonging to a thread. + parameters: + - name: thread_id + in: path + required: true + schema: + type: string + description: The ID of the thread the run belongs to. + - name: limit + in: query + description: *pagination_limit_param_description + required: false + schema: + type: integer + default: 20 + - name: order + in: query + description: *pagination_order_param_description + schema: + type: string + default: desc + enum: ["asc", "desc"] + - name: after + in: query + description: *pagination_after_param_description + schema: + type: string + - name: before + in: query + description: *pagination_before_param_description + schema: + type: string + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/ListRunsResponse" + x-oaiMeta: + name: List runs + group: threads + beta: true + returns: A list of [run](/docs/api-reference/runs/object) objects. + examples: + request: + curl: | + curl https://api.openai.com/v1/threads/thread_abc123/runs \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "Content-Type: application/json" \ + -H "OpenAI-Beta: assistants=v1" + python: | + from openai import OpenAI + client = OpenAI() + + runs = client.beta.threads.runs.list( + "thread_abc123" + ) + print(runs) + node.js: | + import OpenAI from "openai"; + + const openai = new OpenAI(); + + async function main() { + const runs = await openai.beta.threads.runs.list( + "thread_abc123" + ); + + console.log(runs); + } + + main(); + response: | + { + "object": "list", + "data": [ + { + "id": "run_abc123", + "object": "thread.run", + "created_at": 1699075072, + "assistant_id": "asst_abc123", + "thread_id": "thread_abc123", + "status": "completed", + "started_at": 1699075072, + "expires_at": null, + "cancelled_at": null, + "failed_at": null, + "completed_at": 1699075073, + "last_error": null, + "model": "gpt-3.5-turbo", + "instructions": null, + "tools": [ + { + "type": "code_interpreter" + } + ], + "file_ids": [ + "file-abc123", + "file-abc456" + ], + "metadata": {}, + "usage": { + "prompt_tokens": 123, + "completion_tokens": 456, + "total_tokens": 579 + } + }, + { + "id": "run_abc456", + "object": "thread.run", + "created_at": 1699063290, + "assistant_id": "asst_abc123", + "thread_id": "thread_abc123", + "status": "completed", + "started_at": 1699063290, + "expires_at": null, + "cancelled_at": null, + "failed_at": null, + "completed_at": 1699063291, + "last_error": null, + "model": "gpt-3.5-turbo", + "instructions": null, + "tools": [ + { + "type": "code_interpreter" + } + ], + "file_ids": [ + "file-abc123", + "file-abc456" + ], + "metadata": {}, + "usage": { + "prompt_tokens": 123, + "completion_tokens": 456, + "total_tokens": 579 + } + } + ], + "first_id": "run_abc123", + "last_id": "run_abc456", + "has_more": false + } + post: + operationId: createRun + tags: + - Assistants + summary: Create a run. + parameters: + - in: path + name: thread_id + required: true + schema: + type: string + description: The ID of the thread to run. + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/CreateRunRequest" + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/RunObject" + x-oaiMeta: + name: Create run + group: threads + beta: true + returns: A [run](/docs/api-reference/runs/object) object. + examples: + request: + curl: | + curl https://api.openai.com/v1/threads/thread_abc123/runs \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "Content-Type: application/json" \ + -H "OpenAI-Beta: assistants=v1" \ + -d '{ + "assistant_id": "asst_abc123" + }' + python: | + from openai import OpenAI + client = OpenAI() + + run = client.beta.threads.runs.create( + thread_id="thread_abc123", + assistant_id="asst_abc123" + ) + print(run) + node.js: | + import OpenAI from "openai"; + + const openai = new OpenAI(); + + async function main() { + const run = await openai.beta.threads.runs.create( + "thread_abc123", + { assistant_id: "asst_abc123" } + ); + + console.log(run); + } + + main(); + response: &run_object_example | + { + "id": "run_abc123", + "object": "thread.run", + "created_at": 1699063290, + "assistant_id": "asst_abc123", + "thread_id": "thread_abc123", + "status": "queued", + "started_at": 1699063290, + "expires_at": null, + "cancelled_at": null, + "failed_at": null, + "completed_at": 1699063291, + "last_error": null, + "model": "gpt-4", + "instructions": null, + "tools": [ + { + "type": "code_interpreter" + } + ], + "file_ids": [ + "file-abc123", + "file-abc456" + ], + "metadata": {}, + "usage": null + } + + /threads/{thread_id}/runs/{run_id}: + get: + operationId: getRun + tags: + - Assistants + summary: Retrieves a run. + parameters: + - in: path + name: thread_id + required: true + schema: + type: string + description: The ID of the [thread](/docs/api-reference/threads) that was run. + - in: path + name: run_id + required: true + schema: + type: string + description: The ID of the run to retrieve. + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/RunObject" + x-oaiMeta: + name: Retrieve run + group: threads + beta: true + returns: The [run](/docs/api-reference/runs/object) object matching the specified ID. + examples: + request: + curl: | + curl https://api.openai.com/v1/threads/thread_abc123/runs/run_abc123 \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "OpenAI-Beta: assistants=v1" + python: | + from openai import OpenAI + client = OpenAI() + + run = client.beta.threads.runs.retrieve( + thread_id="thread_abc123", + run_id="run_abc123" + ) + print(run) + node.js: | + import OpenAI from "openai"; + + const openai = new OpenAI(); + + async function main() { + const run = await openai.beta.threads.runs.retrieve( + "thread_abc123", + "run_abc123" + ); + + console.log(run); + } + + main(); + response: | + { + "id": "run_abc123", + "object": "thread.run", + "created_at": 1699075072, + "assistant_id": "asst_abc123", + "thread_id": "thread_abc123", + "status": "completed", + "started_at": 1699075072, + "expires_at": null, + "cancelled_at": null, + "failed_at": null, + "completed_at": 1699075073, + "last_error": null, + "model": "gpt-3.5-turbo", + "instructions": null, + "tools": [ + { + "type": "code_interpreter" + } + ], + "file_ids": [ + "file-abc123", + "file-abc456" + ], + "metadata": {}, + "usage": { + "prompt_tokens": 123, + "completion_tokens": 456, + "total_tokens": 579 + } + } + post: + operationId: modifyRun + tags: + - Assistants + summary: Modifies a run. + parameters: + - in: path + name: thread_id + required: true + schema: + type: string + description: The ID of the [thread](/docs/api-reference/threads) that was run. + - in: path + name: run_id + required: true + schema: + type: string + description: The ID of the run to modify. + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/ModifyRunRequest" + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/RunObject" + x-oaiMeta: + name: Modify run + group: threads + beta: true + returns: The modified [run](/docs/api-reference/runs/object) object matching the specified ID. + examples: + request: + curl: | + curl https://api.openai.com/v1/threads/thread_abc123/runs/run_abc123 \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "Content-Type: application/json" \ + -H "OpenAI-Beta: assistants=v1" \ + -d '{ + "metadata": { + "user_id": "user_abc123" + } + }' + python: | + from openai import OpenAI + client = OpenAI() + + run = client.beta.threads.runs.update( + thread_id="thread_abc123", + run_id="run_abc123", + metadata={"user_id": "user_abc123"}, + ) + print(run) + node.js: | + import OpenAI from "openai"; + + const openai = new OpenAI(); + + async function main() { + const run = await openai.beta.threads.runs.update( + "thread_abc123", + "run_abc123", + { + metadata: { + user_id: "user_abc123", + }, + } + ); + + console.log(run); + } + + main(); + response: | + { + "id": "run_abc123", + "object": "thread.run", + "created_at": 1699075072, + "assistant_id": "asst_abc123", + "thread_id": "thread_abc123", + "status": "completed", + "started_at": 1699075072, + "expires_at": null, + "cancelled_at": null, + "failed_at": null, + "completed_at": 1699075073, + "last_error": null, + "model": "gpt-3.5-turbo", + "instructions": null, + "tools": [ + { + "type": "code_interpreter" + } + ], + "file_ids": [ + "file-abc123", + "file-abc456" + ], + "metadata": { + "user_id": "user_abc123" + }, + "usage": { + "prompt_tokens": 123, + "completion_tokens": 456, + "total_tokens": 579 + } + } + + /threads/{thread_id}/runs/{run_id}/submit_tool_outputs: + post: + operationId: submitToolOuputsToRun + tags: + - Assistants + summary: | + When a run has the `status: "requires_action"` and `required_action.type` is `submit_tool_outputs`, this endpoint can be used to submit the outputs from the tool calls once they're all completed. All outputs must be submitted in a single request. + parameters: + - in: path + name: thread_id + required: true + schema: + type: string + description: The ID of the [thread](/docs/api-reference/threads) to which this run belongs. + - in: path + name: run_id + required: true + schema: + type: string + description: The ID of the run that requires the tool output submission. + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/SubmitToolOutputsRunRequest" + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/RunObject" + x-oaiMeta: + name: Submit tool outputs to run + group: threads + beta: true + returns: The modified [run](/docs/api-reference/runs/object) object matching the specified ID. + examples: + request: + curl: | + curl https://api.openai.com/v1/threads/thread_abc123/runs/run_abc123/submit_tool_outputs \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "Content-Type: application/json" \ + -H "OpenAI-Beta: assistants=v1" \ + -d '{ + "tool_outputs": [ + { + "tool_call_id": "call_abc123", + "output": "28C" + } + ] + }' + python: | + from openai import OpenAI + client = OpenAI() + + run = client.beta.threads.runs.submit_tool_outputs( + thread_id="thread_abc123", + run_id="run_abc123", + tool_outputs=[ + { + "tool_call_id": "call_abc123", + "output": "28C" + } + ] + ) + print(run) + node.js: | + import OpenAI from "openai"; + + const openai = new OpenAI(); + + async function main() { + const run = await openai.beta.threads.runs.submitToolOutputs( + "thread_abc123", + "run_abc123", + { + tool_outputs: [ + { + tool_call_id: "call_abc123", + output: "28C", + }, + ], + } + ); + + console.log(run); + } + + main(); + response: | + { + "id": "run_abc123", + "object": "thread.run", + "created_at": 1699075592, + "assistant_id": "asst_abc123", + "thread_id": "thread_abc123", + "status": "queued", + "started_at": 1699075592, + "expires_at": 1699076192, + "cancelled_at": null, + "failed_at": null, + "completed_at": null, + "last_error": null, + "model": "gpt-4", + "instructions": "You tell the weather.", + "tools": [ + { + "type": "function", + "function": { + "name": "get_weather", + "description": "Determine weather in my location", + "parameters": { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state e.g. San Francisco, CA" + }, + "unit": { + "type": "string", + "enum": [ + "c", + "f" + ] + } + }, + "required": [ + "location" + ] + } + } + } + ], + "file_ids": [], + "metadata": {}, + "usage": null + } + + /threads/{thread_id}/runs/{run_id}/cancel: + post: + operationId: cancelRun + tags: + - Assistants + summary: Cancels a run that is `in_progress`. + parameters: + - in: path + name: thread_id + required: true + schema: + type: string + description: The ID of the thread to which this run belongs. + - in: path + name: run_id + required: true + schema: + type: string + description: The ID of the run to cancel. + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/RunObject" + x-oaiMeta: + name: Cancel a run + group: threads + beta: true + returns: The modified [run](/docs/api-reference/runs/object) object matching the specified ID. + examples: + request: + curl: | + curl https://api.openai.com/v1/threads/thread_abc123/runs/run_abc123/cancel \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "OpenAI-Beta: assistants=v1" \ + -X POST + python: | + from openai import OpenAI + client = OpenAI() + + run = client.beta.threads.runs.cancel( + thread_id="thread_abc123", + run_id="run_abc123" + ) + print(run) + node.js: | + import OpenAI from "openai"; + + const openai = new OpenAI(); + + async function main() { + const run = await openai.beta.threads.runs.cancel( + "thread_abc123", + "run_abc123" + ); + + console.log(run); + } + + main(); + response: | + { + "id": "run_abc123", + "object": "thread.run", + "created_at": 1699076126, + "assistant_id": "asst_abc123", + "thread_id": "thread_abc123", + "status": "cancelling", + "started_at": 1699076126, + "expires_at": 1699076726, + "cancelled_at": null, + "failed_at": null, + "completed_at": null, + "last_error": null, + "model": "gpt-4", + "instructions": "You summarize books.", + "tools": [ + { + "type": "retrieval" + } + ], + "file_ids": [], + "metadata": {}, + "usage": null + } + + /threads/{thread_id}/runs/{run_id}/steps: + get: + operationId: listRunSteps + tags: + - Assistants + summary: Returns a list of run steps belonging to a run. + parameters: + - name: thread_id + in: path + required: true + schema: + type: string + description: The ID of the thread the run and run steps belong to. + - name: run_id + in: path + required: true + schema: + type: string + description: The ID of the run the run steps belong to. + - name: limit + in: query + description: *pagination_limit_param_description + required: false + schema: + type: integer + default: 20 + - name: order + in: query + description: *pagination_order_param_description + schema: + type: string + default: desc + enum: ["asc", "desc"] + - name: after + in: query + description: *pagination_after_param_description + schema: + type: string + - name: before + in: query + description: *pagination_before_param_description + schema: + type: string + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/ListRunStepsResponse" + x-oaiMeta: + name: List run steps + group: threads + beta: true + returns: A list of [run step](/docs/api-reference/runs/step-object) objects. + examples: + request: + curl: | + curl https://api.openai.com/v1/threads/thread_abc123/runs/run_abc123/steps \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "Content-Type: application/json" \ + -H "OpenAI-Beta: assistants=v1" + python: | + from openai import OpenAI + client = OpenAI() + + run_steps = client.beta.threads.runs.steps.list( + thread_id="thread_abc123", + run_id="run_abc123" + ) + print(run_steps) + node.js: | + import OpenAI from "openai"; + const openai = new OpenAI(); + + async function main() { + const runStep = await openai.beta.threads.runs.steps.list( + "thread_abc123", + "run_abc123" + ); + console.log(runStep); + } + + main(); + response: | + { + "object": "list", + "data": [ + { + "id": "step_abc123", + "object": "thread.run.step", + "created_at": 1699063291, + "run_id": "run_abc123", + "assistant_id": "asst_abc123", + "thread_id": "thread_abc123", + "type": "message_creation", + "status": "completed", + "cancelled_at": null, + "completed_at": 1699063291, + "expired_at": null, + "failed_at": null, + "last_error": null, + "step_details": { + "type": "message_creation", + "message_creation": { + "message_id": "msg_abc123" + } + }, + "usage": { + "prompt_tokens": 123, + "completion_tokens": 456, + "total_tokens": 579 + } + } + ], + "first_id": "step_abc123", + "last_id": "step_abc456", + "has_more": false + } + + /threads/{thread_id}/runs/{run_id}/steps/{step_id}: + get: + operationId: getRunStep + tags: + - Assistants + summary: Retrieves a run step. + parameters: + - in: path + name: thread_id + required: true + schema: + type: string + description: The ID of the thread to which the run and run step belongs. + - in: path + name: run_id + required: true + schema: + type: string + description: The ID of the run to which the run step belongs. + - in: path + name: step_id + required: true + schema: + type: string + description: The ID of the run step to retrieve. + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/RunStepObject" + x-oaiMeta: + name: Retrieve run step + group: threads + beta: true + returns: The [run step](/docs/api-reference/runs/step-object) object matching the specified ID. + examples: + request: + curl: | + curl https://api.openai.com/v1/threads/thread_abc123/runs/run_abc123/steps/step_abc123 \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "Content-Type: application/json" \ + -H "OpenAI-Beta: assistants=v1" + python: | + from openai import OpenAI + client = OpenAI() + + run_step = client.beta.threads.runs.steps.retrieve( + thread_id="thread_abc123", + run_id="run_abc123", + step_id="step_abc123" + ) + print(run_step) + node.js: | + import OpenAI from "openai"; + const openai = new OpenAI(); + + async function main() { + const runStep = await openai.beta.threads.runs.steps.retrieve( + "thread_abc123", + "run_abc123", + "step_abc123" + ); + console.log(runStep); + } + + main(); + response: &run_step_object_example | + { + "id": "step_abc123", + "object": "thread.run.step", + "created_at": 1699063291, + "run_id": "run_abc123", + "assistant_id": "asst_abc123", + "thread_id": "thread_abc123", + "type": "message_creation", + "status": "completed", + "cancelled_at": null, + "completed_at": 1699063291, + "expired_at": null, + "failed_at": null, + "last_error": null, + "step_details": { + "type": "message_creation", + "message_creation": { + "message_id": "msg_abc123" + } + }, + "usage": { + "prompt_tokens": 123, + "completion_tokens": 456, + "total_tokens": 579 + } + } + + /assistants/{assistant_id}/files: + get: + operationId: listAssistantFiles + tags: + - Assistants + summary: Returns a list of assistant files. + parameters: + - name: assistant_id + in: path + description: The ID of the assistant the file belongs to. + required: true + schema: + type: string + - name: limit + in: query + description: *pagination_limit_param_description + required: false + schema: + type: integer + default: 20 + - name: order + in: query + description: *pagination_order_param_description + schema: + type: string + default: desc + enum: ["asc", "desc"] + - name: after + in: query + description: *pagination_after_param_description + schema: + type: string + - name: before + in: query + description: *pagination_before_param_description + schema: + type: string + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/ListAssistantFilesResponse" + x-oaiMeta: + name: List assistant files + group: assistants + beta: true + returns: A list of [assistant file](/docs/api-reference/assistants/file-object) objects. + examples: + request: + curl: | + curl https://api.openai.com/v1/assistants/asst_abc123/files \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "Content-Type: application/json" \ + -H "OpenAI-Beta: assistants=v1" + python: | + from openai import OpenAI + client = OpenAI() + + assistant_files = client.beta.assistants.files.list( + assistant_id="asst_abc123" + ) + print(assistant_files) + node.js: | + import OpenAI from "openai"; + const openai = new OpenAI(); + + async function main() { + const assistantFiles = await openai.beta.assistants.files.list( + "asst_abc123" + ); + console.log(assistantFiles); + } + + main(); + response: | + { + "object": "list", + "data": [ + { + "id": "file-abc123", + "object": "assistant.file", + "created_at": 1699060412, + "assistant_id": "asst_abc123" + }, + { + "id": "file-abc456", + "object": "assistant.file", + "created_at": 1699060412, + "assistant_id": "asst_abc123" + } + ], + "first_id": "file-abc123", + "last_id": "file-abc456", + "has_more": false + } + post: + operationId: createAssistantFile + tags: + - Assistants + summary: Create an assistant file by attaching a [File](/docs/api-reference/files) to an [assistant](/docs/api-reference/assistants). + parameters: + - in: path + name: assistant_id + required: true + schema: + type: string + example: file-abc123 + description: | + The ID of the assistant for which to create a File. + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/CreateAssistantFileRequest" + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/AssistantFileObject" + x-oaiMeta: + name: Create assistant file + group: assistants + beta: true + returns: An [assistant file](/docs/api-reference/assistants/file-object) object. + examples: + request: + curl: | + curl https://api.openai.com/v1/assistants/asst_abc123/files \ + -H 'Authorization: Bearer $OPENAI_API_KEY"' \ + -H 'Content-Type: application/json' \ + -H 'OpenAI-Beta: assistants=v1' \ + -d '{ + "file_id": "file-abc123" + }' + python: | + from openai import OpenAI + client = OpenAI() + + assistant_file = client.beta.assistants.files.create( + assistant_id="asst_abc123", + file_id="file-abc123" + ) + print(assistant_file) + node.js: | + import OpenAI from "openai"; + const openai = new OpenAI(); + + async function main() { + const myAssistantFile = await openai.beta.assistants.files.create( + "asst_abc123", + { + file_id: "file-abc123" + } + ); + console.log(myAssistantFile); + } + + main(); + response: &assistant_file_object | + { + "id": "file-abc123", + "object": "assistant.file", + "created_at": 1699055364, + "assistant_id": "asst_abc123" + } + + /assistants/{assistant_id}/files/{file_id}: + get: + operationId: getAssistantFile + tags: + - Assistants + summary: Retrieves an AssistantFile. + parameters: + - in: path + name: assistant_id + required: true + schema: + type: string + description: The ID of the assistant who the file belongs to. + - in: path + name: file_id + required: true + schema: + type: string + description: The ID of the file we're getting. + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/AssistantFileObject" + x-oaiMeta: + name: Retrieve assistant file + group: assistants + beta: true + returns: The [assistant file](/docs/api-reference/assistants/file-object) object matching the specified ID. + examples: + request: + curl: | + curl https://api.openai.com/v1/assistants/asst_abc123/files/file-abc123 \ + -H 'Authorization: Bearer $OPENAI_API_KEY"' \ + -H 'Content-Type: application/json' \ + -H 'OpenAI-Beta: assistants=v1' + python: | + from openai import OpenAI + client = OpenAI() + + assistant_file = client.beta.assistants.files.retrieve( + assistant_id="asst_abc123", + file_id="file-abc123" + ) + print(assistant_file) + node.js: | + import OpenAI from "openai"; + const openai = new OpenAI(); + + async function main() { + const myAssistantFile = await openai.beta.assistants.files.retrieve( + "asst_abc123", + "file-abc123" + ); + console.log(myAssistantFile); + } + + main(); + response: *assistant_file_object + delete: + operationId: deleteAssistantFile + tags: + - Assistants + summary: Delete an assistant file. + parameters: + - in: path + name: assistant_id + required: true + schema: + type: string + description: The ID of the assistant that the file belongs to. + - in: path + name: file_id + required: true + schema: + type: string + description: The ID of the file to delete. + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/DeleteAssistantFileResponse" + x-oaiMeta: + name: Delete assistant file + group: assistants + beta: true + returns: Deletion status + examples: + request: + curl: | + curl https://api.openai.com/v1/assistants/asst_abc123/files/file-abc123 \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "Content-Type: application/json" \ + -H "OpenAI-Beta: assistants=v1" \ + -X DELETE + python: | + from openai import OpenAI + client = OpenAI() + + deleted_assistant_file = client.beta.assistants.files.delete( + assistant_id="asst_abc123", + file_id="file-abc123" + ) + print(deleted_assistant_file) + node.js: | + import OpenAI from "openai"; + const openai = new OpenAI(); + + async function main() { + const deletedAssistantFile = await openai.beta.assistants.files.del( + "asst_abc123", + "file-abc123" + ); + console.log(deletedAssistantFile); + } + + main(); + response: | + { + id: "file-abc123", + object: "assistant.file.deleted", + deleted: true + } + + /threads/{thread_id}/messages/{message_id}/files: + get: + operationId: listMessageFiles + tags: + - Assistants + summary: Returns a list of message files. + parameters: + - name: thread_id + in: path + description: The ID of the thread that the message and files belong to. + required: true + schema: + type: string + - name: message_id + in: path + description: The ID of the message that the files belongs to. + required: true + schema: + type: string + - name: limit + in: query + description: *pagination_limit_param_description + required: false + schema: + type: integer + default: 20 + - name: order + in: query + description: *pagination_order_param_description + schema: + type: string + default: desc + enum: ["asc", "desc"] + - name: after + in: query + description: *pagination_after_param_description + schema: + type: string + - name: before + in: query + description: *pagination_before_param_description + schema: + type: string + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/ListMessageFilesResponse" + x-oaiMeta: + name: List message files + group: threads + beta: true + returns: A list of [message file](/docs/api-reference/messages/file-object) objects. + examples: + request: + curl: | + curl https://api.openai.com/v1/threads/thread_abc123/messages/msg_abc123/files \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "Content-Type: application/json" \ + -H "OpenAI-Beta: assistants=v1" + python: | + from openai import OpenAI + client = OpenAI() + + message_files = client.beta.threads.messages.files.list( + thread_id="thread_abc123", + message_id="msg_abc123" + ) + print(message_files) + node.js: | + import OpenAI from "openai"; + const openai = new OpenAI(); + + async function main() { + const messageFiles = await openai.beta.threads.messages.files.list( + "thread_abc123", + "msg_abc123" + ); + console.log(messageFiles); + } + + main(); + response: | + { + "object": "list", + "data": [ + { + "id": "file-abc123", + "object": "thread.message.file", + "created_at": 1699061776, + "message_id": "msg_abc123" + }, + { + "id": "file-abc123", + "object": "thread.message.file", + "created_at": 1699061776, + "message_id": "msg_abc123" + } + ], + "first_id": "file-abc123", + "last_id": "file-abc123", + "has_more": false + } + + /threads/{thread_id}/messages/{message_id}/files/{file_id}: + get: + operationId: getMessageFile + tags: + - Assistants + summary: Retrieves a message file. + parameters: + - in: path + name: thread_id + required: true + schema: + type: string + example: thread_abc123 + description: The ID of the thread to which the message and File belong. + - in: path + name: message_id + required: true + schema: + type: string + example: msg_abc123 + description: The ID of the message the file belongs to. + - in: path + name: file_id + required: true + schema: + type: string + example: file-abc123 + description: The ID of the file being retrieved. + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: "#/components/schemas/MessageFileObject" + x-oaiMeta: + name: Retrieve message file + group: threads + beta: true + returns: The [message file](/docs/api-reference/messages/file-object) object. + examples: + request: + curl: | + curl https://api.openai.com/v1/threads/thread_abc123/messages/msg_abc123/files/file-abc123 \ + -H "Authorization: Bearer $OPENAI_API_KEY" \ + -H "Content-Type: application/json" \ + -H "OpenAI-Beta: assistants=v1" + python: | + from openai import OpenAI + client = OpenAI() + + message_files = client.beta.threads.messages.files.retrieve( + thread_id="thread_abc123", + message_id="msg_abc123", + file_id="file-abc123" + ) + print(message_files) + node.js: | + import OpenAI from "openai"; + const openai = new OpenAI(); + + async function main() { + const messageFile = await openai.beta.threads.messages.files.retrieve( + "thread_abc123", + "msg_abc123", + "file-abc123" + ); + console.log(messageFile); + } + + main(); + response: | + { + "id": "file-abc123", + "object": "thread.message.file", + "created_at": 1699061776, + "message_id": "msg_abc123" + } + +components: + securitySchemes: + ApiKeyAuth: + type: http + scheme: "bearer" + + schemas: + Error: + type: object + properties: + code: + type: string + nullable: true + message: + type: string + nullable: false + param: + type: string + nullable: true + type: + type: string + nullable: false + required: + - type + - message + - param + - code + ErrorResponse: + type: object + properties: + error: + $ref: "#/components/schemas/Error" + required: + - error + + ListModelsResponse: + type: object + properties: + object: + type: string + enum: [list] + data: + type: array + items: + $ref: "#/components/schemas/Model" + required: + - object + - data + DeleteModelResponse: + type: object + properties: + id: + type: string + deleted: + type: boolean + object: + type: string + required: + - id + - object + - deleted + + CreateCompletionRequest: + type: object + properties: + model: + description: &model_description | + ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](/docs/models/overview) for descriptions of them. + anyOf: + - type: string + - type: string + enum: ["gpt-3.5-turbo-instruct", "davinci-002", "babbage-002"] + x-oaiTypeLabel: string + prompt: + description: &completions_prompt_description | + The prompt(s) to generate completions for, encoded as a string, array of strings, array of tokens, or array of token arrays. + + Note that <|endoftext|> is the document separator that the model sees during training, so if a prompt is not specified the model will generate as if from the beginning of a new document. + default: "<|endoftext|>" + nullable: true + oneOf: + - type: string + default: "" + example: "This is a test." + - type: array + items: + type: string + default: "" + example: "This is a test." + - type: array + minItems: 1 + items: + type: integer + example: "[1212, 318, 257, 1332, 13]" + - type: array + minItems: 1 + items: + type: array + minItems: 1 + items: + type: integer + example: "[[1212, 318, 257, 1332, 13]]" + best_of: + type: integer + default: 1 + minimum: 0 + maximum: 20 + nullable: true + description: &completions_best_of_description | + Generates `best_of` completions server-side and returns the "best" (the one with the highest log probability per token). Results cannot be streamed. + + When used with `n`, `best_of` controls the number of candidate completions and `n` specifies how many to return – `best_of` must be greater than `n`. + + **Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. + echo: + type: boolean + default: false + nullable: true + description: &completions_echo_description > + Echo back the prompt in addition to the completion + frequency_penalty: + type: number + default: 0 + minimum: -2 + maximum: 2 + nullable: true + description: &completions_frequency_penalty_description | + Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim. + + [See more information about frequency and presence penalties.](/docs/guides/text-generation/parameter-details) + logit_bias: &completions_logit_bias + type: object + x-oaiTypeLabel: map + default: null + nullable: true + additionalProperties: + type: integer + description: &completions_logit_bias_description | + Modify the likelihood of specified tokens appearing in the completion. + + Accepts a JSON object that maps tokens (specified by their token ID in the GPT tokenizer) to an associated bias value from -100 to 100. You can use this [tokenizer tool](/tokenizer?view=bpe) to convert text to token IDs. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token. + + As an example, you can pass `{"50256": -100}` to prevent the <|endoftext|> token from being generated. + logprobs: &completions_logprobs_configuration + type: integer + minimum: 0 + maximum: 5 + default: null + nullable: true + description: &completions_logprobs_description | + Include the log probabilities on the `logprobs` most likely output tokens, as well the chosen tokens. For example, if `logprobs` is 5, the API will return a list of the 5 most likely tokens. The API will always return the `logprob` of the sampled token, so there may be up to `logprobs+1` elements in the response. + + The maximum value for `logprobs` is 5. + max_tokens: + type: integer + minimum: 0 + default: 16 + example: 16 + nullable: true + description: &completions_max_tokens_description | + The maximum number of [tokens](/tokenizer) that can be generated in the completion. + + The token count of your prompt plus `max_tokens` cannot exceed the model's context length. [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) for counting tokens. + n: + type: integer + minimum: 1 + maximum: 128 + default: 1 + example: 1 + nullable: true + description: &completions_completions_description | + How many completions to generate for each prompt. + + **Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. + presence_penalty: + type: number + default: 0 + minimum: -2 + maximum: 2 + nullable: true + description: &completions_presence_penalty_description | + Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics. + + [See more information about frequency and presence penalties.](/docs/guides/text-generation/parameter-details) + seed: &completions_seed_param + type: integer + minimum: -9223372036854775808 + maximum: 9223372036854775807 + nullable: true + description: | + If specified, our system will make a best effort to sample deterministically, such that repeated requests with the same `seed` and parameters should return the same result. + + Determinism is not guaranteed, and you should refer to the `system_fingerprint` response parameter to monitor changes in the backend. + stop: + description: &completions_stop_description > + Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence. + default: null + nullable: true + oneOf: + - type: string + default: <|endoftext|> + example: "\n" + nullable: true + - type: array + minItems: 1 + maxItems: 4 + items: + type: string + example: '["\n"]' + stream: + description: > + Whether to stream back partial progress. If set, tokens will be sent as data-only [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) + as they become available, with the stream terminated by a `data: [DONE]` message. [Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions). + type: boolean + nullable: true + default: false + suffix: + description: The suffix that comes after a completion of inserted text. + default: null + nullable: true + type: string + example: "test." + temperature: + type: number + minimum: 0 + maximum: 2 + default: 1 + example: 1 + nullable: true + description: &completions_temperature_description | + What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. + + We generally recommend altering this or `top_p` but not both. + top_p: + type: number + minimum: 0 + maximum: 1 + default: 1 + example: 1 + nullable: true + description: &completions_top_p_description | + An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. + + We generally recommend altering this or `temperature` but not both. + user: &end_user_param_configuration + type: string + example: user-1234 + description: | + A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + required: + - model + - prompt + + CreateCompletionResponse: + type: object + description: | + Represents a completion response from the API. Note: both the streamed and non-streamed response objects share the same shape (unlike the chat endpoint). + properties: + id: + type: string + description: A unique identifier for the completion. + choices: + type: array + description: The list of completion choices the model generated for the input prompt. + items: + type: object + required: + - finish_reason + - index + - logprobs + - text + properties: + finish_reason: + type: string + description: &completion_finish_reason_description | + The reason the model stopped generating tokens. This will be `stop` if the model hit a natural stop point or a provided stop sequence, + `length` if the maximum number of tokens specified in the request was reached, + or `content_filter` if content was omitted due to a flag from our content filters. + enum: ["stop", "length", "content_filter"] + index: + type: integer + logprobs: + type: object + nullable: true + properties: + text_offset: + type: array + items: + type: integer + token_logprobs: + type: array + items: + type: number + tokens: + type: array + items: + type: string + top_logprobs: + type: array + items: + type: object + additionalProperties: + type: number + text: + type: string + created: + type: integer + description: The Unix timestamp (in seconds) of when the completion was created. + model: + type: string + description: The model used for completion. + system_fingerprint: + type: string + description: | + 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. + object: + type: string + description: The object type, which is always "text_completion" + enum: [text_completion] + usage: + $ref: "#/components/schemas/CompletionUsage" + required: + - id + - object + - created + - model + - choices + x-oaiMeta: + name: The completion object + legacy: true + example: | + { + "id": "cmpl-uqkvlQyYK7bGYrRHQ0eXlWi7", + "object": "text_completion", + "created": 1589478378, + "model": "gpt-3.5-turbo", + "choices": [ + { + "text": "\n\nThis is indeed a test", + "index": 0, + "logprobs": null, + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 5, + "completion_tokens": 7, + "total_tokens": 12 + } + } + + ChatCompletionRequestMessageContentPart: + oneOf: + - $ref: "#/components/schemas/ChatCompletionRequestMessageContentPartText" + - $ref: "#/components/schemas/ChatCompletionRequestMessageContentPartImage" + x-oaiExpandable: true + + ChatCompletionRequestMessageContentPartImage: + type: object + title: Image content part + properties: + type: + type: string + enum: ["image_url"] + description: The type of the content part. + image_url: + type: object + properties: + url: + type: string + description: Either a URL of the image or the base64 encoded image data. + format: uri + detail: + type: string + description: Specifies the detail level of the image. Learn more in the [Vision guide](/docs/guides/vision/low-or-high-fidelity-image-understanding). + enum: ["auto", "low", "high"] + default: "auto" + required: + - url + required: + - type + - image_url + + ChatCompletionRequestMessageContentPartText: + type: object + title: Text content part + properties: + type: + type: string + enum: ["text"] + description: The type of the content part. + text: + type: string + description: The text content. + required: + - type + - text + + ChatCompletionRequestMessage: + oneOf: + - $ref: "#/components/schemas/ChatCompletionRequestSystemMessage" + - $ref: "#/components/schemas/ChatCompletionRequestUserMessage" + - $ref: "#/components/schemas/ChatCompletionRequestAssistantMessage" + - $ref: "#/components/schemas/ChatCompletionRequestToolMessage" + - $ref: "#/components/schemas/ChatCompletionRequestFunctionMessage" + x-oaiExpandable: true + + ChatCompletionRequestSystemMessage: + type: object + title: System message + properties: + content: + description: The contents of the system message. + type: string + role: + type: string + enum: ["system"] + description: The role of the messages author, in this case `system`. + name: + type: string + description: An optional name for the participant. Provides the model information to differentiate between participants of the same role. + required: + - content + - role + + ChatCompletionRequestUserMessage: + type: object + title: User message + properties: + content: + description: | + The contents of the user message. + oneOf: + - type: string + description: The text contents of the message. + title: Text content + - type: array + description: 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. + title: Array of content parts + items: + $ref: "#/components/schemas/ChatCompletionRequestMessageContentPart" + minItems: 1 + x-oaiExpandable: true + role: + type: string + enum: ["user"] + description: The role of the messages author, in this case `user`. + name: + type: string + description: An optional name for the participant. Provides the model information to differentiate between participants of the same role. + required: + - content + - role + + ChatCompletionRequestAssistantMessage: + type: object + title: Assistant message + properties: + content: + nullable: true + type: string + description: | + The contents of the assistant message. Required unless `tool_calls` or `function_call` is specified. + role: + type: string + enum: ["assistant"] + description: The role of the messages author, in this case `assistant`. + name: + type: string + description: An optional name for the participant. Provides the model information to differentiate between participants of the same role. + tool_calls: + $ref: "#/components/schemas/ChatCompletionMessageToolCalls" + function_call: + type: object + deprecated: true + description: "Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model." + properties: + arguments: + type: string + description: The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function. + name: + type: string + description: The name of the function to call. + required: + - arguments + - name + required: + - role + + ChatCompletionRequestToolMessage: + type: object + title: Tool message + properties: + role: + type: string + enum: ["tool"] + description: The role of the messages author, in this case `tool`. + content: + type: string + description: The contents of the tool message. + tool_call_id: + type: string + description: Tool call that this message is responding to. + required: + - role + - content + - tool_call_id + + ChatCompletionRequestFunctionMessage: + type: object + title: Function message + deprecated: true + properties: + role: + type: string + enum: ["function"] + description: The role of the messages author, in this case `function`. + content: + nullable: true + type: string + description: The contents of the function message. + name: + type: string + description: The name of the function to call. + required: + - role + - content + - name + + FunctionParameters: + type: object + description: "The parameters the functions accepts, described as a JSON Schema object. See the [guide](/docs/guides/text-generation/function-calling) for examples, and the [JSON Schema reference](https://json-schema.org/understanding-json-schema/) for documentation about the format. \n\nOmitting `parameters` defines a function with an empty parameter list." + additionalProperties: true + + ChatCompletionFunctions: + type: object + deprecated: true + properties: + description: + type: string + description: A description of what the function does, used by the model to choose when and how to call the function. + name: + type: string + description: The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64. + parameters: + $ref: "#/components/schemas/FunctionParameters" + required: + - name + + ChatCompletionFunctionCallOption: + type: object + description: > + Specifying a particular function via `{"name": "my_function"}` forces the model to call that function. + properties: + name: + type: string + description: The name of the function to call. + required: + - name + + ChatCompletionTool: + type: object + properties: + type: + type: string + enum: ["function"] + description: The type of the tool. Currently, only `function` is supported. + function: + $ref: "#/components/schemas/FunctionObject" + required: + - type + - function + + FunctionObject: + type: object + properties: + description: + type: string + description: A description of what the function does, used by the model to choose when and how to call the function. + name: + type: string + description: The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64. + parameters: + $ref: "#/components/schemas/FunctionParameters" + required: + - name + + ChatCompletionToolChoiceOption: + description: | + Controls which (if any) function is called by the model. + `none` means the model will not call a function and instead generates a message. + `auto` means the model can pick between generating a message or calling a function. + Specifying a particular function via `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that function. + + `none` is the default when no functions are present. `auto` is the default if functions are present. + oneOf: + - type: string + description: > + `none` means the model will not call a function and instead generates a message. + `auto` means the model can pick between generating a message or calling a function. + enum: [none, auto] + - $ref: "#/components/schemas/ChatCompletionNamedToolChoice" + x-oaiExpandable: true + + ChatCompletionNamedToolChoice: + type: object + description: Specifies a tool the model should use. Use to force the model to call a specific function. + properties: + type: + type: string + enum: ["function"] + description: The type of the tool. Currently, only `function` is supported. + function: + type: object + properties: + name: + type: string + description: The name of the function to call. + required: + - name + required: + - type + - function + + ChatCompletionMessageToolCalls: + type: array + description: The tool calls generated by the model, such as function calls. + items: + $ref: "#/components/schemas/ChatCompletionMessageToolCall" + + ChatCompletionMessageToolCall: + type: object + properties: + # TODO: index included when streaming + id: + type: string + description: The ID of the tool call. + type: + type: string + enum: ["function"] + description: The type of the tool. Currently, only `function` is supported. + function: + type: object + description: The function that the model called. + properties: + name: + type: string + description: The name of the function to call. + arguments: + type: string + description: The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function. + required: + - name + - arguments + required: + - id + - type + - function + + ChatCompletionMessageToolCallChunk: + type: object + properties: + index: + type: integer + id: + type: string + description: The ID of the tool call. + type: + type: string + enum: ["function"] + description: The type of the tool. Currently, only `function` is supported. + function: + type: object + properties: + name: + type: string + description: The name of the function to call. + arguments: + type: string + description: The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function. + required: + - index + + # Note, this isn't referenced anywhere, but is kept as a convenience to record all possible roles in one place. + ChatCompletionRole: + type: string + description: The role of the author of a message + enum: + - system + - user + - assistant + - tool + - function + + ChatCompletionResponseMessage: + type: object + description: A chat completion message generated by the model. + properties: + content: + type: string + description: The contents of the message. + nullable: true + tool_calls: + $ref: "#/components/schemas/ChatCompletionMessageToolCalls" + role: + type: string + enum: ["assistant"] + description: The role of the author of this message. + function_call: + type: object + deprecated: true + description: "Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model." + properties: + arguments: + type: string + description: The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function. + name: + type: string + description: The name of the function to call. + required: + - name + - arguments + required: + - role + - content + + ChatCompletionStreamResponseDelta: + type: object + description: A chat completion delta generated by streamed model responses. + properties: + content: + type: string + description: The contents of the chunk message. + nullable: true + function_call: + deprecated: true + type: object + description: "Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model." + properties: + arguments: + type: string + description: The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function. + name: + type: string + description: The name of the function to call. + tool_calls: + type: array + items: + $ref: "#/components/schemas/ChatCompletionMessageToolCallChunk" + role: + type: string + enum: ["system", "user", "assistant", "tool"] + description: The role of the author of this message. + + CreateChatCompletionRequest: + type: object + properties: + messages: + description: A list of messages comprising the conversation so far. [Example Python code](https://cookbook.openai.com/examples/how_to_format_inputs_to_chatgpt_models). + type: array + minItems: 1 + items: + $ref: "#/components/schemas/ChatCompletionRequestMessage" + model: + description: ID of the model to use. See the [model endpoint compatibility](/docs/models/model-endpoint-compatibility) table for details on which models work with the Chat API. + example: "gpt-3.5-turbo" + anyOf: + - type: string + - type: string + enum: + [ + "gpt-4-0125-preview", + "gpt-4-turbo-preview", + "gpt-4-1106-preview", + "gpt-4-vision-preview", + "gpt-4", + "gpt-4-0314", + "gpt-4-0613", + "gpt-4-32k", + "gpt-4-32k-0314", + "gpt-4-32k-0613", + "gpt-3.5-turbo", + "gpt-3.5-turbo-16k", + "gpt-3.5-turbo-0301", + "gpt-3.5-turbo-0613", + "gpt-3.5-turbo-1106", + "gpt-3.5-turbo-16k-0613", + ] + x-oaiTypeLabel: string + frequency_penalty: + type: number + default: 0 + minimum: -2 + maximum: 2 + nullable: true + description: *completions_frequency_penalty_description + logit_bias: + type: object + x-oaiTypeLabel: map + default: null + nullable: true + additionalProperties: + type: integer + description: | + Modify the likelihood of specified tokens appearing in the completion. + + Accepts a JSON object that maps tokens (specified by their token ID in the tokenizer) to an associated bias value from -100 to 100. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token. + logprobs: + description: Whether to return log probabilities of the output tokens or not. If true, returns the log probabilities of each output token returned in the `content` of `message`. This option is currently not available on the `gpt-4-vision-preview` model. + type: boolean + default: false + nullable: true + top_logprobs: + description: An integer between 0 and 5 specifying the number of most likely tokens to return at each token position, each with an associated log probability. `logprobs` must be set to `true` if this parameter is used. + type: integer + minimum: 0 + maximum: 5 + nullable: true + max_tokens: + description: | + The maximum number of [tokens](/tokenizer) that can be generated in the chat completion. + + The total length of input tokens and generated tokens is limited by the model's context length. [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) for counting tokens. + type: integer + nullable: true + n: + type: integer + minimum: 1 + maximum: 128 + default: 1 + example: 1 + nullable: true + description: How many chat completion choices to generate for each input message. Note that you will be charged based on the number of generated tokens across all of the choices. Keep `n` as `1` to minimize costs. + presence_penalty: + type: number + default: 0 + minimum: -2 + maximum: 2 + nullable: true + description: *completions_presence_penalty_description + response_format: + type: object + description: | + An object specifying the format that the model must output. Compatible with [GPT-4 Turbo](/docs/models/gpt-4-and-gpt-4-turbo) and `gpt-3.5-turbo-1106`. + + 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. + properties: + type: + type: string + enum: ["text", "json_object"] + example: "json_object" + default: "text" + description: Must be one of `text` or `json_object`. + seed: + type: integer + minimum: -9223372036854775808 + maximum: 9223372036854775807 + nullable: true + description: | + This feature is in Beta. + If specified, our system will make a best effort to sample deterministically, such that repeated requests with the same `seed` and parameters should return the same result. + Determinism is not guaranteed, and you should refer to the `system_fingerprint` response parameter to monitor changes in the backend. + x-oaiMeta: + beta: true + stop: + description: | + Up to 4 sequences where the API will stop generating further tokens. + default: null + oneOf: + - type: string + nullable: true + - type: array + minItems: 1 + maxItems: 4 + items: + type: string + stream: + description: > + If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) + as they become available, with the stream terminated by a `data: [DONE]` message. [Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions). + type: boolean + nullable: true + default: false + temperature: + type: number + minimum: 0 + maximum: 2 + default: 1 + example: 1 + nullable: true + description: *completions_temperature_description + top_p: + type: number + minimum: 0 + maximum: 1 + default: 1 + example: 1 + nullable: true + description: *completions_top_p_description + tools: + type: array + description: > + A list of tools the model may call. Currently, only functions are supported as a tool. + Use this to provide a list of functions the model may generate JSON inputs for. + items: + $ref: "#/components/schemas/ChatCompletionTool" + tool_choice: + $ref: "#/components/schemas/ChatCompletionToolChoiceOption" + user: *end_user_param_configuration + function_call: + deprecated: true + description: | + Deprecated in favor of `tool_choice`. + + Controls which (if any) function is called by the model. + `none` means the model will not call a function and instead generates a message. + `auto` means the model can pick between generating a message or calling a function. + Specifying a particular function via `{"name": "my_function"}` forces the model to call that function. + + `none` is the default when no functions are present. `auto` is the default if functions are present. + oneOf: + - type: string + description: > + `none` means the model will not call a function and instead generates a message. + `auto` means the model can pick between generating a message or calling a function. + enum: [none, auto] + - $ref: "#/components/schemas/ChatCompletionFunctionCallOption" + x-oaiExpandable: true + functions: + deprecated: true + description: | + Deprecated in favor of `tools`. + + A list of functions the model may generate JSON inputs for. + type: array + minItems: 1 + maxItems: 128 + items: + $ref: "#/components/schemas/ChatCompletionFunctions" + + required: + - model + - messages + + CreateChatCompletionResponse: + type: object + description: Represents a chat completion response returned by model, based on the provided input. + properties: + id: + type: string + description: A unique identifier for the chat completion. + choices: + type: array + description: A list of chat completion choices. Can be more than one if `n` is greater than 1. + items: + type: object + required: + - finish_reason + - index + - message + - logprobs + properties: + finish_reason: + type: string + description: &chat_completion_finish_reason_description | + The reason the model stopped generating tokens. This will be `stop` if the model hit a natural stop point or a provided stop sequence, + `length` if the maximum number of tokens specified in the request was reached, + `content_filter` if content was omitted due to a flag from our content filters, + `tool_calls` if the model called a tool, or `function_call` (deprecated) if the model called a function. + enum: + [ + "stop", + "length", + "tool_calls", + "content_filter", + "function_call", + ] + index: + type: integer + description: The index of the choice in the list of choices. + message: + $ref: "#/components/schemas/ChatCompletionResponseMessage" + logprobs: &chat_completion_response_logprobs + description: Log probability information for the choice. + type: object + nullable: true + properties: + content: + description: A list of message content tokens with log probability information. + type: array + items: + $ref: "#/components/schemas/ChatCompletionTokenLogprob" + nullable: true + required: + - content + created: + type: integer + description: The Unix timestamp (in seconds) of when the chat completion was created. + model: + type: string + description: The model used for the chat completion. + system_fingerprint: + type: string + description: | + 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. + object: + type: string + description: The object type, which is always `chat.completion`. + enum: [chat.completion] + usage: + $ref: "#/components/schemas/CompletionUsage" + required: + - choices + - created + - id + - model + - object + x-oaiMeta: + name: The chat completion object + group: chat + example: *chat_completion_example + + CreateChatCompletionFunctionResponse: + type: object + description: Represents a chat completion response returned by model, based on the provided input. + properties: + id: + type: string + description: A unique identifier for the chat completion. + choices: + type: array + description: A list of chat completion choices. Can be more than one if `n` is greater than 1. + items: + type: object + required: + - finish_reason + - index + - message + - logprobs + properties: + finish_reason: + type: string + description: + &chat_completion_function_finish_reason_description | + The reason the model stopped generating tokens. This will be `stop` if the model hit a natural stop point or a provided stop sequence, `length` if the maximum number of tokens specified in the request was reached, `content_filter` if content was omitted due to a flag from our content filters, or `function_call` if the model called a function. + enum: ["stop", "length", "function_call", "content_filter"] + index: + type: integer + description: The index of the choice in the list of choices. + message: + $ref: "#/components/schemas/ChatCompletionResponseMessage" + created: + type: integer + description: The Unix timestamp (in seconds) of when the chat completion was created. + model: + type: string + description: The model used for the chat completion. + system_fingerprint: + type: string + description: | + 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. + object: + type: string + description: The object type, which is always `chat.completion`. + enum: [chat.completion] + usage: + $ref: "#/components/schemas/CompletionUsage" + required: + - choices + - created + - id + - model + - object + x-oaiMeta: + name: The chat completion object + group: chat + example: *chat_completion_function_example + + ChatCompletionTokenLogprob: + type: object + properties: + token: &chat_completion_response_logprobs_token + description: The token. + type: string + logprob: &chat_completion_response_logprobs_token_logprob + description: The log probability of this token. + type: number + bytes: &chat_completion_response_logprobs_bytes + description: A list of integers representing the UTF-8 bytes representation of the token. Useful in instances where characters are represented by multiple tokens and their byte representations must be combined to generate the correct text representation. Can be `null` if there is no bytes representation for the token. + type: array + items: + type: integer + nullable: true + top_logprobs: + description: List of the most likely tokens and their log probability, at this token position. In rare cases, there may be fewer than the number of requested `top_logprobs` returned. + type: array + items: + type: object + properties: + token: *chat_completion_response_logprobs_token + logprob: *chat_completion_response_logprobs_token_logprob + bytes: *chat_completion_response_logprobs_bytes + required: + - token + - logprob + - bytes + required: + - token + - logprob + - bytes + - top_logprobs + + ListPaginatedFineTuningJobsResponse: + type: object + properties: + data: + type: array + items: + $ref: "#/components/schemas/FineTuningJob" + has_more: + type: boolean + object: + type: string + enum: [list] + required: + - object + - data + - has_more + + CreateChatCompletionStreamResponse: + type: object + description: Represents a streamed chunk of a chat completion response returned by model, based on the provided input. + properties: + id: + type: string + description: A unique identifier for the chat completion. Each chunk has the same ID. + choices: + type: array + description: A list of chat completion choices. Can be more than one if `n` is greater than 1. + items: + type: object + required: + - delta + - finish_reason + - index + properties: + delta: + $ref: "#/components/schemas/ChatCompletionStreamResponseDelta" + logprobs: *chat_completion_response_logprobs + finish_reason: + type: string + description: *chat_completion_finish_reason_description + enum: + [ + "stop", + "length", + "tool_calls", + "content_filter", + "function_call", + ] + nullable: true + index: + type: integer + description: The index of the choice in the list of choices. + created: + type: integer + description: The Unix timestamp (in seconds) of when the chat completion was created. Each chunk has the same timestamp. + model: + type: string + description: The model to generate the completion. + system_fingerprint: + type: string + description: | + 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. + object: + type: string + description: The object type, which is always `chat.completion.chunk`. + enum: [chat.completion.chunk] + required: + - choices + - created + - id + - model + - object + x-oaiMeta: + name: The chat completion chunk object + group: chat + example: *chat_completion_chunk_example + + CreateChatCompletionImageResponse: + type: object + description: Represents a streamed chunk of a chat completion response returned by model, based on the provided input. + x-oaiMeta: + name: The chat completion chunk object + group: chat + example: *chat_completion_image_example + + CreateImageRequest: + type: object + properties: + prompt: + description: A text description of the desired image(s). The maximum length is 1000 characters for `dall-e-2` and 4000 characters for `dall-e-3`. + type: string + example: "A cute baby sea otter" + model: + anyOf: + - type: string + - type: string + enum: ["dall-e-2", "dall-e-3"] + x-oaiTypeLabel: string + default: "dall-e-2" + example: "dall-e-3" + nullable: true + description: The model to use for image generation. + n: &images_n + type: integer + minimum: 1 + maximum: 10 + default: 1 + example: 1 + nullable: true + description: The number of images to generate. Must be between 1 and 10. For `dall-e-3`, only `n=1` is supported. + quality: + type: string + enum: ["standard", "hd"] + default: "standard" + example: "standard" + description: The quality of the image that will be generated. `hd` creates images with finer details and greater consistency across the image. This param is only supported for `dall-e-3`. + response_format: &images_response_format + type: string + enum: ["url", "b64_json"] + default: "url" + example: "url" + nullable: true + description: The format in which the generated images are returned. Must be one of `url` or `b64_json`. + size: &images_size + type: string + enum: ["256x256", "512x512", "1024x1024", "1792x1024", "1024x1792"] + default: "1024x1024" + example: "1024x1024" + nullable: true + description: 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. + style: + type: string + enum: ["vivid", "natural"] + default: "vivid" + example: "vivid" + nullable: true + description: The style of the generated images. Must be one of `vivid` or `natural`. Vivid causes the model to lean towards generating hyper-real and dramatic images. Natural causes the model to produce more natural, less hyper-real looking images. This param is only supported for `dall-e-3`. + user: *end_user_param_configuration + required: + - prompt + + ImagesResponse: + properties: + created: + type: integer + data: + type: array + items: + $ref: "#/components/schemas/Image" + required: + - created + - data + + Image: + type: object + description: Represents the url or the content of an image generated by the OpenAI API. + properties: + b64_json: + type: string + description: The base64-encoded JSON of the generated image, if `response_format` is `b64_json`. + url: + type: string + description: The URL of the generated image, if `response_format` is `url` (default). + revised_prompt: + type: string + description: The prompt that was used to generate the image, if there was any revision to the prompt. + x-oaiMeta: + name: The image object + example: | + { + "url": "...", + "revised_prompt": "..." + } + + CreateImageEditRequest: + type: object + properties: + image: + description: The image to edit. Must be a valid PNG file, less than 4MB, and square. If mask is not provided, image must have transparency, which will be used as the mask. + type: string + format: binary + prompt: + description: A text description of the desired image(s). The maximum length is 1000 characters. + type: string + example: "A cute baby sea otter wearing a beret" + mask: + description: An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where `image` should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions as `image`. + type: string + format: binary + model: + anyOf: + - type: string + - type: string + enum: ["dall-e-2"] + x-oaiTypeLabel: string + default: "dall-e-2" + example: "dall-e-2" + nullable: true + description: The model to use for image generation. Only `dall-e-2` is supported at this time. + n: + type: integer + minimum: 1 + maximum: 10 + default: 1 + example: 1 + nullable: true + description: The number of images to generate. Must be between 1 and 10. + size: &dalle2_images_size + type: string + enum: ["256x256", "512x512", "1024x1024"] + default: "1024x1024" + example: "1024x1024" + nullable: true + description: The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`. + response_format: *images_response_format + user: *end_user_param_configuration + required: + - prompt + - image + + CreateImageVariationRequest: + type: object + properties: + image: + description: The image to use as the basis for the variation(s). Must be a valid PNG file, less than 4MB, and square. + type: string + format: binary + model: + anyOf: + - type: string + - type: string + enum: ["dall-e-2"] + x-oaiTypeLabel: string + default: "dall-e-2" + example: "dall-e-2" + nullable: true + description: The model to use for image generation. Only `dall-e-2` is supported at this time. + n: *images_n + response_format: *images_response_format + size: *dalle2_images_size + user: *end_user_param_configuration + required: + - image + + CreateModerationRequest: + type: object + properties: + input: + description: The input text to classify + oneOf: + - type: string + default: "" + example: "I want to kill them." + - type: array + items: + type: string + default: "" + example: "I want to kill them." + model: + description: | + Two content moderations models are available: `text-moderation-stable` and `text-moderation-latest`. + + The default is `text-moderation-latest` which will be automatically upgraded over time. This ensures you are always using our most accurate model. If you use `text-moderation-stable`, we will provide advanced notice before updating the model. Accuracy of `text-moderation-stable` may be slightly lower than for `text-moderation-latest`. + nullable: false + default: "text-moderation-latest" + example: "text-moderation-stable" + anyOf: + - type: string + - type: string + enum: ["text-moderation-latest", "text-moderation-stable"] + x-oaiTypeLabel: string + required: + - input - securitySchemes: - ApiKeyAuth: - type: http - scheme: 'bearer' + CreateModerationResponse: + type: object + description: Represents policy compliance report by OpenAI's content moderation model against a given input. + properties: + id: + type: string + description: The unique identifier for the moderation request. + model: + type: string + description: The model used to generate the moderation results. + results: + type: array + description: A list of moderation objects. + items: + type: object + properties: + flagged: + type: boolean + description: Whether the content violates [OpenAI's usage policies](/policies/usage-policies). + categories: + type: object + description: A list of the categories, and whether they are flagged or not. + properties: + hate: + type: boolean + description: Content that expresses, incites, or promotes hate based on race, gender, ethnicity, religion, nationality, sexual orientation, disability status, or caste. Hateful content aimed at non-protected groups (e.g., chess players) is harassment. + hate/threatening: + type: boolean + description: Hateful content that also includes violence or serious harm towards the targeted group based on race, gender, ethnicity, religion, nationality, sexual orientation, disability status, or caste. + harassment: + type: boolean + description: Content that expresses, incites, or promotes harassing language towards any target. + harassment/threatening: + type: boolean + description: Harassment content that also includes violence or serious harm towards any target. + self-harm: + type: boolean + description: Content that promotes, encourages, or depicts acts of self-harm, such as suicide, cutting, and eating disorders. + self-harm/intent: + type: boolean + description: Content where the speaker expresses that they are engaging or intend to engage in acts of self-harm, such as suicide, cutting, and eating disorders. + self-harm/instructions: + type: boolean + description: Content that encourages performing acts of self-harm, such as suicide, cutting, and eating disorders, or that gives instructions or advice on how to commit such acts. + sexual: + type: boolean + description: Content meant to arouse sexual excitement, such as the description of sexual activity, or that promotes sexual services (excluding sex education and wellness). + sexual/minors: + type: boolean + description: Sexual content that includes an individual who is under 18 years old. + violence: + type: boolean + description: Content that depicts death, violence, or physical injury. + violence/graphic: + type: boolean + description: Content that depicts death, violence, or physical injury in graphic detail. + required: + - hate + - hate/threatening + - harassment + - harassment/threatening + - self-harm + - self-harm/intent + - self-harm/instructions + - sexual + - sexual/minors + - violence + - violence/graphic + category_scores: + type: object + description: A list of the categories along with their scores as predicted by model. + properties: + hate: + type: number + description: The score for the category 'hate'. + hate/threatening: + type: number + description: The score for the category 'hate/threatening'. + harassment: + type: number + description: The score for the category 'harassment'. + harassment/threatening: + type: number + description: The score for the category 'harassment/threatening'. + self-harm: + type: number + description: The score for the category 'self-harm'. + self-harm/intent: + type: number + description: The score for the category 'self-harm/intent'. + self-harm/instructions: + type: number + description: The score for the category 'self-harm/instructions'. + sexual: + type: number + description: The score for the category 'sexual'. + sexual/minors: + type: number + description: The score for the category 'sexual/minors'. + violence: + type: number + description: The score for the category 'violence'. + violence/graphic: + type: number + description: The score for the category 'violence/graphic'. + required: + - hate + - hate/threatening + - harassment + - harassment/threatening + - self-harm + - self-harm/intent + - self-harm/instructions + - sexual + - sexual/minors + - violence + - violence/graphic + required: + - flagged + - categories + - category_scores + required: + - id + - model + - results + x-oaiMeta: + name: The moderation object + example: *moderation_example - schemas: - Error: + ListFilesResponse: type: object properties: - type: + data: + type: array + items: + $ref: "#/components/schemas/OpenAIFile" + object: type: string - nullable: false - message: + enum: [list] + required: + - object + - data + + CreateFileRequest: + type: object + additionalProperties: false + properties: + file: + description: | + The File object (not file name) to be uploaded. type: string - nullable: false - param: + format: binary + purpose: + description: | + The intended purpose of the uploaded file. + + Use "fine-tune" for [Fine-tuning](/docs/api-reference/fine-tuning) and "assistants" for [Assistants](/docs/api-reference/assistants) and [Messages](/docs/api-reference/messages). This allows us to validate the format of the uploaded file is correct for fine-tuning. type: string - nullable: true - code: + enum: ["fine-tune", "assistants"] + required: + - file + - purpose + + DeleteFileResponse: + type: object + properties: + id: type: string - nullable: true + object: + type: string + enum: [file] + deleted: + type: boolean required: - - type - - message - - param - - code + - id + - object + - deleted - ErrorResponse: + CreateFineTuningJobRequest: type: object properties: - error: - $ref: "#/components/schemas/Error" + model: + description: | + The name of the model to fine-tune. You can select one of the + [supported models](/docs/guides/fine-tuning/what-models-can-be-fine-tuned). + example: "gpt-3.5-turbo" + anyOf: + - type: string + - type: string + enum: ["babbage-002", "davinci-002", "gpt-3.5-turbo"] + x-oaiTypeLabel: string + training_file: + description: | + The ID of an uploaded file that contains training data. + + See [upload file](/docs/api-reference/files/upload) for how to upload a file. + + Your dataset must be formatted as a JSONL file. Additionally, you must upload your file with the purpose `fine-tune`. + + See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. + type: string + example: "file-abc123" + hyperparameters: + type: object + description: The hyperparameters used for the fine-tuning job. + properties: + batch_size: + description: | + Number of examples in each batch. A larger batch size means that model parameters + are updated less frequently, but with lower variance. + oneOf: + - type: string + enum: [auto] + - type: integer + minimum: 1 + maximum: 256 + default: auto + learning_rate_multiplier: + description: | + Scaling factor for the learning rate. A smaller learning rate may be useful to avoid + overfitting. + oneOf: + - type: string + enum: [auto] + - type: number + minimum: 0 + exclusiveMinimum: true + default: auto + n_epochs: + description: | + The number of epochs to train the model for. An epoch refers to one full cycle + through the training dataset. + oneOf: + - type: string + enum: [auto] + - type: integer + minimum: 1 + maximum: 50 + default: auto + suffix: + description: | + 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`. + type: string + minLength: 1 + maxLength: 40 + default: null + nullable: true + validation_file: + description: | + The ID of an uploaded file that contains validation data. + + If you provide this file, the data is used to generate validation + metrics periodically during fine-tuning. These metrics can be viewed in + the fine-tuning results file. + The same data should not be present in both train and validation files. + + Your dataset must be formatted as a JSONL file. You must upload your file with the purpose `fine-tune`. + + See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. + type: string + nullable: true + example: "file-abc123" required: - - error + - model + - training_file - ListModelsResponse: + ListFineTuningJobEventsResponse: type: object properties: - object: - type: string data: type: array items: - $ref: "#/components/schemas/Model" - required: - - object - - data - - DeleteModelResponse: - type: object - properties: - id: - type: string + $ref: "#/components/schemas/FineTuningJobEvent" object: type: string - deleted: - type: boolean + enum: [list] required: - - id - object - - deleted + - data - CreateCompletionRequest: + CreateEmbeddingRequest: type: object + additionalProperties: false properties: - model: - description: &model_description | - ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](/docs/models/overview) for descriptions of them. - anyOf: - - type: string - - type: string - enum: - [ - "babbage-002", - "davinci-002", - "gpt-3.5-turbo-instruct", - "text-davinci-003", - "text-davinci-002", - "text-davinci-001", - "code-davinci-002", - "text-curie-001", - "text-babbage-001", - "text-ada-001", - ] - x-oaiTypeLabel: string - prompt: - description: &completions_prompt_description | - The prompt(s) to generate completions for, encoded as a string, array of strings, array of tokens, or array of token arrays. - - Note that <|endoftext|> is the document separator that the model sees during training, so if a prompt is not specified the model will generate as if from the beginning of a new document. - default: "<|endoftext|>" - nullable: true + input: + description: | + Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a single request, pass an array of strings or array of token arrays. The input must not exceed the max input tokens for the model (8192 tokens for `text-embedding-ada-002`), cannot be an empty string, and any array must be 2048 dimensions or less. [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) for counting tokens. + example: "The quick brown fox jumped over the lazy dog" oneOf: - type: string + title: string + description: The string that will be turned into an embedding. default: "" example: "This is a test." - type: array + title: array + description: The array of strings that will be turned into an embedding. + minItems: 1 + maxItems: 2048 items: type: string default: "" - example: "This is a test." + example: "['This is a test.']" - type: array + title: array + description: The array of integers that will be turned into an embedding. minItems: 1 + maxItems: 2048 items: type: integer example: "[1212, 318, 257, 1332, 13]" - type: array + title: array + description: The array of arrays containing integers that will be turned into an embedding. minItems: 1 + maxItems: 2048 items: type: array minItems: 1 items: type: integer example: "[[1212, 318, 257, 1332, 13]]" - suffix: - description: The suffix that comes after a completion of inserted text. - default: null - nullable: true + x-oaiExpandable: true + model: + description: *model_description + example: "text-embedding-3-small" + anyOf: + - type: string + - type: string + enum: ["text-embedding-ada-002", "text-embedding-3-small", "text-embedding-3-large"] + x-oaiTypeLabel: string + encoding_format: + description: "The format to return the embeddings in. Can be either `float` or [`base64`](https://pypi.org/project/pybase64/)." + example: "float" + default: "float" type: string - example: "test." - max_tokens: - type: integer - minimum: 0 - default: 16 - example: 16 - nullable: true - description: &completions_max_tokens_description | - The maximum number of [tokens](/tokenizer) to generate in the completion. - - The token count of your prompt plus `max_tokens` cannot exceed the model's context length. [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) for counting tokens. - temperature: - type: number - minimum: 0 - maximum: 2 - default: 1 - example: 1 - nullable: true - description: &completions_temperature_description | - What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. - - We generally recommend altering this or `top_p` but not both. - top_p: - type: number - minimum: 0 - maximum: 1 - default: 1 - example: 1 - nullable: true - description: &completions_top_p_description | - An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. - - We generally recommend altering this or `temperature` but not both. - n: + enum: ["float", "base64"] + dimensions: + description: | + The number of dimensions the resulting output embeddings should have. Only supported in `text-embedding-3` and later models. type: integer minimum: 1 - maximum: 128 - default: 1 - example: 1 - nullable: true - description: &completions_completions_description | - How many completions to generate for each prompt. + user: *end_user_param_configuration + required: + - model + - input - **Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. - stream: - description: > - Whether to stream back partial progress. If set, tokens will be sent as data-only [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) - as they become available, with the stream terminated by a `data: [DONE]` message. [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_stream_completions.ipynb). - type: boolean - nullable: true - default: false - logprobs: &completions_logprobs_configuration - type: integer - minimum: 0 - maximum: 5 - default: null - nullable: true - description: &completions_logprobs_description | - Include the log probabilities on the `logprobs` most likely tokens, as well the chosen tokens. For example, if `logprobs` is 5, the API will return a list of the 5 most likely tokens. The API will always return the `logprob` of the sampled token, so there may be up to `logprobs+1` elements in the response. + CreateEmbeddingResponse: + type: object + properties: + data: + type: array + description: The list of embeddings generated by the model. + items: + $ref: "#/components/schemas/Embedding" + model: + type: string + description: The name of the model used to generate the embedding. + object: + type: string + description: The object type, which is always "list". + enum: [list] + usage: + type: object + description: The usage information for the request. + properties: + prompt_tokens: + type: integer + description: The number of tokens used by the prompt. + total_tokens: + type: integer + description: The total number of tokens used by the request. + required: + - prompt_tokens + - total_tokens + required: + - object + - model + - data + - usage - The maximum value for `logprobs` is 5. - echo: - type: boolean - default: false - nullable: true - description: &completions_echo_description > - Echo back the prompt in addition to the completion - stop: - description: &completions_stop_description > - Up to 4 sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence. - default: null - nullable: true - oneOf: + CreateTranscriptionRequest: + type: object + additionalProperties: false + properties: + file: + description: | + The audio file object (not file name) to transcribe, in one of these formats: flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm. + type: string + x-oaiTypeLabel: file + format: binary + model: + description: | + ID of the model to use. Only `whisper-1` is currently available. + example: whisper-1 + anyOf: - type: string - default: <|endoftext|> - example: "\n" - nullable: true - - type: array - minItems: 1 - maxItems: 4 - items: - type: string - example: '["\n"]' - presence_penalty: + - type: string + enum: ["whisper-1"] + x-oaiTypeLabel: string + language: + description: | + The language of the input audio. Supplying the input language in [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) format will improve accuracy and latency. + type: string + prompt: + description: | + An optional text to guide the model's style or continue a previous audio segment. The [prompt](/docs/guides/speech-to-text/prompting) should match the audio language. + type: string + response_format: + description: | + The format of the transcript output, in one of these options: `json`, `text`, `srt`, `verbose_json`, or `vtt`. + type: string + enum: + - json + - text + - srt + - verbose_json + - vtt + default: json + temperature: + description: | + The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to automatically increase the temperature until certain thresholds are hit. type: number default: 0 - minimum: -2 - maximum: 2 - nullable: true - description: &completions_presence_penalty_description | - Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics. + required: + - file + - model - [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) - frequency_penalty: + # Note: This does not currently support the non-default response format types. + CreateTranscriptionResponse: + type: object + properties: + text: + type: string + required: + - text + + CreateTranslationRequest: + type: object + additionalProperties: false + properties: + file: + description: | + The audio file object (not file name) translate, in one of these formats: flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm. + type: string + x-oaiTypeLabel: file + format: binary + model: + description: | + ID of the model to use. Only `whisper-1` is currently available. + example: whisper-1 + anyOf: + - type: string + - type: string + enum: ["whisper-1"] + x-oaiTypeLabel: string + prompt: + description: | + An optional text to guide the model's style or continue a previous audio segment. The [prompt](/docs/guides/speech-to-text/prompting) should be in English. + type: string + response_format: + description: | + The format of the transcript output, in one of these options: `json`, `text`, `srt`, `verbose_json`, or `vtt`. + type: string + default: json + temperature: + description: | + The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to automatically increase the temperature until certain thresholds are hit. type: number default: 0 - minimum: -2 - maximum: 2 - nullable: true - description: &completions_frequency_penalty_description | - Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim. - - [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) - best_of: - type: integer - default: 1 - minimum: 0 - maximum: 20 - nullable: true - description: &completions_best_of_description | - Generates `best_of` completions server-side and returns the "best" (the one with the highest log probability per token). Results cannot be streamed. - - When used with `n`, `best_of` controls the number of candidate completions and `n` specifies how many to return – `best_of` must be greater than `n`. - - **Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. - logit_bias: &completions_logit_bias - type: object - x-oaiTypeLabel: map - default: null - nullable: true - additionalProperties: - type: integer - description: &completions_logit_bias_description | - Modify the likelihood of specified tokens appearing in the completion. - - Accepts a json object that maps tokens (specified by their token ID in the GPT tokenizer) to an associated bias value from -100 to 100. You can use this [tokenizer tool](/tokenizer?view=bpe) (which works for both GPT-2 and GPT-3) to convert text to token IDs. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token. + required: + - file + - model - As an example, you can pass `{"50256": -100}` to prevent the <|endoftext|> token from being generated. - user: &end_user_param_configuration + # Note: This does not currently support the non-default response format types. + CreateTranslationResponse: + type: object + properties: + text: type: string - example: user-1234 + required: + - text + + CreateSpeechRequest: + type: object + additionalProperties: false + properties: + model: description: | - A unique identifier representing your end-user, which can help OpenAI to monitor and detect abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + One of the available [TTS models](/docs/models/tts): `tts-1` or `tts-1-hd` + anyOf: + - type: string + - type: string + enum: ["tts-1", "tts-1-hd"] + x-oaiTypeLabel: string + input: + type: string + description: The text to generate audio for. The maximum length is 4096 characters. + maxLength: 4096 + voice: + description: The voice to use when generating the audio. Supported voices are `alloy`, `echo`, `fable`, `onyx`, `nova`, and `shimmer`. Previews of the voices are available in the [Text to speech guide](/docs/guides/text-to-speech/voice-options). + type: string + enum: ["alloy", "echo", "fable", "onyx", "nova", "shimmer"] + response_format: + description: "The format to audio in. Supported formats are `mp3`, `opus`, `aac`, and `flac`." + default: "mp3" + type: string + enum: ["mp3", "opus", "aac", "flac"] + speed: + description: "The speed of the generated audio. Select a value from `0.25` to `4.0`. `1.0` is the default." + type: number + default: 1.0 + minimum: 0.25 + maximum: 4.0 required: - model - - prompt + - input + - voice - CreateCompletionResponse: - type: object - description: | - Represents a completion response from the API. Note: both the streamed and non-streamed response objects share the same shape (unlike the chat endpoint). + Model: + title: Model + description: Describes an OpenAI model offering that can be used with the API. properties: id: type: string - description: A unique identifier for the completion. - object: - type: string - description: The object type, which is always "text_completion" + description: The model identifier, which can be referenced in the API endpoints. created: type: integer - description: The Unix timestamp (in seconds) of when the completion was created. - model: + description: The Unix timestamp (in seconds) when the model was created. + object: type: string - description: The model used for completion. - choices: - type: array - description: The list of completion choices the model generated for the input prompt. - items: - type: object - required: - - text - - index - - logprobs - - finish_reason - properties: - text: - type: string - index: - type: integer - logprobs: - type: object - nullable: true - properties: - tokens: - type: array - items: - type: string - token_logprobs: - type: array - items: - type: number - top_logprobs: - type: array - items: - type: object - additionalProperties: - type: integer - text_offset: - type: array - items: - type: integer - finish_reason: - type: string - description: &completion_finish_reason_description | - The reason the model stopped generating tokens. This will be `stop` if the model hit a natural stop point or a provided stop sequence, - `length` if the maximum number of tokens specified in the request was reached, - or `content_filter` if content was omitted due to a flag from our content filters. - enum: ["stop", "length", "content_filter"] - usage: - $ref: "#/components/schemas/CompletionUsage" + description: The object type, which is always "model". + enum: [model] + owned_by: + type: string + description: The organization that owns the model. required: - id - object - created - - model - - choices + - owned_by x-oaiMeta: - name: The completion object - legacy: true - example: | - { - "id": "cmpl-uqkvlQyYK7bGYrRHQ0eXlWi7", - "object": "text_completion", - "created": 1589478378, - "model": "gpt-3.5-turbo", - "choices": [ - { - "text": "\n\nThis is indeed a test", - "index": 0, - "logprobs": null, - "finish_reason": "length" - } - ], - "usage": { - "prompt_tokens": 5, - "completion_tokens": 7, - "total_tokens": 12 - } - } + name: The model object + example: *retrieve_model_response - ChatCompletionRequestMessage: - type: object + OpenAIFile: + title: OpenAIFile + description: The `File` object represents a document that has been uploaded to OpenAI. properties: - role: + id: type: string - enum: ["system", "user", "assistant", "function"] - description: The role of the messages author. One of `system`, `user`, `assistant`, or `function`. - content: + description: The file identifier, which can be referenced in the API endpoints. + bytes: + type: integer + description: The size of the file, in bytes. + created_at: + type: integer + description: The Unix timestamp (in seconds) for when the file was created. + filename: type: string - nullable: true - description: The contents of the message. `content` is required for all messages, and may be null for assistant messages with function calls. - name: + description: The name of the file. + object: type: string - description: The name of the author of this message. `name` is required if role is `function`, and it should be the name of the function whose response is in the `content`. May contain a-z, A-Z, 0-9, and underscores, with a maximum length of 64 characters. - function_call: - type: object - description: The name and arguments of a function that should be called, as generated by the model. - properties: - name: - type: string - description: The name of the function to call. - arguments: - type: string - description: The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function. - required: - - name - - arguments - required: - - role - - content - - ChatCompletionFunctionParameters: - type: object - description: "The parameters the functions accepts, described as a JSON Schema object. See the [guide](/docs/guides/gpt/function-calling) for examples, and the [JSON Schema reference](https://json-schema.org/understanding-json-schema/) for documentation about the format.\n\nTo describe a function that accepts no parameters, provide the value `{\"type\": \"object\", \"properties\": {}}`." - additionalProperties: true - - ChatCompletionFunctions: - type: object - properties: - name: + description: The object type, which is always `file`. + enum: ["file"] + purpose: type: string - description: The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum length of 64. - description: + description: The intended purpose of the file. Supported values are `fine-tune`, `fine-tune-results`, `assistants`, and `assistants_output`. + enum: + [ + "fine-tune", + "fine-tune-results", + "assistants", + "assistants_output", + ] + status: type: string - description: A description of what the function does, used by the model to choose when and how to call the function. - parameters: - $ref: "#/components/schemas/ChatCompletionFunctionParameters" + deprecated: true + description: Deprecated. The current status of the file, which can be either `uploaded`, `processed`, or `error`. + enum: ["uploaded", "processed", "error"] + status_details: + type: string + deprecated: true + description: Deprecated. For details on why a fine-tuning training file failed validation, see the `error` field on `fine_tuning.job`. required: - - name - - parameters - - ChatCompletionFunctionCallOption: + - id + - object + - bytes + - created_at + - filename + - purpose + - status + x-oaiMeta: + name: The file object + example: | + { + "id": "file-abc123", + "object": "file", + "bytes": 120000, + "created_at": 1677610602, + "filename": "salesOverview.pdf", + "purpose": "assistants", + } + Embedding: type: object + description: | + Represents an embedding vector returned by embedding endpoint. properties: - name: + index: + type: integer + description: The index of the embedding in the list of embeddings. + embedding: + type: array + description: | + The embedding vector, which is a list of floats. The length of vector depends on the model as listed in the [embedding guide](/docs/guides/embeddings). + items: + type: number + object: type: string - description: The name of the function to call. + description: The object type, which is always "embedding". + enum: [embedding] required: - - name + - index + - object + - embedding + x-oaiMeta: + name: The embedding object + example: | + { + "object": "embedding", + "embedding": [ + 0.0023064255, + -0.009327292, + .... (1536 floats total for ada-002) + -0.0028842222, + ], + "index": 0 + } - ChatCompletionResponseMessage: + FineTuningJob: type: object - description: A chat completion message generated by the model. + title: FineTuningJob + description: | + The `fine_tuning.job` object represents a fine-tuning job that has been created through the API. properties: - role: - type: string - enum: ["system", "user", "assistant", "function"] - description: The role of the author of this message. - content: + id: type: string - description: The contents of the message. - nullable: true - function_call: + description: The object identifier, which can be referenced in the API endpoints. + created_at: + type: integer + description: The Unix timestamp (in seconds) for when the fine-tuning job was created. + error: type: object - description: The name and arguments of a function that should be called, as generated by the model. + nullable: true + description: For fine-tuning jobs that have `failed`, this will contain more information on the cause of the failure. properties: - name: + code: type: string - description: The name of the function to call. - arguments: + description: A machine-readable error code. + message: type: string - description: The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function. + description: A human-readable error message. + param: + type: string + description: The parameter that was invalid, usually `training_file` or `validation_file`. This field will be null if the failure was not parameter-specific. + nullable: true required: - - name - - arguments - required: - - role - - content - - ChatCompletionStreamResponseDelta: - type: object - description: A chat completion delta generated by streamed model responses. - properties: - role: - type: string - enum: ["system", "user", "assistant", "function"] - description: The role of the author of this message. - content: + - code + - message + - param + fine_tuned_model: type: string - description: The contents of the chunk message. nullable: true - function_call: + description: The name of the fine-tuned model that is being created. The value will be null if the fine-tuning job is still running. + finished_at: + type: integer + nullable: true + description: The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be null if the fine-tuning job is still running. + hyperparameters: type: object - description: The name and arguments of a function that should be called, as generated by the model. + description: The hyperparameters used for the fine-tuning job. See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. properties: - name: - type: string - description: The name of the function to call. - arguments: - type: string - description: The arguments to call the function with, as generated by the model in JSON format. Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your function schema. Validate the arguments in your code before calling your function. + n_epochs: + oneOf: + - type: string + enum: [auto] + - type: integer + minimum: 1 + maximum: 50 + default: auto + description: + The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset. - CreateChatCompletionRequest: - type: object - properties: + "auto" decides the optimal number of epochs based on the size of the dataset. If setting the number manually, we support any number between 1 and 50 epochs. + required: + - n_epochs model: - description: ID of the model to use. See the [model endpoint compatibility](/docs/models/model-endpoint-compatibility) table for details on which models work with the Chat API. - example: "gpt-3.5-turbo" - anyOf: - - type: string - - type: string - enum: - [ - "gpt-4", - "gpt-4-0314", - "gpt-4-0613", - "gpt-4-32k", - "gpt-4-32k-0314", - "gpt-4-32k-0613", - "gpt-3.5-turbo", - "gpt-3.5-turbo-16k", - "gpt-3.5-turbo-0301", - "gpt-3.5-turbo-0613", - "gpt-3.5-turbo-16k-0613", - ] - x-oaiTypeLabel: string - messages: - description: A list of messages comprising the conversation so far. [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb). - type: array - minItems: 1 - items: - $ref: "#/components/schemas/ChatCompletionRequestMessage" - functions: - description: A list of functions the model may generate JSON inputs for. + type: string + description: The base model that is being fine-tuned. + object: + type: string + description: The object type, which is always "fine_tuning.job". + enum: [fine_tuning.job] + organization_id: + type: string + description: The organization that owns the fine-tuning job. + result_files: type: array - minItems: 1 - maxItems: 128 + description: The compiled results file ID(s) for the fine-tuning job. You can retrieve the results with the [Files API](/docs/api-reference/files/retrieve-contents). items: - $ref: "#/components/schemas/ChatCompletionFunctions" - function_call: - description: "Controls how the model responds to function calls. `none` means the model does not call a function, and responds to the end-user. `auto` means the model can pick between an end-user or calling a function. Specifying a particular function via `{\"name\": \"my_function\"}` forces the model to call that function. `none` is the default when no functions are present. `auto` is the default if functions are present." - oneOf: - - type: string - enum: [none, auto] - - $ref: "#/components/schemas/ChatCompletionFunctionCallOption" - temperature: - type: number - minimum: 0 - maximum: 2 - default: 1 - example: 1 - nullable: true - description: *completions_temperature_description - top_p: - type: number - minimum: 0 - maximum: 1 - default: 1 - example: 1 - nullable: true - description: *completions_top_p_description - n: + type: string + example: file-abc123 + status: + type: string + description: The current status of the fine-tuning job, which can be either `validating_files`, `queued`, `running`, `succeeded`, `failed`, or `cancelled`. + enum: + [ + "validating_files", + "queued", + "running", + "succeeded", + "failed", + "cancelled", + ] + trained_tokens: type: integer - minimum: 1 - maximum: 128 - default: 1 - example: 1 nullable: true - description: How many chat completion choices to generate for each input message. - stream: - description: > - If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) - as they become available, with the stream terminated by a `data: [DONE]` message. [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_stream_completions.ipynb). - type: boolean + description: The total number of billable tokens processed by this fine-tuning job. The value will be null if the fine-tuning job is still running. + training_file: + type: string + description: The file ID used for training. You can retrieve the training data with the [Files API](/docs/api-reference/files/retrieve-contents). + validation_file: + type: string nullable: true - default: false - stop: - description: | - Up to 4 sequences where the API will stop generating further tokens. - default: null - oneOf: - - type: string - nullable: true - - type: array - minItems: 1 - maxItems: 4 - items: - type: string - max_tokens: - description: | - The maximum number of [tokens](/tokenizer) to generate in the chat completion. + description: The file ID used for validation. You can retrieve the validation results with the [Files API](/docs/api-reference/files/retrieve-contents). + required: + - created_at + - error + - finished_at + - fine_tuned_model + - hyperparameters + - id + - model + - object + - organization_id + - result_files + - status + - trained_tokens + - training_file + - validation_file + x-oaiMeta: + name: The fine-tuning job object + example: *fine_tuning_example - The total length of input tokens and generated tokens is limited by the model's context length. [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) for counting tokens. - default: inf + FineTuningJobEvent: + type: object + description: Fine-tuning job event object + properties: + id: + type: string + created_at: type: integer - nullable: true - presence_penalty: - type: number - default: 0 - minimum: -2 - maximum: 2 - nullable: true - description: *completions_presence_penalty_description - frequency_penalty: - type: number - default: 0 - minimum: -2 - maximum: 2 - nullable: true - description: *completions_frequency_penalty_description - logit_bias: - type: object - x-oaiTypeLabel: map - default: null - nullable: true - additionalProperties: - type: integer - description: | - Modify the likelihood of specified tokens appearing in the completion. + level: + type: string + enum: ["info", "warn", "error"] + message: + type: string + object: + type: string + enum: [fine_tuning.job.event] + required: + - id + - object + - created_at + - level + - message + x-oaiMeta: + name: The fine-tuning job event object + example: | + { + "object": "fine_tuning.job.event", + "id": "ftevent-abc123" + "created_at": 1677610602, + "level": "info", + "message": "Created fine-tuning job" + } - Accepts a json object that maps tokens (specified by their token ID in the tokenizer) to an associated bias value from -100 to 100. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token. - user: *end_user_param_configuration + CompletionUsage: + type: object + description: Usage statistics for the completion request. + properties: + completion_tokens: + type: integer + description: Number of tokens in the generated completion. + prompt_tokens: + type: integer + description: Number of tokens in the prompt. + total_tokens: + type: integer + description: Total number of tokens used in the request (prompt + completion). required: - - model - - messages + - prompt_tokens + - completion_tokens + - total_tokens - CreateChatCompletionResponse: + RunCompletionUsage: type: object - description: Represents a chat completion response returned by model, based on the provided input. + description: Usage statistics related to the run. This value will be `null` if the run is not in a terminal state (i.e. `in_progress`, `queued`, etc.). properties: - id: - type: string - description: A unique identifier for the chat completion. - object: - type: string - description: The object type, which is always `chat.completion`. - created: + completion_tokens: type: integer - description: The Unix timestamp (in seconds) of when the chat completion was created. - model: - type: string - description: The model used for the chat completion. - choices: - type: array - description: A list of chat completion choices. Can be more than one if `n` is greater than 1. - items: - type: object - required: - - index - - message - - finish_reason - properties: - index: - type: integer - description: The index of the choice in the list of choices. - message: - $ref: "#/components/schemas/ChatCompletionResponseMessage" - finish_reason: - type: string - description: &chat_completion_finish_reason_description | - The reason the model stopped generating tokens. This will be `stop` if the model hit a natural stop point or a provided stop sequence, - `length` if the maximum number of tokens specified in the request was reached, - `content_filter` if content was omitted due to a flag from our content filters, - or `function_call` if the model called a function. - enum: ["stop", "length", "function_call", "content_filter"] - usage: - $ref: "#/components/schemas/CompletionUsage" + description: Number of completion tokens used over the course of the run. + prompt_tokens: + type: integer + description: Number of prompt tokens used over the course of the run. + total_tokens: + type: integer + description: Total number of tokens used (prompt + completion). required: - - id - - object - - created - - model - - choices - x-oaiMeta: - name: The chat completion object - group: chat - example: *chat_completion_example + - prompt_tokens + - completion_tokens + - total_tokens + nullable: true - ListPaginatedFineTuningJobsResponse: + RunStepCompletionUsage: type: object + description: Usage statistics related to the run step. This value will be `null` while the run step's status is `in_progress`. properties: - object: - type: string - data: - type: array - items: - $ref: "#/components/schemas/FineTuningJob" - has_more: - type: boolean + completion_tokens: + type: integer + description: Number of completion tokens used over the course of the run step. + prompt_tokens: + type: integer + description: Number of prompt tokens used over the course of the run step. + total_tokens: + type: integer + description: Total number of tokens used (prompt + completion). required: - - object - - data - - has_more + - prompt_tokens + - completion_tokens + - total_tokens + nullable: true - CreateChatCompletionStreamResponse: + AssistantObject: type: object - description: Represents a streamed chunk of a chat completion response returned by model, based on the provided input. + title: Assistant + description: Represents an `assistant` that can call the model and use tools. properties: id: + description: The identifier, which can be referenced in API endpoints. type: string - description: A unique identifier for the chat completion chunk. object: + description: The object type, which is always `assistant`. type: string - description: The object type, which is always `chat.completion.chunk`. - created: + enum: [assistant] + created_at: + description: The Unix timestamp (in seconds) for when the assistant was created. type: integer - description: The Unix timestamp (in seconds) of when the chat completion chunk was created. + name: + description: &assistant_name_param_description | + The name of the assistant. The maximum length is 256 characters. + type: string + maxLength: 256 + nullable: true + description: + description: &assistant_description_param_description | + The description of the assistant. The maximum length is 512 characters. + type: string + maxLength: 512 + nullable: true model: + description: *model_description type: string - description: The model to generate the completion. - choices: + instructions: + description: &assistant_instructions_param_description | + The system instructions that the assistant uses. The maximum length is 32768 characters. + type: string + maxLength: 32768 + nullable: true + tools: + description: &assistant_tools_param_description | + A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. Tools can be of types `code_interpreter`, `retrieval`, or `function`. + default: [] type: array - description: A list of chat completion choices. Can be more than one if `n` is greater than 1. + maxItems: 128 items: - type: object - required: - - index - - delta - - finish_reason - properties: - index: - type: integer - description: The index of the choice in the list of choices. - delta: - $ref: "#/components/schemas/ChatCompletionStreamResponseDelta" - finish_reason: - type: string - description: *chat_completion_finish_reason_description - enum: ["stop", "length", "function_call"] - nullable: true + oneOf: + - $ref: "#/components/schemas/AssistantToolsCode" + - $ref: "#/components/schemas/AssistantToolsRetrieval" + - $ref: "#/components/schemas/AssistantToolsFunction" + x-oaiExpandable: true + file_ids: + description: &assistant_file_param_description | + A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a maximum of 20 files attached to the assistant. Files are ordered by their creation date in ascending order. + default: [] + type: array + maxItems: 20 + items: + type: string + metadata: + description: &metadata_description | + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing additional information about the object in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long. + type: object + x-oaiTypeLabel: map + nullable: true required: - id - object - - created + - created_at + - name + - description - model - - choices + - instructions + - tools + - file_ids + - metadata x-oaiMeta: - name: The chat completion chunk object - group: chat - example: *chat_completion_chunk_example + name: The assistant object + beta: true + example: *create_assistants_example - CreateEditRequest: + CreateAssistantRequest: type: object + additionalProperties: false properties: model: - description: ID of the model to use. You can use the `text-davinci-edit-001` or `code-davinci-edit-001` model with this endpoint. - example: "text-davinci-edit-001" + description: *model_description anyOf: - type: string - - type: string - enum: ["text-davinci-edit-001", "code-davinci-edit-001"] - x-oaiTypeLabel: string - input: - description: The input text to use as a starting point for the edit. + name: + description: *assistant_name_param_description type: string - default: "" nullable: true - example: "What day of the wek is it?" - instruction: - description: The instruction that tells the model how to edit the prompt. + maxLength: 256 + description: + description: *assistant_description_param_description type: string - example: "Fix the spelling mistakes." - n: - type: integer - minimum: 1 - maximum: 20 - default: 1 - example: 1 - nullable: true - description: How many edits to generate for the input and instruction. - temperature: - type: number - minimum: 0 - maximum: 2 - default: 1 - example: 1 - nullable: true - description: *completions_temperature_description - top_p: - type: number - minimum: 0 - maximum: 1 - default: 1 - example: 1 nullable: true - description: *completions_top_p_description - required: - - model - - instruction - - CreateEditResponse: - type: object - title: Edit - deprecated: true - properties: - object: + maxLength: 512 + instructions: + description: *assistant_instructions_param_description type: string - description: The object type, which is always `edit`. - created: - type: integer - description: The Unix timestamp (in seconds) of when the edit was created. - choices: + nullable: true + maxLength: 32768 + tools: + description: *assistant_tools_param_description + default: [] type: array - description: A list of edit choices. Can be more than one if `n` is greater than 1. + maxItems: 128 items: - type: object - required: - - text - - index - - finish_reason - properties: - text: - type: string - description: The edited result. - index: - type: integer - description: The index of the choice in the list of choices. - finish_reason: - type: string - description: *completion_finish_reason_description - enum: ["stop", "length"] - usage: - $ref: "#/components/schemas/CompletionUsage" + oneOf: + - $ref: "#/components/schemas/AssistantToolsCode" + - $ref: "#/components/schemas/AssistantToolsRetrieval" + - $ref: "#/components/schemas/AssistantToolsFunction" + x-oaiExpandable: true + file_ids: + description: *assistant_file_param_description + default: [] + maxItems: 20 + type: array + items: + type: string + metadata: + description: *metadata_description + type: object + x-oaiTypeLabel: map + nullable: true required: - - object - - created - - choices - - usage - x-oaiMeta: - name: The edit object - example: *edit_example + - model - CreateImageRequest: + ModifyAssistantRequest: type: object + additionalProperties: false properties: - prompt: - description: A text description of the desired image(s). The maximum length is 1000 characters. + model: + description: *model_description + anyOf: + - type: string + name: + description: *assistant_name_param_description type: string - example: "A cute baby sea otter" - n: &images_n - type: integer - minimum: 1 - maximum: 10 - default: 1 - example: 1 nullable: true - description: The number of images to generate. Must be between 1 and 10. - size: &images_size + maxLength: 256 + description: + description: *assistant_description_param_description type: string - enum: ["256x256", "512x512", "1024x1024"] - default: "1024x1024" - example: "1024x1024" nullable: true - description: The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`. - response_format: &images_response_format + maxLength: 512 + instructions: + description: *assistant_instructions_param_description type: string - enum: ["url", "b64_json"] - default: "url" - example: "url" nullable: true - description: The format in which the generated images are returned. Must be one of `url` or `b64_json`. - user: *end_user_param_configuration - required: - - prompt - - ImagesResponse: - properties: - created: - type: integer - data: + maxLength: 32768 + tools: + description: *assistant_tools_param_description + default: [] type: array + maxItems: 128 items: - $ref: "#/components/schemas/Image" - required: - - created - - data + oneOf: + - $ref: "#/components/schemas/AssistantToolsCode" + - $ref: "#/components/schemas/AssistantToolsRetrieval" + - $ref: "#/components/schemas/AssistantToolsFunction" + x-oaiExpandable: true + file_ids: + description: | + A list of [File](/docs/api-reference/files) IDs attached to this assistant. There can be a maximum of 20 files attached to the assistant. Files are ordered by their creation date in ascending order. If a file was previously attached to the list but does not show up in the list, it will be deleted from the assistant. + default: [] + type: array + maxItems: 20 + items: + type: string + metadata: + description: *metadata_description + type: object + x-oaiTypeLabel: map + nullable: true - Image: + DeleteAssistantResponse: type: object - description: Represents the url or the content of an image generated by the OpenAI API. properties: - url: + id: type: string - description: The URL of the generated image, if `response_format` is `url` (default). - b64_json: + deleted: + type: boolean + object: type: string - description: The base64-encoded JSON of the generated image, if `response_format` is `b64_json`. - x-oaiMeta: - name: The image object - example: | - { - "url": "..." - } + enum: [assistant.deleted] + required: + - id + - object + - deleted - CreateImageEditRequest: + ListAssistantsResponse: type: object properties: - image: - description: The image to edit. Must be a valid PNG file, less than 4MB, and square. If mask is not provided, image must have transparency, which will be used as the mask. + object: type: string - format: binary - mask: - description: An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where `image` should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions as `image`. + example: "list" + data: + type: array + items: + $ref: "#/components/schemas/AssistantObject" + first_id: type: string - format: binary - prompt: - description: A text description of the desired image(s). The maximum length is 1000 characters. + example: "asst_abc123" + last_id: type: string - example: "A cute baby sea otter wearing a beret" - n: *images_n - size: *images_size - response_format: *images_response_format - user: *end_user_param_configuration + example: "asst_abc456" + has_more: + type: boolean + example: false required: - - prompt - - image + - object + - data + - first_id + - last_id + - has_more + x-oaiMeta: + name: List assistants response object + group: chat + example: *list_assistants_example - CreateImageVariationRequest: + AssistantToolsCode: type: object + title: Code interpreter tool properties: - image: - description: The image to use as the basis for the variation(s). Must be a valid PNG file, less than 4MB, and square. + type: type: string - format: binary - n: *images_n - size: *images_size - response_format: *images_response_format - user: *end_user_param_configuration + description: "The type of tool being defined: `code_interpreter`" + enum: ["code_interpreter"] required: - - image + - type - CreateModerationRequest: + AssistantToolsRetrieval: type: object + title: Retrieval tool properties: - input: - description: The input text to classify - oneOf: - - type: string - default: "" - example: "I want to kill them." - - type: array - items: - type: string - default: "" - example: "I want to kill them." - model: - description: | - Two content moderations models are available: `text-moderation-stable` and `text-moderation-latest`. + type: + type: string + description: "The type of tool being defined: `retrieval`" + enum: ["retrieval"] + required: + - type - The default is `text-moderation-latest` which will be automatically upgraded over time. This ensures you are always using our most accurate model. If you use `text-moderation-stable`, we will provide advanced notice before updating the model. Accuracy of `text-moderation-stable` may be slightly lower than for `text-moderation-latest`. - nullable: false - default: "text-moderation-latest" - example: "text-moderation-stable" - anyOf: - - type: string - - type: string - enum: ["text-moderation-latest", "text-moderation-stable"] - x-oaiTypeLabel: string + AssistantToolsFunction: + type: object + title: Function tool + properties: + type: + type: string + description: "The type of tool being defined: `function`" + enum: ["function"] + function: + $ref: "#/components/schemas/FunctionObject" required: - - input + - type + - function - CreateModerationResponse: + RunObject: type: object - description: Represents policy compliance report by OpenAI's content moderation model against a given input. + title: A run on a thread + description: Represents an execution run on a [thread](/docs/api-reference/threads). properties: id: + description: The identifier, which can be referenced in API endpoints. type: string - description: The unique identifier for the moderation request. + object: + description: The object type, which is always `thread.run`. + type: string + enum: ["thread.run"] + created_at: + description: The Unix timestamp (in seconds) for when the run was created. + type: integer + thread_id: + description: The ID of the [thread](/docs/api-reference/threads) that was executed on as a part of this run. + type: string + assistant_id: + description: The ID of the [assistant](/docs/api-reference/assistants) used for execution of this run. + type: string + status: + description: The status of the run, which can be either `queued`, `in_progress`, `requires_action`, `cancelling`, `cancelled`, `failed`, `completed`, or `expired`. + type: string + enum: + [ + "queued", + "in_progress", + "requires_action", + "cancelling", + "cancelled", + "failed", + "completed", + "expired", + ] + required_action: + type: object + description: Details on the action required to continue the run. Will be `null` if no action is required. + nullable: true + properties: + type: + description: For now, this is always `submit_tool_outputs`. + type: string + enum: ["submit_tool_outputs"] + submit_tool_outputs: + type: object + description: Details on the tool outputs needed for this run to continue. + properties: + tool_calls: + type: array + description: A list of the relevant tool calls. + items: + $ref: "#/components/schemas/RunToolCallObject" + required: + - tool_calls + required: + - type + - submit_tool_outputs + last_error: + type: object + description: The last error associated with this run. Will be `null` if there are no errors. + nullable: true + properties: + code: + type: string + description: One of `server_error` or `rate_limit_exceeded`. + enum: ["server_error", "rate_limit_exceeded"] + message: + type: string + description: A human-readable description of the error. + required: + - code + - message + expires_at: + description: The Unix timestamp (in seconds) for when the run will expire. + type: integer + started_at: + description: The Unix timestamp (in seconds) for when the run was started. + type: integer + nullable: true + cancelled_at: + description: The Unix timestamp (in seconds) for when the run was cancelled. + type: integer + nullable: true + failed_at: + description: The Unix timestamp (in seconds) for when the run failed. + type: integer + nullable: true + completed_at: + description: The Unix timestamp (in seconds) for when the run was completed. + type: integer + nullable: true model: + description: The model that the [assistant](/docs/api-reference/assistants) used for this run. type: string - description: The model used to generate the moderation results. - results: + instructions: + description: The instructions that the [assistant](/docs/api-reference/assistants) used for this run. + type: string + tools: + description: The list of tools that the [assistant](/docs/api-reference/assistants) used for this run. + default: [] type: array - description: A list of moderation objects. + maxItems: 20 items: - type: object - properties: - flagged: - type: boolean - description: Whether the content violates [OpenAI's usage policies](/policies/usage-policies). - categories: - type: object - description: A list of the categories, and whether they are flagged or not. - properties: - hate: - type: boolean - description: Content that expresses, incites, or promotes hate based on race, gender, ethnicity, religion, nationality, sexual orientation, disability status, or caste. Hateful content aimed at non-protected groups (e.g., chess players) is harrassment. - hate/threatening: - type: boolean - description: Hateful content that also includes violence or serious harm towards the targeted group based on race, gender, ethnicity, religion, nationality, sexual orientation, disability status, or caste. - harassment: - type: boolean - description: Content that expresses, incites, or promotes harassing language towards any target. - harassment/threatening: - type: boolean - description: Harassment content that also includes violence or serious harm towards any target. - self-harm: - type: boolean - description: Content that promotes, encourages, or depicts acts of self-harm, such as suicide, cutting, and eating disorders. - self-harm/intent: - type: boolean - description: Content where the speaker expresses that they are engaging or intend to engage in acts of self-harm, such as suicide, cutting, and eating disorders. - self-harm/instructions: - type: boolean - description: Content that encourages performing acts of self-harm, such as suicide, cutting, and eating disorders, or that gives instructions or advice on how to commit such acts. - sexual: - type: boolean - description: Content meant to arouse sexual excitement, such as the description of sexual activity, or that promotes sexual services (excluding sex education and wellness). - sexual/minors: - type: boolean - description: Sexual content that includes an individual who is under 18 years old. - violence: - type: boolean - description: Content that depicts death, violence, or physical injury. - violence/graphic: - type: boolean - description: Content that depicts death, violence, or physical injury in graphic detail. - required: - - hate - - hate/threatening - - harassment - - harassment/threatening - - self-harm - - self-harm/intent - - self-harm/instructions - - sexual - - sexual/minors - - violence - - violence/graphic - category_scores: - type: object - description: A list of the categories along with their scores as predicted by model. - properties: - hate: - type: number - description: The score for the category 'hate'. - hate/threatening: - type: number - description: The score for the category 'hate/threatening'. - harassment: - type: number - description: The score for the category 'harassment'. - harassment/threatening: - type: number - description: The score for the category 'harassment/threatening'. - self-harm: - type: number - description: The score for the category 'self-harm'. - self-harm/intent: - type: number - description: The score for the category 'self-harm/intent'. - self-harm/instructions: - type: number - description: The score for the category 'self-harm/instructions'. - sexual: - type: number - description: The score for the category 'sexual'. - sexual/minors: - type: number - description: The score for the category 'sexual/minors'. - violence: - type: number - description: The score for the category 'violence'. - violence/graphic: - type: number - description: The score for the category 'violence/graphic'. - required: - - hate - - hate/threatening - - harassment - - harassment/threatening - - self-harm - - self-harm/intent - - self-harm/instructions - - sexual - - sexual/minors - - violence - - violence/graphic - required: - - flagged - - categories - - category_scores + oneOf: + - $ref: "#/components/schemas/AssistantToolsCode" + - $ref: "#/components/schemas/AssistantToolsRetrieval" + - $ref: "#/components/schemas/AssistantToolsFunction" + x-oaiExpandable: true + file_ids: + description: The list of [File](/docs/api-reference/files) IDs the [assistant](/docs/api-reference/assistants) used for this run. + default: [] + type: array + items: + type: string + metadata: + description: *metadata_description + type: object + x-oaiTypeLabel: map + nullable: true + usage: + $ref: "#/components/schemas/RunCompletionUsage" + required: + - id + - object + - created_at + - thread_id + - assistant_id + - status + - required_action + - last_error + - expires_at + - started_at + - cancelled_at + - failed_at + - completed_at + - model + - instructions + - tools + - file_ids + - metadata + - usage + x-oaiMeta: + name: The run object + beta: true + example: | + { + "id": "run_abc123", + "object": "thread.run", + "created_at": 1698107661, + "assistant_id": "asst_abc123", + "thread_id": "thread_abc123", + "status": "completed", + "started_at": 1699073476, + "expires_at": null, + "cancelled_at": null, + "failed_at": null, + "completed_at": 1699073498, + "last_error": null, + "model": "gpt-4", + "instructions": null, + "tools": [{"type": "retrieval"}, {"type": "code_interpreter"}], + "file_ids": [], + "metadata": {}, + "usage": { + "prompt_tokens": 123, + "completion_tokens": 456, + "total_tokens": 579 + } + } + CreateRunRequest: + type: object + additionalProperties: false + properties: + assistant_id: + description: The ID of the [assistant](/docs/api-reference/assistants) to use to execute this run. + type: string + model: + description: The ID of the [Model](/docs/api-reference/models) to be used to execute this run. If a value is provided here, it will override the model associated with the assistant. If not, the model associated with the assistant will be used. + type: string + nullable: true + instructions: + description: Overrides the [instructions](/docs/api-reference/assistants/createAssistant) of the assistant. This is useful for modifying the behavior on a per-run basis. + type: string + nullable: true + additional_instructions: + description: Appends additional instructions at the end of the instructions for the run. This is useful for modifying the behavior on a per-run basis without overriding other instructions. + type: string + nullable: true + tools: + description: Override the tools the assistant can use for this run. This is useful for modifying the behavior on a per-run basis. + nullable: true + type: array + maxItems: 20 + items: + oneOf: + - $ref: "#/components/schemas/AssistantToolsCode" + - $ref: "#/components/schemas/AssistantToolsRetrieval" + - $ref: "#/components/schemas/AssistantToolsFunction" + x-oaiExpandable: true + metadata: + description: *metadata_description + type: object + x-oaiTypeLabel: map + nullable: true required: - - id - - model - - results - x-oaiMeta: - name: The moderation object - example: *moderation_example - - ListFilesResponse: + - thread_id + - assistant_id + ListRunsResponse: type: object properties: object: type: string + example: "list" data: type: array items: - $ref: "#/components/schemas/OpenAIFile" + $ref: "#/components/schemas/RunObject" + first_id: + type: string + example: "run_abc123" + last_id: + type: string + example: "run_abc456" + has_more: + type: boolean + example: false required: - object - data - - CreateFileRequest: + - first_id + - last_id + - has_more + ModifyRunRequest: type: object additionalProperties: false properties: - file: - description: | - Name of the [JSON Lines](https://jsonlines.readthedocs.io/en/latest/) file to be uploaded. + metadata: + description: *metadata_description + type: object + x-oaiTypeLabel: map + nullable: true + SubmitToolOutputsRunRequest: + type: object + additionalProperties: false + properties: + tool_outputs: + description: A list of tools for which the outputs are being submitted. + type: array + items: + type: object + properties: + tool_call_id: + type: string + description: The ID of the tool call in the `required_action` object within the run object the output is being submitted for. + output: + type: string + description: The output of the tool call to be submitted to continue the run. + required: + - tool_outputs - If the `purpose` is set to "fine-tune", the file will be used for fine-tuning. + RunToolCallObject: + type: object + description: Tool call objects + properties: + id: type: string - format: binary - purpose: - description: | - The intended purpose of the uploaded documents. + description: The ID of the tool call. This ID must be referenced when you submit the tool outputs in using the [Submit tool outputs to run](/docs/api-reference/runs/submitToolOutputs) endpoint. + type: + type: string + description: The type of tool call the output is required for. For now, this is always `function`. + enum: ["function"] + function: + type: object + description: The function definition. + properties: + name: + type: string + description: The name of the function. + arguments: + type: string + description: The arguments that the model expects you to pass to the function. + required: + - name + - arguments + required: + - id + - type + - function - Use "fine-tune" for [fine-tuning](/docs/api-reference/fine-tuning). This allows us to validate the format of the uploaded file. + CreateThreadAndRunRequest: + type: object + additionalProperties: false + properties: + assistant_id: + description: The ID of the [assistant](/docs/api-reference/assistants) to use to execute this run. type: string + thread: + $ref: "#/components/schemas/CreateThreadRequest" + description: If no thread is provided, an empty thread will be created. + model: + description: The ID of the [Model](/docs/api-reference/models) to be used to execute this run. If a value is provided here, it will override the model associated with the assistant. If not, the model associated with the assistant will be used. + type: string + nullable: true + instructions: + description: Override the default system message of the assistant. This is useful for modifying the behavior on a per-run basis. + type: string + nullable: true + tools: + description: Override the tools the assistant can use for this run. This is useful for modifying the behavior on a per-run basis. + nullable: true + type: array + maxItems: 20 + items: + oneOf: + - $ref: "#/components/schemas/AssistantToolsCode" + - $ref: "#/components/schemas/AssistantToolsRetrieval" + - $ref: "#/components/schemas/AssistantToolsFunction" + metadata: + description: *metadata_description + type: object + x-oaiTypeLabel: map + nullable: true required: - - file - - purpose + - thread_id + - assistant_id - DeleteFileResponse: + ThreadObject: type: object + title: Thread + description: Represents a thread that contains [messages](/docs/api-reference/messages). properties: id: + description: The identifier, which can be referenced in API endpoints. type: string object: + description: The object type, which is always `thread`. type: string - deleted: - type: boolean + enum: ["thread"] + created_at: + description: The Unix timestamp (in seconds) for when the thread was created. + type: integer + metadata: + description: *metadata_description + type: object + x-oaiTypeLabel: map + nullable: true required: - id - object - - deleted + - created_at + - metadata + x-oaiMeta: + name: The thread object + beta: true + example: | + { + "id": "thread_abc123", + "object": "thread", + "created_at": 1698107661, + "metadata": {} + } - CreateFineTuningJobRequest: + CreateThreadRequest: type: object + additionalProperties: false properties: - training_file: - description: | - The ID of an uploaded file that contains training data. - - See [upload file](/docs/api-reference/files/upload) for how to upload a file. - - Your dataset must be formatted as a JSONL file. Additionally, you must upload your file with the purpose `fine-tune`. - - See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. - type: string - example: "file-abc123" - validation_file: - description: | - The ID of an uploaded file that contains validation data. - - If you provide this file, the data is used to generate validation - metrics periodically during fine-tuning. These metrics can be viewed in - the fine-tuning results file. - The same data should not be present in both train and validation files. - - Your dataset must be formatted as a JSONL file. You must upload your file with the purpose `fine-tune`. - - See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. - type: string + messages: + description: A list of [messages](/docs/api-reference/messages) to start the thread with. + type: array + items: + $ref: "#/components/schemas/CreateMessageRequest" + metadata: + description: *metadata_description + type: object + x-oaiTypeLabel: map nullable: true - example: "file-abc123" - model: - description: | - The name of the model to fine-tune. You can select one of the - [supported models](/docs/guides/fine-tuning/what-models-can-be-fine-tuned). - example: "gpt-3.5-turbo" - anyOf: - - type: string - - type: string - enum: ["babbage-002", "davinci-002", "gpt-3.5-turbo"] - x-oaiTypeLabel: string - hyperparameters: + + ModifyThreadRequest: + type: object + additionalProperties: false + properties: + metadata: + description: *metadata_description type: object - description: The hyperparameters used for the fine-tuning job. - properties: - n_epochs: - description: | - The number of epochs to train the model for. An epoch refers to one - full cycle through the training dataset. - oneOf: - - type: string - enum: [auto] - - type: integer - minimum: 1 - maximum: 50 - default: auto - suffix: - description: | - A string of up to 18 characters that will be added to your fine-tuned model name. + x-oaiTypeLabel: map + nullable: true - For example, a `suffix` of "custom-model-name" would produce a model name like `ft:gpt-3.5-turbo:openai:custom-model-name:7p4lURel`. + DeleteThreadResponse: + type: object + properties: + id: type: string - minLength: 1 - maxLength: 40 - default: null - nullable: true + deleted: + type: boolean + object: + type: string + enum: [thread.deleted] required: - - training_file - - model + - id + - object + - deleted - ListFineTuningJobEventsResponse: - type: object + ListThreadsResponse: properties: object: type: string + example: "list" data: type: array items: - $ref: "#/components/schemas/FineTuningJobEvent" + $ref: "#/components/schemas/ThreadObject" + first_id: + type: string + example: "asst_abc123" + last_id: + type: string + example: "asst_abc456" + has_more: + type: boolean + example: false required: - object - data + - first_id + - last_id + - has_more - CreateFineTuneRequest: + MessageObject: type: object + title: The message object + description: Represents a message within a [thread](/docs/api-reference/threads). properties: - training_file: - description: | - The ID of an uploaded file that contains training data. - - See [upload file](/docs/api-reference/files/upload) for how to upload a file. - - Your dataset must be formatted as a JSONL file, where each training - example is a JSON object with the keys "prompt" and "completion". - Additionally, you must upload your file with the purpose `fine-tune`. - - See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more details. + id: + description: The identifier, which can be referenced in API endpoints. type: string - example: "file-abc123" - validation_file: - description: | - The ID of an uploaded file that contains validation data. - - If you provide this file, the data is used to generate validation - metrics periodically during fine-tuning. These metrics can be viewed in - the [fine-tuning results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model). - Your train and validation data should be mutually exclusive. - - Your dataset must be formatted as a JSONL file, where each validation - example is a JSON object with the keys "prompt" and "completion". - Additionally, you must upload your file with the purpose `fine-tune`. - - See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more details. + object: + description: The object type, which is always `thread.message`. type: string - nullable: true - example: "file-abc123" - model: - description: | - The name of the base model to fine-tune. You can select one of "ada", - "babbage", "curie", "davinci", or a fine-tuned model created after 2022-04-21 and before 2023-08-22. - To learn more about these models, see the - [Models](/docs/models) documentation. - default: "curie" - example: "curie" - nullable: true - anyOf: - - type: string - - type: string - enum: ["ada", "babbage", "curie", "davinci"] - x-oaiTypeLabel: string - n_epochs: - description: | - The number of epochs to train the model for. An epoch refers to one - full cycle through the training dataset. - default: 4 - type: integer - nullable: true - batch_size: - description: | - The batch size to use for training. The batch size is the number of - training examples used to train a single forward and backward pass. - - By default, the batch size will be dynamically configured to be - ~0.2% of the number of examples in the training set, capped at 256 - - in general, we've found that larger batch sizes tend to work better - for larger datasets. - default: null - type: integer - nullable: true - learning_rate_multiplier: - description: | - The learning rate multiplier to use for training. - The fine-tuning learning rate is the original learning rate used for - pretraining multiplied by this value. - - By default, the learning rate multiplier is the 0.05, 0.1, or 0.2 - depending on final `batch_size` (larger learning rates tend to - perform better with larger batch sizes). We recommend experimenting - with values in the range 0.02 to 0.2 to see what produces the best - results. - default: null - type: number - nullable: true - prompt_loss_weight: - description: | - The weight to use for loss on the prompt tokens. This controls how - much the model tries to learn to generate the prompt (as compared - to the completion which always has a weight of 1.0), and can add - a stabilizing effect to training when completions are short. - - If prompts are extremely long (relative to completions), it may make - sense to reduce this weight so as to avoid over-prioritizing - learning the prompt. - default: 0.01 - type: number - nullable: true - compute_classification_metrics: - description: | - If set, we calculate classification-specific metrics such as accuracy - and F-1 score using the validation set at the end of every epoch. - These metrics can be viewed in the [results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model). - - In order to compute classification metrics, you must provide a - `validation_file`. Additionally, you must - specify `classification_n_classes` for multiclass classification or - `classification_positive_class` for binary classification. - type: boolean - default: false - nullable: true - classification_n_classes: - description: | - The number of classes in a classification task. - - This parameter is required for multiclass classification. + enum: ["thread.message"] + created_at: + description: The Unix timestamp (in seconds) for when the message was created. type: integer - default: null - nullable: true - classification_positive_class: - description: | - The positive class in binary classification. - - This parameter is needed to generate precision, recall, and F1 - metrics when doing binary classification. + thread_id: + description: The [thread](/docs/api-reference/threads) ID that this message belongs to. type: string - default: null - nullable: true - classification_betas: - description: | - If this is provided, we calculate F-beta scores at the specified - beta values. The F-beta score is a generalization of F-1 score. - This is only used for binary classification. - - With a beta of 1 (i.e. the F-1 score), precision and recall are - given the same weight. A larger beta score puts more weight on - recall and less on precision. A smaller beta score puts more weight - on precision and less on recall. + role: + description: The entity that produced the message. One of `user` or `assistant`. + type: string + enum: ["user", "assistant"] + content: + description: The content of the message in array of text and/or images. type: array items: - type: number - example: [0.6, 1, 1.5, 2] - default: null - nullable: true - suffix: - description: | - A string of up to 40 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 `ada:ft-your-org:custom-model-name-2022-02-15-04-21-04`. - type: string - minLength: 1 - maxLength: 40 - default: null + oneOf: + - $ref: "#/components/schemas/MessageContentImageFileObject" + - $ref: "#/components/schemas/MessageContentTextObject" + x-oaiExpandable: true + assistant_id: + description: If applicable, the ID of the [assistant](/docs/api-reference/assistants) that authored this message. + type: string nullable: true - required: - - training_file - - ListFineTunesResponse: - type: object - properties: - object: + run_id: + description: If applicable, the ID of the [run](/docs/api-reference/runs) associated with the authoring of this message. type: string - data: + nullable: true + file_ids: + description: A list of [file](/docs/api-reference/files) IDs that the assistant should use. Useful for tools like retrieval and code_interpreter that can access files. A maximum of 10 files can be attached to a message. + default: [] + maxItems: 10 type: array items: - $ref: "#/components/schemas/FineTune" + type: string + metadata: + description: *metadata_description + type: object + x-oaiTypeLabel: map + nullable: true required: + - id - object - - data + - created_at + - thread_id + - role + - content + - assistant_id + - run_id + - file_ids + - metadata + x-oaiMeta: + name: The message object + beta: true + example: | + { + "id": "msg_abc123", + "object": "thread.message", + "created_at": 1698983503, + "thread_id": "thread_abc123", + "role": "assistant", + "content": [ + { + "type": "text", + "text": { + "value": "Hi! How can I help you today?", + "annotations": [] + } + } + ], + "file_ids": [], + "assistant_id": "asst_abc123", + "run_id": "run_abc123", + "metadata": {} + } - ListFineTuneEventsResponse: + CreateMessageRequest: type: object + additionalProperties: false + required: + - role + - content properties: - object: + role: type: string - data: + enum: ["user"] + description: The role of the entity that is creating the message. Currently only `user` is supported. + content: + type: string + minLength: 1 + maxLength: 32768 + description: The content of the message. + file_ids: + description: A list of [File](/docs/api-reference/files) IDs that the message should use. There can be a maximum of 10 files attached to a message. Useful for tools like `retrieval` and `code_interpreter` that can access and use files. + default: [] type: array + minItems: 1 + maxItems: 10 items: - $ref: "#/components/schemas/FineTuneEvent" - required: - - object - - data + type: string + metadata: + description: *metadata_description + type: object + x-oaiTypeLabel: map + nullable: true - CreateEmbeddingRequest: + ModifyMessageRequest: type: object additionalProperties: false properties: - model: - description: *model_description - example: "text-embedding-ada-002" - anyOf: - - type: string - - type: string - enum: ["text-embedding-ada-002"] - x-oaiTypeLabel: string - input: - description: | - Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a single request, pass an array of strings or array of token arrays. Each input must not exceed the max input tokens for the model (8191 tokens for `text-embedding-ada-002`) and cannot be an empty string. [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) for counting tokens. - example: "The quick brown fox jumped over the lazy dog" - oneOf: - - type: string - default: "" - example: "This is a test." - - type: array - items: - type: string - default: "" - example: "This is a test." - - type: array - minItems: 1 - items: - type: integer - example: "[1212, 318, 257, 1332, 13]" - - type: array - minItems: 1 - items: - type: array - minItems: 1 - items: - type: integer - example: "[[1212, 318, 257, 1332, 13]]" - user: *end_user_param_configuration - required: - - model - - input + metadata: + description: *metadata_description + type: object + x-oaiTypeLabel: map + nullable: true - CreateEmbeddingResponse: + DeleteMessageResponse: type: object properties: + id: + type: string + deleted: + type: boolean object: type: string - description: The object type, which is always "embedding". - model: + enum: [thread.message.deleted] + required: + - id + - object + - deleted + + ListMessagesResponse: + properties: + object: type: string - description: The name of the model used to generate the embedding. + example: "list" data: type: array - description: The list of embeddings generated by the model. items: - $ref: "#/components/schemas/Embedding" - usage: - type: object - description: The usage information for the request. - properties: - prompt_tokens: - type: integer - description: The number of tokens used by the prompt. - total_tokens: - type: integer - description: The total number of tokens used by the request. - required: - - prompt_tokens - - total_tokens + $ref: "#/components/schemas/MessageObject" + first_id: + type: string + example: "msg_abc123" + last_id: + type: string + example: "msg_abc123" + has_more: + type: boolean + example: false required: - object - - model - data - - usage + - first_id + - last_id + - has_more - CreateTranscriptionRequest: + MessageContentImageFileObject: + title: Image file type: object - additionalProperties: false + description: References an image [File](/docs/api-reference/files) in the content of a message. properties: - file: - description: | - The audio file object (not file name) to transcribe, in one of these formats: flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm. - type: string - x-oaiTypeLabel: file - format: binary - model: - description: | - ID of the model to use. Only `whisper-1` is currently available. - example: whisper-1 - anyOf: - - type: string - - type: string - enum: ["whisper-1"] - x-oaiTypeLabel: string - prompt: - description: | - An optional text to guide the model's style or continue a previous audio segment. The [prompt](/docs/guides/speech-to-text/prompting) should match the audio language. - type: string - response_format: - description: | - The format of the transcript output, in one of these options: json, text, srt, verbose_json, or vtt. - type: string - enum: - - json - - text - - srt - - verbose_json - - vtt - default: json - temperature: - description: | - The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to automatically increase the temperature until certain thresholds are hit. - type: number - default: 0 - language: - description: | - The language of the input audio. Supplying the input language in [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) format will improve accuracy and latency. + type: + description: Always `image_file`. type: string + enum: ["image_file"] + image_file: + type: object + properties: + file_id: + description: The [File](/docs/api-reference/files) ID of the image in the message content. + type: string + required: + - file_id required: - - file - - model + - type + - image_file - # Note: This does not currently support the non-default response format types. - CreateTranscriptionResponse: + MessageContentTextObject: + title: Text type: object + description: The text content that is part of a message. properties: - text: + type: + description: Always `text`. type: string + enum: ["text"] + text: + type: object + properties: + value: + description: The data that makes up the text. + type: string + annotations: + type: array + items: + oneOf: + - $ref: "#/components/schemas/MessageContentTextAnnotationsFileCitationObject" + - $ref: "#/components/schemas/MessageContentTextAnnotationsFilePathObject" + x-oaiExpandable: true + required: + - value + - annotations required: + - type - text - CreateTranslationRequest: + MessageContentTextAnnotationsFileCitationObject: + title: File citation type: object - additionalProperties: false + description: A citation within the message that points to a specific quote from a specific File associated with the assistant or the message. Generated when the assistant uses the "retrieval" tool to search files. properties: - file: - description: | - The audio file object (not file name) translate, in one of these formats: flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm. - type: string - x-oaiTypeLabel: file - format: binary - model: - description: | - ID of the model to use. Only `whisper-1` is currently available. - example: whisper-1 - anyOf: - - type: string - - type: string - enum: ["whisper-1"] - x-oaiTypeLabel: string - prompt: - description: | - An optional text to guide the model's style or continue a previous audio segment. The [prompt](/docs/guides/speech-to-text/prompting) should be in English. - type: string - response_format: - description: | - The format of the transcript output, in one of these options: json, text, srt, verbose_json, or vtt. + type: + description: Always `file_citation`. type: string - default: json - temperature: - description: | - The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to automatically increase the temperature until certain thresholds are hit. - type: number - default: 0 - required: - - file - - model - - # Note: This does not currently support the non-default response format types. - CreateTranslationResponse: - type: object - properties: + enum: ["file_citation"] text: + description: The text in the message content that needs to be replaced. type: string + file_citation: + type: object + properties: + file_id: + description: The ID of the specific File the citation is from. + type: string + quote: + description: The specific quote in the file. + type: string + required: + - file_id + - quote + start_index: + type: integer + minimum: 0 + end_index: + type: integer + minimum: 0 required: + - type - text + - file_citation + - start_index + - end_index - Model: - title: Model - description: Describes an OpenAI model offering that can be used with the API. + MessageContentTextAnnotationsFilePathObject: + title: File path + type: object + description: A URL for the file that's generated when the assistant used the `code_interpreter` tool to generate a file. properties: - id: + type: + description: Always `file_path`. type: string - description: The model identifier, which can be referenced in the API endpoints. - object: + enum: ["file_path"] + text: + description: The text in the message content that needs to be replaced. type: string - description: The object type, which is always "model". - created: + file_path: + type: object + properties: + file_id: + description: The ID of the file that was generated. + type: string + required: + - file_id + start_index: type: integer - description: The Unix timestamp (in seconds) when the model was created. - owned_by: - type: string - description: The organization that owns the model. - required: - - id - - object - - created - - owned_by - x-oaiMeta: - name: The model object - example: *retrieve_model_response + minimum: 0 + end_index: + type: integer + minimum: 0 + required: + - type + - text + - file_path + - start_index + - end_index - OpenAIFile: - title: OpenAIFile + RunStepObject: + type: object + title: Run steps description: | - The `File` object represents a document that has been uploaded to OpenAI. + Represents a step in execution of a run. properties: id: + description: The identifier of the run step, which can be referenced in API endpoints. type: string - description: The file identifier, which can be referenced in the API endpoints. object: + description: The object type, which is always `thread.run.step`. type: string - description: The object type, which is always "file". - bytes: - type: integer - description: The size of the file in bytes. + enum: ["thread.run.step"] created_at: + description: The Unix timestamp (in seconds) for when the run step was created. type: integer - description: The Unix timestamp (in seconds) for when the file was created. - filename: + assistant_id: + description: The ID of the [assistant](/docs/api-reference/assistants) associated with the run step. type: string - description: The name of the file. - purpose: + thread_id: + description: The ID of the [thread](/docs/api-reference/threads) that was run. type: string - description: The intended purpose of the file. Currently, only "fine-tune" is supported. - status: + run_id: + description: The ID of the [run](/docs/api-reference/runs) that this run step is a part of. type: string - description: The current status of the file, which can be either `uploaded`, `processed`, `pending`, `error`, `deleting` or `deleted`. - status_details: + type: + description: The type of run step, which can be either `message_creation` or `tool_calls`. type: string + enum: ["message_creation", "tool_calls"] + status: + description: The status of the run step, which can be either `in_progress`, `cancelled`, `failed`, `completed`, or `expired`. + type: string + enum: ["in_progress", "cancelled", "failed", "completed", "expired"] + step_details: + type: object + description: The details of the run step. + oneOf: + - $ref: "#/components/schemas/RunStepDetailsMessageCreationObject" + - $ref: "#/components/schemas/RunStepDetailsToolCallsObject" + x-oaiExpandable: true + last_error: + type: object + description: The last error associated with this run step. Will be `null` if there are no errors. nullable: true - description: | - Additional details about the status of the file. If the file is in the `error` state, this will include a message describing the error. + properties: + code: + type: string + description: One of `server_error` or `rate_limit_exceeded`. + enum: ["server_error", "rate_limit_exceeded"] + message: + type: string + description: A human-readable description of the error. + required: + - code + - message + expired_at: + description: The Unix timestamp (in seconds) for when the run step expired. A step is considered expired if the parent run is expired. + type: integer + nullable: true + cancelled_at: + description: The Unix timestamp (in seconds) for when the run step was cancelled. + type: integer + nullable: true + failed_at: + description: The Unix timestamp (in seconds) for when the run step failed. + type: integer + nullable: true + completed_at: + description: The Unix timestamp (in seconds) for when the run step completed. + type: integer + nullable: true + metadata: + description: *metadata_description + type: object + x-oaiTypeLabel: map + nullable: true + usage: + $ref: "#/components/schemas/RunStepCompletionUsage" required: - id - object - - bytes - created_at - - filename - - purpose - - format + - assistant_id + - thread_id + - run_id + - type + - status + - step_details + - last_error + - expired_at + - cancelled_at + - failed_at + - completed_at + - metadata + - usage x-oaiMeta: - name: The file object - example: | - { - "id": "file-abc123", - "object": "file", - "bytes": 120000, - "created_at": 1677610602, - "filename": "my_file.jsonl", - "purpose": "fine-tune", - "status": "uploaded", - "status_details": null - } - Embedding: - type: object - description: | - Represents an embedding vector returned by embedding endpoint. + name: The run step object + beta: true + example: *run_step_object_example + + ListRunStepsResponse: properties: - index: - type: integer - description: The index of the embedding in the list of embeddings. object: type: string - description: The object type, which is always "embedding". - embedding: + example: "list" + data: type: array - description: | - The embedding vector, which is a list of floats. The length of vector depends on the model as listed in the [embedding guide](/docs/guides/embeddings). items: - type: number + $ref: "#/components/schemas/RunStepObject" + first_id: + type: string + example: "step_abc123" + last_id: + type: string + example: "step_abc456" + has_more: + type: boolean + example: false required: - - index - object - - embedding - x-oaiMeta: - name: The embedding object - example: | - { - "object": "embedding", - "embedding": [ - 0.0023064255, - -0.009327292, - .... (1536 floats total for ada-002) - -0.0028842222, - ], - "index": 0 - } + - data + - first_id + - last_id + - has_more - FineTuningJob: - title: FineTuningJob - description: | - The `fine_tuning.job` object represents a fine-tuning job that has been created through the API. + RunStepDetailsMessageCreationObject: + title: Message creation + type: object + description: Details of the message creation by the run step. properties: - id: + type: + description: Always `message_creation`. type: string - description: The object identifier, which can be referenced in the API endpoints. - object: + enum: ["message_creation"] + message_creation: + type: object + properties: + message_id: + type: string + description: The ID of the message that was created by this run step. + required: + - message_id + required: + - type + - message_creation + + RunStepDetailsToolCallsObject: + title: Tool calls + type: object + description: Details of the tool call. + properties: + type: + description: Always `tool_calls`. type: string - description: The object type, which is always "fine_tuning.job". - created_at: - type: integer - description: The Unix timestamp (in seconds) for when the fine-tuning job was created. - finished_at: - type: integer - nullable: true - description: The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be null if the fine-tuning job is still running. - model: + enum: ["tool_calls"] + tool_calls: + type: array + description: | + An array of tool calls the run step was involved in. These can be associated with one of three types of tools: `code_interpreter`, `retrieval`, or `function`. + items: + oneOf: + - $ref: "#/components/schemas/RunStepDetailsToolCallsCodeObject" + - $ref: "#/components/schemas/RunStepDetailsToolCallsRetrievalObject" + - $ref: "#/components/schemas/RunStepDetailsToolCallsFunctionObject" + x-oaiExpandable: true + required: + - type + - tool_calls + + RunStepDetailsToolCallsCodeObject: + title: Code interpreter tool call + type: object + description: Details of the Code Interpreter tool call the run step was involved in. + properties: + id: type: string - description: The base model that is being fine-tuned. - fine_tuned_model: + description: The ID of the tool call. + type: type: string - nullable: true - description: The name of the fine-tuned model that is being created. The value will be null if the fine-tuning job is still running. - organization_id: + description: The type of tool call. This is always going to be `code_interpreter` for this type of tool call. + enum: ["code_interpreter"] + code_interpreter: + type: object + description: The Code Interpreter tool call definition. + required: + - input + - outputs + properties: + input: + type: string + description: The input to the Code Interpreter tool call. + outputs: + type: array + description: The outputs from the Code Interpreter tool call. Code Interpreter can output one or more items, including text (`logs`) or images (`image`). Each of these are represented by a different object type. + items: + type: object + oneOf: + - $ref: "#/components/schemas/RunStepDetailsToolCallsCodeOutputLogsObject" + - $ref: "#/components/schemas/RunStepDetailsToolCallsCodeOutputImageObject" + x-oaiExpandable: true + required: + - id + - type + - code_interpreter + + RunStepDetailsToolCallsCodeOutputLogsObject: + title: Code interpreter log output + type: object + description: Text output from the Code Interpreter tool call as part of a run step. + properties: + type: + description: Always `logs`. type: string - description: The organization that owns the fine-tuning job. - status: + enum: ["logs"] + logs: type: string - description: The current status of the fine-tuning job, which can be either `validating_files`, `queued`, `running`, `succeeded`, `failed`, or `cancelled`. - hyperparameters: + description: The text output from the Code Interpreter tool call. + required: + - type + - logs + + RunStepDetailsToolCallsCodeOutputImageObject: + title: Code interpreter image output + type: object + properties: + type: + description: Always `image`. + type: string + enum: ["image"] + image: type: object - description: The hyperparameters used for the fine-tuning job. See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. properties: - n_epochs: - oneOf: - - type: string - enum: [auto] - - type: integer - minimum: 1 - maximum: 50 - default: auto - description: - The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset. - - "auto" decides the optimal number of epochs based on the size of the dataset. If setting the number manually, we support any number between 1 and 50 epochs. + file_id: + description: The [file](/docs/api-reference/files) ID of the image. + type: string required: - - n_epochs - training_file: + - file_id + required: + - type + - image + + RunStepDetailsToolCallsRetrievalObject: + title: Retrieval tool call + type: object + properties: + id: type: string - description: The file ID used for training. You can retrieve the training data with the [Files API](/docs/api-reference/files/retrieve-contents). - validation_file: + description: The ID of the tool call object. + type: type: string - nullable: true - description: The file ID used for validation. You can retrieve the validation results with the [Files API](/docs/api-reference/files/retrieve-contents). - result_files: - type: array - description: The compiled results file ID(s) for the fine-tuning job. You can retrieve the results with the [Files API](/docs/api-reference/files/retrieve-contents). - items: - type: string - example: file-abc123 - trained_tokens: - type: integer - nullable: true - description: The total number of billable tokens processed by this fine-tuning job. The value will be null if the fine-tuning job is still running. - error: + description: The type of tool call. This is always going to be `retrieval` for this type of tool call. + enum: ["retrieval"] + retrieval: type: object - nullable: true - description: For fine-tuning jobs that have `failed`, this will contain more information on the cause of the failure. + description: For now, this is always going to be an empty object. + x-oaiTypeLabel: map + required: + - id + - type + - retrieval + + RunStepDetailsToolCallsFunctionObject: + type: object + title: Function tool call + properties: + id: + type: string + description: The ID of the tool call object. + type: + type: string + description: The type of tool call. This is always going to be `function` for this type of tool call. + enum: ["function"] + function: + type: object + description: The definition of the function that was called. properties: - message: + name: type: string - description: A human-readable error message. - code: + description: The name of the function. + arguments: type: string - description: A machine-readable error code. - param: + description: The arguments passed to the function. + output: type: string - description: The parameter that was invalid, usually `training_file` or `validation_file`. This field will be null if the failure was not parameter-specific. + description: The output of the function. This will be `null` if the outputs have not been [submitted](/docs/api-reference/runs/submitToolOutputs) yet. nullable: true required: - - message - - code - - param + - name + - arguments + - output required: - id - - object - - created_at - - finished_at - - model - - fine_tuned_model - - organization_id - - status - - hyperparameters - - training_file - - validation_file - - result_files - - trained_tokens - - error - x-oaiMeta: - name: The fine-tuning job object - example: *fine_tuning_example + - type + - function - FineTuningEvent: - title: FineTuningEvent + AssistantFileObject: + type: object + title: Assistant files + description: A list of [Files](/docs/api-reference/files) attached to an `assistant`. properties: + id: + description: The identifier, which can be referenced in API endpoints. + type: string object: + description: The object type, which is always `assistant.file`. type: string + enum: [assistant.file] created_at: + description: The Unix timestamp (in seconds) for when the assistant file was created. type: integer - level: - type: string - message: + assistant_id: + description: The assistant ID that the file is attached to. type: string - data: - oneOf: - - type: string - default: none - enum: [none, string] - type: - oneOf: - - type: string - default: none - enum: ["message", "metrics"] required: + - id - object - - created_at - - level - - message - x-oiMeta: - name: The fine-tuning event object + - created_at + - assistant_id + x-oaiMeta: + name: The assistant file object + beta: true example: | { - "object": "fine_tuning.job.event", - "created_at": "1689376978", - "level": "info" | "warn" | "error", - "message": "", - "data": null | JSON, - "type": "message"| "metrics" + "id": "file-abc123", + "object": "assistant.file", + "created_at": 1699055364, + "assistant_id": "asst_abc123" } - FineTune: - title: FineTune - deprecated: true - description: | - The `FineTune` object represents a legacy fine-tune job that has been created through the API. + CreateAssistantFileRequest: + type: object + additionalProperties: false + properties: + file_id: + description: A [File](/docs/api-reference/files) ID (with `purpose="assistants"`) that the assistant should use. Useful for tools like `retrieval` and `code_interpreter` that can access files. + type: string + required: + - file_id + + DeleteAssistantFileResponse: + type: object + description: Deletes the association between the assistant and the file, but does not delete the [File](/docs/api-reference/files) object itself. properties: id: type: string - description: The object identifier, which can be referenced in the API endpoints. + deleted: + type: boolean object: type: string - description: The object type, which is always "fine-tune". - created_at: - type: integer - description: The Unix timestamp (in seconds) for when the fine-tuning job was created. - updated_at: - type: integer - description: The Unix timestamp (in seconds) for when the fine-tuning job was last updated. - model: - type: string - description: The base model that is being fine-tuned. - fine_tuned_model: - type: string - nullable: true - description: The name of the fine-tuned model that is being created. - organization_id: - type: string - description: The organization that owns the fine-tuning job. - status: + enum: [assistant.file.deleted] + required: + - id + - object + - deleted + ListAssistantFilesResponse: + properties: + object: type: string - description: The current status of the fine-tuning job, which can be either `created`, `running`, `succeeded`, `failed`, or `cancelled`. - hyperparams: - type: object - description: The hyperparameters used for the fine-tuning job. See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/hyperparameters) for more details. - properties: - n_epochs: - type: integer - description: | - The number of epochs to train the model for. An epoch refers to one - full cycle through the training dataset. - batch_size: - type: integer - description: | - The batch size to use for training. The batch size is the number of - training examples used to train a single forward and backward pass. - prompt_loss_weight: - type: number - description: | - The weight to use for loss on the prompt tokens. - learning_rate_multiplier: - type: number - description: | - The learning rate multiplier to use for training. - compute_classification_metrics: - type: boolean - description: | - The classification metrics to compute using the validation dataset at the end of every epoch. - classification_positive_class: - type: string - description: | - The positive class to use for computing classification metrics. - classification_n_classes: - type: integer - description: | - The number of classes to use for computing classification metrics. - required: - - n_epochs - - batch_size - - prompt_loss_weight - - learning_rate_multiplier - training_files: - type: array - description: The list of files used for training. - items: - $ref: "#/components/schemas/OpenAIFile" - validation_files: - type: array - description: The list of files used for validation. - items: - $ref: "#/components/schemas/OpenAIFile" - result_files: - type: array - description: The compiled results files for the fine-tuning job. - items: - $ref: "#/components/schemas/OpenAIFile" - events: + example: "list" + data: type: array - description: The list of events that have been observed in the lifecycle of the FineTune job. items: - $ref: "#/components/schemas/FineTuneEvent" + $ref: "#/components/schemas/AssistantFileObject" + first_id: + type: string + example: "file-abc123" + last_id: + type: string + example: "file-abc456" + has_more: + type: boolean + example: false required: - - id - object - - created_at - - updated_at - - model - - fine_tuned_model - - organization_id - - status - - hyperparams - - training_files - - validation_files - - result_files - x-oaiMeta: - name: The fine-tune object - example: *fine_tune_example + - data + - items + - first_id + - last_id + - has_more - FineTuningJobEvent: - title: FineTuningJobEvent + MessageFileObject: + type: object + title: Message files + description: A list of files attached to a `message`. properties: id: + description: The identifier, which can be referenced in API endpoints. type: string object: + description: The object type, which is always `thread.message.file`. type: string + enum: ["thread.message.file"] created_at: + description: The Unix timestamp (in seconds) for when the message file was created. type: integer - level: - type: string - enum: ["info", "warn", "error"] - message: + message_id: + description: The ID of the [message](/docs/api-reference/messages) that the [File](/docs/api-reference/files) is attached to. type: string required: - id - object - created_at - - level - - message - x-oiMeta: - name: The fine-tuning job event object + - message_id + x-oaiMeta: + name: The message file object + beta: true example: | { - "object": "event", - "id": "ftevent-abc123" - "created_at": 1677610602, - "level": "info", - "message": "Created fine-tuning job" + "id": "file-abc123", + "object": "thread.message.file", + "created_at": 1698107661, + "message_id": "message_QLoItBbqwyAJEzlTy4y9kOMM", + "file_id": "file-abc123" } - FineTuneEvent: - title: FineTuneEvent + ListMessageFilesResponse: properties: object: type: string - created_at: - type: integer - level: + example: "list" + data: + type: array + items: + $ref: "#/components/schemas/MessageFileObject" + first_id: type: string - message: + example: "file-abc123" + last_id: type: string + example: "file-abc456" + has_more: + type: boolean + example: false required: - object - - created_at - - level - - message - x-oiMeta: - name: The fine-tune event object - example: | - { - "object": "event", - "created_at": 1677610602, - "level": "info", - "message": "Created fine-tune job" - } - CompletionUsage: - type: object - description: Usage statistics for the completion request. - properties: - prompt_tokens: - type: integer - description: Number of tokens in the prompt. - completion_tokens: - type: integer - description: Number of tokens in the generated completion. - total_tokens: - type: integer - description: Total number of tokens used in the request (prompt + completion). - required: - - prompt_tokens - - completion_tokens - - total_tokens + - data + - items + - first_id + - last_id + - has_more security: - ApiKeyAuth: [] - x-oaiMeta: groups: # > General Notes @@ -4193,10 +8697,13 @@ x-oaiMeta: - id: audio title: Audio description: | - Learn how to turn audio into text. + Learn how to turn audio into text or text into audio. Related guide: [Speech to text](/docs/guides/speech-to-text) sections: + - type: endpoint + key: createSpeech + path: createSpeech - type: endpoint key: createTranscription path: createTranscription @@ -4208,31 +8715,17 @@ x-oaiMeta: description: | Given a list of messages comprising a conversation, the model will return a response. - Related guide: [Chat completions](/docs/guides/gpt) + Related guide: [Chat Completions](/docs/guides/text-generation) sections: + - type: endpoint + key: createChatCompletion + path: create - type: object key: CreateChatCompletionResponse path: object - type: object key: CreateChatCompletionStreamResponse path: streaming - - type: endpoint - key: createChatCompletion - path: create - - id: completions - title: Completions - legacy: true - description: | - Given a prompt, the model will return one or more predicted completions, and can also return the probabilities of alternative tokens at each position. We recommend most users use our Chat completions API. [Learn more](/docs/deprecations/2023-07-06-gpt-and-embeddings) - - Related guide: [Legacy Completions](/docs/guides/gpt/completions-api) - sections: - - type: object - key: CreateCompletionResponse - path: object - - type: endpoint - key: createCompletion - path: create - id: embeddings title: Embeddings description: | @@ -4240,59 +8733,63 @@ x-oaiMeta: Related guide: [Embeddings](/docs/guides/embeddings) sections: - - type: object - key: Embedding - path: object - type: endpoint key: createEmbedding path: create + - type: object + key: Embedding + path: object - id: fine-tuning title: Fine-tuning description: | Manage fine-tuning jobs to tailor a model to your specific training data. - Related guide: [fine-tune models](/docs/guides/fine-tuning) + Related guide: [Fine-tune models](/docs/guides/fine-tuning) sections: - - type: object - path: object - key: FineTuningJob - type: endpoint key: createFineTuningJob path: create - type: endpoint key: listPaginatedFineTuningJobs + path: list + - type: endpoint + key: listFineTuningEvents + path: list-events - type: endpoint key: retrieveFineTuningJob path: retrieve - type: endpoint key: cancelFineTuningJob path: cancel - - type: endpoint - key: listFineTuningEvents - path: list-events + - type: object + key: FineTuningJob + path: object + - type: object + key: FineTuningJobEvent + path: event-object - id: files title: Files description: | - Files are used to upload documents that can be used with features like [fine-tuning](/docs/api-reference/fine-tuning). + Files are used to upload documents that can be used with features like [Assistants](/docs/api-reference/assistants) and [Fine-tuning](/docs/api-reference/fine-tuning). sections: - - type: object - key: OpenAIFile - path: object - - type: endpoint - key: listFiles - path: list - type: endpoint key: createFile path: create - type: endpoint - key: deleteFile - path: delete + key: listFiles + path: list - type: endpoint key: retrieveFile path: retrieve + - type: endpoint + key: deleteFile + path: delete - type: endpoint key: downloadFile path: retrieve-contents + - type: object + key: OpenAIFile + path: object - id: images title: Images description: | @@ -4300,9 +8797,6 @@ x-oaiMeta: Related guide: [Image generation](/docs/guides/images) sections: - - type: object - key: Image - path: object - type: endpoint key: createImage path: create @@ -4312,14 +8806,14 @@ x-oaiMeta: - type: endpoint key: createImageVariation path: createVariation + - type: object + key: Image + path: object - id: models title: Models description: | List and describe the various models available in the API. You can refer to the [Models](/docs/models) documentation to understand what models are available and the differences between them. sections: - - type: object - key: Model - path: object - type: endpoint key: listModels path: list @@ -4329,6 +8823,9 @@ x-oaiMeta: - type: endpoint key: deleteModel path: delete + - type: object + key: Model + path: object - id: moderations title: Moderations description: | @@ -4336,47 +8833,158 @@ x-oaiMeta: Related guide: [Moderations](/docs/guides/moderation) sections: + - type: endpoint + key: createModeration + path: create - type: object key: CreateModerationResponse path: object + - id: assistants + title: Assistants + beta: true + description: | + Build assistants that can call models and use tools to perform tasks. + + [Get started with the Assistants API](/docs/assistants) + sections: - type: endpoint - key: createModeration - path: create - - id: fine-tunes - title: Fine-tunes - deprecated: true + key: createAssistant + path: createAssistant + - type: endpoint + key: createAssistantFile + path: createAssistantFile + - type: endpoint + key: listAssistants + path: listAssistants + - type: endpoint + key: listAssistantFiles + path: listAssistantFiles + - type: endpoint + key: getAssistant + path: getAssistant + - type: endpoint + key: getAssistantFile + path: getAssistantFile + - type: endpoint + key: modifyAssistant + path: modifyAssistant + - type: endpoint + key: deleteAssistant + path: deleteAssistant + - type: endpoint + key: deleteAssistantFile + path: deleteAssistantFile + - type: object + key: AssistantObject + path: object + - type: object + key: AssistantFileObject + path: file-object + - id: threads + title: Threads + beta: true description: | - Manage legacy fine-tuning jobs to tailor a model to your specific training data. + Create threads that assistants can interact with. - We recommend transitioning to the updating [fine-tuning API](/docs/guides/fine-tuning) + Related guide: [Assistants](/docs/assistants/overview) sections: + - type: endpoint + key: createThread + path: createThread + - type: endpoint + key: getThread + path: getThread + - type: endpoint + key: modifyThread + path: modifyThread + - type: endpoint + key: deleteThread + path: deleteThread - type: object + key: ThreadObject path: object - key: FineTune + - id: messages + title: Messages + beta: true + description: | + Create messages within threads + + Related guide: [Assistants](/docs/assistants/overview) + sections: - type: endpoint - key: createFineTune - path: create + key: createMessage + path: createMessage - type: endpoint - key: listFineTunes - path: list + key: listMessages + path: listMessages - type: endpoint - key: retrieveFineTune - path: retrieve + key: listMessageFiles + path: listMessageFiles - type: endpoint - key: cancelFineTune - path: cancel + key: getMessage + path: getMessage - type: endpoint - key: listFineTuneEvents - path: list-events - - id: edits - title: Edits - deprecated: true + key: getMessageFile + path: getMessageFile + - type: endpoint + key: modifyMessage + path: modifyMessage + - type: object + key: MessageObject + path: object + - type: object + key: MessageFileObject + path: file-object + - id: runs + title: Runs + beta: true description: | - Given a prompt and an instruction, the model will return an edited version of the prompt. + Represents an execution run on a thread. + + Related guide: [Assistants](/docs/assistants/overview) sections: + - type: endpoint + key: createRun + path: createRun + - type: endpoint + key: createThreadAndRun + path: createThreadAndRun + - type: endpoint + key: listRuns + path: listRuns + - type: endpoint + key: listRunSteps + path: listRunSteps + - type: endpoint + key: getRun + path: getRun + - type: endpoint + key: getRunStep + path: getRunStep + - type: endpoint + key: modifyRun + path: modifyRun + - type: endpoint + key: submitToolOuputsToRun + path: submitToolOutputs + - type: endpoint + key: cancelRun + path: cancelRun - type: object - key: CreateEditResponse + key: RunObject path: object + - type: object + key: RunStepObject + path: step-object + - id: completions + title: Completions + legacy: true + description: | + Given a prompt, the model will return one or more predicted completions along with the probabilities of alternative tokens at each position. Most developer should use our [Chat Completions API](/docs/guides/text-generation/text-generation-models) to leverage our best and newest models. Most models that support the legacy Completions endpoint [will be shut off on January 4th, 2024](/docs/deprecations/2023-07-06-gpt-and-embeddings). + sections: - type: endpoint - key: createEdit + key: createCompletion path: create + - type: object + key: CreateCompletionResponse + path: object \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index a77b672a3..1c8159a55 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,18 +8,77 @@ "name": "openai-tsp", "version": "0.1.0", "dependencies": { - "@typespec/compiler": "^0.49.0-dev.11", - "@typespec/openapi": "^0.49.0-dev.4", - "@typespec/openapi3": "^0.49.0-dev.10", - "@typespec/rest": "^0.49.0-dev.3" + "@azure-tools/typespec-csharp": "latest", + "@typespec/compiler": "^0.52.0", + "@typespec/http": "^0.52.0", + "@typespec/openapi": "^0.52.0", + "@typespec/openapi3": "^0.52.0", + "@typespec/rest": "^0.52.0", + "@typespec/versioning": "^0.52.0" + } + }, + "node_modules/@autorest/csharp": { + "version": "3.0.0-beta.20240202.1", + "resolved": "https://registry.npmjs.org/@autorest/csharp/-/csharp-3.0.0-beta.20240202.1.tgz", + "integrity": "sha512-us+dLFipCJbR0uDLiUg7nFsVpV2bJB6CWSTKc30WbE8HvrX0inYxm97LcDw3k3EiOM5frQGSYetWJgXbyuW+jw==" + }, + "node_modules/@azure-tools/typespec-azure-core": { + "version": "0.38.0", + "resolved": "https://registry.npmjs.org/@azure-tools/typespec-azure-core/-/typespec-azure-core-0.38.0.tgz", + "integrity": "sha512-ASM+njC2lpzPykzw2OicWIaAOH+OBe3bVMrufEnINBjlr7owAtudvjrTLLWmAVMBciL/YOF579KdyjxTbaxJ5A==", + "peer": true, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@typespec/compiler": "~0.52.0", + "@typespec/http": "~0.52.0", + "@typespec/rest": "~0.52.0" + } + }, + "node_modules/@azure-tools/typespec-client-generator-core": { + "version": "0.38.0", + "resolved": "https://registry.npmjs.org/@azure-tools/typespec-client-generator-core/-/typespec-client-generator-core-0.38.0.tgz", + "integrity": "sha512-DUDIHJikz3Ai8uPk3vKFoMkkGPUxoD5DbGdwkN/pQxaL6Aze8HV4LGEOGtvaIu0SsGjCX9G3XPAXoBoupYgXbw==", + "peer": true, + "dependencies": { + "change-case": "~5.3.0", + "pluralize": "^8.0.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "@typespec/compiler": "~0.52.0", + "@typespec/http": "~0.52.0", + "@typespec/rest": "~0.52.0", + "@typespec/versioning": "~0.52.0" + } + }, + "node_modules/@azure-tools/typespec-csharp": { + "version": "0.2.0-beta.20240202.1", + "resolved": "https://registry.npmjs.org/@azure-tools/typespec-csharp/-/typespec-csharp-0.2.0-beta.20240202.1.tgz", + "integrity": "sha512-V+AvsqS7OMUcYIdIcVEyhS3i2MVP/rPZqCzDpIOJAcH/4oK4dHVz4RcgB/7+fM+PY7agWrM3zvR5XTkAeBqL9A==", + "dependencies": { + "@autorest/csharp": "3.0.0-beta.20240202.1", + "json-serialize-refs": "0.1.0-0", + "winston": "^3.8.2" + }, + "peerDependencies": { + "@azure-tools/typespec-azure-core": ">=0.36.0 <1.0.0", + "@azure-tools/typespec-client-generator-core": ">=0.36.0 <1.0.0", + "@typespec/compiler": ">=0.50.0 <1.0.0", + "@typespec/http": ">=0.50.0 <1.0.0", + "@typespec/rest": ">=0.50.0 <1.0.0", + "@typespec/versioning": ">=0.50.0 <1.0.0" } }, "node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dependencies": { - "@babel/highlight": "^7.22.13", + "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" }, "engines": { @@ -27,19 +86,19 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", - "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz", - "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, @@ -47,6 +106,24 @@ "node": ">=6.9.0" } }, + "node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@dabh/diagnostics": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", + "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", + "dependencies": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -79,23 +156,39 @@ "node": ">= 8" } }, + "node_modules/@sindresorhus/merge-streams": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-1.0.0.tgz", + "integrity": "sha512-rUV5WyJrJLoloD4NDN1V1+LDMDWOa4OTsT4yYJwQNpTU6FWxkxHpL7eu4w+DmiH8x/EAM1otkPE1+LaspIbplw==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@types/triple-beam": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==" + }, "node_modules/@typespec/compiler": { - "version": "0.49.0-dev.11", - "resolved": "https://registry.npmjs.org/@typespec/compiler/-/compiler-0.49.0-dev.11.tgz", - "integrity": "sha512-SNt6hqu017JhwU3qPpolsGRKgSnb9Wc4FZs5FPQ6i1Ktubtgx9Ac9pxEdSNgOsdoBC3efzbpNCBasLGms0V+Fw==", + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@typespec/compiler/-/compiler-0.52.0.tgz", + "integrity": "sha512-36cZ5RWxRjL4SUe41KjPh3j3RQibpUoOzHcSllQJ3ByTSZdXv1zckMHLiRfaAbTXUADSAn2GMs4ZO3s8GdOGIQ==", "dependencies": { - "@babel/code-frame": "~7.22.13", + "@babel/code-frame": "~7.23.5", "ajv": "~8.12.0", - "change-case": "~4.1.2", - "globby": "~13.2.2", + "change-case": "~5.3.0", + "globby": "~14.0.0", "mustache": "~4.2.0", "picocolors": "~1.0.0", - "prettier": "~3.0.3", + "prettier": "~3.1.1", "prompts": "~2.4.2", "semver": "^7.5.4", "vscode-languageserver": "~9.0.0", "vscode-languageserver-textdocument": "~1.0.8", - "yaml": "~2.3.2", + "yaml": "~2.3.4", "yargs": "~17.7.2" }, "bin": { @@ -103,72 +196,70 @@ "tsp-server": "cmd/tsp-server.js" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" } }, "node_modules/@typespec/http": { - "version": "0.48.0", - "resolved": "https://registry.npmjs.org/@typespec/http/-/http-0.48.0.tgz", - "integrity": "sha512-e+0Y0Ky71flUNZSRzCfoOm8XvXsSYGmQgB9VZFDbLl8mQlXwuTfib4tWrU531TCtZHMnylbXx2wAk5+3uC6b9g==", - "peer": true, + "version": "0.52.1", + "resolved": "https://registry.npmjs.org/@typespec/http/-/http-0.52.1.tgz", + "integrity": "sha512-2i7t6eSKi96F/zt1w0yJvhRhubYej0F9o8jDRhPA+TZI6SAxcv/Vyi+lkKnkOcu90HPH7b8T+YNizudb00BO6A==", "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" }, "peerDependencies": { - "@typespec/compiler": "~0.48.0" + "@typespec/compiler": "~0.52.0" } }, "node_modules/@typespec/openapi": { - "version": "0.49.0-dev.4", - "resolved": "https://registry.npmjs.org/@typespec/openapi/-/openapi-0.49.0-dev.4.tgz", - "integrity": "sha512-qH2borMxQoAdiMDvd88MTvlF2vFZUzusDFtxmKx/GEy+aqkw7pAnR0fqeCbPGR/P8a6slpDchusY/le3608yAQ==", + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@typespec/openapi/-/openapi-0.52.0.tgz", + "integrity": "sha512-2Otnu9glehxvp6TU7NOHEniBDDKufV03XTmeVGgGEmu/j+cveAMg8lA1/O0RBpS2oHGsCFnMEuPcR8M1c0LI+Q==", "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" }, "peerDependencies": { - "@typespec/compiler": "~0.48.1 || >=0.49.0-dev <0.49.0", - "@typespec/http": "~0.48.0 || >=0.49.0-dev <0.49.0" + "@typespec/compiler": "~0.52.0", + "@typespec/http": "~0.52.0" } }, "node_modules/@typespec/openapi3": { - "version": "0.49.0-dev.10", - "resolved": "https://registry.npmjs.org/@typespec/openapi3/-/openapi3-0.49.0-dev.10.tgz", - "integrity": "sha512-J9oiVJKv3pTcNIUzftHS676w4LOxvQe6fqAAx37Nql7SJ3AZrqHXwOrlxjMKZHifU7T+V/KZKF8Y6Li4ORPTPw==", + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@typespec/openapi3/-/openapi3-0.52.0.tgz", + "integrity": "sha512-PPhNdpKQD2iHJemOaRUhnaeFWa4ApW4HtcZI+jrg4hyNSIwDYxL0OwwRohKjRUKM98iacpXvEh+5rKtkPiY2Qw==", "dependencies": { - "yaml": "~2.3.2" + "yaml": "~2.3.4" }, "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" }, "peerDependencies": { - "@typespec/compiler": "~0.48.1 || >=0.49.0-dev <0.49.0", - "@typespec/http": "~0.48.0 || >=0.49.0-dev <0.49.0", - "@typespec/openapi": "~0.48.0 || >=0.49.0-dev <0.49.0", - "@typespec/versioning": "~0.48.0 || >=0.49.0-dev <0.49.0" + "@typespec/compiler": "~0.52.0", + "@typespec/http": "~0.52.0", + "@typespec/openapi": "~0.52.0", + "@typespec/versioning": "~0.52.0" } }, "node_modules/@typespec/rest": { - "version": "0.49.0-dev.3", - "resolved": "https://registry.npmjs.org/@typespec/rest/-/rest-0.49.0-dev.3.tgz", - "integrity": "sha512-/33xOp3N5wtUZ6O+kNssIzCEXR7+fjThtGysnsUL0lS8W3OesCgF9gKZH9fB0beaRlccmzFoRcHSOQLwalkfmg==", + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@typespec/rest/-/rest-0.52.0.tgz", + "integrity": "sha512-dLsY0fS60IVaAt4eCRcvEqorX/miPVV33du3dETTYYmbHtfEbvBKgTj/m6OH4noey7oaihlvLz5kYyLv8Am7zA==", "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" }, "peerDependencies": { - "@typespec/compiler": "~0.48.1 || >=0.49.0-dev <0.49.0", - "@typespec/http": "~0.48.0 || >=0.49.0-dev <0.49.0" + "@typespec/compiler": "~0.52.0", + "@typespec/http": "~0.52.0" } }, "node_modules/@typespec/versioning": { - "version": "0.48.0", - "resolved": "https://registry.npmjs.org/@typespec/versioning/-/versioning-0.48.0.tgz", - "integrity": "sha512-WF26vmMPwizhSnjX0ox23nbp7hthtB4cN/J5w1tlryXyp/BXySHoYsJEMK7fviSpj4WdreVXdM6wmRIG33zqig==", - "peer": true, + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@typespec/versioning/-/versioning-0.52.0.tgz", + "integrity": "sha512-Vr4WHaZiDOxJqRp8/u6X0R45E+rFKEprYmSZX0o5bzetj0cVjOIEbQZvDJCif1Uz0S3K0KKfqf/kYmdYWMJ7Dw==", "engines": { - "node": ">=16.0.0" + "node": ">=18.0.0" }, "peerDependencies": { - "@typespec/compiler": "~0.48.0" + "@typespec/compiler": "~0.52.0" } }, "node_modules/ajv": { @@ -205,6 +296,11 @@ "node": ">=4" } }, + "node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" + }, "node_modules/braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", @@ -216,25 +312,6 @@ "node": ">=8" } }, - "node_modules/camel-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", - "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dependencies": { - "pascal-case": "^3.1.2", - "tslib": "^2.0.3" - } - }, - "node_modules/capital-case": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", - "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case-first": "^2.0.2" - } - }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -249,23 +326,9 @@ } }, "node_modules/change-case": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz", - "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==", - "dependencies": { - "camel-case": "^4.1.2", - "capital-case": "^1.0.4", - "constant-case": "^3.0.4", - "dot-case": "^3.0.4", - "header-case": "^2.0.4", - "no-case": "^3.0.4", - "param-case": "^3.0.4", - "pascal-case": "^3.1.2", - "path-case": "^3.0.4", - "sentence-case": "^3.0.4", - "snake-case": "^3.0.4", - "tslib": "^2.0.3" - } + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-5.3.0.tgz", + "integrity": "sha512-Eykca0fGS/xYlx2fG5NqnGSnsWauhSGiSXYhB1kO6E909GUfo8S54u4UZNS7lMJmgZumZ2SUpWaoLgAcfQRICg==" }, "node_modules/cliui": { "version": "8.0.1", @@ -280,6 +343,15 @@ "node": ">=12" } }, + "node_modules/color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "dependencies": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -293,34 +365,22 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, - "node_modules/constant-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz", - "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==", + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case": "^2.0.2" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" } }, - "node_modules/dot-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", - "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "node_modules/colorspace": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", + "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" + "color": "^3.1.3", + "text-hex": "1.0.x" } }, "node_modules/emoji-regex": { @@ -328,6 +388,11 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, + "node_modules/enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -350,9 +415,9 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -365,13 +430,18 @@ } }, "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.0.tgz", + "integrity": "sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w==", "dependencies": { "reusify": "^1.0.4" } }, + "node_modules/fecha": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -383,6 +453,11 @@ "node": ">=8" } }, + "node_modules/fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -403,18 +478,19 @@ } }, "node_modules/globby": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", - "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.0.tgz", + "integrity": "sha512-/1WM/LNHRAOH9lZta77uGbq0dAEQM+XjNesWwhlERDVenqothRbnzTrL3/LrIoEPPjeUHC3vrS6TwoyxeHs7MQ==", "dependencies": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.3.0", + "@sindresorhus/merge-streams": "^1.0.0", + "fast-glob": "^3.3.2", "ignore": "^5.2.4", - "merge2": "^1.4.1", - "slash": "^4.0.0" + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -428,23 +504,24 @@ "node": ">=4" } }, - "node_modules/header-case": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz", - "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==", - "dependencies": { - "capital-case": "^1.0.4", - "tslib": "^2.0.3" - } - }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "engines": { "node": ">= 4" } }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -480,6 +557,17 @@ "node": ">=0.12.0" } }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -490,6 +578,11 @@ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, + "node_modules/json-serialize-refs": { + "version": "0.1.0-0", + "resolved": "https://registry.npmjs.org/json-serialize-refs/-/json-serialize-refs-0.1.0-0.tgz", + "integrity": "sha512-SnNMfW2RRPDXIMKa8zdLb59UjMSI1UFZCtIb8ae68GcZ0a6x8b77lIWqqTOdq1azzmkXupD6UWriPLd0JCrFng==" + }, "node_modules/kleur": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", @@ -498,12 +591,25 @@ "node": ">=6" } }, - "node_modules/lower-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", - "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "node_modules/kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" + }, + "node_modules/logform": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.0.tgz", + "integrity": "sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==", "dependencies": { - "tslib": "^2.0.3" + "@colors/colors": "1.6.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" } }, "node_modules/lru-cache": { @@ -537,6 +643,11 @@ "node": ">=8.6" } }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, "node_modules/mustache": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", @@ -545,48 +656,23 @@ "mustache": "bin/mustache" } }, - "node_modules/no-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", - "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dependencies": { - "lower-case": "^2.0.2", - "tslib": "^2.0.3" - } - }, - "node_modules/param-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", - "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/pascal-case": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", - "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3" - } - }, - "node_modules/path-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz", - "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==", + "node_modules/one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" + "fn.name": "1.x.x" } }, "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/picocolors": { @@ -605,10 +691,19 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "peer": true, + "engines": { + "node": ">=4" + } + }, "node_modules/prettier": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", - "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz", + "integrity": "sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==", "bin": { "prettier": "bin/prettier.cjs" }, @@ -658,6 +753,19 @@ } ] }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -705,6 +813,33 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-stable-stringify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", + "engines": { + "node": ">=10" + } + }, "node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -719,14 +854,12 @@ "node": ">=10" } }, - "node_modules/sentence-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz", - "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==", + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", "dependencies": { - "no-case": "^3.0.4", - "tslib": "^2.0.3", - "upper-case-first": "^2.0.2" + "is-arrayish": "^0.3.1" } }, "node_modules/sisteransi": { @@ -735,23 +868,30 @@ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" }, "node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", "engines": { - "node": ">=12" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/snake-case": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", - "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", + "engines": { + "node": "*" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dependencies": { - "dot-case": "^3.0.4", - "tslib": "^2.0.3" + "safe-buffer": "~5.2.0" } }, "node_modules/string-width": { @@ -789,6 +929,11 @@ "node": ">=4" } }, + "node_modules/text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -800,25 +945,23 @@ "node": ">=8.0" } }, - "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" - }, - "node_modules/upper-case": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz", - "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==", - "dependencies": { - "tslib": "^2.0.3" + "node_modules/triple-beam": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", + "engines": { + "node": ">= 14.0.0" } }, - "node_modules/upper-case-first": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz", - "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==", - "dependencies": { - "tslib": "^2.0.3" + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/uri-js": { @@ -829,6 +972,11 @@ "punycode": "^2.1.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, "node_modules/vscode-jsonrpc": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", @@ -867,6 +1015,40 @@ "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.4.tgz", "integrity": "sha512-9YXi5pA3XF2V+NUQg6g+lulNS0ncRCKASYdK3Cs7kiH9sVFXWq27prjkC/B8M/xJLRPPRSPCHVMuBTgRNFh2sQ==" }, + "node_modules/winston": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.11.0.tgz", + "integrity": "sha512-L3yR6/MzZAOl0DsysUXHVjOwv8mKZ71TrA/41EIduGpOOV5LQVodqN+QdQ6BS6PJ/RdIshZhq84P/fStEZkk7g==", + "dependencies": { + "@colors/colors": "^1.6.0", + "@dabh/diagnostics": "^2.0.2", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.4.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.5.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-transport": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.6.0.tgz", + "integrity": "sha512-wbBA9PbPAHxKiygo7ub7BYRiKxms0tpfU2ljtWzb3SjRjv5yl6Ozuy/TkXf00HTAt+Uylo3gSkNwzc4ME0wiIg==", + "dependencies": { + "logform": "^2.3.2", + "readable-stream": "^3.6.0", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -927,9 +1109,9 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yaml": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.2.tgz", - "integrity": "sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", "engines": { "node": ">= 14" } diff --git a/package.json b/package.json index eba48058d..f43e693fb 100644 --- a/package.json +++ b/package.json @@ -3,12 +3,13 @@ "version": "0.1.0", "type": "module", "dependencies": { - "@typespec/compiler": "^0.49.0-dev.11", - "@typespec/openapi": "^0.49.0-dev.4", - "@typespec/openapi3": "^0.49.0-dev.10", - "@typespec/rest": "^0.49.0-dev.3", - "@typespec/http": "^0.49.0-dev.0", - "@typespec/versioning": "^0.49.0-dev.0" + "@azure-tools/typespec-csharp": "latest", + "@typespec/compiler": "^0.52.0", + "@typespec/http": "^0.52.0", + "@typespec/openapi": "^0.52.0", + "@typespec/openapi3": "^0.52.0", + "@typespec/rest": "^0.52.0", + "@typespec/versioning": "^0.52.0" }, "private": true } From 587222bd1553d9989848413df093ecf066f7ce2e Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado Date: Wed, 7 Feb 2024 10:15:50 -0800 Subject: [PATCH 02/50] Add Assistants API --- assistants/main.tsp | 1 + assistants/meta.tsp | 42 ++++ assistants/models.tsp | 233 ++++++++++++++++++ assistants/operations.tsp | 161 +++++++++++++ main.tsp | 4 + messages/main.tsp | 1 + messages/meta.tsp | 52 ++++ messages/models.tsp | 211 +++++++++++++++++ messages/operations.tsp | 142 +++++++++++ runs/main.tsp | 1 + runs/meta.tsp | 50 ++++ runs/models.tsp | 486 ++++++++++++++++++++++++++++++++++++++ runs/operations.tsp | 185 +++++++++++++++ threads/main.tsp | 1 + threads/meta.tsp | 22 ++ threads/models.tsp | 55 +++++ threads/operations.tsp | 52 ++++ 17 files changed, 1699 insertions(+) create mode 100644 assistants/main.tsp create mode 100644 assistants/meta.tsp create mode 100644 assistants/models.tsp create mode 100644 assistants/operations.tsp create mode 100644 messages/main.tsp create mode 100644 messages/meta.tsp create mode 100644 messages/models.tsp create mode 100644 messages/operations.tsp create mode 100644 runs/main.tsp create mode 100644 runs/meta.tsp create mode 100644 runs/models.tsp create mode 100644 runs/operations.tsp create mode 100644 threads/main.tsp create mode 100644 threads/meta.tsp create mode 100644 threads/models.tsp create mode 100644 threads/operations.tsp diff --git a/assistants/main.tsp b/assistants/main.tsp new file mode 100644 index 000000000..6a754bcb5 --- /dev/null +++ b/assistants/main.tsp @@ -0,0 +1 @@ +import "./operations.tsp"; \ No newline at end of file diff --git a/assistants/meta.tsp b/assistants/meta.tsp new file mode 100644 index 000000000..fd2481ecb --- /dev/null +++ b/assistants/meta.tsp @@ -0,0 +1,42 @@ +import "./models.tsp"; + +import "@typespec/openapi"; + +using TypeSpec.OpenAPI; + +namespace OpenAI; + +// TODO: Fill in example here. +@@extension(OpenAI.ListAssistantsResponse, + "x-oaiMeta", + """ + name: List assistants response object + group: chat + example: *list_assistants_example + """ +); + +// TODO: Fill in example here. +@@extension(OpenAI.AssistantObject, + "x-oaiMeta", + """ + name: The assistant object + beta: true + example: *create_assistants_example + """ +); + +@@extension(OpenAI.AssistantFileObject, + "x-oaiMeta", + """ + name: The assistant file object + beta: true + example: | + { + "id": "file-abc123", + "object": "assistant.file", + "created_at": 1699055364, + "assistant_id": "asst_abc123" + } + """ +); \ No newline at end of file diff --git a/assistants/models.tsp b/assistants/models.tsp new file mode 100644 index 000000000..358d95d48 --- /dev/null +++ b/assistants/models.tsp @@ -0,0 +1,233 @@ +import "../common/models.tsp"; + +using TypeSpec.Http; +using TypeSpec.OpenAPI; + +namespace OpenAI; + +model CreateAssistantRequest { + /** + * ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + * see all of your available models, or see our [Model overview](/docs/models/overview) for + * descriptions of them. + */ + `model`: string; + + /** The name of the assistant. The maximum length is 256 characters. */ + @maxLength(256) + name?: string | null; + + /** The description of the assistant. The maximum length is 512 characters. */ + @maxLength(512) + description?: string | null; + + /** The system instructions that the assistant uses. The maximum length is 32768 characters. */ + @maxLength(32768) + instructions?: string | null; + + /** + * A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. + * Tools can be of types `code_interpreter`, `retrieval`, or `function`. + */ + + tools?: CreateAssistantRequestTools = []; // TODO: Double-check default empty array + + /** + * A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a + * maximum of 20 files attached to the assistant. Files are ordered by their creation date in + * ascending order. + */ + @maxItems(20) + file_ids?: string[] = []; + + /** + * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + * additional information about the object in a structured format. Keys can be a maximum of 64 + * characters long and values can be a maxium of 512 characters long. + */ + @extension("x-oaiTypeLabel", "map") + metadata?: Record | null; +} + +model ModifyAssistantRequest { + /** + * ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + * see all of your available models, or see our [Model overview](/docs/models/overview) for + * descriptions of them. + */ + `model`?: string; + + /** The name of the assistant. The maximum length is 256 characters. */ + @maxLength(256) + name?: string | null; + + /** The description of the assistant. The maximum length is 512 characters. */ + @maxLength(512) + description?: string | null; + + /** The system instructions that the assistant uses. The maximum length is 32768 characters. */ + @maxLength(32768) + instructions?: string | null; + + /** + * A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. + * Tools can be of types `code_interpreter`, `retrieval`, or `function`. + */ + @maxItems(128) + tools?: CreateAssistantRequestTools[] = []; // TODO: Double-check default empty array + + /** + * A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a + * maximum of 20 files attached to the assistant. Files are ordered by their creation date in + * ascending order. + */ + @maxItems(20) + file_ids?: string[] = []; + + /** + * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + * additional information about the object in a structured format. Keys can be a maximum of 64 + * characters long and values can be a maxium of 512 characters long. + */ + @extension("x-oaiTypeLabel", "map") + metadata?: Record | null; +} + +model CreateAssistantFileRequest { + /** + * A [File](/docs/api-reference/files) ID (with `purpose="assistants"`) that the assistant should + * use. Useful for tools like `retrieval` and `code_interpreter` that can access files. + */ + file_id: string; +} + +model ListAssistantsResponse { + object: "list"; + data: AssistantObject[]; + first_id: string; + last_id: string; + has_more: boolean; +} + +model DeleteAssistantResponse { + id: string; + deleted: boolean; + object: "assistant.deleted"; +} + +model ListAssistantFilesResponse { + object: "list"; + data: AssistantFileObject[]; + first_id: string; + last_id: string; + has_more: boolean; +} + +/** + * Deletes the association between the assistant and the file, but does not delete the + * [File](/docs/api-reference/files) object itself. + */ +model DeleteAssistantFileResponse { + id: string; + deleted: boolean; + object: "assistant.file.deleted"; +} + +@maxItems(128) +model CreateAssistantRequestTools is CreateAssistantRequestTool[]; + +@oneOf +@extension("x-oaiExpandable", true) +union CreateAssistantRequestTool { + AssistantToolsCode, + AssistantToolsRetrieval, + AssistantToolsFunction +} + +model AssistantToolsCode { + /** The type of tool being defined: `code_interpreter` */ + type: "code_interpreter"; +} + +model AssistantToolsRetrieval { + /** The type of tool being defined: `retrieval` */ + type: "retrieval"; +} + +model AssistantToolsFunction { + /** The type of tool being defined: `function` */ + type: "function"; + + function: FunctionObject; +} + +/** Represents an `assistant` that can call the model and use tools. */ +model AssistantObject { + /** The identifier, which can be referenced in API endpoints. */ + id: string; + + /** The object type, which is always `assistant`. */ + object: "assistant"; + + /** The Unix timestamp (in seconds) for when the assistant was created. */ + @encode("unixTimestamp", int32) + created_at: utcDateTime; + + /** The name of the assistant. The maximum length is 256 characters. */ + @maxLength(256) + name: string | null; + + /** The description of the assistant. The maximum length is 512 characters. */ + @maxLength(512) + description: string | null; + + /** + * ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + * see all of your available models, or see our [Model overview](/docs/models/overview) for + * descriptions of them. + */ + `model`: string; + + /** The system instructions that the assistant uses. The maximum length is 32768 characters. */ + @maxLength(32768) + instructions: string | null; + + /** + * A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. + * Tools can be of types `code_interpreter`, `retrieval`, or `function`. + */ + @maxItems(128) + tools: CreateAssistantRequestTools[] = []; // TODO: Double-check default empty array + + /** + * A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a + * maximum of 20 files attached to the assistant. Files are ordered by their creation date in + * ascending order. + */ + @maxItems(20) + file_ids: string[] = []; + + /** + * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + * additional information about the object in a structured format. Keys can be a maximum of 64 + * characters long and values can be a maxium of 512 characters long. + */ + @extension("x-oaiTypeLabel", "map") + metadata: Record | null; +} + +/** A list of [Files](/docs/api-reference/files) attached to an `assistant`. */ +model AssistantFileObject { + /** The identifier, which can be referenced in API endpoints. */ + id: string; + + /** The object type, which is always `assistant.file`. */ + object: "assistant.file"; + + /** The Unix timestamp (in seconds) for when the assistant file was created. */ + @encode("unixTimestamp", int32) + created_at: utcDateTime; + + /** The assistant ID that the file is attached to. */ + assistant_id: string; +} \ No newline at end of file diff --git a/assistants/operations.tsp b/assistants/operations.tsp new file mode 100644 index 000000000..e98f03e7e --- /dev/null +++ b/assistants/operations.tsp @@ -0,0 +1,161 @@ +import "@typespec/http"; +import "@typespec/openapi"; + +import "../common/errors.tsp"; +import "./models.tsp"; + +using TypeSpec.Http; +using TypeSpec.OpenAPI; + +namespace OpenAI; + +@route("/assistants") +interface Assistants { + @post + @operationId("createAssistant") + @tag("OpenAI") + @summary("Create an assistant with a model and instructions.") + createAssistant( + @body assistant: CreateAssistantRequest, + ): AssistantObject | ErrorResponse; + + @get + @operationId("listAssistants") + @tag("OpenAI") + @summary("Returns a list of assistants.") + listFiles( + /** + * A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + * default is 20. + */ + @query limit?: int32 = 20; + + /** + * Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + * for descending order. + */ + @query order?: "asc" | "desc" = "desc"; + + /** + * A cursor for use in pagination. `after` is an object ID that defines your place in the list. + * For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + * subsequent call can include after=obj_foo in order to fetch the next page of the list. + */ + @query after?: string; + + /** + * A cursor for use in pagination. `before` is an object ID that defines your place in the list. + * For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + * subsequent call can include before=obj_foo in order to fetch the previous page of the list. + */ + @query before?: string; + ): ListAssistantsResponse | ErrorResponse; + + @route("{assistant_id}") + @get + @operationId("getAssistant") + @tag("OpenAI") + @summary("Retrieves an assistant.") + getAssistant( + /** The ID of the assistant to retrieve. */ + @path assistant_id: string, + ): AssistantObject | ErrorResponse; + + @route("{assistant_id}") + @post + @operationId("modifyAssistant") + @tag("OpenAI") + @summary("Modifies an assistant.") + modifyAssistant( + /** The ID of the assistant to modify. */ + @path assistant_id: string, + + @body assistant: ModifyAssistantRequest, + ): AssistantObject | ErrorResponse; + + @route("{assistant_id}") + @delete + @operationId("deleteAssistant") + @tag("OpenAI") + @summary("Delete an assistant.") + deleteAssistant( + /** The ID of the assistant to delete. */ + @path assistant_id: string, + ): DeleteAssistantResponse | ErrorResponse; + + @route("{assistant_id}/files") + @post + @operationId("createAssistantFile") + @tag("OpenAI") + @summary(""" + Create an assistant file by attaching a [File](/docs/api-reference/files) to a + [assistant](/docs/api-reference/assistants). + """) + createAssistantFile( + /** The ID of the assistant for which to create a file. */ + @path assistant_id: string, + @body file: CreateAssistantFileRequest, + ): AssistantFileObject | ErrorResponse; + + @route("{assistant_id}/files") + @get + @operationId("listAssistantFiles") + @tag("OpenAI") + @summary("Returns a list of assistant files.") + listAssistantFiles( + /** The ID of the assistant the file belongs to. */ + @path assistant_id: string, + + /** + * A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + * default is 20. + */ + @query limit?: int32 = 20; + + /** + * Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + * for descending order. + */ + @query order?: "asc" | "desc" = "desc"; + + /** + * A cursor for use in pagination. `after` is an object ID that defines your place in the list. + * For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + * subsequent call can include after=obj_foo in order to fetch the next page of the list. + */ + @query after?: string; + + /** + * A cursor for use in pagination. `before` is an object ID that defines your place in the list. + * For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + * subsequent call can include before=obj_foo in order to fetch the previous page of the list. + */ + @query before?: string; + ): ListAssistantFilesResponse | ErrorResponse; + + @route("{assistant_id}/files/{file_id}") + @get + @operationId("getAssistantFile") + @tag("OpenAI") + @summary("Retrieves an assistant file.") + getAssistantFile( + /** The ID of the assistant the file belongs to. */ + @path assistant_id: string, + + /** The ID of the file we're getting. */ + @path file_id: string, + ): AssistantFileObject | ErrorResponse; + + @route("{assistant_id}/files/{file_id}") + @delete + @operationId("deleteAssistantFile") + @tag("OpenAI") + @summary("Delete an assistant file.") + deleteAssistantFile( + /** The ID of the assistant the file belongs to. */ + @path assistant_id: string, + + /** The ID of the file to delete. */ + @path file_id: string, + ): DeleteAssistantFileResponse | ErrorResponse; +} diff --git a/main.tsp b/main.tsp index fe7b08d3a..604a75f8c 100644 --- a/main.tsp +++ b/main.tsp @@ -3,14 +3,18 @@ import "@typespec/openapi3"; import "@typespec/openapi"; import "./audio"; +import "./assistants"; import "./chat"; import "./completions"; import "./embeddings"; import "./files"; import "./fine-tuning"; import "./images"; +import "./messages"; import "./models"; import "./moderations"; +import "./runs"; +import "./threads"; using TypeSpec.Http; diff --git a/messages/main.tsp b/messages/main.tsp new file mode 100644 index 000000000..6a754bcb5 --- /dev/null +++ b/messages/main.tsp @@ -0,0 +1 @@ +import "./operations.tsp"; \ No newline at end of file diff --git a/messages/meta.tsp b/messages/meta.tsp new file mode 100644 index 000000000..682702c76 --- /dev/null +++ b/messages/meta.tsp @@ -0,0 +1,52 @@ +import "./models.tsp"; + +import "@typespec/openapi"; + +using TypeSpec.OpenAPI; + +namespace OpenAI; + +@@extension(OpenAI.MessageObject, + "x-oaiMeta", + """ + name: The message object + beta: true + example: | + { + "id": "msg_abc123", + "object": "thread.message", + "created_at": 1698983503, + "thread_id": "thread_abc123", + "role": "assistant", + "content": [ + { + "type": "text", + "text": { + "value": "Hi! How can I help you today?", + "annotations": [] + } + } + ], + "file_ids": [], + "assistant_id": "asst_abc123", + "run_id": "run_abc123", + "metadata": {} + } + """ +); + +@@extension(OpenAI.MessageFileObject, + "x-oaiMeta", + """ + name: The message file object + beta: true + example: | + { + "id": "file-abc123", + "object": "thread.message.file", + "created_at": 1698107661, + "message_id": "message_QLoItBbqwyAJEzlTy4y9kOMM", + "file_id": "file-abc123" + } + """ +); \ No newline at end of file diff --git a/messages/models.tsp b/messages/models.tsp new file mode 100644 index 000000000..075bef16d --- /dev/null +++ b/messages/models.tsp @@ -0,0 +1,211 @@ +import "../common/models.tsp"; + +using TypeSpec.Http; +using TypeSpec.OpenAPI; + +namespace OpenAI; + +model CreateMessageRequest { + /** The role of the entity that is creating the message. Currently only `user` is supported. */ + role: "user"; + + /** The content of the message. */ + @minLength(1) + @maxLength(32768) + content: string; + + /** + * A list of [File](/docs/api-reference/files) IDs that the message should use. There can be a + * maximum of 10 files attached to a message. Useful for tools like `retrieval` and + * `code_interpreter` that can access and use files. + */ + @minItems(1) + @maxItems(10) + file_ids?: string[] = []; + + /** + * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + * additional information about the object in a structured format. Keys can be a maximum of 64 + * characters long and values can be a maxium of 512 characters long. + */ + @extension("x-oaiTypeLabel", "map") + metadata?: Record | null; +} + +model ModifyMessageRequest { + /** + * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + * additional information about the object in a structured format. Keys can be a maximum of 64 + * characters long and values can be a maxium of 512 characters long. + */ + @extension("x-oaiTypeLabel", "map") + metadata?: Record | null; +} + +model ListMessagesResponse { + object: "list"; + data: MessageObject[]; + first_id: string; + last_id: string; + has_more: boolean; +} + +model ListMessageFilesResponse { + object: "list"; + data: MessageFileObject[]; + first_id: string; + last_id: string; + has_more: boolean; +} + +model MessageObject { + /** The identifier, which can be referenced in API endpoints. */ + id: string; + + /** The object type, which is always `thread.message`. */ + object: "thread.message"; + + /** The Unix timestamp (in seconds) for when the message was created. */ + @encode("unixTimestamp", int32) + created_at: utcDateTime; + + /** The [thread](/docs/api-reference/threads) ID that this message belongs to. */ + thread_id: string; + + /** The entity that produced the message. One of `user` or `assistant`. */ + role: "user" | "assistant"; + + /** The content of the message in array of text and/or images. */ + content: MessageObjectContent[]; + + /** + * If applicable, the ID of the [assistant](/docs/api-reference/assistants) that authored this + * message. + */ + assistant_id: string | null; + + /** + * If applicable, the ID of the [run](/docs/api-reference/runs) associated with the authoring of + * this message. + */ + run_id: string | null; + + /** + * A list of [file](/docs/api-reference/files) IDs that the assistant should use. Useful for + * tools like retrieval and code_interpreter that can access files. A maximum of 10 files can be + * attached to a message. + */ + @maxItems(10) + file_ids: string[] = []; + + /** + * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + * additional information about the object in a structured format. Keys can be a maximum of 64 + * characters long and values can be a maxium of 512 characters long. + */ + @extension("x-oaiTypeLabel", "map") + metadata: Record | null; +} + +@oneOf +@extension("x-oaiExpandable", true) +union MessageObjectContent { + MessageContentImageFileObject, + MessageContentTextObject, +} + +/** References an image [File](/docs/api-reference/files) in the content of a message. */ +model MessageContentImageFileObject { + /** Always `image_file`. */ + type: "image_file"; + + image_file: { + /** The [File](/docs/api-reference/files) ID of the image in the message content. */ + file_id: string; + } +} + +model MessageContentTextObject { + /** Always `text`. */ + type: "text"; + + text: { + /** The data that makes up the text. */ + value: string; + + annotations: MessageContentTextObjectAnnotations[]; + } +} + +@oneOf +@extension("x-oaiExpandable", true) +union MessageContentTextObjectAnnotations { + MessageContentTextAnnotationsFileCitationObject, + MessageContentTextAnnotationsFilePathObject, +} + +/** + * A citation within the message that points to a specific quote from a specific File associated + * with the assistant or the message. Generated when the assistant uses the "retrieval" tool to + * search files. + */ +model MessageContentTextAnnotationsFileCitationObject { + /** Always `file_citation`. */ + type: "file_citation"; + + /** The text in the message content that needs to be replaced. */ + text: string; + + file_citation: { + /** The ID of the specific File the citation is from. */ + file_id: string; + + /** The specific quote in the file. */ + quote: string; + }; + + @minValue(0) + start_index: safeint; + + @minValue(0) + end_index: safeint; +} + +/** + * A URL for the file that's generated when the assistant used the `code_interpreter` tool to + * generate a file. + */ +model MessageContentTextAnnotationsFilePathObject { + /** Always `file_path`. */ + type: "file_path"; + + /** The text in the message content that needs to be replaced. */ + text: string; + + file_path: { + /** The ID of the file that was generated. */ + file_id: string; + }; + + @minValue(0) + start_index: safeint; + + @minValue(0) + end_index: safeint; +} + +/** A list of files attached to a `message`. */ +model MessageFileObject { + /** TThe identifier, which can be referenced in API endpoints. */ + id: string; + + /** The object type, which is always `thread.message.file`. */ + object: "thread.message.file"; + + /** The Unix timestamp (in seconds) for when the message file was created. */ + @encode("unixTimestamp", int32) + created_at: utcDateTime; + + /** The ID of the [message](/docs/api-reference/messages) that the [File](/docs/api-reference/files) is attached to. */ + message_id: string; +} \ No newline at end of file diff --git a/messages/operations.tsp b/messages/operations.tsp new file mode 100644 index 000000000..3cdf4ea84 --- /dev/null +++ b/messages/operations.tsp @@ -0,0 +1,142 @@ +import "@typespec/http"; +import "@typespec/openapi"; + +import "../common/errors.tsp"; +import "./models.tsp"; + +using TypeSpec.Http; +using TypeSpec.OpenAPI; + +namespace OpenAI; + +@route("threads/{thread_id}/messages") +interface Messages { + @post + @operationId("createMessage") + @tag("OpenAI") + @summary("Create a message.") + createMessage( + /** The ID of the [thread](/docs/api-reference/threads) to create a message for. */ + @path thread_id: string, + + @body message: CreateMessageRequest, + ): MessageObject | ErrorResponse; + + @get + @operationId("listMessages") + @tag("OpenAI") + @summary("Returns a list of messages for a given thread.") + listMessages( + /** The ID of the [thread](/docs/api-reference/threads) the messages belong to. */ + @path thread_id: string, + + /** + * A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + * default is 20. + */ + @query limit?: int32 = 20; + + /** + * Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + * for descending order. + */ + @query order?: "asc" | "desc" = "desc"; + + /** + * A cursor for use in pagination. `after` is an object ID that defines your place in the list. + * For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + * subsequent call can include after=obj_foo in order to fetch the next page of the list. + */ + @query after?: string; + + /** + * A cursor for use in pagination. `before` is an object ID that defines your place in the list. + * For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + * subsequent call can include before=obj_foo in order to fetch the previous page of the list. + */ + @query before?: string; + ): ListMessagesResponse | ErrorResponse; + + @route("{message_id}") + @get + @operationId("getMessage") + @tag("OpenAI") + @summary("Retrieve a message.") + getMessage( + /** The ID of the [thread](/docs/api-reference/threads) to which this message belongs. */ + @path thread_id: string, + + /** The ID of the message to retrieve. */ + @path message_id: string, + ): MessageObject | ErrorResponse; + + @route("{message_id}") + @post + @operationId("modifyMessage") + @tag("OpenAI") + @summary("Modifies a message.") + modifyMessage( + /** The ID of the thread to which this message belongs. */ + @path thread_id: string, + + /** The ID of the message to modify. */ + @path message_id: string, + + @body message: ModifyMessageRequest, + ): MessageObject | ErrorResponse; + + @route("{message_id}/files") + @get + @operationId("listMessageFiles") + @tag("OpenAI") + @summary("Returns a list of message files.") + listMessageFiles( + /** The ID of the thread that the message and files belong to. */ + @path thread_id: string, + + /** The ID of the message that the files belongs to. */ + @path message_id: string, + + /** + * A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + * default is 20. + */ + @query limit?: int32 = 20; + + /** + * Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + * for descending order. + */ + @query order?: "asc" | "desc" = "desc"; + + /** + * A cursor for use in pagination. `after` is an object ID that defines your place in the list. + * For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + * subsequent call can include after=obj_foo in order to fetch the next page of the list. + */ + @query after?: string; + + /** + * A cursor for use in pagination. `before` is an object ID that defines your place in the list. + * For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + * subsequent call can include before=obj_foo in order to fetch the previous page of the list. + */ + @query before?: string; + ): ListMessageFilesResponse | ErrorResponse; + + @route("{message_id}/files/{file_id}") + @get + @operationId("getMessageFile") + @tag("OpenAI") + @summary("RRetrieves a message file.") + getMessageFile( + /** The ID of the thread to which the message and File belong. */ + @path thread_id: string, + + /** The ID of the message the file belongs to. */ + @path message_id: string, + + /** The ID of the file being retrieved. */ + @path file_id: string, + ): MessageFileObject | ErrorResponse; +} diff --git a/runs/main.tsp b/runs/main.tsp new file mode 100644 index 000000000..6a754bcb5 --- /dev/null +++ b/runs/main.tsp @@ -0,0 +1 @@ +import "./operations.tsp"; \ No newline at end of file diff --git a/runs/meta.tsp b/runs/meta.tsp new file mode 100644 index 000000000..6819970c2 --- /dev/null +++ b/runs/meta.tsp @@ -0,0 +1,50 @@ +import "./models.tsp"; + +import "@typespec/openapi"; + +using TypeSpec.OpenAPI; + +namespace OpenAI; + +@@extension(OpenAI.RunObject, + "x-oaiMeta", + """ + name: The run object + beta: true + example: | + { + "id": "run_abc123", + "object": "thread.run", + "created_at": 1698107661, + "assistant_id": "asst_abc123", + "thread_id": "thread_abc123", + "status": "completed", + "started_at": 1699073476, + "expires_at": null, + "cancelled_at": null, + "failed_at": null, + "completed_at": 1699073498, + "last_error": null, + "model": "gpt-4", + "instructions": null, + "tools": [{"type": "retrieval"}, {"type": "code_interpreter"}], + "file_ids": [], + "metadata": {}, + "usage": { + "prompt_tokens": 123, + "completion_tokens": 456, + "total_tokens": 579 + } + } + """ +); + +// TODO: Fill in example here. +@@extension(OpenAI.RunStepObject, + "x-oaiMeta", + """ + name: The run step object + beta: true + example: *run_step_object_example + """ +); \ No newline at end of file diff --git a/runs/models.tsp b/runs/models.tsp new file mode 100644 index 000000000..113e43124 --- /dev/null +++ b/runs/models.tsp @@ -0,0 +1,486 @@ +import "../common/models.tsp"; +import "../assistants/models.tsp"; +import "../threads/models.tsp"; + +using TypeSpec.Http; +using TypeSpec.OpenAPI; + +namespace OpenAI; + +model CreateRunRequest { + /** The ID of the [assistant](/docs/api-reference/assistants) to use to execute this run. */ + assistant_id: string; + + /** + * The ID of the [Model](/docs/api-reference/models) to be used to execute this run. If a value + * is provided here, it will override the model associated with the assistant. If not, the model + * associated with the assistant will be used. */ + `model`?: string | null; + + /** + * Overrides the [instructions](/docs/api-reference/assistants/createAssistant) of the assistant. + * This is useful for modifying the behavior on a per-run basis. + */ + instructions?: string | null; + + /** + * Appends additional instructions at the end of the instructions for the run. This is useful for + * modifying the behavior on a per-run basis without overriding other instructions. + */ + additional_instructions?: string | null; + + /** + * Override the tools the assistant can use for this run. This is useful for modifying the + * behavior on a per-run basis. + */ + tools?: CreateRunRequestTools | null; + + /** + * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + * additional information about the object in a structured format. Keys can be a maximum of 64 + * characters long and values can be a maxium of 512 characters long. + */ + @extension("x-oaiTypeLabel", "map") + metadata?: Record | null; +} + +model ModifyRunRequest { + /** + * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + * additional information about the object in a structured format. Keys can be a maximum of 64 + * characters long and values can be a maxium of 512 characters long. + */ + @extension("x-oaiTypeLabel", "map") + metadata?: Record | null; +} + +model CreateThreadAndRunRequest { + /** The ID of the [assistant](/docs/api-reference/assistants) to use to execute this run. */ + assistant_id: string; + + /** If no thread is provided, an empty thread will be created. */ + thread?: CreateThreadRequest; + + /** + * The ID of the [Model](/docs/api-reference/models) to be used to execute this run. If a value is + * provided here, it will override the model associated with the assistant. If not, the model + * associated with the assistant will be used. + */ + `model`?: string | null; + + /** + * Override the default system message of the assistant. This is useful for modifying the behavior + * on a per-run basis. + */ + instructions?: string | null; + + /** + * Override the tools the assistant can use for this run. This is useful for modifying the + * behavior on a per-run basis. + */ + tools?: CreateRunRequestTools | null; + + /** + * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + * additional information about the object in a structured format. Keys can be a maximum of 64 + * characters long and values can be a maxium of 512 characters long. + */ + @extension("x-oaiTypeLabel", "map") + metadata?: Record | null; +} + +model SubmitToolOutputsRunRequest { + /** A list of tools for which the outputs are being submitted. */ + tool_outputs: { + /** + * The ID of the tool call in the `required_action` object within the run object the output is + * being submitted for. */ + tool_call_id?: string; + + /** The output of the tool call to be submitted to continue the run. */ + output?: string; + } +} + +model ListRunsResponse { + object: "list"; + data: RunObject[]; + first_id: string; + last_id: string; + has_more: boolean; +} + +model ListRunStepsResponse { + object: "list"; + data: RunStepObject[]; + first_id: string; + last_id: string; + has_more: boolean; +} + +@maxItems(20) +model CreateRunRequestTools is CreateRunRequestTool[]; + +@oneOf +@extension("x-oaiExpandable", true) +union CreateRunRequestTool { + AssistantToolsCode, + AssistantToolsRetrieval, + AssistantToolsFunction +} + +@oneOf +@extension("x-oaiExpandable", true) +union RunStepDetails { + RunStepDetailsMessageCreationObject, + RunStepDetailsToolCallsObject, +} + +/** Details of the message creation by the run step. */ +model RunStepDetailsMessageCreationObject { + /** Details of the message creation by the run step. */ + type: "message_creation"; + + message_creation: { + /** The ID of the message that was created by this run step. */ + message_id: string; + } +} + +/** Details of the tool call. */ +model RunStepDetailsToolCallsObject { + /** Always `tool_calls`. */ + type: "tool_calls"; + + /** + * An array of tool calls the run step was involved in. These can be associated with one of three + * types of tools: `code_interpreter`, `retrieval`, or `function`. + */ + tool_calls: RunStepDetailsToolCallsObjectToolCalls; +} + +model RunStepDetailsToolCallsObjectToolCalls is RunStepDetailsToolCallsObjectToolCall[]; + +@oneOf +@extension("x-oaiExpandable", true) +union RunStepDetailsToolCallsObjectToolCall { + RunStepDetailsToolCallsCodeObject, + RunStepDetailsToolCallsRetrievalObject, + RunStepDetailsToolCallsFunctionObject, +} + +/** Details of the Code Interpreter tool call the run step was involved in. */ +model RunStepDetailsToolCallsCodeObject { + /** The ID of the tool call. */ + id: string; + + /** + * The type of tool call. This is always going to be `code_interpreter` for this type of tool + * call. + */ + type: "code_interpreter"; + + /** The Code Interpreter tool call definition. */ + code_interpreter: { + /** The input to the Code Interpreter tool call. */ + input: string; + + /** + * The outputs from the Code Interpreter tool call. Code Interpreter can output one or more + * items, including text (`logs`) or images (`image`). Each of these are represented by a + * different object type. + */ + outputs: RunStepDetailsToolCallsCodeOutputs; + } +} + +model RunStepDetailsToolCallsCodeOutputs is RunStepDetailsToolCallsCodeOutput[]; + +@oneOf +@extension("x-oaiExpandable", true) +union RunStepDetailsToolCallsCodeOutput { + RunStepDetailsToolCallsCodeOutputLogsObject, + RunStepDetailsToolCallsCodeOutputImageObject, +} + +/** Text output from the Code Interpreter tool call as part of a run step. */ +model RunStepDetailsToolCallsCodeOutputLogsObject { + /** Always `logs`. */ + type: "logs"; + + /** The text output from the Code Interpreter tool call. */ + logs: string; +} + +model RunStepDetailsToolCallsCodeOutputImageObject { + /** Always `image`. */ + type: "image"; + + image: { + /** The [file](/docs/api-reference/files) ID of the image. */ + file_id: string; + } +} + +model RunStepDetailsToolCallsRetrievalObject { + /** The ID of the tool call object. */ + id: string; + + /** The type of tool call. This is always going to be `retrieval` for this type of tool call. */ + type: "retrieval"; + + /** For now, this is always going to be an empty object. */ + @extension("x-oaiTypeLabel", "map") + retrieval: { }; // TODO: Is this the appropriate way to represent an empty object? +} + +model RunStepDetailsToolCallsFunctionObject { + /** The ID of the tool call object. */ + id: string; + + /** The type of tool call. This is always going to be `function` for this type of tool call. */ + type: "function"; + + /** The definition of the function that was called. */ + function: { + /** The name of the function. */ + name: string; + + /** The arguments passed to the function. */ + arguments: string; + + /** + * The output of the function. This will be `null` if the outputs have not been + * [submitted](/docs/api-reference/runs/submitToolOutputs) yet. + */ + output: string | null; + } +} + +/** + * Usage statistics related to the run. This value will be `null` if the run is not in a terminal + * state (i.e. `in_progress`, `queued`, etc.). + */ +model RunCompletionUsage { + /** Number of completion tokens used over the course of the run. */ + completion_tokens: safeint; + + /** Number of prompt tokens used over the course of the run. */ + prompt_tokens: safeint; + + /** Total number of tokens used (prompt + completion). */ + total_tokens: safeint; +} + +/** + * Usage statistics related to the run step. This value will be `null` while the run step's status + * is `in_progress`. + */ +model RunStepCompletionUsage { + /** Number of completion tokens used over the course of the run step. */ + completion_tokens: safeint; + + /** Number of prompt tokens used over the course of the run step. */ + prompt_tokens: safeint; + + /** Total number of tokens used (prompt + completion). */ + total_tokens: safeint; +} + +/** Represents an execution run on a [thread](/docs/api-reference/threads). */ +model RunObject { + /** The identifier, which can be referenced in API endpoints. */ + id: string; + + /** The object type, which is always `thread.run`. */ + object: "thread.run"; + + /** The Unix timestamp (in seconds) for when the run was created. */ + @encode("unixTimestamp", int32) + created_at: utcDateTime; + + /** + * The ID of the [thread](/docs/api-reference/threads) that was executed on as a part of this + * run. + */ + thread_id: string; + + /** The ID of the [assistant](/docs/api-reference/assistants) used for execution of this run. */ + assistant_id: string; + + /** + * The status of the run, which can be either `queued`, `in_progress`, `requires_action`, + * `cancelling`, `cancelled`, `failed`, `completed`, or `expired`. + */ + status: + | "queued" + | "in_progress" + | "requires_action" + | "cancelling" + | "cancelled" + | "failed" + | "completed" + | "expired"; + + /** + * Details on the action required to continue the run. Will be `null` if no action is + * required. + */ + required_action: { + /** For now, this is always `submit_tool_outputs`. */ + type: "ubmit_tool_outputs"; + + /** Details on the tool outputs needed for this run to continue. */ + submit_tool_outputs: { + /** A list of the relevant tool calls. */ + tool_calls: RunToolCallObject[]; + } + } | null; + + /** The last error associated with this run. Will be `null` if there are no errors. */ + last_error: { + /** One of `server_error` or `rate_limit_exceeded`. */ + code: "server_error" | "rate_limit_exceeded"; + + /** A human-readable description of the error. */ + message: string; + } | null; + + /** The Unix timestamp (in seconds) for when the run will expire. */ + @encode("unixTimestamp", int32) + expires_at: utcDateTime; + + /** The Unix timestamp (in seconds) for when the run was started. */ + @encode("unixTimestamp", int32) + started_at: utcDateTime | null; + + /** The Unix timestamp (in seconds) for when the run was cancelled. */ + @encode("unixTimestamp", int32) + cancelled_at: utcDateTime | null; + + /** The Unix timestamp (in seconds) for when the run failed. */ + @encode("unixTimestamp", int32) + failed_at: utcDateTime | null; + + /** The Unix timestamp (in seconds) for when the run was completed. */ + @encode("unixTimestamp", int32) + completed_at: utcDateTime | null; + + /** The model that the [assistant](/docs/api-reference/assistants) used for this run. */ + `model`: string; + + /** The instructions that the [assistant](/docs/api-reference/assistants) used for this run. */ + instructions: string; + + /** The list of tools that the [assistant](/docs/api-reference/assistants) used for this run. */ + tools: CreateRunRequestTools; + + /** + * The list of [File](/docs/api-reference/files) IDs the + * [assistant](/docs/api-reference/assistants) used for this run. + */ + file_ids: string[] = []; + + /** + * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + * additional information about the object in a structured format. Keys can be a maximum of 64 + * characters long and values can be a maxium of 512 characters long. + */ + @extension("x-oaiTypeLabel", "map") + metadata: Record | null; + + usage: RunCompletionUsage | null; +} + +/** Represents a step in execution of a run. */ +model RunStepObject { + /** The identifier of the run step, which can be referenced in API endpoints. */ + id: string; + + /** The object type, which is always `thread.run.step`. */ + object: "thread.run.step"; + + /** The Unix timestamp (in seconds) for when the run step was created. */ + @encode("unixTimestamp", int32) + created_at: utcDateTime; + + /** The ID of the [assistant](/docs/api-reference/assistants) associated with the run step. */ + assistant_id: string; + + /** The ID of the [thread](/docs/api-reference/threads) that was run. */ + thread_id: string; + + /** The ID of the [run](/docs/api-reference/runs) that this run step is a part of. */ + run_id: string; + + /** The type of run step, which can be either `message_creation` or `tool_calls`. */ + type: "message_creation" | "tool_calls"; + + /** + * The status of the run step, which can be either `in_progress`, `cancelled`, `failed`, + * `completed`, or `expired`. + */ + status: "in_progress" | "cancelled" | "failed" | "completed" | "expired"; + + /** The details of the run step. */ + step_details: RunStepDetails; + + /** The last error associated with this run step. Will be `null` if there are no errors. */ + last_error: { + /** One of `server_error` or `rate_limit_exceeded`. */ + code: "server_error" | "rate_limit_exceeded"; + + /** A human-readable description of the error. */ + message: string; + } | null; + + /** + * The Unix timestamp (in seconds) for when the run step expired. A step is considered expired + * if the parent run is expired. + */ + @encode("unixTimestamp", int32) + expires_at: utcDateTime; + + /** The Unix timestamp (in seconds) for when the run step was cancelled. */ + @encode("unixTimestamp", int32) + cancelled_at: utcDateTime | null; + + /** The Unix timestamp (in seconds) for when the run step failed. */ + @encode("unixTimestamp", int32) + failed_at: utcDateTime | null; + + /** T The Unix timestamp (in seconds) for when the run step completed.. */ + @encode("unixTimestamp", int32) + completed_at: utcDateTime | null; + + /** + * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + * additional information about the object in a structured format. Keys can be a maximum of 64 + * characters long and values can be a maxium of 512 characters long. + */ + @extension("x-oaiTypeLabel", "map") + metadata: Record | null; + + usage: RunCompletionUsage | null; +} + +/** Tool call objects */ +model RunToolCallObject { + /** + * The ID of the tool call. This ID must be referenced when you submit the tool outputs in using + * the [Submit tool outputs to run](/docs/api-reference/runs/submitToolOutputs) endpoint. + */ + id: string; + + /** The type of tool call the output is required for. For now, this is always `function`. */ + type: "function"; + + /** The function definition. */ + function: { + /** The name of the function. */ + name: string; + + /** The arguments that the model expects you to pass to the function. */ + arguments: string; + } +} \ No newline at end of file diff --git a/runs/operations.tsp b/runs/operations.tsp new file mode 100644 index 000000000..0a7c3ab2b --- /dev/null +++ b/runs/operations.tsp @@ -0,0 +1,185 @@ +import "@typespec/http"; +import "@typespec/openapi"; + +import "../common/errors.tsp"; +import "./models.tsp"; + +using TypeSpec.Http; +using TypeSpec.OpenAPI; + +namespace OpenAI; + +@route("threads") +interface Runs { + @route("runs") + @post + @operationId("createThreadAndRun") + @tag("OpenAI") + @summary("Create a thread and run it in one request.") + createThreadAndRun( + @body threadAndRun: CreateThreadAndRunRequest; + ): RunObject | ErrorResponse; + + @route("{thread_id}/runs") + @post + @operationId("createRun") + @tag("OpenAI") + @summary("Create a run.") + createRun( + /** The ID of the thread to run. */ + @path thread_id: string, + + @body run: CreateRunRequest, + ): RunObject | ErrorResponse; + + @route("thread_id}/runs") + @get + @operationId("listRuns") + @tag("OpenAI") + @summary("Returns a list of runs belonging to a thread.") + listRuns( + /** The ID of the thread the run belongs to. */ + @path thread_id: string, + + /** + * A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + * default is 20. + */ + @query limit?: int32 = 20; + + /** + * Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + * for descending order. + */ + @query order?: "asc" | "desc" = "desc"; + + /** + * A cursor for use in pagination. `after` is an object ID that defines your place in the list. + * For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + * subsequent call can include after=obj_foo in order to fetch the next page of the list. + */ + @query after?: string; + + /** + * A cursor for use in pagination. `before` is an object ID that defines your place in the list. + * For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + * subsequent call can include before=obj_foo in order to fetch the previous page of the list. + */ + @query before?: string; + ): ListRunsResponse | ErrorResponse; + + @route("{thread_id}/runs/{run_id}") + @get + @operationId("getRun") + @tag("OpenAI") + @summary("Retrieves a run.") + getRun( + /** The ID of the [thread](/docs/api-reference/threads) that was run. */ + @path thread_id: string, + + /** The ID of the run to retrieve. */ + @path run_id: string, + ): RunObject | ErrorResponse; + + @route("{thread_id}/runs/{run_id}") + @post + @operationId("modifyRun") + @tag("OpenAI") + @summary("Modifies a run.") + modifyRun( + /** The ID of the [thread](/docs/api-reference/threads) that was run. */ + @path thread_id: string, + + /** The ID of the run to modify. */ + @path run_id: string, + + @body run: ModifyRunRequest, + ): RunObject | ErrorResponse; + + @route("{thread_id}/runs/{run_id}/cancel") + @post + @operationId("cancelRun") + @tag("OpenAI") + @summary("Cancels a run that is `in_progress`.") + cancelRun( + /** The ID of the thread to which this run belongs. */ + @path thread_id: string, + + /** The ID of the run to cancel. */ + @path run_id: string, + ): RunObject | ErrorResponse; + + @route("{thread_id}/runs/{run_id}/submit_tool_outputs") + @post + @operationId("submitToolOuputsToRun") + @tag("OpenAI") + @summary(""" + When a run has the `status: "requires_action"` and `required_action.type` is + `submit_tool_outputs`, this endpoint can be used to submit the outputs from the tool calls once + they're all completed. All outputs must be submitted in a single request. + """) + submitToolOuputsToRun( + /** The ID of the [thread](/docs/api-reference/threads) to which this run belongs. */ + @path thread_id: string, + + /** The ID of the run that requires the tool output submission. */ + @path run_id: string, + + @body submitToolOutputsRun: SubmitToolOutputsRunRequest, + ): RunObject | ErrorResponse; + + @route("{thread_id}/runs/{run_id}/steps") + @get + @operationId("listRunSteps") + @tag("OpenAI") + @summary("Returns a list of run steps belonging to a run.") + listRunSteps( + /** The ID of the thread the run and run steps belong to. */ + @path thread_id: string, + + /** The ID of the run the run steps belong to. */ + @path run_id: string, + + /** + * A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + * default is 20. + */ + @query limit?: int32 = 20; + + /** + * Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + * for descending order. + */ + @query order?: "asc" | "desc" = "desc"; + + /** + * A cursor for use in pagination. `after` is an object ID that defines your place in the list. + * For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + * subsequent call can include after=obj_foo in order to fetch the next page of the list. + */ + @query after?: string; + + /** + * A cursor for use in pagination. `before` is an object ID that defines your place in the list. + * For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + * subsequent call can include before=obj_foo in order to fetch the previous page of the list. + */ + @query before?: string; + ): ListRunStepsResponse | ErrorResponse; + + @route("{thread_id}/runs/{run_id}/steps/{step_id}") + @get + @operationId("getRunStep") + @tag("OpenAI") + @summary("Retrieves a run step.") + getRunStep( + /** The ID of the thread to which the run and run step belongs. */ + @path thread_id: string, + + /** The ID of the run to which the run step belongs. */ + @path run_id: string, + + /** The ID of the run step to retrieve. */ + @path step_id: string, + ): RunStepObject | ErrorResponse; +} \ No newline at end of file diff --git a/threads/main.tsp b/threads/main.tsp new file mode 100644 index 000000000..6a754bcb5 --- /dev/null +++ b/threads/main.tsp @@ -0,0 +1 @@ +import "./operations.tsp"; \ No newline at end of file diff --git a/threads/meta.tsp b/threads/meta.tsp new file mode 100644 index 000000000..9a6edf95b --- /dev/null +++ b/threads/meta.tsp @@ -0,0 +1,22 @@ +import "./models.tsp"; + +import "@typespec/openapi"; + +using TypeSpec.OpenAPI; + +namespace OpenAI; + +@@extension(OpenAI.ThreadObject, + "x-oaiMeta", + """ + name: The thread object + beta: true + example: | + { + "id": "thread_abc123", + "object": "thread", + "created_at": 1698107661, + "metadata": {} + } + """ +); \ No newline at end of file diff --git a/threads/models.tsp b/threads/models.tsp new file mode 100644 index 000000000..4bdb28fae --- /dev/null +++ b/threads/models.tsp @@ -0,0 +1,55 @@ +import "../common/models.tsp"; +import "../messages/models.tsp"; + +using TypeSpec.Http; +using TypeSpec.OpenAPI; + +namespace OpenAI; + +model CreateThreadRequest { + /** A list of [messages](/docs/api-reference/messages) to start the thread with. */ + messages?: CreateMessageRequest[]; + + /** + * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + * additional information about the object in a structured format. Keys can be a maximum of 64 + * characters long and values can be a maxium of 512 characters long. + */ + metadata?: Record | null; +} + +model ModifyThreadRequest { + /** + * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + * additional information about the object in a structured format. Keys can be a maximum of 64 + * characters long and values can be a maxium of 512 characters long. + */ + metadata?: Record | null; +} + +model DeleteThreadResponse { + id: string; + deleted: boolean; + object: "thread.deleted"; +} + +/** Represents a thread that contains [messages](/docs/api-reference/messages). */ +model ThreadObject { + /** The identifier, which can be referenced in API endpoints. */ + id: string; + + /** The object type, which is always `thread`. */ + object: "thread"; + + /** The Unix timestamp (in seconds) for when the thread was created. */ + @encode("unixTimestamp", int32) + created_at: utcDateTime; + + /** + * Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + * additional information about the object in a structured format. Keys can be a maximum of 64 + * characters long and values can be a maxium of 512 characters long. + */ + @extension("x-oaiTypeLabel", "map") + metadata: Record | null; +} \ No newline at end of file diff --git a/threads/operations.tsp b/threads/operations.tsp new file mode 100644 index 000000000..e2599024e --- /dev/null +++ b/threads/operations.tsp @@ -0,0 +1,52 @@ +import "@typespec/http"; +import "@typespec/openapi"; + +import "../common/errors.tsp"; +import "./models.tsp"; + +using TypeSpec.Http; +using TypeSpec.OpenAPI; + +namespace OpenAI; + +@route("/threads") +interface Threads { + @post + @operationId("createThread") + @tag("OpenAI") + @summary("Create a thread.") + createThread( + @body thread: CreateThreadRequest, + ): ThreadObject | ErrorResponse; + + @route("{thread_id}") + @get + @operationId("getThread") + @tag("OpenAI") + @summary("Retrieves a thread.") + getThread( + /** The ID of the thread to retrieve. */ + @path thread_id: string, + ): ThreadObject | ErrorResponse; + + @route("{thread_id}") + @post + @operationId("modifyThread") + @tag("OpenAI") + @summary("Modifies a thread.") + modifyThread( + /** The ID of the thread to modify. Only the `metadata` can be modified. */ + @path thread_id: string, + @body thread: ModifyThreadRequest, + ): ThreadObject | ErrorResponse; + + @route("{thread_id}") + @delete + @operationId("deleteThread") + @tag("OpenAI") + @summary("Delete a thread.") + deleteThread( + /** The ID of the thread to delete. */ + @path thread_id: string, + ): DeleteThreadResponse | ErrorResponse; +} From dd840f70516fa3037b8a161878b7b00778f782c4 Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado Date: Wed, 7 Feb 2024 15:41:48 -0800 Subject: [PATCH 03/50] Re-generate OpenAPI spec with a few fixes --- assistants/models.tsp | 8 +- assistants/operations.tsp | 18 +- audio/models.tsp | 15 +- audio/operations.tsp | 14 +- chat/meta.tsp | 3 +- chat/models.tsp | 59 +- chat/operations.tsp | 2 +- common/models.tsp | 2 + completions/meta.tsp | 35 + completions/models.tsp | 42 +- completions/operations.tsp | 2 +- embeddings/meta.tsp | 24 + embeddings/models.tsp | 41 +- embeddings/operations.tsp | 2 +- files/meta.tsp | 22 + files/models.tsp | 16 - files/operations.tsp | 13 +- fine-tuning/operations.tsp | 20 +- images/meta.tsp | 18 + images/models.tsp | 18 +- images/operations.tsp | 6 +- messages/models.tsp | 5 +- messages/operations.tsp | 14 +- models/meta.tsp | 15 + models/models.tsp | 10 +- models/operations.tsp | 6 +- moderations/meta.tsp | 15 + moderations/models.tsp | 18 +- moderations/operations.tsp | 2 +- readme.md | 2 + runs/models.tsp | 4 +- runs/operations.tsp | 18 +- threads/operations.tsp | 8 +- tsp-output/@typespec/openapi3/openapi.yaml | 6993 ++++++++++++++------ 34 files changed, 5344 insertions(+), 2146 deletions(-) create mode 100644 completions/meta.tsp create mode 100644 embeddings/meta.tsp create mode 100644 files/meta.tsp create mode 100644 images/meta.tsp create mode 100644 models/meta.tsp create mode 100644 moderations/meta.tsp diff --git a/assistants/models.tsp b/assistants/models.tsp index 358d95d48..acea5a1d4 100644 --- a/assistants/models.tsp +++ b/assistants/models.tsp @@ -30,7 +30,7 @@ model CreateAssistantRequest { * Tools can be of types `code_interpreter`, `retrieval`, or `function`. */ - tools?: CreateAssistantRequestTools = []; // TODO: Double-check default empty array + tools?: CreateAssistantRequestTools = []; /** * A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a @@ -73,8 +73,7 @@ model ModifyAssistantRequest { * A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. * Tools can be of types `code_interpreter`, `retrieval`, or `function`. */ - @maxItems(128) - tools?: CreateAssistantRequestTools[] = []; // TODO: Double-check default empty array + tools?: CreateAssistantRequestTools = []; /** * A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a @@ -196,8 +195,7 @@ model AssistantObject { * A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. * Tools can be of types `code_interpreter`, `retrieval`, or `function`. */ - @maxItems(128) - tools: CreateAssistantRequestTools[] = []; // TODO: Double-check default empty array + tools: CreateAssistantRequestTools = []; /** * A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a diff --git a/assistants/operations.tsp b/assistants/operations.tsp index e98f03e7e..2883342b1 100644 --- a/assistants/operations.tsp +++ b/assistants/operations.tsp @@ -13,7 +13,7 @@ namespace OpenAI; interface Assistants { @post @operationId("createAssistant") - @tag("OpenAI") + @tag("Assistants") @summary("Create an assistant with a model and instructions.") createAssistant( @body assistant: CreateAssistantRequest, @@ -21,7 +21,7 @@ interface Assistants { @get @operationId("listAssistants") - @tag("OpenAI") + @tag("Assistants") @summary("Returns a list of assistants.") listFiles( /** @@ -54,7 +54,7 @@ interface Assistants { @route("{assistant_id}") @get @operationId("getAssistant") - @tag("OpenAI") + @tag("Assistants") @summary("Retrieves an assistant.") getAssistant( /** The ID of the assistant to retrieve. */ @@ -64,7 +64,7 @@ interface Assistants { @route("{assistant_id}") @post @operationId("modifyAssistant") - @tag("OpenAI") + @tag("Assistants") @summary("Modifies an assistant.") modifyAssistant( /** The ID of the assistant to modify. */ @@ -76,7 +76,7 @@ interface Assistants { @route("{assistant_id}") @delete @operationId("deleteAssistant") - @tag("OpenAI") + @tag("Assistants") @summary("Delete an assistant.") deleteAssistant( /** The ID of the assistant to delete. */ @@ -86,7 +86,7 @@ interface Assistants { @route("{assistant_id}/files") @post @operationId("createAssistantFile") - @tag("OpenAI") + @tag("Assistants") @summary(""" Create an assistant file by attaching a [File](/docs/api-reference/files) to a [assistant](/docs/api-reference/assistants). @@ -100,7 +100,7 @@ interface Assistants { @route("{assistant_id}/files") @get @operationId("listAssistantFiles") - @tag("OpenAI") + @tag("Assistants") @summary("Returns a list of assistant files.") listAssistantFiles( /** The ID of the assistant the file belongs to. */ @@ -136,7 +136,7 @@ interface Assistants { @route("{assistant_id}/files/{file_id}") @get @operationId("getAssistantFile") - @tag("OpenAI") + @tag("Assistants") @summary("Retrieves an assistant file.") getAssistantFile( /** The ID of the assistant the file belongs to. */ @@ -149,7 +149,7 @@ interface Assistants { @route("{assistant_id}/files/{file_id}") @delete @operationId("deleteAssistantFile") - @tag("OpenAI") + @tag("Assistants") @summary("Delete an assistant file.") deleteAssistantFile( /** The ID of the assistant the file belongs to. */ diff --git a/audio/models.tsp b/audio/models.tsp index ba931af7e..53d7757c3 100644 --- a/audio/models.tsp +++ b/audio/models.tsp @@ -23,11 +23,8 @@ model CreateSpeechRequest { */ voice: "alloy" | "echo" | "fable" | "onyx" | "nova" | "shimmer"; - /** - * The format of the transcript output, in one of these options: json, text, srt, verbose_json, or - * vtt. - */ - response_format?: "json" | "text" | "srt" | "verbose_json" | "vtt" = "json"; + /** The format to audio in. Supported formats are `mp3`, `opus`, `aac`, and `flac`. */ + response_format?: "mp3" | "opus" | "aac" | "flac" = "mp3"; /** * The speed of the generated audio. Select a value from `0.25` to `4.0`. `1.0` is the default. @@ -75,6 +72,7 @@ model CreateTranscriptionRequest { * the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to * automatically increase the temperature until certain thresholds are hit. */ + // NOTE: Min and max values are absent in the OpenAPI spec but mentioned in the description. @minValue(0) @maxValue(1) temperature?: float64 = 0; @@ -112,12 +110,13 @@ model CreateTranslationRequest { * the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to * automatically increase the temperature until certain thresholds are hit. */ + // NOTE: Min and max values are absent in the OpenAPI spec but mentioned in the description. @minValue(0) @maxValue(1) temperature?: float64 = 0; } -// TODO: This model is not defined in the OpenAI API spec. +// NOTE: This model is not defined in the OpenAI API spec. model CreateTranscriptionResponse { /** The transcribed text for the provided audio data. */ text: string; @@ -141,7 +140,7 @@ model CreateTranscriptionResponse { segments?: AudioSegment[]; } -// TODO: This model is not defined in the OpenAI API spec. +// NOTE: This model is not defined in the OpenAI API spec. model CreateTranslationResponse { /** The translated text for the provided audio data. */ text: string; @@ -170,7 +169,7 @@ alias TEXT_TO_SPEECH_MODELS = alias SPEECH_TO_TEXT_MODELS = | "whisper-1"; -// TODO: This model is not defined in the OpenAI API spec. +// NOTE: This model is not defined in the OpenAI API spec. model AudioSegment { /** The zero-based index of this segment. */ id: safeint; diff --git a/audio/operations.tsp b/audio/operations.tsp index a598297bf..ee1cb428e 100644 --- a/audio/operations.tsp +++ b/audio/operations.tsp @@ -14,20 +14,22 @@ interface Audio { @route("speech") @post @operationId("createSpeech") - @tag("OpenAI") + @tag("Audio") @summary("Generates audio from the input text.") createSpeech( @body speech: CreateSpeechRequest, ): { + /** chunked */ + @header("Transfer-Encoding") transferEncoding?: string; + @header contentType: "application/octet-stream"; - @header("Transfer-Encoding") transferEncoding: "chunked"; @body @encode("binary") audio: bytes; }; @route("transcriptions") @post @operationId("createTranscription") - @tag("OpenAI") + @tag("Audio") @summary("Transcribes audio into the input language.") createTranscription( @header contentType: "multipart/form-data", @@ -35,6 +37,7 @@ interface Audio { ): | CreateTranscriptionResponse | { + // TODO: Is this the appropriate way to describe the multiple possible response types? @header contentType: "text/plain"; @body text: string; } @@ -43,14 +46,15 @@ interface Audio { @route("translations") @post @operationId("createTranslation") - @tag("OpenAI") - @summary("Transcribes audio into the input language.") + @tag("Audio") + @summary("Translates audio into English..") createTranslation( @header contentType: "multipart/form-data", @body audio: CreateTranslationRequest, ): | CreateTranslationResponse | { + // TODO: Is this the appropriate way to describe the multiple possible response types? @header contentType: "text/plain"; @body text: string; } diff --git a/chat/meta.tsp b/chat/meta.tsp index 3296a6c42..6df478c87 100644 --- a/chat/meta.tsp +++ b/chat/meta.tsp @@ -1,8 +1,9 @@ import "./operations.tsp"; -namespace OpenAI; using TypeSpec.OpenAPI; +namespace OpenAI; + @@extension(OpenAI.Chat.createChatCompletion, "x-oaiMeta", { diff --git a/chat/models.tsp b/chat/models.tsp index a80178e99..d0d19bc06 100644 --- a/chat/models.tsp +++ b/chat/models.tsp @@ -26,7 +26,9 @@ model CreateChatCompletionRequest { * * [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) */ - frequency_penalty?: Penalty | null = 0; + @minValue(-2) + @maxValue(2) + frequency_penalty?: float64 | null = 0; /** * Modify the likelihood of specified tokens appearing in the completion. @@ -52,7 +54,9 @@ model CreateChatCompletionRequest { * position, each with an associated log probability. `logprobs` must be set to `true` if this * parameter is used. */ - top_logprobs?: TopLogprobs | null; + @minValue(0) + @maxValue(5) + top_logprobs?: safeint | null; /** * The maximum number of [tokens](/tokenizer) that can be generated in the chat completion. @@ -61,14 +65,17 @@ model CreateChatCompletionRequest { * [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) * for counting tokens. */ - max_tokens?: MaxTokens | null = 16; + @minValue(0) + max_tokens?: safeint | null = 16; /** * How many chat completion choices to generate for each input message. Note that you will be * charged based on the number of generated tokens across all of the choices. Keep `n` as `1` to * minimize costs. */ - n?: N | null = 1; + @minValue(1) + @maxValue(128) + n?: safeint | null = 1; /** * Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear @@ -76,7 +83,9 @@ model CreateChatCompletionRequest { * * [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) */ - presence_penalty?: Penalty | null = 0; + @minValue(-2) + @maxValue(2) + presence_penalty?: float64 | null = 0; /** * An object specifying the format that the model must output. Compatible with @@ -112,7 +121,9 @@ model CreateChatCompletionRequest { beta: true } ) - seed?: Seed | null; + @minValue(-9223372036854775808) // TODO: Min and max exceed the limits of safeint. + @maxValue(9223372036854775807) + seed?: safeint | null; // TODO: Consider inlining when https://github.com/microsoft/typespec/issues/2356 is resolved // https://github.com/microsoft/typespec/issues/2355 @@ -133,7 +144,9 @@ model CreateChatCompletionRequest { * * We generally recommend altering this or `top_p` but not both. */ - temperature?: Temperature | null = 1; + @minValue(0) + @maxValue(2) + temperature?: float64 | null = 1; /** * An alternative to sampling with temperature, called nucleus sampling, where the model considers @@ -142,7 +155,9 @@ model CreateChatCompletionRequest { * * We generally recommend altering this or `temperature` but not both. */ - top_p?: TopP | null = 1; + @minValue(0) + @maxValue(1) + top_p?: float64 | null = 1; /** * A list of tools the model may call. Currently, only functions are supported as a tool. Use this @@ -249,34 +264,6 @@ alias CHAT_COMPLETION_MODELS = | "gpt-3.5-turbo-1106" | "gpt-3.5-turbo-16k-0613"; -@minValue(-2) -@maxValue(2) -scalar Penalty extends float64; - -@minValue(0) -@maxValue(2) -scalar Temperature extends float64; - -@minValue(0) -@maxValue(1) -scalar TopP extends float64; - -@minValue(0) -@maxValue(5) -scalar TopLogprobs extends safeint; - -@minValue(1) -@maxValue(128) -scalar N extends safeint; - -@minValue(0) -scalar MaxTokens extends safeint; - -// TODO: Min and max exceed the limits of safeint. -@minValue(-9223372036854775808) -@maxValue(9223372036854775807) -scalar Seed extends safeint; - @oneOf union Stop { string, diff --git a/chat/operations.tsp b/chat/operations.tsp index c2c5aa364..0b2972421 100644 --- a/chat/operations.tsp +++ b/chat/operations.tsp @@ -14,7 +14,7 @@ interface Chat { @route("completions") @post @operationId("createChatCompletion") - @tag("OpenAI") + @tag("Chat") @summary("Creates a model response for the given chat conversation.") createChatCompletion( ...CreateChatCompletionRequest, diff --git a/common/models.tsp b/common/models.tsp index b5bfcc9b3..611e53e7a 100644 --- a/common/models.tsp +++ b/common/models.tsp @@ -33,4 +33,6 @@ model FunctionObject { * about the format.\n\nTo describe a function that accepts no parameters, provide the value * `{\"type\": \"object\", \"properties\": {}}`. */ +// TODO: The generated spec produces "additionalProperties: {}" for this instead of +// "additionalProperties: true". Are they equivalent? model FunctionParameters is Record; \ No newline at end of file diff --git a/completions/meta.tsp b/completions/meta.tsp new file mode 100644 index 000000000..708dea11d --- /dev/null +++ b/completions/meta.tsp @@ -0,0 +1,35 @@ +import "./models.tsp"; +import "./operations.tsp"; + +using TypeSpec.OpenAPI; + +namespace OpenAI; + +// TODO: Fill in example here. +@@extension(OpenAI.CreateCompletionResponse, + "x-oaiMeta", + """ + name: The completion object + legacy: true, + example: | + { + "id": "cmpl-uqkvlQyYK7bGYrRHQ0eXlWi7", + "object": "text_completion", + "created": 1589478378, + "model": "gpt-3.5-turbo", + "choices": [ + { + "text": "\n\nThis is indeed a test", + "index": 0, + "logprobs": null, + "finish_reason": "length" + } + ], + "usage": { + "prompt_tokens": 5, + "completion_tokens": 7, + "total_tokens": 12 + } + } + """ +); \ No newline at end of file diff --git a/completions/models.tsp b/completions/models.tsp index bfe7bf03c..4122d8bda 100644 --- a/completions/models.tsp +++ b/completions/models.tsp @@ -22,7 +22,7 @@ model CreateCompletionRequest { * prompt is not specified the model will generate as if from the beginning of a new document. */ // TODO: consider inlining when https://github.com/microsoft/typespec/issues/2356 fixed - prompt: Prompt = "<|endoftext|>"; + prompt: Prompt | null = "<|endoftext|>"; /** * Generates `best_of` completions server-side and returns the "best" (the one with the highest @@ -48,7 +48,9 @@ model CreateCompletionRequest { * * [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) */ - frequency_penalty?: Penalty | null = 0; + @minValue(-2) + @maxValue(2) + frequency_penalty?: float64 | null = 0; /** * Modify the likelihood of specified tokens appearing in the completion. @@ -85,7 +87,8 @@ model CreateCompletionRequest { * [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) * for counting tokens. */ - max_tokens?: MaxTokens | null = 16; + @minValue(0) + max_tokens?: safeint | null = 16; /** * How many completions to generate for each prompt. @@ -93,7 +96,9 @@ model CreateCompletionRequest { * **Note:** Because this parameter generates many completions, it can quickly consume your token * quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. */ - n?: N | null = 1; + @minValue(1) + @maxValue(128) + n?: safeint | null = 1; /** * Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear @@ -101,7 +106,9 @@ model CreateCompletionRequest { * * [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) */ - presence_penalty?: Penalty | null = 0; + @minValue(-2) + @maxValue(2) + presence_penalty?: float64 | null = 0; /** * If specified, our system will make a best effort to sample deterministically, such that @@ -116,9 +123,11 @@ model CreateCompletionRequest { beta: true } ) - seed?: Seed | null; + @minValue(-9223372036854775808) // TODO: Min and max exceed the limits of safeint. + @maxValue(9223372036854775807) + seed?: safeint | null; - // todo: consider inlining when https://github.com/microsoft/typespec/issues/2356 is resolved + // TODO: Consider inlining when https://github.com/microsoft/typespec/issues/2356 is resolved // https://github.com/microsoft/typespec/issues/2355 /** Up to 4 sequences where the API will stop generating further tokens. */ stop?: Stop | null = null; @@ -140,7 +149,9 @@ model CreateCompletionRequest { * * We generally recommend altering this or `top_p` but not both. */ - temperature?: Temperature | null = 1; + @minValue(0) + @maxValue(2) + temperature?: float64 | null = 1; /** * An alternative to sampling with temperature, called nucleus sampling, where the model considers @@ -149,7 +160,9 @@ model CreateCompletionRequest { * * We generally recommend altering this or `temperature` but not both. */ - top_p?: TopP | null = 1; + @minValue(0) + @maxValue(1) + top_p?: float64 | null = 1; /** * A unique identifier representing your end-user, which can help OpenAI to monitor and detect @@ -162,14 +175,6 @@ model CreateCompletionRequest { * Represents a completion response from the API. Note: both the streamed and non-streamed response * objects share the same shape (unlike the chat endpoint). */ -@extension( - "x-oaiMeta", - { - name: "The completion object", - legacy: true, - example: "", // fill in - } -) model CreateCompletionResponse { /** A unique identifier for the completion. */ id: string; @@ -192,6 +197,8 @@ model CreateCompletionResponse { * in the request was reached, or `content_filter` if content was omitted due to a flag from our * content filters. */ + // TODO: The generated spec includes other values like "tool_calls" and "function_call". + // Is it because we're importing /chat/models.tsp? finish_reason: "stop" | "length" | "content_filter"; }[]; @@ -228,5 +235,4 @@ union Prompt { string[], TokenArray, TokenArrayArray, - null, } \ No newline at end of file diff --git a/completions/operations.tsp b/completions/operations.tsp index e84d3d44c..b24f018df 100644 --- a/completions/operations.tsp +++ b/completions/operations.tsp @@ -13,7 +13,7 @@ namespace OpenAI; interface Completions { @post @operationId("createCompletion") - @tag("OpenAI") + @tag("Completions") @summary("Creates a completion for the provided prompt and parameters.") createCompletion( ...CreateCompletionRequest, diff --git a/embeddings/meta.tsp b/embeddings/meta.tsp new file mode 100644 index 000000000..284eb01dc --- /dev/null +++ b/embeddings/meta.tsp @@ -0,0 +1,24 @@ +import "./models.tsp"; +import "./operations.tsp"; + +using TypeSpec.OpenAPI; + +namespace OpenAI; + +@@extension(OpenAI.Embedding, + "x-oaiMeta", + """ + name: The embedding object + example: | + { + "object": "embedding", + "embedding": [ + 0.0023064255, + -0.009327292, + .... (1536 floats total for ada-002) + -0.0028842222, + ], + "index": 0 + } + """ +); \ No newline at end of file diff --git a/embeddings/models.tsp b/embeddings/models.tsp index fa80cac4b..fd9c13fde 100644 --- a/embeddings/models.tsp +++ b/embeddings/models.tsp @@ -14,7 +14,7 @@ model CreateEmbeddingRequest { * for counting tokens. */ @extension("x-oaiExpandable", true) - input: string | string[] | TokenArray | TokenArrayArray; + input: CreateEmbeddingRequestInput; /** * ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to @@ -28,12 +28,13 @@ model CreateEmbeddingRequest { * The format to return the embeddings in. Can be either `float` or * [`base64`](https://pypi.org/project/pybase64/). */ - encoding_format?: "float" | "base64" | null = "float"; + encoding_format?: "float" | "base64" = "float"; /** * The number of dimensions the resulting output embeddings should have. Only supported in * `text-embedding-3` and later models. */ + @minValue(1) dimensions?: safeint; /** @@ -50,7 +51,7 @@ model CreateEmbeddingResponse { /** The name of the model used to generate the embedding. */ `model`: string; - /** The object type, which is always "embedding". */ + /** The object type, which is always "list". */ object: "list"; /** The usage information for the request. */ @@ -68,25 +69,23 @@ alias EMBEDDINGS_MODELS = | "text-embedding-3-small" | "text-embedding-3-large"; +@oneOf +union CreateEmbeddingRequestInput +{ + /** The string that will be turned into an embedding. */ + string, + + /** The array of strings that will be turned into an embedding. */ + string[], + + /** The array of integers that will be turned into an embedding. */ + TokenArray, + + /** The array of arrays containing integers that will be turned into an embedding. */ + TokenArrayArray; +} + /** Represents an embedding vector returned by embedding endpoint. */ -@extension( - "x-oaiMeta", - { - name: "The embedding object", - example: | """ - { - "object": "embedding", - "embedding": [ - 0.0023064255, - -0.009327292, - .... (1536 floats total for ada-002) - -0.0028842222, - ], - "index": 0 - } - """ - } -) model Embedding { /** The index of the embedding in the list of embeddings. */ index: safeint; diff --git a/embeddings/operations.tsp b/embeddings/operations.tsp index c53347e6f..61c8e1839 100644 --- a/embeddings/operations.tsp +++ b/embeddings/operations.tsp @@ -13,7 +13,7 @@ namespace OpenAI; interface Embeddings { @post @operationId("createEmbedding") - @tag("OpenAI") + @tag("Embeddings") @summary("Creates an embedding vector representing the input text.") createEmbedding( @body embedding: CreateEmbeddingRequest, diff --git a/files/meta.tsp b/files/meta.tsp new file mode 100644 index 000000000..d1c14977b --- /dev/null +++ b/files/meta.tsp @@ -0,0 +1,22 @@ +import "./models.tsp"; +import "./operations.tsp"; + +using TypeSpec.OpenAPI; + +namespace OpenAI; + +@@extension(OpenAI.OpenAIFile, + "x-oaiMeta", + """ + name: The file object + example: | + { + "id": "file-abc123", + "object": "file", + "bytes": 120000, + "created_at": 1677610602, + "filename": "salesOverview.pdf", + "purpose": "assistants", + } + """ +); \ No newline at end of file diff --git a/files/models.tsp b/files/models.tsp index 72a263413..fdd2b1f45 100644 --- a/files/models.tsp +++ b/files/models.tsp @@ -36,22 +36,6 @@ alias FILE_PURPOSE = | "assistants_output"; /** The `File` object represents a document that has been uploaded to OpenAI. */ -@extension( - "x-oaiMeta", - { - name: "The file object", - example: | """ - { - "id": "file-abc123", - "object": "file", - "bytes": 120000, - "created_at": 1677610602, - "filename": "salesOverview.pdf", - "purpose": "assistants", - } - """ - } -) model OpenAIFile { /** The file identifier, which can be referenced in the API endpoints. */ id: string; diff --git a/files/operations.tsp b/files/operations.tsp index eec58470a..dda5f95b8 100644 --- a/files/operations.tsp +++ b/files/operations.tsp @@ -13,7 +13,7 @@ namespace OpenAI; interface Files { @post @operationId("createFile") - @tag("OpenAI") + @tag("Files") @summary(""" Upload a file that can be used across various endpoints. The size of all the files uploaded by one organization can be up to 100 GB. @@ -31,17 +31,18 @@ interface Files { @get @operationId("listFiles") - @tag("OpenAI") + @tag("Files") @summary("Returns a list of files that belong to the user's organization.") listFiles( /** Only return files with the given purpose. */ + // NOTE: This is just a string in the OpenAPI spec. @query purpose?: FILE_PURPOSE, ): ListFilesResponse | ErrorResponse; @route("{file_id}") @get @operationId("retrieveFile") - @tag("OpenAI") + @tag("Files") @summary("Returns information about a specific file.") retrieveFile( /** The ID of the file to use for this request. */ @@ -51,7 +52,7 @@ interface Files { @route("{file_id}") @delete @operationId("deleteFile") - @tag("OpenAI") + @tag("Files") @summary("Delete a file") deleteFile( /** The ID of the file to use for this request. */ @@ -61,10 +62,10 @@ interface Files { @route("{file_id}/content") @get @operationId("downloadFile") - @tag("OpenAI") + @tag("Files") @summary("Returns the contents of the specified file.") downloadFile( /** The ID of the file to use for this request. */ @path file_id: string, - ): string | ErrorResponse; + ): string | ErrorResponse; // TODO: The OpenAPI spec says this is a string but the Content-Type is application/json? } diff --git a/fine-tuning/operations.tsp b/fine-tuning/operations.tsp index 258382397..07f48e802 100644 --- a/fine-tuning/operations.tsp +++ b/fine-tuning/operations.tsp @@ -22,14 +22,14 @@ namespace FineTuning { * [Learn more about fine-tuning](/docs/guides/fine-tuning) */ @post - @tag("OpenAI") + @tag("Fine-tuning") @operationId("createFineTuningJob") createFineTuningJob( @body job: CreateFineTuningJobRequest, ): FineTuningJob | ErrorResponse; @get - @tag("OpenAI") + @tag("Fine-tuning") @operationId("listPaginatedFineTuningJobs") listPaginatedFineTuningJobs( /** Identifier for the last job from the previous pagination request. */ @@ -45,7 +45,7 @@ namespace FineTuning { [Learn more about fine-tuning](/docs/guides/fine-tuning) """) @route("{fine_tuning_job_id}") - @tag("OpenAI") + @tag("Fine-tuning") @get @operationId("retrieveFineTuningJob") retrieveFineTuningJob( @@ -53,7 +53,7 @@ namespace FineTuning { ): FineTuningJob | ErrorResponse; @summary("Get status updates for a fine-tuning job.") - @tag("OpenAI") + @tag("Fine-tuning") @route("{fine_tuning_job_id}/events") @get @operationId("listFineTuningEvents") @@ -69,7 +69,7 @@ namespace FineTuning { ): ListFineTuningJobEventsResponse | ErrorResponse; @summary("Immediately cancel a fine-tune job.") - @tag("OpenAI") + @tag("Fine-tuning") @route("{fine_tuning_job_id}/cancel") @post @operationId("cancelFineTuningJob") @@ -84,7 +84,7 @@ namespace FineTuning { interface FineTunes { #deprecated "deprecated" @post - @tag("OpenAI") + @tag("Fine-tuning") @summary(""" Creates a job that fine-tunes a specified model from a given dataset. @@ -99,7 +99,7 @@ interface FineTunes { #deprecated "deprecated" @get - @tag("OpenAI") + @tag("Fine-tuning") @summary("List your organization's fine-tuning jobs") @operationId("listFineTunes") listFineTunes(): ListFineTunesResponse | ErrorResponse; @@ -107,7 +107,7 @@ interface FineTunes { #deprecated "deprecated" @get @route("{fine_tune_id}") - @tag("OpenAI") + @tag("Fine-tuning") @summary(""" Gets info about the fine-tune job. @@ -122,7 +122,7 @@ interface FineTunes { #deprecated "deprecated" @route("{fine_tune_id}/events") @get - @tag("OpenAI") + @tag("Fine-tuning") @summary("Get fine-grained status updates for a fine-tune job.") @operationId("listFineTuneEvents") listFineTuneEvents( @@ -144,7 +144,7 @@ interface FineTunes { #deprecated "deprecated" @route("{fine_tune_id}/cancel") @post - @tag("OpenAI") + @tag("Fine-tuning") @summary("Immediately cancel a fine-tune job.") @operationId("cancelFineTune") cancelFineTune( diff --git a/images/meta.tsp b/images/meta.tsp new file mode 100644 index 000000000..79e02b4ee --- /dev/null +++ b/images/meta.tsp @@ -0,0 +1,18 @@ +import "./models.tsp"; +import "./operations.tsp"; + +using TypeSpec.OpenAPI; + +namespace OpenAI; + +@@extension(OpenAI.Image, + "x-oaiMeta", + """ + name: "The image object", + example: | + { + "url": "...", + "revised_prompt": "..." + } + """ +); \ No newline at end of file diff --git a/images/models.tsp b/images/models.tsp index 42f14f067..e308ade23 100644 --- a/images/models.tsp +++ b/images/models.tsp @@ -19,14 +19,14 @@ model CreateImageRequest { * The number of images to generate. Must be between 1 and 10. For `dall-e-3`, only `n=1` is * supported. */ + // TODO: This is generated as a "oneOf" in the tsp-output? n?: ImagesN | null = 1; /** * The quality of the image that will be generated. `hd` creates images with finer details and * greater consistency across the image. This param is only supported for `dall-e-3`. - * - * TODO: Confirm that this is actually nullable. */ + // NOTE: This is not marked as nullable in the OpenAPI spec. quality?: "standard" | "hd" | null = "standard"; /** The format in which the generated images are returned. Must be one of `url` or `b64_json`. */ @@ -61,6 +61,8 @@ model CreateImageEditRequest { image: bytes; /** A text description of the desired image(s). The maximum length is 1000 characters. */ + // NOTE: Max length is not defined in the OpenAI spec but mentioned in the description. + @maxLength(1000) prompt: string; /** @@ -135,18 +137,6 @@ model ImagesResponse { scalar ImagesN extends safeint; /** Represents the url or the content of an image generated by the OpenAI API. */ -@extension( - "x-oaiMeta", - { - name: "The image object", - example: | """ - { - "url": "...", - "revised_prompt": "..." - } - """ - } -) model Image { /** The base64-encoded JSON of the generated image, if `response_format` is `b64_json`. */ @encode("base64", string) diff --git a/images/operations.tsp b/images/operations.tsp index 59928894f..4db5886ae 100644 --- a/images/operations.tsp +++ b/images/operations.tsp @@ -14,7 +14,7 @@ interface Images { @route("generations") @post @operationId("createImage") - @tag("OpenAI") + @tag("Images") @summary("Creates an image given a prompt") createImage( @body image: CreateImageRequest @@ -23,7 +23,7 @@ interface Images { @route("edits") @post @operationId("createImageEdit") - @tag("OpenAI") + @tag("Images") @summary("Creates an edited or extended image given an original image and a prompt.") createImageEdit( @header contentType: "multipart/form-data", @@ -33,7 +33,7 @@ interface Images { @route("variations") @post @operationId("createImageVariation") - @tag("OpenAI") + @tag("Images") @summary("Creates an edited or extended image given an original image and a prompt.") createImageVariation( @header contentType: "multipart/form-data", diff --git a/messages/models.tsp b/messages/models.tsp index 075bef16d..67d78db29 100644 --- a/messages/models.tsp +++ b/messages/models.tsp @@ -7,7 +7,7 @@ namespace OpenAI; model CreateMessageRequest { /** The role of the entity that is creating the message. Currently only `user` is supported. */ - role: "user"; + role: "user"; // TODO: The generated spec add "assistants" to this enum. /** The content of the message. */ @minLength(1) @@ -125,9 +125,10 @@ model MessageContentImageFileObject { } } +/** The text content that is part of a message. */ model MessageContentTextObject { /** Always `text`. */ - type: "text"; + type: "text"; // TODO: The generated spec adds "json_object" to this enum. text: { /** The data that makes up the text. */ diff --git a/messages/operations.tsp b/messages/operations.tsp index 3cdf4ea84..0c9843e0a 100644 --- a/messages/operations.tsp +++ b/messages/operations.tsp @@ -13,7 +13,7 @@ namespace OpenAI; interface Messages { @post @operationId("createMessage") - @tag("OpenAI") + @tag("Assistants") @summary("Create a message.") createMessage( /** The ID of the [thread](/docs/api-reference/threads) to create a message for. */ @@ -24,7 +24,7 @@ interface Messages { @get @operationId("listMessages") - @tag("OpenAI") + @tag("Assistants") @summary("Returns a list of messages for a given thread.") listMessages( /** The ID of the [thread](/docs/api-reference/threads) the messages belong to. */ @@ -60,7 +60,7 @@ interface Messages { @route("{message_id}") @get @operationId("getMessage") - @tag("OpenAI") + @tag("Assistants") @summary("Retrieve a message.") getMessage( /** The ID of the [thread](/docs/api-reference/threads) to which this message belongs. */ @@ -73,7 +73,7 @@ interface Messages { @route("{message_id}") @post @operationId("modifyMessage") - @tag("OpenAI") + @tag("Assistants") @summary("Modifies a message.") modifyMessage( /** The ID of the thread to which this message belongs. */ @@ -88,7 +88,7 @@ interface Messages { @route("{message_id}/files") @get @operationId("listMessageFiles") - @tag("OpenAI") + @tag("Assistants") @summary("Returns a list of message files.") listMessageFiles( /** The ID of the thread that the message and files belong to. */ @@ -127,8 +127,8 @@ interface Messages { @route("{message_id}/files/{file_id}") @get @operationId("getMessageFile") - @tag("OpenAI") - @summary("RRetrieves a message file.") + @tag("Assistants") + @summary("Retrieves a message file.") getMessageFile( /** The ID of the thread to which the message and File belong. */ @path thread_id: string, diff --git a/models/meta.tsp b/models/meta.tsp new file mode 100644 index 000000000..cf8dd65dc --- /dev/null +++ b/models/meta.tsp @@ -0,0 +1,15 @@ +import "./models.tsp"; +import "./operations.tsp"; + +using TypeSpec.OpenAPI; + +namespace OpenAI; + +// TODO: Fill in example here. +@@extension(OpenAI.Model, + "x-oaiMeta", + """ + name: "The model object", + example: "*retrieve_model_response" + """ +); \ No newline at end of file diff --git a/models/models.tsp b/models/models.tsp index 68774d259..f522ca893 100644 --- a/models/models.tsp +++ b/models/models.tsp @@ -10,18 +10,10 @@ model ListModelsResponse { model DeleteModelResponse { id: string; deleted: boolean; - object: "model"; + object: "model"; // NOTE: This is just a string in the OpenAPI spec, no enum. } /** Describes an OpenAI model offering that can be used with the API. */ -// TODO: Fill in example here. -@extension( - "x-oaiMeta", - { - name: "The model object", - example: "*retrieve_model_response" - } -) model Model { /** The model identifier, which can be referenced in the API endpoints. */ id: string; diff --git a/models/operations.tsp b/models/operations.tsp index f017e1585..74f91f332 100644 --- a/models/operations.tsp +++ b/models/operations.tsp @@ -13,7 +13,7 @@ namespace OpenAI; interface Models { @get @operationId("listModels") - @tag("OpenAI") + @tag("Models") @summary(""" Lists the currently available models, and provides basic information about each one such as the owner and availability. @@ -23,7 +23,7 @@ interface Models { @route("{model}") @get @operationId("retrieveModel") - @tag("OpenAI") + @tag("Models") @summary(""" Retrieves a model instance, providing basic information about the model such as the owner and permissioning. @@ -36,7 +36,7 @@ interface Models { @route("{model}") @delete @operationId("deleteModel") - @tag("OpenAI") + @tag("Models") @summary(""" Delete a fine-tuned model. You must have the Owner role in your organization to delete a model. """) diff --git a/moderations/meta.tsp b/moderations/meta.tsp new file mode 100644 index 000000000..7d96cda38 --- /dev/null +++ b/moderations/meta.tsp @@ -0,0 +1,15 @@ +import "./models.tsp"; +import "./operations.tsp"; + +using TypeSpec.OpenAPI; + +namespace OpenAI; + +// TODO: Fill in example here. +@@extension(OpenAI.CreateModerationResponse, + "x-oaiMeta", + """ + name: "The moderation object", + example: "*moderation_example" + """ +); \ No newline at end of file diff --git a/moderations/models.tsp b/moderations/models.tsp index a572a6f2e..b844b2659 100644 --- a/moderations/models.tsp +++ b/moderations/models.tsp @@ -4,7 +4,7 @@ namespace OpenAI; model CreateModerationRequest { /** The input text to classify */ - input: string | string[]; + input: CreateModerationRequestInput; /** * Two content moderations models are available: `text-moderation-stable` and @@ -20,14 +20,6 @@ model CreateModerationRequest { /** * Represents policy compliance report by OpenAI's content moderation model against a given input. */ -// TODO: Fill in example here. -@extension( - "x-oaiMeta", - { - name: "The moderation object", - example: "*moderation_example" - } -) model CreateModerationResponse { /** The unique identifier for the moderation request. */ id: string; @@ -136,4 +128,10 @@ model CreateModerationResponse { alias MODERATION_MODELS = | "text-moderation-latest" - | "text-moderation-stable"; \ No newline at end of file + | "text-moderation-stable"; + +@oneOf +union CreateModerationRequestInput { + string, + string[] +} \ No newline at end of file diff --git a/moderations/operations.tsp b/moderations/operations.tsp index 8efad4cdb..7760ec2b2 100644 --- a/moderations/operations.tsp +++ b/moderations/operations.tsp @@ -13,7 +13,7 @@ namespace OpenAI; interface Moderations { @post @operationId("createModeration") - @tag("OpenAI") + @tag("Moderations") @summary("Classifies if text violates OpenAI's Content Policy") createModeration( @body content: CreateModerationRequest, diff --git a/readme.md b/readme.md index c4dd93188..b65856581 100644 --- a/readme.md +++ b/readme.md @@ -1,5 +1,7 @@ A conversion of the OpenAI OpenAPI to TypeSpec. +Snapshot: https://raw.githubusercontent.com/openai/openai-openapi/b648b7823135e6fa5148ac9a303c16fdad050da6/openapi.yaml + There are some deltas: ### Changes to API Semantics: diff --git a/runs/models.tsp b/runs/models.tsp index 113e43124..d5c33bb22 100644 --- a/runs/models.tsp +++ b/runs/models.tsp @@ -328,7 +328,7 @@ model RunObject { */ required_action: { /** For now, this is always `submit_tool_outputs`. */ - type: "ubmit_tool_outputs"; + type: "submit_tool_outputs"; /** Details on the tool outputs needed for this run to continue. */ submit_tool_outputs: { @@ -439,7 +439,7 @@ model RunStepObject { * if the parent run is expired. */ @encode("unixTimestamp", int32) - expires_at: utcDateTime; + expires_at: utcDateTime | null; /** The Unix timestamp (in seconds) for when the run step was cancelled. */ @encode("unixTimestamp", int32) diff --git a/runs/operations.tsp b/runs/operations.tsp index 0a7c3ab2b..ae6f35778 100644 --- a/runs/operations.tsp +++ b/runs/operations.tsp @@ -14,7 +14,7 @@ interface Runs { @route("runs") @post @operationId("createThreadAndRun") - @tag("OpenAI") + @tag("Assistants") @summary("Create a thread and run it in one request.") createThreadAndRun( @body threadAndRun: CreateThreadAndRunRequest; @@ -23,7 +23,7 @@ interface Runs { @route("{thread_id}/runs") @post @operationId("createRun") - @tag("OpenAI") + @tag("Assistants") @summary("Create a run.") createRun( /** The ID of the thread to run. */ @@ -35,7 +35,7 @@ interface Runs { @route("thread_id}/runs") @get @operationId("listRuns") - @tag("OpenAI") + @tag("Assistants") @summary("Returns a list of runs belonging to a thread.") listRuns( /** The ID of the thread the run belongs to. */ @@ -71,7 +71,7 @@ interface Runs { @route("{thread_id}/runs/{run_id}") @get @operationId("getRun") - @tag("OpenAI") + @tag("Assistants") @summary("Retrieves a run.") getRun( /** The ID of the [thread](/docs/api-reference/threads) that was run. */ @@ -84,7 +84,7 @@ interface Runs { @route("{thread_id}/runs/{run_id}") @post @operationId("modifyRun") - @tag("OpenAI") + @tag("Assistants") @summary("Modifies a run.") modifyRun( /** The ID of the [thread](/docs/api-reference/threads) that was run. */ @@ -99,7 +99,7 @@ interface Runs { @route("{thread_id}/runs/{run_id}/cancel") @post @operationId("cancelRun") - @tag("OpenAI") + @tag("Assistants") @summary("Cancels a run that is `in_progress`.") cancelRun( /** The ID of the thread to which this run belongs. */ @@ -112,7 +112,7 @@ interface Runs { @route("{thread_id}/runs/{run_id}/submit_tool_outputs") @post @operationId("submitToolOuputsToRun") - @tag("OpenAI") + @tag("Assistants") @summary(""" When a run has the `status: "requires_action"` and `required_action.type` is `submit_tool_outputs`, this endpoint can be used to submit the outputs from the tool calls once @@ -131,7 +131,7 @@ interface Runs { @route("{thread_id}/runs/{run_id}/steps") @get @operationId("listRunSteps") - @tag("OpenAI") + @tag("Assistants") @summary("Returns a list of run steps belonging to a run.") listRunSteps( /** The ID of the thread the run and run steps belong to. */ @@ -170,7 +170,7 @@ interface Runs { @route("{thread_id}/runs/{run_id}/steps/{step_id}") @get @operationId("getRunStep") - @tag("OpenAI") + @tag("Assistants") @summary("Retrieves a run step.") getRunStep( /** The ID of the thread to which the run and run step belongs. */ diff --git a/threads/operations.tsp b/threads/operations.tsp index e2599024e..fb1dc5d10 100644 --- a/threads/operations.tsp +++ b/threads/operations.tsp @@ -13,7 +13,7 @@ namespace OpenAI; interface Threads { @post @operationId("createThread") - @tag("OpenAI") + @tag("Assistants") @summary("Create a thread.") createThread( @body thread: CreateThreadRequest, @@ -22,7 +22,7 @@ interface Threads { @route("{thread_id}") @get @operationId("getThread") - @tag("OpenAI") + @tag("Assistants") @summary("Retrieves a thread.") getThread( /** The ID of the thread to retrieve. */ @@ -32,7 +32,7 @@ interface Threads { @route("{thread_id}") @post @operationId("modifyThread") - @tag("OpenAI") + @tag("Assistants") @summary("Modifies a thread.") modifyThread( /** The ID of the thread to modify. Only the `metadata` can be modified. */ @@ -43,7 +43,7 @@ interface Threads { @route("{thread_id}") @delete @operationId("deleteThread") - @tag("OpenAI") + @tag("Assistants") @summary("Delete a thread.") deleteThread( /** The ID of the thread to delete. */ diff --git a/tsp-output/@typespec/openapi3/openapi.yaml b/tsp-output/@typespec/openapi3/openapi.yaml index d37490680..f9d7b16a4 100644 --- a/tsp-output/@typespec/openapi3/openapi.yaml +++ b/tsp-output/@typespec/openapi3/openapi.yaml @@ -4,14 +4,23 @@ info: version: 2.0.0 description: The OpenAI REST API. Please see https://platform.openai.com/docs/api-reference for more details. tags: - - name: OpenAI + - name: Fine-tuning + - name: Audio + - name: Assistants + - name: Chat + - name: Completions + - name: Embeddings + - name: Files + - name: Images + - name: Models + - name: Moderations paths: - /audio/transcriptions: + /assistants: post: tags: - - OpenAI - operationId: createTranscription - summary: Transcribes audio into the input language. + - Assistants + operationId: createAssistant + summary: Create an assistant with a model and instructions. parameters: [] responses: '200': @@ -19,7 +28,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/CreateTranscriptionResponse' + $ref: '#/components/schemas/AssistantObject' default: description: An unexpected error response. content: @@ -29,73 +38,118 @@ paths: requestBody: required: true content: - multipart/form-data: + application/json: schema: - $ref: '#/components/schemas/CreateTranscriptionRequest' - /audio/translations: - post: + $ref: '#/components/schemas/CreateAssistantRequest' + get: tags: - - OpenAI - operationId: createTranslation - summary: Transcribes audio into the input language. - parameters: [] + - Assistants + operationId: listAssistants + summary: Returns a list of assistants. + parameters: + - name: limit + in: query + required: false + description: |- + A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + default is 20. + schema: + type: integer + format: int32 + default: 20 + - name: order + in: query + required: false + description: |- + Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + for descending order. + schema: + type: string + enum: + - asc + - desc + - desc + - desc + - desc + - desc + - desc + default: desc + - name: after + in: query + required: false + description: |- + A cursor for use in pagination. `after` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include after=obj_foo in order to fetch the next page of the list. + schema: + type: string + - name: before + in: query + required: false + description: |- + A cursor for use in pagination. `before` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include before=obj_foo in order to fetch the previous page of the list. + schema: + type: string responses: '200': description: The request has succeeded. content: application/json: schema: - $ref: '#/components/schemas/CreateTranslationResponse' + $ref: '#/components/schemas/ListAssistantsResponse' default: description: An unexpected error response. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - multipart/form-data: - schema: - $ref: '#/components/schemas/CreateTranslationRequest' - /chat/completions: - post: + /assistants/{assistant_id}: + get: tags: - - OpenAI - operationId: createChatCompletion - parameters: [] + - Assistants + operationId: getAssistant + summary: Retrieves an assistant. + parameters: + - name: assistant_id + in: path + required: true + description: The ID of the assistant to retrieve. + schema: + type: string responses: '200': description: The request has succeeded. content: application/json: schema: - $ref: '#/components/schemas/CreateChatCompletionResponse' + $ref: '#/components/schemas/AssistantObject' default: description: An unexpected error response. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateChatCompletionRequest' - /completions: post: tags: - - OpenAI - operationId: createCompletion - parameters: [] + - Assistants + operationId: modifyAssistant + summary: Modifies an assistant. + parameters: + - name: assistant_id + in: path + required: true + description: The ID of the assistant to modify. + schema: + type: string responses: '200': description: The request has succeeded. content: application/json: schema: - $ref: '#/components/schemas/CreateCompletionResponse' + $ref: '#/components/schemas/AssistantObject' default: description: An unexpected error response. content: @@ -107,195 +161,54 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/CreateCompletionRequest' - x-oaiMeta: - name: Create chat completion - group: chat - returns: |- - Returns a [chat completion](/docs/api-reference/chat/object) object, or a streamed sequence of - [chat completion chunk](/docs/api-reference/chat/streaming) objects if the request is streamed. - path: create - examples: - - title: No streaming - request: - curl: |- - curl https://api.openai.com/v1/chat/completions \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer $OPENAI_API_KEY" \ - -d '{ - "model": "VAR_model_id", - "messages": [ - { - "role": "system", - "content": "You are a helpful assistant." - }, - { - "role": "user", - "content": "Hello!" - } - ] - python: |- - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - - completion = openai.ChatCompletion.create( - model="VAR_model_id", - messages=[ - {"role": "system", "content": "You are a helpful assistant."}, - {"role": "user", "content": "Hello!"} - ] - ) - - print(completion.choices[0].message) - node.js: |- - import OpenAI from "openai"; - - const openai = new OpenAI(); - - async function main() { - const completion = await openai.chat.completions.create({ - messages: [{ role: "system", content: "string" }], - model: "VAR_model_id", - }); - - console.log(completion.choices[0]); - } - - main(); - response: |- - { - "id": "chatcmpl-123", - "object": "chat.completion", - "created": 1677652288, - "model": "gpt-3.5-turbo-0613", - "choices": [{ - "index": 0, - "message": { - "role": "assistant", - "content": " - - Hello there, how may I assist you today?", - }, - "finish_reason": "stop" - }], - "usage": { - "prompt_tokens": 9, - "completion_tokens": 12, - "total_tokens": 21 - } - } - - title: Streaming - request: - curl: |- - curl https://api.openai.com/v1/chat/completions \ - -H "Content-Type: application/json" \ - -H "Authorization: Bearer $OPENAI_API_KEY" \ - -d '{ - "model": "VAR_model_id", - "messages": [ - { - "role": "system", - "content": "You are a helpful assistant." - }, - { - "role": "user", - "content": "Hello!" - } - ], - "stream": true - }' - python: |- - import os - import openai - openai.api_key = os.getenv("OPENAI_API_KEY") - - completion = openai.ChatCompletion.create( - model="VAR_model_id", - messages=[ - {"role": "system", "content": "You are a helpful assistant."}, - {"role": "user", "content": "Hello!"} - ], - stream=True - ) - - for chunk in completion: - print(chunk.choices[0].delta) - node.js: |- - import OpenAI from "openai"; - - const openai = new OpenAI(); - - async function main() { - const completion = await openai.chat.completions.create({ - model: "VAR_model_id", - messages: [ - {"role": "system", "content": "You are a helpful assistant."}, - {"role": "user", "content": "Hello!"} - ], - stream: true, - }); - - for await (const chunk of completion) { - console.log(chunk.choices[0].delta.content); - } - } - - main(); - response: |- - { - "id": "chatcmpl-123", - "object": "chat.completion.chunk", - "created": 1677652288, - "model": "gpt-3.5-turbo", - "choices": [{ - "index": 0, - "delta": { - "content": "Hello", - }, - "finish_reason": "stop" - }] - } - /edits: - post: + $ref: '#/components/schemas/ModifyAssistantRequest' + delete: tags: - - OpenAI - operationId: createEdit - parameters: [] + - Assistants + operationId: deleteAssistant + summary: Delete an assistant. + parameters: + - name: assistant_id + in: path + required: true + description: The ID of the assistant to delete. + schema: + type: string responses: '200': description: The request has succeeded. content: application/json: schema: - $ref: '#/components/schemas/CreateEditResponse' + $ref: '#/components/schemas/DeleteAssistantResponse' default: description: An unexpected error response. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateEditRequest' - deprecated: true - /embeddings: + /assistants/{assistant_id}/files: post: tags: - - OpenAI - operationId: createEmbedding - summary: Creates an embedding vector representing the input text. - parameters: [] + - Assistants + operationId: createAssistantFile + summary: |- + Create an assistant file by attaching a [File](/docs/api-reference/files) to a + [assistant](/docs/api-reference/assistants). + parameters: + - name: assistant_id + in: path + required: true + description: The ID of the assistant for which to create a file. + schema: + type: string responses: '200': description: The request has succeeded. content: application/json: schema: - $ref: '#/components/schemas/CreateEmbeddingResponse' + $ref: '#/components/schemas/AssistantFileObject' default: description: An unexpected error response. content: @@ -307,63 +220,125 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/CreateEmbeddingRequest' - /files: + $ref: '#/components/schemas/CreateAssistantFileRequest' get: tags: - - OpenAI - operationId: listFiles - summary: Returns a list of files that belong to the user's organization. - parameters: [] + - Assistants + operationId: listAssistantFiles + summary: Returns a list of assistant files. + parameters: + - name: assistant_id + in: path + required: true + description: The ID of the assistant the file belongs to. + schema: + type: string + - name: limit + in: query + required: false + description: |- + A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + default is 20. + schema: + type: integer + format: int32 + default: 20 + - name: order + in: query + required: false + description: |- + Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + for descending order. + schema: + type: string + enum: + - asc + - desc + - desc + - desc + - desc + - desc + - desc + default: desc + - name: after + in: query + required: false + description: |- + A cursor for use in pagination. `after` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include after=obj_foo in order to fetch the next page of the list. + schema: + type: string + - name: before + in: query + required: false + description: |- + A cursor for use in pagination. `before` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include before=obj_foo in order to fetch the previous page of the list. + schema: + type: string responses: '200': description: The request has succeeded. content: application/json: schema: - $ref: '#/components/schemas/ListFilesResponse' + $ref: '#/components/schemas/ListAssistantFilesResponse' default: description: An unexpected error response. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' - post: + /assistants/{assistant_id}/files/{file_id}: + get: tags: - - OpenAI - operationId: createFile - summary: Returns a list of files that belong to the user's organization. - parameters: [] + - Assistants + operationId: getAssistantFile + summary: Retrieves an assistant file. + parameters: + - name: assistant_id + in: path + required: true + description: The ID of the assistant the file belongs to. + schema: + type: string + - name: file_id + in: path + required: true + description: The ID of the file we're getting. + schema: + type: string responses: '200': description: The request has succeeded. content: application/json: schema: - $ref: '#/components/schemas/OpenAIFile' + $ref: '#/components/schemas/AssistantFileObject' default: description: An unexpected error response. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - multipart/form-data: - schema: - $ref: '#/components/schemas/CreateFileRequest' - /files/files/{file_id}: - post: + delete: tags: - - OpenAI - operationId: retrieveFile - summary: Returns information about a specific file. + - Assistants + operationId: deleteAssistantFile + summary: Delete an assistant file. parameters: + - name: assistant_id + in: path + required: true + description: The ID of the assistant the file belongs to. + schema: + type: string - name: file_id in: path required: true - description: The ID of the file to use for this request. + description: The ID of the file to delete. schema: type: string responses: @@ -372,56 +347,84 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/OpenAIFile' + $ref: '#/components/schemas/DeleteAssistantFileResponse' default: description: An unexpected error response. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' - delete: + /audio/speech: + post: tags: - - OpenAI - operationId: deleteFile - summary: Delete a file - parameters: - - name: file_id - in: path - required: true - description: The ID of the file to use for this request. - schema: - type: string + - Audio + operationId: createSpeech + summary: Generates audio from the input text. + parameters: [] + responses: + '200': + description: The request has succeeded. + headers: + Transfer-Encoding: + required: false + description: chunked + schema: + type: string + content: + application/octet-stream: + schema: + type: string + format: binary + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateSpeechRequest' + /audio/transcriptions: + post: + tags: + - Audio + operationId: createTranscription + summary: Transcribes audio into the input language. + parameters: [] responses: '200': description: The request has succeeded. content: application/json: schema: - $ref: '#/components/schemas/DeleteFileResponse' + $ref: '#/components/schemas/CreateTranscriptionResponse' + text/plain: + schema: + type: string default: description: An unexpected error response. content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' - /files/files/{file_id}/content: - get: + requestBody: + required: true + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/CreateTranscriptionRequestMultiPart' + /audio/translations: + post: tags: - - OpenAI - operationId: downloadFile - summary: Returns the contents of the specified file. - parameters: - - name: file_id - in: path - required: true - description: The ID of the file to use for this request. - schema: - type: string + - Audio + operationId: createTranslation + summary: Translates audio into English.. + parameters: [] responses: '200': description: The request has succeeded. content: application/json: + schema: + $ref: '#/components/schemas/CreateTranslationResponse' + text/plain: schema: type: string default: @@ -430,17 +433,18 @@ paths: application/json: schema: $ref: '#/components/schemas/ErrorResponse' - /fine-tunes: + requestBody: + required: true + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/CreateTranslationRequestMultiPart' + /chat/completions: post: tags: - - OpenAI - operationId: createFineTune - summary: |- - Creates a job that fine-tunes a specified model from a given dataset. - - Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete. - - [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) + - Chat + operationId: createChatCompletion + summary: Creates a model response for the given chat conversation. parameters: [] responses: '200': @@ -448,7 +452,7 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/FineTune' + $ref: '#/components/schemas/CreateChatCompletionResponse' default: description: An unexpected error response. content: @@ -460,13 +464,13 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/CreateFineTuneRequest' - deprecated: true - get: + $ref: '#/components/schemas/CreateChatCompletionRequest' + /completions: + post: tags: - - OpenAI - operationId: listFineTunes - summary: List your organization's fine-tuning jobs + - Completions + operationId: createCompletion + summary: Creates a completion for the provided prompt and parameters. parameters: [] responses: '200': @@ -474,7 +478,231 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ListFineTunesResponse' + $ref: '#/components/schemas/CreateCompletionResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateCompletionRequest' + /embeddings: + post: + tags: + - Embeddings + operationId: createEmbedding + summary: Creates an embedding vector representing the input text. + parameters: [] + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/CreateEmbeddingResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateEmbeddingRequest' + /files: + post: + tags: + - Files + operationId: createFile + summary: |- + Upload a file that can be used across various endpoints. The size of all the files uploaded by + one organization can be up to 100 GB. + + The size of individual files can be a maximum of 512 MB or 2 million tokens for Assistants. See + the [Assistants Tools guide](/docs/assistants/tools) to learn more about the types of files + supported. The Fine-tuning API only supports `.jsonl` files. + + Please [contact us](https://help.openai.com/) if you need to increase these storage limits. + parameters: [] + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/OpenAIFile' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/CreateFileRequestMultiPart' + get: + tags: + - Files + operationId: listFiles + summary: Returns a list of files that belong to the user's organization. + parameters: + - name: purpose + in: query + required: false + description: Only return files with the given purpose. + schema: + type: string + enum: + - fine-tune + - fine-tune-results + - assistants + - assistants_output + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ListFilesResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /files/{file_id}: + get: + tags: + - Files + operationId: retrieveFile + summary: Returns information about a specific file. + parameters: + - name: file_id + in: path + required: true + description: The ID of the file to use for this request. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/OpenAIFile' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + delete: + tags: + - Files + operationId: deleteFile + summary: Delete a file + parameters: + - name: file_id + in: path + required: true + description: The ID of the file to use for this request. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/DeleteFileResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /files/{file_id}/content: + get: + tags: + - Files + operationId: downloadFile + summary: Returns the contents of the specified file. + parameters: + - name: file_id + in: path + required: true + description: The ID of the file to use for this request. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + type: string + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /fine-tunes: + post: + tags: + - Fine-tuning + operationId: createFineTune + summary: |- + Creates a job that fine-tunes a specified model from a given dataset. + + Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete. + + [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) + parameters: [] + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/FineTune' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateFineTuneRequest' + deprecated: true + get: + tags: + - Fine-tuning + operationId: listFineTunes + summary: List your organization's fine-tuning jobs + parameters: [] + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ListFineTunesResponse' default: description: An unexpected error response. content: @@ -485,7 +713,7 @@ paths: /fine-tunes/{fine_tune_id}: get: tags: - - OpenAI + - Fine-tuning operationId: retrieveFineTune summary: |- Gets info about the fine-tune job. @@ -515,7 +743,7 @@ paths: /fine-tunes/{fine_tune_id}/cancel: post: tags: - - OpenAI + - Fine-tuning operationId: cancelFineTune summary: Immediately cancel a fine-tune job. parameters: @@ -542,7 +770,7 @@ paths: /fine-tunes/{fine_tune_id}/events: get: tags: - - OpenAI + - Fine-tuning operationId: listFineTuneEvents summary: Get fine-grained status updates for a fine-tune job. parameters: @@ -583,7 +811,7 @@ paths: /fine_tuning/jobs: post: tags: - - OpenAI + - Fine-tuning operationId: createFineTuningJob description: |- Creates a job that fine-tunes a specified model from a given dataset. @@ -614,7 +842,7 @@ paths: $ref: '#/components/schemas/CreateFineTuningJobRequest' get: tags: - - OpenAI + - Fine-tuning operationId: listPaginatedFineTuningJobs parameters: - name: after @@ -647,7 +875,7 @@ paths: /fine_tuning/jobs/{fine_tuning_job_id}: get: tags: - - OpenAI + - Fine-tuning operationId: retrieveFineTuningJob summary: |- Get info about a fine-tuning job. @@ -675,7 +903,7 @@ paths: /fine_tuning/jobs/{fine_tuning_job_id}/cancel: post: tags: - - OpenAI + - Fine-tuning operationId: cancelFineTuningJob summary: Immediately cancel a fine-tune job. parameters: @@ -701,7 +929,7 @@ paths: /fine_tuning/jobs/{fine_tuning_job_id}/events: get: tags: - - OpenAI + - Fine-tuning operationId: listFineTuningEvents summary: Get status updates for a fine-tuning job. parameters: @@ -740,7 +968,7 @@ paths: /images/edits: post: tags: - - OpenAI + - Images operationId: createImageEdit summary: Creates an edited or extended image given an original image and a prompt. parameters: [] @@ -762,11 +990,11 @@ paths: content: multipart/form-data: schema: - $ref: '#/components/schemas/CreateImageEditRequest' + $ref: '#/components/schemas/CreateImageEditRequestMultiPart' /images/generations: post: tags: - - OpenAI + - Images operationId: createImage summary: Creates an image given a prompt parameters: [] @@ -792,7 +1020,7 @@ paths: /images/variations: post: tags: - - OpenAI + - Images operationId: createImageVariation summary: Creates an edited or extended image given an original image and a prompt. parameters: [] @@ -814,11 +1042,11 @@ paths: content: multipart/form-data: schema: - $ref: '#/components/schemas/CreateImageVariationRequest' + $ref: '#/components/schemas/CreateImageVariationRequestMultiPart' /models: get: tags: - - OpenAI + - Models operationId: listModels summary: |- Lists the currently available models, and provides basic information about each one such as the @@ -840,7 +1068,7 @@ paths: /models/{model}: get: tags: - - OpenAI + - Models operationId: retrieveModel summary: |- Retrieves a model instance, providing basic information about the model such as the owner and @@ -867,7 +1095,7 @@ paths: $ref: '#/components/schemas/ErrorResponse' delete: tags: - - OpenAI + - Models operationId: deleteModel summary: Delete a fine-tuned model. You must have the Owner role in your organization to delete a model. parameters: @@ -893,7 +1121,7 @@ paths: /moderations: post: tags: - - OpenAI + - Moderations operationId: createModeration summary: Classifies if text violates OpenAI's Content Policy parameters: [] @@ -916,89 +1144,2623 @@ paths: application/json: schema: $ref: '#/components/schemas/CreateModerationRequest' -security: - - BearerAuth: [] -components: - schemas: - ChatCompletionFunctionCallOption: - type: object - required: - - name - properties: - name: - type: string - description: The name of the function to call. - ChatCompletionFunctionParameters: - type: object - additionalProperties: {} - ChatCompletionFunctions: - type: object - required: - - name - - parameters - properties: - name: - type: string - description: |- - The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and - dashes, with a maximum length of 64. - description: - type: string - description: |- - A description of what the function does, used by the model to choose when and how to call the - function. - parameters: - allOf: - - $ref: '#/components/schemas/ChatCompletionFunctionParameters' - description: |- - The parameters the functions accepts, described as a JSON Schema object. See the - [guide](/docs/guides/gpt/function-calling) for examples, and the - [JSON Schema reference](https://json-schema.org/understanding-json-schema/) for documentation - about the format.\n\nTo describe a function that accepts no parameters, provide the value - `{\"type\": \"object\", \"properties\": {}}`. - ChatCompletionRequestMessage: - type: object - required: - - role - - content - properties: - role: - type: string - enum: - - system - - user - - assistant - - function - description: The role of the messages author. One of `system`, `user`, `assistant`, or `function`. - content: - type: string - nullable: true - description: |- - The contents of the message. `content` is required for all messages, and may be null for - assistant messages with function calls. - name: - type: string - description: |- - The name of the author of this message. `name` is required if role is `function`, and it - should be the name of the function whose response is in the `content`. May contain a-z, - A-Z, 0-9, and underscores, with a maximum length of 64 characters. - function_call: - type: object - description: The name and arguments of a function that should be called, as generated by the model. - required: - - name + /threads: + post: + tags: + - Assistants + operationId: createThread + summary: Create a thread. + parameters: [] + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ThreadObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateThreadRequest' + /threads/runs: + post: + tags: + - Assistants + operationId: createThreadAndRun + summary: Create a thread and run it in one request. + parameters: [] + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/RunObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateThreadAndRunRequest' + /threads/thread_id}/runs/{thread_id}: + get: + tags: + - Assistants + operationId: listRuns + summary: Returns a list of runs belonging to a thread. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the thread the run belongs to. + schema: + type: string + - name: limit + in: query + required: false + description: |- + A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + default is 20. + schema: + type: integer + format: int32 + default: 20 + - name: order + in: query + required: false + description: |- + Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + for descending order. + schema: + type: string + enum: + - asc + - desc + - desc + - desc + - desc + - desc + - desc + default: desc + - name: after + in: query + required: false + description: |- + A cursor for use in pagination. `after` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include after=obj_foo in order to fetch the next page of the list. + schema: + type: string + - name: before + in: query + required: false + description: |- + A cursor for use in pagination. `before` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include before=obj_foo in order to fetch the previous page of the list. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ListRunsResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /threads/{thread_id}: + get: + tags: + - Assistants + operationId: getThread + summary: Retrieves a thread. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the thread to retrieve. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ThreadObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + post: + tags: + - Assistants + operationId: modifyThread + summary: Modifies a thread. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the thread to modify. Only the `metadata` can be modified. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ThreadObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ModifyThreadRequest' + delete: + tags: + - Assistants + operationId: deleteThread + summary: Delete a thread. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the thread to delete. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/DeleteThreadResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /threads/{thread_id}/messages: + post: + tags: + - Assistants + operationId: createMessage + summary: Create a message. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the [thread](/docs/api-reference/threads) to create a message for. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/MessageObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateMessageRequest' + get: + tags: + - Assistants + operationId: listMessages + summary: Returns a list of messages for a given thread. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the [thread](/docs/api-reference/threads) the messages belong to. + schema: + type: string + - name: limit + in: query + required: false + description: |- + A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + default is 20. + schema: + type: integer + format: int32 + default: 20 + - name: order + in: query + required: false + description: |- + Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + for descending order. + schema: + type: string + enum: + - asc + - desc + - desc + - desc + - desc + - desc + - desc + default: desc + - name: after + in: query + required: false + description: |- + A cursor for use in pagination. `after` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include after=obj_foo in order to fetch the next page of the list. + schema: + type: string + - name: before + in: query + required: false + description: |- + A cursor for use in pagination. `before` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include before=obj_foo in order to fetch the previous page of the list. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ListMessagesResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /threads/{thread_id}/messages/{message_id}: + get: + tags: + - Assistants + operationId: getMessage + summary: Retrieve a message. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the [thread](/docs/api-reference/threads) to which this message belongs. + schema: + type: string + - name: message_id + in: path + required: true + description: The ID of the message to retrieve. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/MessageObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + post: + tags: + - Assistants + operationId: modifyMessage + summary: Modifies a message. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the thread to which this message belongs. + schema: + type: string + - name: message_id + in: path + required: true + description: The ID of the message to modify. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/MessageObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ModifyMessageRequest' + /threads/{thread_id}/messages/{message_id}/files: + get: + tags: + - Assistants + operationId: listMessageFiles + summary: Returns a list of message files. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the thread that the message and files belong to. + schema: + type: string + - name: message_id + in: path + required: true + description: The ID of the message that the files belongs to. + schema: + type: string + - name: limit + in: query + required: false + description: |- + A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + default is 20. + schema: + type: integer + format: int32 + default: 20 + - name: order + in: query + required: false + description: |- + Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + for descending order. + schema: + type: string + enum: + - asc + - desc + - desc + - desc + - desc + - desc + - desc + default: desc + - name: after + in: query + required: false + description: |- + A cursor for use in pagination. `after` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include after=obj_foo in order to fetch the next page of the list. + schema: + type: string + - name: before + in: query + required: false + description: |- + A cursor for use in pagination. `before` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include before=obj_foo in order to fetch the previous page of the list. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ListMessageFilesResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /threads/{thread_id}/messages/{message_id}/files/{file_id}: + get: + tags: + - Assistants + operationId: getMessageFile + summary: Retrieves a message file. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the thread to which the message and File belong. + schema: + type: string + - name: message_id + in: path + required: true + description: The ID of the message the file belongs to. + schema: + type: string + - name: file_id + in: path + required: true + description: The ID of the file being retrieved. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/MessageFileObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /threads/{thread_id}/runs: + post: + tags: + - Assistants + operationId: createRun + summary: Create a run. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the thread to run. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/RunObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateRunRequest' + /threads/{thread_id}/runs/{run_id}: + get: + tags: + - Assistants + operationId: getRun + summary: Retrieves a run. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the [thread](/docs/api-reference/threads) that was run. + schema: + type: string + - name: run_id + in: path + required: true + description: The ID of the run to retrieve. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/RunObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + post: + tags: + - Assistants + operationId: modifyRun + summary: Modifies a run. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the [thread](/docs/api-reference/threads) that was run. + schema: + type: string + - name: run_id + in: path + required: true + description: The ID of the run to modify. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/RunObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ModifyRunRequest' + /threads/{thread_id}/runs/{run_id}/cancel: + post: + tags: + - Assistants + operationId: cancelRun + summary: Cancels a run that is `in_progress`. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the thread to which this run belongs. + schema: + type: string + - name: run_id + in: path + required: true + description: The ID of the run to cancel. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/RunObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /threads/{thread_id}/runs/{run_id}/steps: + get: + tags: + - Assistants + operationId: listRunSteps + summary: Returns a list of run steps belonging to a run. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the thread the run and run steps belong to. + schema: + type: string + - name: run_id + in: path + required: true + description: The ID of the run the run steps belong to. + schema: + type: string + - name: limit + in: query + required: false + description: |- + A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + default is 20. + schema: + type: integer + format: int32 + default: 20 + - name: order + in: query + required: false + description: |- + Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + for descending order. + schema: + type: string + enum: + - asc + - desc + - desc + - desc + - desc + - desc + - desc + default: desc + - name: after + in: query + required: false + description: |- + A cursor for use in pagination. `after` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include after=obj_foo in order to fetch the next page of the list. + schema: + type: string + - name: before + in: query + required: false + description: |- + A cursor for use in pagination. `before` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include before=obj_foo in order to fetch the previous page of the list. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ListRunStepsResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /threads/{thread_id}/runs/{run_id}/steps/{step_id}: + get: + tags: + - Assistants + operationId: getRunStep + summary: Retrieves a run step. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the thread to which the run and run step belongs. + schema: + type: string + - name: run_id + in: path + required: true + description: The ID of the run to which the run step belongs. + schema: + type: string + - name: step_id + in: path + required: true + description: The ID of the run step to retrieve. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/RunStepObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /threads/{thread_id}/runs/{run_id}/submit_tool_outputs: + post: + tags: + - Assistants + operationId: submitToolOuputsToRun + summary: |- + When a run has the `status: "requires_action"` and `required_action.type` is + `submit_tool_outputs`, this endpoint can be used to submit the outputs from the tool calls once + they're all completed. All outputs must be submitted in a single request. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the [thread](/docs/api-reference/threads) to which this run belongs. + schema: + type: string + - name: run_id + in: path + required: true + description: The ID of the run that requires the tool output submission. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/RunObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/SubmitToolOutputsRunRequest' +security: + - BearerAuth: [] +components: + schemas: + AssistantFileObject: + type: object + required: + - id + - object + - created_at + - assistant_id + properties: + id: + type: string + description: The identifier, which can be referenced in API endpoints. + object: + type: string + enum: + - assistant.file + description: The object type, which is always `assistant.file`. + created_at: + type: integer + format: unixtime + description: The Unix timestamp (in seconds) for when the assistant file was created. + assistant_id: + type: string + description: The assistant ID that the file is attached to. + description: A list of [Files](/docs/api-reference/files) attached to an `assistant`. + AssistantObject: + type: object + required: + - id + - object + - created_at + - name + - description + - model + - instructions + - tools + - file_ids + - metadata + properties: + id: + type: string + description: The identifier, which can be referenced in API endpoints. + object: + type: string + enum: + - assistant + description: The object type, which is always `assistant`. + created_at: + type: integer + format: unixtime + description: The Unix timestamp (in seconds) for when the assistant was created. + name: + type: string + nullable: true + maxLength: 256 + description: The name of the assistant. The maximum length is 256 characters. + description: + type: string + nullable: true + maxLength: 512 + description: The description of the assistant. The maximum length is 512 characters. + model: + type: string + description: |- + ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + see all of your available models, or see our [Model overview](/docs/models/overview) for + descriptions of them. + instructions: + type: string + nullable: true + maxLength: 32768 + description: The system instructions that the assistant uses. The maximum length is 32768 characters. + tools: + allOf: + - $ref: '#/components/schemas/CreateAssistantRequestToolsItem' + description: |- + A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. + Tools can be of types `code_interpreter`, `retrieval`, or `function`. + default: [] + file_ids: + type: array + items: + type: string + maxItems: 20 + description: |- + A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a + maximum of 20 files attached to the assistant. Files are ordered by their creation date in + ascending order. + default: [] + metadata: + type: object + additionalProperties: + type: string + nullable: true + description: |- + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + x-oaiTypeLabel: map + description: Represents an `assistant` that can call the model and use tools. + AssistantToolsCode: + type: object + required: + - type + properties: + type: + type: string + enum: + - code_interpreter + description: 'The type of tool being defined: `code_interpreter`' + AssistantToolsFunction: + type: object + required: + - type + - function + properties: + type: + type: string + enum: + - function + description: 'The type of tool being defined: `function`' + function: + $ref: '#/components/schemas/FunctionObject' + AssistantToolsRetrieval: + type: object + required: + - type + properties: + type: + type: string + enum: + - retrieval + description: 'The type of tool being defined: `retrieval`' + AudioSegment: + type: object + required: + - id + - seek + - start + - end + - text + - tokens + - temperature + - avg_logprob + - compression_ratio + - no_speech_prob + properties: + id: + type: integer + format: int64 + description: The zero-based index of this segment. + seek: + type: integer + format: int64 + description: |- + The seek position associated with the processing of this audio segment. Seek positions are + expressed as hundredths of seconds. The model may process several segments from a single seek + position, so while the seek position will never represent a later time than the segment's + start, the segment's start may represent a significantly later time than the segment's + associated seek position. + start: + type: number + format: double + description: The time at which this segment started relative to the beginning of the audio. + end: + type: number + format: double + description: The time at which this segment ended relative to the beginning of the audio. + text: + type: string + description: The text that was part of this audio segment. + tokens: + allOf: + - $ref: '#/components/schemas/TokenArrayItem' + description: The token IDs matching the text in this audio segment. + temperature: + type: number + format: double + minimum: 0 + maximum: 1 + description: The temperature score associated with this audio segment. + avg_logprob: + type: number + format: double + description: The average log probability associated with this audio segment. + compression_ratio: + type: number + format: double + description: The compression ratio of this audio segment. + no_speech_prob: + type: number + format: double + description: The probability of no speech detection within this audio segment. + ChatCompletionFunctionCallOption: + type: object + required: + - name + properties: + name: + type: string + description: The name of the function to call. + description: |- + Specifying a particular function via `{"name": "my_function"}` forces the model to call that + function. + ChatCompletionFunctions: + type: object + required: + - name + properties: + description: + type: string + description: |- + A description of what the function does, used by the model to choose when and how to call the + function. + name: + type: string + description: |- + The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and + dashes, with a maximum length of 64. + parameters: + $ref: '#/components/schemas/FunctionParameters' + deprecated: true + ChatCompletionMessageToolCall: + type: object + required: + - id + - type + - function + properties: + id: + type: string + description: The ID of the tool call. + type: + type: string + enum: + - function + description: The type of the tool. Currently, only `function` is supported. + function: + type: object + properties: + name: + type: string + description: The name of the function to call. + arguments: + type: string + description: |- + The arguments to call the function with, as generated by the model in JSON format. Note that + the model does not always generate valid JSON, and may hallucinate parameters not defined by + your function schema. Validate the arguments in your code before calling your function. + required: + - name + - arguments + description: The function that the model called. + ChatCompletionMessageToolCallsItem: + type: array + items: + $ref: '#/components/schemas/ChatCompletionMessageToolCall' + description: The tool calls generated by the model, such as function calls. + ChatCompletionNamedToolChoice: + type: object + required: + - type + - function + properties: + type: + type: string + enum: + - function + description: The type of the tool. Currently, only `function` is supported. + function: + type: object + properties: + name: + type: string + description: The name of the function to call. + required: + - name + description: Specifies a tool the model should use. Use to force the model to call a specific function. + ChatCompletionRequestAssistantMessage: + type: object + required: + - role + properties: + content: + type: string + nullable: true + description: |- + The contents of the assistant message. Required unless `tool_calls` or `function_call` is' + specified. + role: + type: string + enum: + - assistant + description: The role of the messages author, in this case `assistant`. + name: + type: string + description: |- + An optional name for the participant. Provides the model information to differentiate between + participants of the same role. + tool_calls: + $ref: '#/components/schemas/ChatCompletionMessageToolCallsItem' + function_call: + type: object + properties: + arguments: + type: string + description: |- + The arguments to call the function with, as generated by the model in JSON format. Note that + the model does not always generate valid JSON, and may hallucinate parameters not defined by + your function schema. Validate the arguments in your code before calling your function. + name: + type: string + description: The name of the function to call. + required: + - arguments + - name + description: |- + Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be + called, as generated by the model. + deprecated: true + ChatCompletionRequestFunctionMessage: + type: object + required: + - role + - content + - name + properties: + role: + type: string + enum: + - function + description: The role of the messages author, in this case `function`. + content: + type: string + nullable: true + description: The contents of the function message. + name: + type: string + description: The name of the function to call. + ChatCompletionRequestMessage: + oneOf: + - $ref: '#/components/schemas/ChatCompletionRequestSystemMessage' + - $ref: '#/components/schemas/ChatCompletionRequestUserMessage' + - $ref: '#/components/schemas/ChatCompletionRequestAssistantMessage' + - $ref: '#/components/schemas/ChatCompletionRequestToolMessage' + - $ref: '#/components/schemas/ChatCompletionRequestFunctionMessage' + x-oaiExpandable: true + ChatCompletionRequestMessageContentPart: + oneOf: + - $ref: '#/components/schemas/ChatCompletionRequestMessageContentPartText' + - $ref: '#/components/schemas/ChatCompletionRequestMessageContentPartImage' + x-oaiExpandable: true + ChatCompletionRequestMessageContentPartImage: + type: object + required: + - type + - image_url + properties: + type: + type: string + enum: + - image_url + description: The type of the content part. + image_url: + type: object + properties: + url: + anyOf: + - type: string + format: uri + - type: string + description: Either a URL of the image or the base64 encoded image data. + detail: + type: string + enum: + - auto + - low + - high + description: |- + Specifies the detail level of the image. Learn more in the + [Vision guide](/docs/guides/vision/low-or-high-fidelity-image-understanding). + default: auto + required: + - url + ChatCompletionRequestMessageContentPartText: + type: object + required: + - type + - text + properties: + type: + type: string + enum: + - text + - json_object + description: The type of the content part. + text: + type: string + description: The text content. + ChatCompletionRequestMessageContentParts: + type: array + items: + $ref: '#/components/schemas/ChatCompletionRequestMessageContentPart' + minItems: 1 + ChatCompletionRequestSystemMessage: + type: object + required: + - content + - role + properties: + content: + type: string + description: The contents of the system message. + x-oaiExpandable: true + role: + type: string + enum: + - system + description: The role of the messages author, in this case `system`. + name: + type: string + description: |- + An optional name for the participant. Provides the model information to differentiate between + participants of the same role. + ChatCompletionRequestToolMessage: + type: object + required: + - role + - content + - tool_call_id + properties: + role: + type: string + enum: + - tool + description: The role of the messages author, in this case `tool`. + content: + type: string + description: The contents of the tool message. + tool_call_id: + type: string + description: Tool call that this message is responding to. + ChatCompletionRequestUserMessage: + type: object + required: + - content + - role + properties: + content: + allOf: + - $ref: '#/components/schemas/ChatCompletionRequestUserMessageContent' + description: The contents of the system message. + x-oaiExpandable: true + role: + type: string + enum: + - user + - assistant + description: The role of the messages author, in this case `user`. + name: + type: string + description: |- + An optional name for the participant. Provides the model information to differentiate between + participants of the same role. + ChatCompletionRequestUserMessageContent: + oneOf: + - type: string + - $ref: '#/components/schemas/ChatCompletionRequestMessageContentParts' + ChatCompletionResponseMessage: + type: object + required: + - content + - role + properties: + content: + type: string + nullable: true + description: The contents of the message. + tool_calls: + $ref: '#/components/schemas/ChatCompletionMessageToolCallsItem' + role: + type: string + enum: + - assistant + description: The role of the author of this message. + function_call: + type: object + properties: + arguments: + type: string + description: |- + The arguments to call the function with, as generated by the model in JSON format. Note that + the model does not always generate valid JSON, and may hallucinate parameters not defined by + your function schema. Validate the arguments in your code before calling your function. + name: + type: string + description: The name of the function to call. + required: - arguments + - name + description: Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model. + deprecated: true + ChatCompletionTokenLogprob: + type: object + required: + - token + - logprob + - bytes + - top_logprobs + properties: + token: + type: string + description: The token. + logprob: + type: number + format: double + description: The log probability of this token. + bytes: + type: array + items: + type: integer + format: int64 + nullable: true + description: |- + A list of integers representing the UTF-8 bytes representation of the token. Useful in + instances where characters are represented by multiple tokens and their byte representations + must be combined to generate the correct text representation. Can be `null` if there is no + bytes representation for the token. + top_logprobs: + type: array + items: + type: object + properties: + token: + type: string + description: The token. + logprob: + type: number + format: double + description: The log probability of this token. + bytes: + type: array + items: + type: integer + format: int64 + nullable: true + description: |- + A list of integers representing the UTF-8 bytes representation of the token. Useful in + instances where characters are represented by multiple tokens and their byte representations + must be combined to generate the correct text representation. Can be `null` if there is no + bytes representation for the token. + required: + - token + - logprob + - bytes + description: |- + List of the most likely tokens and their log probability, at this token position. In rare + cases, there may be fewer than the number of requested `top_logprobs` returned. + ChatCompletionTool: + type: object + required: + - type + - function + properties: + type: + type: string + enum: + - function + description: The type of the tool. Currently, only `function` is supported. + function: + $ref: '#/components/schemas/FunctionObject' + ChatCompletionToolChoiceOption: + oneOf: + - type: string + enum: + - none + - auto + - auto + - $ref: '#/components/schemas/ChatCompletionNamedToolChoice' + description: |- + Controls which (if any) function is called by the model. `none` means the model will not call a + function and instead generates a message. `auto` means the model can pick between generating a + message or calling a function. Specifying a particular function via + `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that + function. + + `none` is the default when no functions are present. `auto` is the default if functions are + present. + x-oaiExpandable: true + CompletionUsage: + type: object + required: + - prompt_tokens + - completion_tokens + - total_tokens + properties: + prompt_tokens: + type: integer + format: int64 + description: Number of tokens in the prompt. + completion_tokens: + type: integer + format: int64 + description: Number of tokens in the generated completion + total_tokens: + type: integer + format: int64 + description: Total number of tokens used in the request (prompt + completion). + description: Usage statistics for the completion request. + CreateAssistantFileRequest: + type: object + required: + - file_id + properties: + file_id: + type: string + description: |- + A [File](/docs/api-reference/files) ID (with `purpose="assistants"`) that the assistant should + use. Useful for tools like `retrieval` and `code_interpreter` that can access files. + CreateAssistantRequest: + type: object + required: + - model + properties: + model: + type: string + description: |- + ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + see all of your available models, or see our [Model overview](/docs/models/overview) for + descriptions of them. + name: + type: string + nullable: true + maxLength: 256 + description: The name of the assistant. The maximum length is 256 characters. + description: + type: string + nullable: true + maxLength: 512 + description: The description of the assistant. The maximum length is 512 characters. + instructions: + type: string + nullable: true + maxLength: 32768 + description: The system instructions that the assistant uses. The maximum length is 32768 characters. + tools: + allOf: + - $ref: '#/components/schemas/CreateAssistantRequestToolsItem' + description: |- + A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. + Tools can be of types `code_interpreter`, `retrieval`, or `function`. + default: [] + file_ids: + type: array + items: + type: string + maxItems: 20 + description: |- + A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a + maximum of 20 files attached to the assistant. Files are ordered by their creation date in + ascending order. + default: [] + metadata: + type: object + additionalProperties: + type: string + nullable: true + description: |- + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + x-oaiTypeLabel: map + CreateAssistantRequestTool: + oneOf: + - $ref: '#/components/schemas/AssistantToolsCode' + - $ref: '#/components/schemas/AssistantToolsRetrieval' + - $ref: '#/components/schemas/AssistantToolsFunction' + x-oaiExpandable: true + CreateAssistantRequestToolsItem: + type: array + items: + $ref: '#/components/schemas/CreateAssistantRequestTool' + maxItems: 128 + CreateChatCompletionRequest: + type: object + required: + - messages + - model + properties: + messages: + type: array + items: + $ref: '#/components/schemas/ChatCompletionRequestMessage' + minItems: 1 + description: |- + A list of messages comprising the conversation so far. + [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb). + model: + anyOf: + - type: string + - type: string + enum: + - gpt-4-0125-preview + - gpt-4-turbo-preview + - gpt-4-1106-preview + - gpt-4-vision-preview + - gpt-4 + - gpt-4-0314 + - gpt-4-0613 + - gpt-4-32k + - gpt-4-32k-0314 + - gpt-4-32k-0613 + - gpt-3.5-turbo + - gpt-3.5-turbo-16k + - gpt-3.5-turbo-0301 + - gpt-3.5-turbo-0613 + - gpt-3.5-turbo-1106 + - gpt-3.5-turbo-16k-0613 + description: |- + ID of the model to use. See the [model endpoint compatibility](/docs/models/model-endpoint-compatibility) + table for details on which models work with the Chat API. + x-oaiTypeLabel: string + frequency_penalty: + type: number + format: double + nullable: true + minimum: -2 + maximum: 2 + description: |- + Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing + frequency in the text so far, decreasing the model's likelihood to repeat the same line + verbatim. + + [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) + default: 0 + logit_bias: + type: object + additionalProperties: + type: integer + format: int64 + nullable: true + description: |- + Modify the likelihood of specified tokens appearing in the completion. + + Accepts a JSON object that maps tokens (specified by their token ID in the tokenizer) to an + associated bias value from -100 to 100. Mathematically, the bias is added to the logits + generated by the model prior to sampling. The exact effect will vary per model, but values + between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 + should result in a ban or exclusive selection of the relevant token. + x-oaiTypeLabel: map + default: null + logprobs: + type: boolean + nullable: true + description: |- + Whether to return log probabilities of the output tokens or not. If true, returns the log + probabilities of each output token returned in the `content` of `message`. This option is + currently not available on the `gpt-4-vision-preview` model. + default: false + top_logprobs: + type: integer + format: int64 + nullable: true + minimum: 0 + maximum: 5 + description: |- + An integer between 0 and 5 specifying the number of most likely tokens to return at each token + position, each with an associated log probability. `logprobs` must be set to `true` if this + parameter is used. + max_tokens: + type: integer + format: int64 + nullable: true + minimum: 0 + description: |- + The maximum number of [tokens](/tokenizer) that can be generated in the chat completion. + + The total length of input tokens and generated tokens is limited by the model's context length. + [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) + for counting tokens. + default: 16 + n: + type: integer + format: int64 + nullable: true + minimum: 1 + maximum: 128 + description: |- + How many chat completion choices to generate for each input message. Note that you will be + charged based on the number of generated tokens across all of the choices. Keep `n` as `1` to + minimize costs. + default: 1 + presence_penalty: + type: number + format: double + nullable: true + minimum: -2 + maximum: 2 + description: |- + Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear + in the text so far, increasing the model's likelihood to talk about new topics. + + [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) + default: 0 + response_format: + type: object + properties: + type: + type: string + enum: + - text + - json_object + description: Must be one of `text` or `json_object`. + default: text + description: |- + An object specifying the format that the model must output. Compatible with + [GPT-4 Turbo](/docs/models/gpt-4-and-gpt-4-turbo) and `gpt-3.5-turbo-1106`. + + 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. + seed: + type: integer + format: int64 + nullable: true + minimum: -9223372036854776000 + maximum: 9223372036854776000 + description: |- + This feature is in Beta. + + If specified, our system will make a best effort to sample deterministically, such that + repeated requests with the same `seed` and parameters should return the same result. + + Determinism is not guaranteed, and you should refer to the `system_fingerprint` response + parameter to monitor changes in the backend. + x-oaiMeta: + beta: true + stop: + oneOf: + - $ref: '#/components/schemas/Stop' + nullable: true + description: Up to 4 sequences where the API will stop generating further tokens. + default: null + stream: + type: boolean + nullable: true + description: |- + If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only + [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) + as they become available, with the stream terminated by a `data: [DONE]` message. + [Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions). + default: false + temperature: + type: number + format: double + nullable: true + minimum: 0 + maximum: 2 + description: |- + What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output + more random, while lower values like 0.2 will make it more focused and deterministic. + + We generally recommend altering this or `top_p` but not both. + default: 1 + top_p: + type: number + format: double + nullable: true + minimum: 0 + maximum: 1 + description: |- + An alternative to sampling with temperature, called nucleus sampling, where the model considers + the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising + the top 10% probability mass are considered. + + We generally recommend altering this or `temperature` but not both. + default: 1 + tools: + type: array + items: + $ref: '#/components/schemas/ChatCompletionTool' + description: |- + A list of tools the model may call. Currently, only functions are supported as a tool. Use this + to provide a list of functions the model may generate JSON inputs for. + tool_choice: + $ref: '#/components/schemas/ChatCompletionToolChoiceOption' + user: + allOf: + - $ref: '#/components/schemas/User' + description: |- + A unique identifier representing your end-user, which can help OpenAI to monitor and detect + abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + function_call: + anyOf: + - type: string + enum: + - none + - auto + - auto + - $ref: '#/components/schemas/ChatCompletionFunctionCallOption' + description: |- + Deprecated in favor of `tool_choice`. + + Controls which (if any) function is called by the model. `none` means the model will not call a + function and instead generates a message. `auto` means the model can pick between generating a + message or calling a function. Specifying a particular function via `{"name": "my_function"}` + forces the model to call that function. + + `none` is the default when no functions are present. `auto` is the default if functions are + present. + deprecated: true + x-oaiExpandable: true + functions: + type: array + items: + $ref: '#/components/schemas/ChatCompletionFunctions' + minItems: 1 + maxItems: 128 + description: |- + Deprecated in favor of `tools`. + + A list of functions the model may generate JSON inputs for. + deprecated: true + CreateChatCompletionResponse: + type: object + required: + - id + - choices + - created + - model + - object + properties: + id: + type: string + description: A unique identifier for the chat completion. + choices: + type: array + items: + type: object + properties: + finish_reason: + type: string + enum: + - stop + - length + - tool_calls + - content_filter + - function_call + - length + - content_filter + description: |- + The reason the model stopped generating tokens. This will be `stop` if the model hit a + natural stop point or a provided stop sequence, `length` if the maximum number of tokens + specified in the request was reached, `content_filter` if content was omitted due to a flag + from our content filters, `tool_calls` if the model called a tool, or `function_call` + (deprecated) if the model called a function. + index: + type: integer + format: int64 + description: The index of the choice in the list of choices. + message: + $ref: '#/components/schemas/ChatCompletionResponseMessage' + logprobs: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/ChatCompletionTokenLogprob' + nullable: true + required: + - content + nullable: true + description: Log probability information for the choice. + required: + - finish_reason + - index + - message + - logprobs + description: A list of chat completion choices. Can be more than one if `n` is greater than 1. + created: + type: integer + format: unixtime + description: The Unix timestamp (in seconds) of when the chat completion was created. + model: + type: string + description: The model used for the chat completion. + system_fingerprint: + type: string + description: |- + 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. + object: + type: string + enum: + - chat.completion + description: The object type, which is always `chat.completion`. + usage: + $ref: '#/components/schemas/CompletionUsage' + description: Represents a chat completion response returned by model, based on the provided input. + CreateCompletionRequest: + type: object + required: + - model + - prompt + properties: + model: + anyOf: + - type: string + - type: string + enum: + - gpt-3.5-turbo-instruct + - davinci-002 + - babbage-002 + description: |- + ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + see all of your available models, or see our [Model overview](/docs/models/overview) for + descriptions of them. + x-oaiTypeLabel: string + prompt: + oneOf: + - $ref: '#/components/schemas/Prompt' + nullable: true + description: |- + The prompt(s) to generate completions for, encoded as a string, array of strings, array of + tokens, or array of token arrays. + + Note that <|endoftext|> is the document separator that the model sees during training, so if a + prompt is not specified the model will generate as if from the beginning of a new document. + default: <|endoftext|> + best_of: + type: integer + format: int64 + nullable: true + minimum: 0 + maximum: 20 + description: |- + Generates `best_of` completions server-side and returns the "best" (the one with the highest + log probability per token). Results cannot be streamed. + + When used with `n`, `best_of` controls the number of candidate completions and `n` specifies + how many to return – `best_of` must be greater than `n`. + + **Note:** Because this parameter generates many completions, it can quickly consume your token + quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. + default: 1 + echo: + type: boolean + nullable: true + description: Echo back the prompt in addition to the completion + default: false + frequency_penalty: + type: number + format: double + nullable: true + minimum: -2 + maximum: 2 + description: |- + Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing + frequency in the text so far, decreasing the model's likelihood to repeat the same line + verbatim. + + [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) + default: 0 + logit_bias: + type: object + additionalProperties: + type: integer + format: int64 + nullable: true + description: |- + Modify the likelihood of specified tokens appearing in the completion. + + Accepts a JSON object that maps tokens (specified by their token ID in the GPT tokenizer) to an + associated bias value from -100 to 100. You can use this [tokenizer tool](/tokenizer?view=bpe) + to convert text to token IDs. Mathematically, the bias is added to the logits generated by the + model prior to sampling. The exact effect will vary per model, but values between -1 and 1 + should decrease or increase likelihood of selection; values like -100 or 100 should result in a + ban or exclusive selection of the relevant token. + + As an example, you can pass `{"50256": -100}` to prevent the <|endoftext|> token from being + generated. + x-oaiTypeLabel: map + default: null + logprobs: + type: integer + format: int64 + nullable: true + minimum: 0 + maximum: 5 + description: |- + Include the log probabilities on the `logprobs` most likely tokens, as well the chosen tokens. + For example, if `logprobs` is 5, the API will return a list of the 5 most likely tokens. The + API will always return the `logprob` of the sampled token, so there may be up to `logprobs+1` + elements in the response. + + The maximum value for `logprobs` is 5. + default: null + max_tokens: + type: integer + format: int64 + nullable: true + minimum: 0 + description: |- + The maximum number of [tokens](/tokenizer) to generate in the completion. + + The token count of your prompt plus `max_tokens` cannot exceed the model's context length. + [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) + for counting tokens. + default: 16 + n: + type: integer + format: int64 + nullable: true + minimum: 1 + maximum: 128 + description: |- + How many completions to generate for each prompt. + + **Note:** Because this parameter generates many completions, it can quickly consume your token + quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. + default: 1 + presence_penalty: + type: number + format: double + nullable: true + minimum: -2 + maximum: 2 + description: |- + Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear + in the text so far, increasing the model's likelihood to talk about new topics. + + [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) + default: 0 + seed: + type: integer + format: int64 + nullable: true + minimum: -9223372036854776000 + maximum: 9223372036854776000 + description: |- + If specified, our system will make a best effort to sample deterministically, such that + repeated requests with the same `seed` and parameters should return the same result. + + Determinism is not guaranteed, and you should refer to the `system_fingerprint` response + parameter to monitor changes in the backend. + x-oaiMeta: + beta: true + stop: + oneOf: + - $ref: '#/components/schemas/Stop' + nullable: true + description: Up to 4 sequences where the API will stop generating further tokens. + default: null + stream: + type: boolean + nullable: true + description: |- + If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only + [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) + as they become available, with the stream terminated by a `data: [DONE]` message. + [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_stream_completions.ipynb). + default: false + suffix: + type: string + nullable: true + description: The suffix that comes after a completion of inserted text. + default: null + temperature: + type: number + format: double + nullable: true + minimum: 0 + maximum: 2 + description: |- + What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output + more random, while lower values like 0.2 will make it more focused and deterministic. + + We generally recommend altering this or `top_p` but not both. + default: 1 + top_p: + type: number + format: double + nullable: true + minimum: 0 + maximum: 1 + description: |- + An alternative to sampling with temperature, called nucleus sampling, where the model considers + the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising + the top 10% probability mass are considered. + + We generally recommend altering this or `temperature` but not both. + default: 1 + user: + allOf: + - $ref: '#/components/schemas/User' + description: |- + A unique identifier representing your end-user, which can help OpenAI to monitor and detect + abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + CreateCompletionResponse: + type: object + required: + - id + - choices + - created + - model + - object + properties: + id: + type: string + description: A unique identifier for the completion. + choices: + type: array + items: + type: object + properties: + index: + type: integer + format: int64 + text: + type: string + logprobs: + type: object + properties: + tokens: + type: array + items: + type: string + token_logprobs: + type: array + items: + type: number + format: double + top_logprobs: + type: array + items: + type: object + additionalProperties: + type: integer + format: int64 + text_offset: + type: array + items: + type: integer + format: int64 + required: + - tokens + - token_logprobs + - top_logprobs + - text_offset + nullable: true + finish_reason: + type: string + enum: + - stop + - length + - tool_calls + - content_filter + - function_call + - length + - content_filter + description: |- + The reason the model stopped generating tokens. This will be `stop` if the model hit a + natural stop point or a provided stop sequence, or `content_filter` if content was omitted + due to a flag from our content filters, `length` if the maximum number of tokens specified + in the request was reached, or `content_filter` if content was omitted due to a flag from our + content filters. + required: + - index + - text + - logprobs + - finish_reason + description: The list of completion choices the model generated for the input. + created: + type: integer + format: unixtime + description: The Unix timestamp (in seconds) of when the completion was created. + model: + type: string + description: The model used for the completion. + system_fingerprint: + type: string + description: |- + 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. + object: + type: string + enum: + - text_completion + description: The object type, which is always `text_completion`. + usage: + allOf: + - $ref: '#/components/schemas/CompletionUsage' + description: Usage statistics for the completion request. + description: |- + Represents a completion response from the API. Note: both the streamed and non-streamed response + objects share the same shape (unlike the chat endpoint). + CreateEmbeddingRequest: + type: object + required: + - input + - model + properties: + input: + allOf: + - $ref: '#/components/schemas/CreateEmbeddingRequestInput' + description: |- + Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a + single request, pass an array of strings or array of token arrays. Each input must not exceed + the max input tokens for the model (8191 tokens for `text-embedding-ada-002`) and cannot be an + empty string. + [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) + for counting tokens. + x-oaiExpandable: true + model: + anyOf: + - type: string + - type: string + enum: + - text-embedding-ada-002 + - text-embedding-3-small + - text-embedding-3-large + description: |- + ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + see all of your available models, or see our [Model overview](/docs/models/overview) for + descriptions of them. + x-oaiTypeLabel: string + encoding_format: + type: string + enum: + - float + - base64 + description: |- + The format to return the embeddings in. Can be either `float` or + [`base64`](https://pypi.org/project/pybase64/). + default: float + dimensions: + type: integer + format: int64 + minimum: 1 + description: |- + The number of dimensions the resulting output embeddings should have. Only supported in + `text-embedding-3` and later models. + user: + allOf: + - $ref: '#/components/schemas/User' + description: |- + A unique identifier representing your end-user, which can help OpenAI to monitor and detect + abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + CreateEmbeddingRequestInput: + oneOf: + - type: string + - type: array + items: + type: string + - $ref: '#/components/schemas/TokenArrayItem' + - $ref: '#/components/schemas/TokenArrayArray' + CreateEmbeddingResponse: + type: object + required: + - data + - model + - object + - usage + properties: + data: + type: array + items: + $ref: '#/components/schemas/Embedding' + description: The list of embeddings generated by the model. + model: + type: string + description: The name of the model used to generate the embedding. + object: + type: string + enum: + - list + description: The object type, which is always "list". + usage: + type: object + properties: + prompt_tokens: + type: integer + format: int64 + description: The number of tokens used by the prompt. + total_tokens: + type: integer + format: int64 + description: The total number of tokens used by the request. + required: + - prompt_tokens + - total_tokens + description: The usage information for the request. + CreateFileRequestMultiPart: + type: object + required: + - file + - purpose + properties: + file: + type: string + format: binary + description: The file object (not file name) to be uploaded. + purpose: + type: string + enum: + - fine-tune + - assistants + description: |- + The intended purpose of the uploaded file. Use "fine-tune" for + [Fine-tuning](/docs/api-reference/fine-tuning) and "assistants" for + [Assistants](/docs/api-reference/assistants) and [Messages](/docs/api-reference/messages). This + allows us to validate the format of the uploaded file is correct for fine-tuning. + CreateFineTuneRequest: + type: object + required: + - training_file + properties: + training_file: + type: string + description: |- + The ID of an uploaded file that contains training data. + + See [upload file](/docs/api-reference/files/upload) for how to upload a file. + + Your dataset must be formatted as a JSONL file, where each training example is a JSON object + with the keys "prompt" and "completion". Additionally, you must upload your file with the + purpose `fine-tune`. + + See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more + details. + validation_file: + type: string + nullable: true + description: |- + The ID of an uploaded file that contains validation data. + + If you provide this file, the data is used to generate validation metrics periodically during + fine-tuning. These metrics can be viewed in the + [fine-tuning results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model). + Your train and validation data should be mutually exclusive. + + Your dataset must be formatted as a JSONL file, where each validation example is a JSON object + with the keys "prompt" and "completion". Additionally, you must upload your file with the + purpose `fine-tune`. + + See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more + details. + model: + anyOf: + - type: string + - type: string + enum: + - ada + - babbage + - curie + - davinci + nullable: true + description: |- + The name of the base model to fine-tune. You can select one of "ada", "babbage", "curie", + "davinci", or a fine-tuned model created after 2022-04-21 and before 2023-08-22. To learn more + about these models, see the [Models](/docs/models) documentation. + x-oaiTypeLabel: string + n_epochs: + type: integer + format: int64 + nullable: true + description: |- + The number of epochs to train the model for. An epoch refers to one full cycle through the + training dataset. + default: 4 + batch_size: + type: integer + format: int64 + nullable: true + description: |- + The batch size to use for training. The batch size is the number of training examples used to + train a single forward and backward pass. + + By default, the batch size will be dynamically configured to be ~0.2% of the number of examples + in the training set, capped at 256 - in general, we've found that larger batch sizes tend to + work better for larger datasets. + default: null + learning_rate_multiplier: + type: number + format: double + nullable: true + description: |- + The learning rate multiplier to use for training. The fine-tuning learning rate is the original + learning rate used for pretraining multiplied by this value. + + By default, the learning rate multiplier is the 0.05, 0.1, or 0.2 depending on final + `batch_size` (larger learning rates tend to perform better with larger batch sizes). We + recommend experimenting with values in the range 0.02 to 0.2 to see what produces the best + results. + default: null + prompt_loss_rate: + type: number + format: double + nullable: true + description: |- + The weight to use for loss on the prompt tokens. This controls how much the model tries to + learn to generate the prompt (as compared to the completion which always has a weight of 1.0), + and can add a stabilizing effect to training when completions are short. + + If prompts are extremely long (relative to completions), it may make sense to reduce this + weight so as to avoid over-prioritizing learning the prompt. + default: 0.01 + compute_classification_metrics: + type: boolean + nullable: true + description: |- + If set, we calculate classification-specific metrics such as accuracy and F-1 score using the + validation set at the end of every epoch. These metrics can be viewed in the + [results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model). + + In order to compute classification metrics, you must provide a `validation_file`. Additionally, + you must specify `classification_n_classes` for multiclass classification or + `classification_positive_class` for binary classification. + default: false + classification_n_classes: + type: integer + format: int64 + nullable: true + description: |- + The number of classes in a classification task. + + This parameter is required for multiclass classification. + default: null + classification_positive_class: + type: string + nullable: true + description: |- + The positive class in binary classification. + + This parameter is needed to generate precision, recall, and F1 metrics when doing binary + classification. + default: null + classification_betas: + type: array + items: + type: number + format: double + nullable: true + description: |- + If this is provided, we calculate F-beta scores at the specified beta values. The F-beta score + is a generalization of F-1 score. This is only used for binary classification. + + With a beta of 1 (i.e. the F-1 score), precision and recall are given the same weight. A larger + beta score puts more weight on recall and less on precision. A smaller beta score puts more + weight on precision and less on recall. + default: null + suffix: + oneOf: + - $ref: '#/components/schemas/SuffixString' + nullable: true + description: |- + 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 + `ada:ft-your-org:custom-model-name-2022-02-15-04-21-04`. + default: null + CreateFineTuningJobRequest: + type: object + required: + - training_file + - model + properties: + training_file: + type: string + description: |- + The ID of an uploaded file that contains training data. + + See [upload file](/docs/api-reference/files/upload) for how to upload a file. + + Your dataset must be formatted as a JSONL file. Additionally, you must upload your file with + the purpose `fine-tune`. + + See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. + validation_file: + type: string + nullable: true + description: |- + The ID of an uploaded file that contains validation data. + + If you provide this file, the data is used to generate validation metrics periodically during + fine-tuning. These metrics can be viewed in the fine-tuning results file. The same data should + not be present in both train and validation files. + + Your dataset must be formatted as a JSONL file. You must upload your file with the purpose + `fine-tune`. + + See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. + model: + anyOf: + - type: string + - type: string + enum: + - babbage-002 + - davinci-002 + - gpt-3.5-turbo + description: |- + The name of the model to fine-tune. You can select one of the + [supported models](/docs/guides/fine-tuning/what-models-can-be-fine-tuned). + x-oaiTypeLabel: string + hyperparameters: + type: object properties: - name: - type: string - description: The name of the function to call. - arguments: - type: string + n_epochs: + anyOf: + - type: string + enum: + - auto + - low + - high + - $ref: '#/components/schemas/NEpochs' description: |- - The arguments to call the function with, as generated by the model in JSON format. Note that - the model does not always generate valid JSON, and may hallucinate parameters not defined by - your function schema. Validate the arguments in your code before calling your function. - ChatCompletionResponseMessage: + The number of epochs to train the model for. An epoch refers to one full cycle through the + training dataset. + default: auto + description: The hyperparameters used for the fine-tuning job. + suffix: + oneOf: + - $ref: '#/components/schemas/SuffixString' + nullable: true + description: |- + 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`. + default: null + CreateImageEditRequestMultiPart: + type: object + required: + - image + - prompt + properties: + image: + type: string + format: binary + description: |- + The image to edit. Must be a valid PNG file, less than 4MB, and square. If mask is not + provided, image must have transparency, which will be used as the mask. + prompt: + type: string + maxLength: 1000 + description: A text description of the desired image(s). The maximum length is 1000 characters. + mask: + type: string + format: binary + description: |- + An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where + `image` should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions + as `image`. + model: + anyOf: + - type: string + - type: string + enum: + - dall-e-2 + description: The model to use for image generation. Only `dall-e-2` is supported at this time. + x-oaiTypeLabel: string + default: dall-e-2 + n: + oneOf: + - $ref: '#/components/schemas/ImagesN' + nullable: true + description: The number of images to generate. Must be between 1 and 10. + default: 1 + size: + type: string + enum: + - 256x256 + - 512x512 + - 1024x1024 + - 512x512 + - 1024x1024 + nullable: true + description: The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`. + default: 1024x1024 + response_format: + type: string + enum: + - url + - b64_json + - b64_json + nullable: true + description: The format in which the generated images are returned. Must be one of `url` or `b64_json`. + default: url + user: + allOf: + - $ref: '#/components/schemas/User' + description: |- + A unique identifier representing your end-user, which can help OpenAI to monitor and detect + abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + CreateImageRequest: + type: object + required: + - prompt + properties: + prompt: + type: string + description: |- + A text description of the desired image(s). The maximum length is 1000 characters for + `dall-e-2` and 4000 characters for `dall-e-3`. + model: + anyOf: + - type: string + - type: string + enum: + - dall-e-2 + - dall-e-3 + description: The model to use for image generation. + x-oaiTypeLabel: string + default: dall-e-2 + n: + oneOf: + - $ref: '#/components/schemas/ImagesN' + nullable: true + description: |- + The number of images to generate. Must be between 1 and 10. For `dall-e-3`, only `n=1` is + supported. + default: 1 + quality: + type: string + enum: + - standard + - hd + nullable: true + description: |- + The quality of the image that will be generated. `hd` creates images with finer details and + greater consistency across the image. This param is only supported for `dall-e-3`. + default: standard + response_format: + type: string + enum: + - url + - b64_json + nullable: true + description: The format in which the generated images are returned. Must be one of `url` or `b64_json`. + default: url + size: + type: string + enum: + - 256x256 + - 512x512 + - 1024x1024 + - 1792x1024 + - 1024x1792 + nullable: true + description: |- + 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. + default: 1024x1024 + style: + type: string + enum: + - vivid + - natural + nullable: true + description: |- + The style of the generated images. Must be one of `vivid` or `natural`. Vivid causes the model + to lean towards generating hyper-real and dramatic images. Natural causes the model to produce + more natural, less hyper-real looking images. This param is only supported for `dall-e-3`. + default: vivid + user: + allOf: + - $ref: '#/components/schemas/User' + description: |- + A unique identifier representing your end-user, which can help OpenAI to monitor and detect + abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + CreateImageVariationRequestMultiPart: + type: object + required: + - image + properties: + image: + type: string + format: binary + description: |- + The image to use as the basis for the variation(s). Must be a valid PNG file, less than 4MB, + and square. + model: + anyOf: + - type: string + - type: string + enum: + - dall-e-2 + description: The model to use for image generation. Only `dall-e-2` is supported at this time. + x-oaiTypeLabel: string + default: dall-e-2 + n: + oneOf: + - $ref: '#/components/schemas/ImagesN' + nullable: true + description: The number of images to generate. Must be between 1 and 10. + default: 1 + response_format: + type: string + enum: + - url + - b64_json + - b64_json + nullable: true + description: The format in which the generated images are returned. Must be one of `url` or `b64_json`. + default: url + size: + type: string + enum: + - 256x256 + - 512x512 + - 1024x1024 + - 512x512 + - 1024x1024 + nullable: true + description: The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`. + default: 1024x1024 + user: + allOf: + - $ref: '#/components/schemas/User' + description: |- + A unique identifier representing your end-user, which can help OpenAI to monitor and detect + abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + CreateMessageRequest: type: object required: - role @@ -1007,1950 +3769,2293 @@ components: role: type: string enum: - - system - user - assistant - - function - description: The role of the author of this message. + description: The role of the entity that is creating the message. Currently only `user` is supported. content: type: string - nullable: true - description: The contents of the message. - function_call: + minLength: 1 + maxLength: 32768 + description: The content of the message. + file_ids: + type: array + items: + type: string + minItems: 1 + maxItems: 10 + description: |- + A list of [File](/docs/api-reference/files) IDs that the message should use. There can be a + maximum of 10 files attached to a message. Useful for tools like `retrieval` and + `code_interpreter` that can access and use files. + default: [] + metadata: type: object - description: The name and arguments of a function that should be called, as generated by the model. - required: - - name - - arguments - properties: - name: - type: string - description: The name of the function to call. - arguments: - type: string - description: |- - The arguments to call the function with, as generated by the model in JSON format. Note that - the model does not always generate valid JSON, and may hallucinate parameters not defined by - your function schema. Validate the arguments in your code before calling your function. - CompletionUsage: + additionalProperties: + type: string + nullable: true + description: |- + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + x-oaiTypeLabel: map + CreateModerationRequest: + type: object + required: + - input + properties: + input: + allOf: + - $ref: '#/components/schemas/CreateModerationRequestInput' + description: The input text to classify + model: + anyOf: + - type: string + - type: string + enum: + - text-moderation-latest + - text-moderation-stable + description: |- + Two content moderations models are available: `text-moderation-stable` and + `text-moderation-latest`. The default is `text-moderation-latest` which will be automatically + upgraded over time. This ensures you are always using our most accurate model. If you use + `text-moderation-stable`, we will provide advanced notice before updating the model. Accuracy + of `text-moderation-stable` may be slightly lower than for `text-moderation-latest`. + x-oaiTypeLabel: string + default: text-moderation-latest + CreateModerationRequestInput: + oneOf: + - type: string + - type: array + items: + type: string + CreateModerationResponse: + type: object + required: + - id + - model + - results + properties: + id: + type: string + description: The unique identifier for the moderation request. + model: + type: string + description: The model used to generate the moderation results. + results: + type: array + items: + type: object + properties: + flagged: + type: boolean + description: Whether the content violates [OpenAI's usage policies](/policies/usage-policies). + categories: + type: object + properties: + hate: + type: boolean + description: |- + Content that expresses, incites, or promotes hate based on race, gender, ethnicity, + religion, nationality, sexual orientation, disability status, or caste. Hateful content + aimed at non-protected groups (e.g., chess players) is harrassment. + hate/threatening: + type: boolean + description: |- + Hateful content that also includes violence or serious harm towards the targeted group + based on race, gender, ethnicity, religion, nationality, sexual orientation, disability + status, or caste. + harassment: + type: boolean + description: Content that expresses, incites, or promotes harassing language towards any target. + harassment/threatening: + type: boolean + description: Harassment content that also includes violence or serious harm towards any target. + self-harm: + type: boolean + description: |- + Content that promotes, encourages, or depicts acts of self-harm, such as suicide, cutting, + and eating disorders. + self-harm/intent: + type: boolean + description: |- + Content where the speaker expresses that they are engaging or intend to engage in acts of + self-harm, such as suicide, cutting, and eating disorders. + self-harm/instructions: + type: boolean + description: |- + Content that encourages performing acts of self-harm, such as suicide, cutting, and eating + disorders, or that gives instructions or advice on how to commit such acts. + sexual: + type: boolean + description: |- + Content meant to arouse sexual excitement, such as the description of sexual activity, or + that promotes sexual services (excluding sex education and wellness). + sexual/minors: + type: boolean + description: Sexual content that includes an individual who is under 18 years old. + violence: + type: boolean + description: Content that depicts death, violence, or physical injury. + violence/graphic: + type: boolean + description: Content that depicts death, violence, or physical injury in graphic detail. + required: + - hate + - hate/threatening + - harassment + - harassment/threatening + - self-harm + - self-harm/intent + - self-harm/instructions + - sexual + - sexual/minors + - violence + - violence/graphic + description: A list of the categories, and whether they are flagged or not. + category_scores: + type: object + properties: + hate: + type: number + format: double + description: The score for the category 'hate'. + hate/threatening: + type: number + format: double + description: The score for the category 'hate/threatening'. + harassment: + type: number + format: double + description: The score for the category 'harassment'. + harassment/threatening: + type: number + format: double + description: The score for the category 'harassment/threatening'. + self-harm: + type: number + format: double + description: The score for the category 'self-harm'. + self-harm/intent: + type: number + format: double + description: The score for the category 'self-harm/intent'. + self-harm/instructions: + type: number + format: double + description: The score for the category 'self-harm/instructive'. + sexual: + type: number + format: double + description: The score for the category 'sexual'. + sexual/minors: + type: number + format: double + description: The score for the category 'sexual/minors'. + violence: + type: number + format: double + description: The score for the category 'violence'. + violence/graphic: + type: number + format: double + description: The score for the category 'violence/graphic'. + required: + - hate + - hate/threatening + - harassment + - harassment/threatening + - self-harm + - self-harm/intent + - self-harm/instructions + - sexual + - sexual/minors + - violence + - violence/graphic + description: A list of the categories along with their scores as predicted by model. + required: + - flagged + - categories + - category_scores + description: A list of moderation objects. + description: Represents policy compliance report by OpenAI's content moderation model against a given input. + CreateRunRequest: type: object - description: Usage statistics for the completion request. required: - - prompt_tokens - - completion_tokens - - total_tokens + - assistant_id properties: - prompt_tokens: - type: integer - format: int64 - description: Number of tokens in the prompt. - completion_tokens: - type: integer - format: int64 - description: Number of tokens in the generated completion - total_tokens: - type: integer - format: int64 - description: Total number of tokens used in the request (prompt + completion). - CreateChatCompletionRequest: + assistant_id: + type: string + description: The ID of the [assistant](/docs/api-reference/assistants) to use to execute this run. + model: + type: string + nullable: true + description: |- + The ID of the [Model](/docs/api-reference/models) to be used to execute this run. If a value + is provided here, it will override the model associated with the assistant. If not, the model + associated with the assistant will be used. + instructions: + type: string + nullable: true + description: |- + Overrides the [instructions](/docs/api-reference/assistants/createAssistant) of the assistant. + This is useful for modifying the behavior on a per-run basis. + additional_instructions: + type: string + nullable: true + description: |- + Appends additional instructions at the end of the instructions for the run. This is useful for + modifying the behavior on a per-run basis without overriding other instructions. + tools: + type: object + allOf: + - $ref: '#/components/schemas/CreateRunRequestToolsItem' + nullable: true + description: |- + Override the tools the assistant can use for this run. This is useful for modifying the + behavior on a per-run basis. + metadata: + type: object + additionalProperties: + type: string + nullable: true + description: |- + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + x-oaiTypeLabel: map + CreateRunRequestTool: + oneOf: + - $ref: '#/components/schemas/AssistantToolsCode' + - $ref: '#/components/schemas/AssistantToolsRetrieval' + - $ref: '#/components/schemas/AssistantToolsFunction' + x-oaiExpandable: true + CreateRunRequestToolsItem: + type: array + items: + $ref: '#/components/schemas/CreateRunRequestTool' + maxItems: 20 + CreateSpeechRequest: type: object required: - model - - messages + - input + - voice properties: model: anyOf: - type: string - type: string enum: - - gpt4 - - gpt-4-0314 - - gpt-4-0613 - - gpt-4-32k - - gpt-4-32k-0314 - - gpt-4-32k-0613 - - gpt-3.5-turbo - - gpt-3.5-turbo-16k - - gpt-3.5-turbo-0301 - - gpt-3.5-turbo-0613 - - gpt-3.5-turbo-16k-0613 - description: |- - ID of the model to use. See the [model endpoint compatibility](/docs/models/model-endpoint-compatibility) - table for details on which models work with the Chat API. + - tts-1 + - tts-1-hd + description: 'One of the available [TTS models](/docs/models/tts): `tts-1` or `tts-1-hd`' x-oaiTypeLabel: string - messages: - type: array - items: - $ref: '#/components/schemas/ChatCompletionRequestMessage' - description: |- - A list of messages comprising the conversation so far. - [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb). - minItems: 1 - functions: - type: array - items: - $ref: '#/components/schemas/ChatCompletionFunctions' - description: A list of functions the model may generate JSON inputs for. - minItems: 1 - maxItems: 128 - function_call: - anyOf: - - type: string - enum: - - none - - auto - - $ref: '#/components/schemas/ChatCompletionFunctionCallOption' - description: |- - Controls how the model responds to function calls. `none` means the model does not call a - function, and responds to the end-user. `auto` means the model can pick between an end-user or - calling a function. Specifying a particular function via `{\"name":\ \"my_function\"}` forces the - model to call that function. `none` is the default when no functions are present. `auto` is the - default if functions are present. - temperature: - oneOf: - - $ref: '#/components/schemas/Temperature' - nullable: true - description: |- - What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output - more random, while lower values like 0.2 will make it more focused and deterministic. - - We generally recommend altering this or `top_p` but not both. - default: 1 - top_p: - oneOf: - - $ref: '#/components/schemas/TopP' - nullable: true + input: + type: string + maxLength: 4096 + description: The text to generate audio for. The maximum length is 4096 characters. + voice: + type: string + enum: + - alloy + - echo + - fable + - onyx + - nova + - shimmer description: |- - An alternative to sampling with temperature, called nucleus sampling, where the model considers - the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising - the top 10% probability mass are considered. - - We generally recommend altering this or `temperature` but not both. + The voice to use when generating the audio. Supported voices are `alloy`, `echo`, `fable`, + `onyx`, `nova`, and `shimmer`. Previews of the voices are available in the + [Text to speech guide](/docs/guides/text-to-speech/voice-options). + response_format: + type: string + enum: + - mp3 + - opus + - aac + - flac + description: The format to audio in. Supported formats are `mp3`, `opus`, `aac`, and `flac`. + default: mp3 + speed: + type: number + format: double + minimum: 0.25 + maximum: 4 + description: The speed of the generated audio. Select a value from `0.25` to `4.0`. `1.0` is the default. default: 1 - n: - oneOf: - - $ref: '#/components/schemas/N' + CreateThreadAndRunRequest: + type: object + required: + - assistant_id + properties: + assistant_id: + type: string + description: The ID of the [assistant](/docs/api-reference/assistants) to use to execute this run. + thread: + allOf: + - $ref: '#/components/schemas/CreateThreadRequest' + description: If no thread is provided, an empty thread will be created. + model: + type: string nullable: true description: |- - How many completions to generate for each prompt. - **Note:** Because this parameter generates many completions, it can quickly consume your token - quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. - default: 1 - max_tokens: - oneOf: - - $ref: '#/components/schemas/MaxTokens' + The ID of the [Model](/docs/api-reference/models) to be used to execute this run. If a value is + provided here, it will override the model associated with the assistant. If not, the model + associated with the assistant will be used. + instructions: + type: string nullable: true description: |- - The maximum number of [tokens](/tokenizer) to generate in the completion. - - The token count of your prompt plus `max_tokens` cannot exceed the model's context length. - [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) - for counting tokens. - default: 16 - stop: + Override the default system message of the assistant. This is useful for modifying the behavior + on a per-run basis. + tools: + type: object allOf: - - $ref: '#/components/schemas/Stop' - description: Up to 4 sequences where the API will stop generating further tokens. - default: null - presence_penalty: - oneOf: - - $ref: '#/components/schemas/Penalty' - nullable: true - description: |- - Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear - in the text so far, increasing the model's likelihood to talk about new topics. - - [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) - frequency_penalty: - oneOf: - - $ref: '#/components/schemas/Penalty' + - $ref: '#/components/schemas/CreateRunRequestToolsItem' nullable: true description: |- - Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing - frequency in the text so far, decreasing the model's likelihood to repeat the same line - verbatim. - - [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) - logit_bias: + Override the tools the assistant can use for this run. This is useful for modifying the + behavior on a per-run basis. + metadata: type: object - description: |- - Modify the likelihood of specified tokens appearing in the completion. - Accepts a json object that maps tokens (specified by their token ID in the tokenizer) to an - associated bias value from -100 to 100. Mathematically, the bias is added to the logits - generated by the model prior to sampling. The exact effect will vary per model, but values - between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 - should result in a ban or exclusive selection of the relevant token. additionalProperties: - type: integer - format: int64 + type: string nullable: true - x-oaiTypeLabel: map - user: - allOf: - - $ref: '#/components/schemas/User' description: |- - A unique identifier representing your end-user, which can help OpenAI to monitor and detect - abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). - stream: - type: boolean + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + x-oaiTypeLabel: map + CreateThreadRequest: + type: object + properties: + messages: + type: array + items: + $ref: '#/components/schemas/CreateMessageRequest' + description: A list of [messages](/docs/api-reference/messages) to start the thread with. + metadata: + type: object + additionalProperties: + type: string nullable: true description: |- - If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only - [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) - as they become available, with the stream terminated by a `data: [DONE]` message. - [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_stream_completions.ipynb). - default: true - CreateChatCompletionResponse: + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + CreateTranscriptionRequestMultiPart: type: object - description: Represents a chat completion response returned by model, based on the provided input. required: - - id - - object - - created + - file - model - - choices properties: - id: + file: + type: string + format: binary + description: |- + The audio file object (not file name) to transcribe, in one of these formats: flac, mp3, mp4, + mpeg, mpga, m4a, ogg, wav, or webm. + x-oaiTypeLabel: file + model: + anyOf: + - type: string + - type: string + enum: + - whisper-1 + description: ID of the model to use. Only `whisper-1` is currently available. + x-oaiTypeLabel: string + language: + type: string + description: |- + The language of the input audio. Supplying the input language in + [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) format will improve accuracy + and latency. + prompt: + type: string + description: |- + An optional text to guide the model's style or continue a previous audio segment. The + [prompt](/docs/guides/speech-to-text/prompting) should match the audio language. + response_format: + type: string + enum: + - json + - text + - srt + - verbose_json + - vtt + - text + - srt + - verbose_json + - vtt + description: |- + The format of the transcript output, in one of these options: json, text, srt, verbose_json, or + vtt. + default: json + temperature: + type: number + format: double + minimum: 0 + maximum: 1 + description: |- + The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more + random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, + the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to + automatically increase the temperature until certain thresholds are hit. + default: 0 + CreateTranscriptionResponse: + type: object + required: + - text + properties: + text: type: string - description: A unique identifier for the chat completion. - object: + description: The transcribed text for the provided audio data. + task: type: string - description: The object type, which is always `chat.completion`. - created: - type: integer - format: unixtime - description: The Unix timestamp (in seconds) of when the chat completion was created. - model: + enum: + - transcribe + description: The label that describes which operation type generated the accompanying response data. + language: type: string - description: The model used for the chat completion. - choices: + description: The spoken language that was detected in the audio data. + duration: + type: number + format: double + description: The total duration of the audio processed to produce accompanying transcription information. + segments: type: array items: - type: object - required: - - index - - message - - finish_reason - properties: - index: - type: integer - format: int64 - description: The index of the choice in the list of choices. - message: - $ref: '#/components/schemas/ChatCompletionResponseMessage' - finish_reason: - type: string - enum: - - stop - - length - - function_call - - content_filter - description: |- - The reason the model stopped generating tokens. This will be `stop` if the model hit a - natural stop point or a provided stop sequence, `length` if the maximum number of tokens - specified in the request was reached, `content_filter` if the content was omitted due to - a flag from our content filters, or `function_call` if the model called a function. - description: A list of chat completion choices. Can be more than one if `n` is greater than 1. - usage: - $ref: '#/components/schemas/CompletionUsage' - x-oaiMeta: - name: The chat completion object - group: chat - example: '' - CreateCompletionRequest: + $ref: '#/components/schemas/AudioSegment' + description: |- + A collection of information about the timing, probabilities, and other detail of each processed + audio segment. + CreateTranslationRequestMultiPart: type: object required: + - file - model - - prompt properties: + file: + type: string + format: binary + description: |- + The audio file object (not file name) to translate, in one of these formats: flac, mp3, mp4, + mpeg, mpga, m4a, ogg, wav, or webm. + x-oaiTypeLabel: file model: anyOf: - type: string - type: string enum: - - babbage-002 - - davinci-002 - - text-davinci-003 - - text-davinci-002 - - text-davinci-001 - - code-davinci-002 - - text-curie-001 - - text-babbage-001 - - text-ada-001 - description: |- - ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to - see all of your available models, or see our [Model overview](/docs/models/overview) for - descriptions of them. + - whisper-1 + description: ID of the model to use. Only `whisper-1` is currently available. x-oaiTypeLabel: string prompt: - allOf: - - $ref: '#/components/schemas/Prompt' - description: |- - The prompt(s) to generate completions for, encoded as a string, array of strings, array of - tokens, or array of token arrays. - - Note that <|endoftext|> is the document separator that the model sees during training, so if a - prompt is not specified the model will generate as if from the beginning of a new document. - default: <|endoftext|> - suffix: type: string - nullable: true - description: The suffix that comes after a completion of inserted text. - default: null - temperature: - oneOf: - - $ref: '#/components/schemas/Temperature' - nullable: true - description: |- - What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output - more random, while lower values like 0.2 will make it more focused and deterministic. - - We generally recommend altering this or `top_p` but not both. - default: 1 - top_p: - oneOf: - - $ref: '#/components/schemas/TopP' - nullable: true - description: |- - An alternative to sampling with temperature, called nucleus sampling, where the model considers - the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising - the top 10% probability mass are considered. - - We generally recommend altering this or `temperature` but not both. - default: 1 - n: - oneOf: - - $ref: '#/components/schemas/N' - nullable: true - description: |- - How many completions to generate for each prompt. - **Note:** Because this parameter generates many completions, it can quickly consume your token - quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. - default: 1 - max_tokens: - oneOf: - - $ref: '#/components/schemas/MaxTokens' - nullable: true - description: |- - The maximum number of [tokens](/tokenizer) to generate in the completion. - - The token count of your prompt plus `max_tokens` cannot exceed the model's context length. - [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) - for counting tokens. - default: 16 - stop: - allOf: - - $ref: '#/components/schemas/Stop' - description: Up to 4 sequences where the API will stop generating further tokens. - default: null - presence_penalty: - oneOf: - - $ref: '#/components/schemas/Penalty' - nullable: true - description: |- - Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear - in the text so far, increasing the model's likelihood to talk about new topics. - - [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) - frequency_penalty: - oneOf: - - $ref: '#/components/schemas/Penalty' - nullable: true - description: |- - Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing - frequency in the text so far, decreasing the model's likelihood to repeat the same line - verbatim. - - [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) - logit_bias: - type: object - description: |- - Modify the likelihood of specified tokens appearing in the completion. - Accepts a json object that maps tokens (specified by their token ID in the tokenizer) to an - associated bias value from -100 to 100. Mathematically, the bias is added to the logits - generated by the model prior to sampling. The exact effect will vary per model, but values - between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 - should result in a ban or exclusive selection of the relevant token. - additionalProperties: - type: integer - format: int64 - nullable: true - x-oaiTypeLabel: map - user: - allOf: - - $ref: '#/components/schemas/User' description: |- - A unique identifier representing your end-user, which can help OpenAI to monitor and detect - abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). - stream: - type: boolean - nullable: true + An optional text to guide the model's style or continue a previous audio segment. The + [prompt](/docs/guides/speech-to-text/prompting) should match the audio language. + response_format: + type: string + enum: + - json + - text + - srt + - verbose_json + - vtt + - text + - srt + - verbose_json + - vtt description: |- - If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only - [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) - as they become available, with the stream terminated by a `data: [DONE]` message. - [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_stream_completions.ipynb). - default: true - logprobs: - type: integer - format: int64 - nullable: true + The format of the transcript output, in one of these options: json, text, srt, verbose_json, or + vtt. + default: json + temperature: + type: number + format: double + minimum: 0 + maximum: 1 description: |- - Include the log probabilities on the `logprobs` most likely tokens, as well the chosen tokens. - For example, if `logprobs` is 5, the API will return a list of the 5 most likely tokens. The - API will always return the `logprob` of the sampled token, so there may be up to `logprobs+1` - elements in the response. - - The maximum value for `logprobs` is 5. - default: null - echo: - type: boolean - nullable: true - description: Echo back the prompt in addition to the completion - default: false - best_of: - type: integer - format: int64 - nullable: true + The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more + random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, + the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to + automatically increase the temperature until certain thresholds are hit. + default: 0 + CreateTranslationResponse: + type: object + required: + - text + properties: + text: + type: string + description: The translated text for the provided audio data. + task: + type: string + enum: + - translate + description: The label that describes which operation type generated the accompanying response data. + language: + type: string + description: The spoken language that was detected in the audio data. + duration: + type: number + format: double + description: The total duration of the audio processed to produce accompanying translation information. + segments: + type: array + items: + $ref: '#/components/schemas/AudioSegment' description: |- - Generates `best_of` completions server-side and returns the "best" (the one with the highest - log probability per token). Results cannot be streamed. - - When used with `n`, `best_of` controls the number of candidate completions and `n` specifies - how many to return – `best_of` must be greater than `n`. - - **Note:** Because this parameter generates many completions, it can quickly consume your token - quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. - default: 1 - CreateCompletionResponse: + A collection of information about the timing, probabilities, and other detail of each processed + audio segment. + DeleteAssistantFileResponse: type: object + required: + - id + - deleted + - object + properties: + id: + type: string + deleted: + type: boolean + object: + type: string + enum: + - assistant.file.deleted description: |- - Represents a completion response from the API. Note: both the streamed and non-streamed response - objects share the same shape (unlike the chat endpoint). + Deletes the association between the assistant and the file, but does not delete the + [File](/docs/api-reference/files) object itself. + DeleteAssistantResponse: + type: object + required: + - id + - deleted + - object + properties: + id: + type: string + deleted: + type: boolean + object: + type: string + enum: + - assistant.deleted + DeleteFileResponse: + type: object required: - id - object - - created - - model - - choices + - deleted properties: id: type: string - description: A unique identifier for the completion. object: type: string - description: The object type, which is always `text_completion`. - created: - type: integer - format: unixtime - description: The Unix timestamp (in seconds) of when the completion was created. - model: - type: string - description: The model used for the completion. - choices: - type: array - items: - type: object - required: - - index - - text - - logprobs - - finish_reason - properties: - index: - type: integer - format: int64 - text: - type: string - logprobs: - type: object - required: - - tokens - - token_logprobs - - top_logprobs - - text_offset - properties: - tokens: - type: array - items: - type: string - token_logprobs: - type: array - items: - type: number - format: double - top_logprobs: - type: array - items: - type: object - additionalProperties: - type: integer - format: int64 - text_offset: - type: array - items: - type: integer - format: int64 - nullable: true - finish_reason: - type: string - enum: - - stop - - length - - content_filter - description: |- - The reason the model stopped generating tokens. This will be `stop` if the model hit a - natural stop point or a provided stop sequence, or `content_filter` if content was omitted - due to a flag from our content filters, `length` if the maximum number of tokens specified - in the request was reached, or `content_filter` if content was omitted due to a flag from our - content filters. - description: The list of completion choices the model generated for the input. - usage: - $ref: '#/components/schemas/CompletionUsage' - x-oaiMeta: - name: The completion object - legacy: true - example: '' - CreateEditRequest: + enum: + - file + deleted: + type: boolean + DeleteModelResponse: type: object required: - - model - - instruction + - id + - deleted + - object properties: - model: - anyOf: - - type: string - - type: string - enum: - - text-davinci-edit-001 - - code-davinci-edit-001 - description: |- - ID of the model to use. You can use the `text-davinci-edit-001` or `code-davinci-edit-001` - model with this endpoint. - x-oaiTypeLabel: string - input: + id: type: string - nullable: true - description: The input text to use as a starting point for the edit. - default: '' - instruction: + deleted: + type: boolean + object: type: string - description: The instruction that tells the model how to edit the prompt. - n: - oneOf: - - $ref: '#/components/schemas/EditN' - nullable: true - description: How many edits to generate for the input and instruction. - default: 1 - temperature: - oneOf: - - $ref: '#/components/schemas/Temperature' - nullable: true - description: |- - What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output - more random, while lower values like 0.2 will make it more focused and deterministic. - - We generally recommend altering this or `top_p` but not both. - default: 1 - top_p: - oneOf: - - $ref: '#/components/schemas/TopP' - nullable: true - description: |- - An alternative to sampling with temperature, called nucleus sampling, where the model considers - the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising - the top 10% probability mass are considered. - - We generally recommend altering this or `temperature` but not both. - default: 1 - CreateEditResponse: + enum: + - model + DeleteThreadResponse: type: object required: + - id + - deleted - object - - created - - choices - - usage properties: + id: + type: string + deleted: + type: boolean object: type: string enum: - - edit - description: The object type, which is always `edit`. - created: - type: integer - format: unixtime - description: The Unix timestamp (in seconds) of when the edit was created. - choices: - type: array - items: - type: object - required: - - text - - index - - finish_reason - properties: - text: - type: string - description: The edited result. - index: - type: integer - format: int64 - description: The index of the choice in the list of choices. - finish_reason: - type: string - enum: - - stop - - length - description: |- - The reason the model stopped generating tokens. This will be `stop` if the model hit a - natural stop point or a provided stop sequence, or `length` if the maximum number of tokens - specified in the request was reached. - description: 'description: A list of edit choices. Can be more than one if `n` is greater than 1.' - usage: - $ref: '#/components/schemas/CompletionUsage' - CreateEmbeddingRequest: + - thread.deleted + Embedding: type: object required: - - model - - input + - index + - embedding + - object properties: - model: - anyOf: - - type: string - - type: string - enum: - - text-embedding-ada-002 - description: ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to see all of your available models, or see our [Model overview](/docs/models/overview) for descriptions of them. - x-oaiTypeLabel: string - input: + index: + type: integer + format: int64 + description: The index of the embedding in the list of embeddings. + embedding: anyOf: - - type: string - type: array items: - type: string - - $ref: '#/components/schemas/TokenArray' - - $ref: '#/components/schemas/TokenArrayArray' + type: number + format: double + - type: string description: |- - Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a - single request, pass an array of strings or array of token arrays. Each input must not exceed - the max input tokens for the model (8191 tokens for `text-embedding-ada-002`) and cannot be an empty string. - [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) - for counting tokens. - user: - $ref: '#/components/schemas/User' - CreateEmbeddingResponse: + The embedding vector, which is a list of floats. The length of vector depends on the model as + listed in the [embedding guide](/docs/guides/embeddings). + object: + type: string + enum: + - embedding + description: The object type, which is always "embedding". + description: Represents an embedding vector returned by embedding endpoint. + Error: + type: object + required: + - type + - message + - param + - code + properties: + type: + type: string + message: + type: string + param: + type: string + nullable: true + code: + type: string + nullable: true + ErrorResponse: + type: object + required: + - error + properties: + error: + $ref: '#/components/schemas/Error' + FineTune: type: object required: + - id - object + - created_at + - updated_at - model - - data - - usage + - fine_tuned_model + - organization_id + - status + - hyperparams + - training_files + - validation_files + - result_files properties: + id: + type: string + description: The object identifier, which can be referenced in the API endpoints. object: type: string enum: - - embedding - description: The object type, which is always "embedding". - model: - type: string - description: The name of the model used to generate the embedding. - data: - type: array - items: - $ref: '#/components/schemas/Embedding' - description: The list of embeddings generated by the model. - usage: + - fine-tune + - fine-tune-results + - assistants + - assistants_output + description: The object type, which is always "fine-tune". + created_at: + type: integer + format: unixtime + description: The Unix timestamp (in seconds) for when the fine-tuning job was created. + updated_at: + type: integer + format: unixtime + description: The Unix timestamp (in seconds) for when the fine-tuning job was last updated. + model: + type: string + description: The base model that is being fine-tuned. + fine_tuned_model: + type: string + nullable: true + description: The name of the fine-tuned model that is being created. + organization_id: + type: string + description: The organization that owns the fine-tuning job. + status: + type: string + enum: + - created + - pending + - running + - succeeded + - failed + - cancelled + - running + - succeeded + - failed + - cancelled + description: |- + The current status of the fine-tuning job, which can be either `created`, `running`, + `succeeded`, `failed`, or `cancelled`. + hyperparams: type: object - description: The usage information for the request. - required: - - prompt_tokens - - total_tokens properties: - prompt_tokens: + n_epochs: type: integer format: int64 - description: The number of tokens used by the prompt. - total_tokens: + description: |- + The number of epochs to train the model for. An epoch refers to one full cycle through the + training dataset. + batch_size: type: integer format: int64 - description: The total number of tokens used by the request. - CreateFileRequest: + description: |- + The batch size to use for training. The batch size is the number of training examples used to + train a single forward and backward pass. + prompt_loss_weight: + type: number + format: double + description: The weight to use for loss on the prompt tokens. + learning_rate_multiplier: + type: number + format: double + description: The learning rate multiplier to use for training. + compute_classification_metrics: + type: boolean + description: The classification metrics to compute using the validation dataset at the end of every epoch. + classification_positive_class: + type: string + description: The positive class to use for computing classification metrics. + classification_n_classes: + type: integer + format: int64 + description: The number of classes to use for computing classification metrics. + required: + - n_epochs + - batch_size + - prompt_loss_weight + - learning_rate_multiplier + description: |- + The hyperparameters used for the fine-tuning job. See the + [fine-tuning guide](/docs/guides/legacy-fine-tuning/hyperparameters) for more details. + training_files: + type: array + items: + $ref: '#/components/schemas/OpenAIFile' + description: The list of files used for training. + validation_files: + type: array + items: + $ref: '#/components/schemas/OpenAIFile' + description: The list of files used for validation. + result_files: + type: array + items: + $ref: '#/components/schemas/OpenAIFile' + description: The compiled results files for the fine-tuning job. + events: + type: array + items: + $ref: '#/components/schemas/FineTuneEvent' + description: The list of events that have been observed in the lifecycle of the FineTune job. + description: The `FineTune` object represents a legacy fine-tune job that has been created through the API. + deprecated: true + FineTuneEvent: type: object required: - - file - - purpose + - object + - created_at + - level + - message properties: - file: + object: type: string - format: binary - description: |- - Name of the [JSON Lines](https://jsonlines.readthedocs.io/en/latest/) file to be uploaded. - - If the `purpose` is set to "fine-tune", the file will be used for fine-tuning. - purpose: + created_at: + type: integer + format: unixtime + level: type: string - description: |- - The intended purpose of the uploaded documents. Use "fine-tune" for - [fine-tuning](/docs/api-reference/fine-tuning). This allows us to validate the format of the - uploaded file. - CreateFineTuneRequest: + message: + type: string + FineTuningEvent: type: object required: - - training_file + - object + - created_at + - level + - message properties: - training_file: - type: string - description: |- - The ID of an uploaded file that contains training data. - - See [upload file](/docs/api-reference/files/upload) for how to upload a file. - - Your dataset must be formatted as a JSONL file, where each training example is a JSON object - with the keys "prompt" and "completion". Additionally, you must upload your file with the - purpose `fine-tune`. - - See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more - details. - validation_file: + object: type: string - nullable: true - description: |- - The ID of an uploaded file that contains validation data. - - If you provide this file, the data is used to generate validation metrics periodically during - fine-tuning. These metrics can be viewed in the - [fine-tuning results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model). - Your train and validation data should be mutually exclusive. - - Your dataset must be formatted as a JSONL file, where each validation example is a JSON object - with the keys "prompt" and "completion". Additionally, you must upload your file with the - purpose `fine-tune`. - - See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more - details. - model: - anyOf: - - type: string - - type: string - enum: - - ada - - babbage - - curie - - davinci - nullable: true - description: |- - The name of the base model to fine-tune. You can select one of "ada", "babbage", "curie", - "davinci", or a fine-tuned model created after 2022-04-21 and before 2023-08-22. To learn more - about these models, see the [Models](/docs/models) documentation. - x-oaiTypeLabel: string - n_epochs: - type: integer - format: int64 - nullable: true - description: |- - The number of epochs to train the model for. An epoch refers to one full cycle through the - training dataset. - default: 4 - batch_size: - type: integer - format: int64 - nullable: true - description: |- - The batch size to use for training. The batch size is the number of training examples used to - train a single forward and backward pass. - - By default, the batch size will be dynamically configured to be ~0.2% of the number of examples - in the training set, capped at 256 - in general, we've found that larger batch sizes tend to - work better for larger datasets. - default: null - learning_rate_multiplier: - type: number - format: double - nullable: true - description: |- - The learning rate multiplier to use for training. The fine-tuning learning rate is the original - learning rate used for pretraining multiplied by this value. - - By default, the learning rate multiplier is the 0.05, 0.1, or 0.2 depending on final - `batch_size` (larger learning rates tend to perform better with larger batch sizes). We - recommend experimenting with values in the range 0.02 to 0.2 to see what produces the best - results. - default: null - prompt_loss_rate: - type: number - format: double - nullable: true - description: |- - The weight to use for loss on the prompt tokens. This controls how much the model tries to - learn to generate the prompt (as compared to the completion which always has a weight of 1.0), - and can add a stabilizing effect to training when completions are short. - - If prompts are extremely long (relative to completions), it may make sense to reduce this - weight so as to avoid over-prioritizing learning the prompt. - default: 0.01 - compute_classification_metrics: - type: boolean - nullable: true - description: |- - If set, we calculate classification-specific metrics such as accuracy and F-1 score using the - validation set at the end of every epoch. These metrics can be viewed in the - [results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model). - - In order to compute classification metrics, you must provide a `validation_file`. Additionally, - you must specify `classification_n_classes` for multiclass classification or - `classification_positive_class` for binary classification. - default: false - classification_n_classes: + created_at: type: integer - format: int64 - nullable: true - description: |- - The number of classes in a classification task. - - This parameter is required for multiclass classification. - default: null - classification_positive_class: + format: unixtime + level: type: string + message: + type: string + data: + type: object + additionalProperties: {} nullable: true - description: |- - The positive class in binary classification. - - This parameter is needed to generate precision, recall, and F1 metrics when doing binary - classification. - default: null - classification_betas: - type: array - items: - type: number - format: double - nullable: true - description: |- - If this is provided, we calculate F-beta scores at the specified beta values. The F-beta score - is a generalization of F-1 score. This is only used for binary classification. - - With a beta of 1 (i.e. the F-1 score), precision and recall are given the same weight. A larger - beta score puts more weight on recall and less on precision. A smaller beta score puts more - weight on precision and less on recall. - default: null - suffix: - oneOf: - - $ref: '#/components/schemas/SuffixString' - nullable: true - description: |- - 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 - `ada:ft-your-org:custom-model-name-2022-02-15-04-21-04`. - default: null - CreateFineTuningJobRequest: + type: + type: string + enum: + - message + - metrics + FineTuningJob: type: object required: - - training_file + - id + - object + - created_at + - finished_at - model + - fine_tuned_model + - organization_id + - status + - hyperparameters + - training_file + - validation_file + - result_files + - trained_tokens + - error properties: - training_file: + id: type: string - description: |- - The ID of an uploaded file that contains training data. - - See [upload file](/docs/api-reference/files/upload) for how to upload a file. - - Your dataset must be formatted as a JSONL file. Additionally, you must upload your file with - the purpose `fine-tune`. - - See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. - validation_file: + description: The object identifier, which can be referenced in the API endpoints. + object: + type: string + enum: + - fine_tuning.job + description: The object type, which is always "fine_tuning.job". + created_at: + type: integer + format: unixtime + description: The Unix timestamp (in seconds) for when the fine-tuning job was created. + finished_at: type: string + format: date-time nullable: true description: |- - The ID of an uploaded file that contains validation data. - - If you provide this file, the data is used to generate validation metrics periodically during - fine-tuning. These metrics can be viewed in the fine-tuning results file. The same data should - not be present in both train and validation files. - - Your dataset must be formatted as a JSONL file. You must upload your file with the purpose - `fine-tune`. - - See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. + The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be + null if the fine-tuning job is still running. model: - anyOf: - - type: string - - type: string - enum: - - babbage-002 - - davinci-002 - - gpt-3.5-turbo + type: string + description: The base model that is being fine-tuned. + fine_tuned_model: + type: string + nullable: true description: |- - The name of the model to fine-tune. You can select one of the - [supported models](/docs/guides/fine-tuning/what-models-can-be-fine-tuned). - x-oaiTypeLabel: string + The name of the fine-tuned model that is being created. The value will be null if the + fine-tuning job is still running. + organization_id: + type: string + description: The organization that owns the fine-tuning job. + status: + type: string + enum: + - created + - pending + - running + - succeeded + - failed + - cancelled + - running + - succeeded + - failed + - cancelled + description: |- + The current status of the fine-tuning job, which can be either `created`, `pending`, `running`, + `succeeded`, `failed`, or `cancelled`. hyperparameters: type: object - description: The hyperparameters used for the fine-tuning job. properties: n_epochs: anyOf: - type: string enum: - auto + - low + - high - $ref: '#/components/schemas/NEpochs' description: |- The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset. + + "Auto" decides the optimal number of epochs based on the size of the dataset. If setting the + number manually, we support any number between 1 and 50 epochs. default: auto - suffix: - oneOf: - - $ref: '#/components/schemas/SuffixString' + description: |- + The hyperparameters used for the fine-tuning job. See the + [fine-tuning guide](/docs/guides/fine-tuning) for more details. + training_file: + type: string + description: |- + The file ID used for training. You can retrieve the training data with the + [Files API](/docs/api-reference/files/retrieve-contents). + validation_file: + type: string nullable: true description: |- - 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`. - default: null - CreateImageEditRequest: + The file ID used for validation. You can retrieve the validation results with the + [Files API](/docs/api-reference/files/retrieve-contents). + result_files: + type: array + items: + type: string + description: |- + The compiled results file ID(s) for the fine-tuning job. You can retrieve the results with the + [Files API](/docs/api-reference/files/retrieve-contents). + trained_tokens: + type: integer + format: int64 + nullable: true + description: |- + The total number of billable tokens processed by this fine tuning job. The value will be null + if the fine-tuning job is still running. + error: + type: object + properties: + message: + type: string + description: A human-readable error message. + code: + type: string + description: A machine-readable error code. + param: + type: string + nullable: true + description: |- + The parameter that was invalid, usually `training_file` or `validation_file`. This field + will be null if the failure was not parameter-specific. + nullable: true + description: |- + For fine-tuning jobs that have `failed`, this will contain more information on the cause of the + failure. + FineTuningJobEvent: type: object required: - - prompt - - image + - id + - object + - created_at + - level + - message properties: - prompt: + id: type: string - description: A text description of the desired image(s). The maximum length is 1000 characters. - image: + object: + type: string + created_at: + type: integer + format: unixtime + level: + type: string + enum: + - info + - warn + - error + message: + type: string + FunctionObject: + type: object + required: + - name + properties: + description: type: string - format: binary description: |- - The image to edit. Must be a valid PNG file, less than 4MB, and square. If mask is not - provided, image must have transparency, which will be used as the mask. - mask: + A description of what the function does, used by the model to choose when and how to call the + function. + name: type: string - format: binary description: |- - An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where - `image` should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions - as `image`. - n: - oneOf: - - $ref: '#/components/schemas/ImagesN' - nullable: true - description: The number of images to generate. Must be between 1 and 10. - default: 1 - size: + The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and + dashes, with a maximum length of 64. + parameters: + $ref: '#/components/schemas/FunctionParameters' + FunctionParameters: + type: object + additionalProperties: {} + description: |- + The parameters the functions accepts, described as a JSON Schema object. See the + [guide](/docs/guides/gpt/function-calling) for examples, and the + [JSON Schema reference](https://json-schema.org/understanding-json-schema/) for documentation + about the format.\n\nTo describe a function that accepts no parameters, provide the value + `{\"type\": \"object\", \"properties\": {}}`. + Image: + type: object + properties: + b64_json: type: string - enum: - - 256x256 - - 512x512 - - 1024x1024 - nullable: true - description: The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`. - default: 1024x1024 - response_format: + format: base64 + description: The base64-encoded JSON of the generated image, if `response_format` is `b64_json`. + url: type: string - enum: - - url - - b64_json - nullable: true - description: The format in which the generated images are returned. Must be one of `url` or `b64_json`. - default: url - user: - $ref: '#/components/schemas/User' - CreateImageRequest: + format: uri + description: The URL of the generated image, if `response_format` is `url` (default). + revised_prompt: + type: string + description: The prompt that was used to generate the image, if there was any revision to the prompt. + description: Represents the url or the content of an image generated by the OpenAI API. + ImagesN: + type: integer + format: int64 + minimum: 1 + maximum: 10 + ImagesResponse: + type: object + required: + - created + - data + properties: + created: + type: integer + format: unixtime + data: + type: array + items: + $ref: '#/components/schemas/Image' + ListAssistantFilesResponse: type: object required: - - prompt + - object + - data + - first_id + - last_id + - has_more properties: - prompt: - type: string - description: A text description of the desired image(s). The maximum length is 1000 characters. - n: - oneOf: - - $ref: '#/components/schemas/ImagesN' - nullable: true - description: The number of images to generate. Must be between 1 and 10. - default: 1 - size: + object: type: string enum: - - 256x256 - - 512x512 - - 1024x1024 - nullable: true - description: The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`. - default: 1024x1024 - response_format: + - list + data: + type: array + items: + $ref: '#/components/schemas/AssistantFileObject' + first_id: type: string - enum: - - url - - b64_json - nullable: true - description: The format in which the generated images are returned. Must be one of `url` or `b64_json`. - default: url - user: - $ref: '#/components/schemas/User' - CreateImageVariationRequest: + last_id: + type: string + has_more: + type: boolean + ListAssistantsResponse: type: object required: - - image + - object + - data + - first_id + - last_id + - has_more properties: - image: - type: string - format: binary - description: |- - The image to use as the basis for the variation(s). Must be a valid PNG file, less than 4MB, - and square. - n: - oneOf: - - $ref: '#/components/schemas/ImagesN' - nullable: true - description: The number of images to generate. Must be between 1 and 10. - default: 1 - size: + object: type: string enum: - - 256x256 - - 512x512 - - 1024x1024 - nullable: true - description: The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`. - default: 1024x1024 - response_format: + - list + data: + type: array + items: + $ref: '#/components/schemas/AssistantObject' + first_id: type: string - enum: - - url - - b64_json - nullable: true - description: The format in which the generated images are returned. Must be one of `url` or `b64_json`. - default: url - user: - $ref: '#/components/schemas/User' - CreateModerationRequest: + last_id: + type: string + has_more: + type: boolean + ListFilesResponse: type: object required: - - input + - data + - object properties: - input: - anyOf: - - type: string - - type: array - items: - type: string - description: The input text to classify - model: - anyOf: - - type: string - - type: string - enum: - - text-moderation-latest - - text-moderation-stable - description: |- - Two content moderations models are available: `text-moderation-stable` and - `text-moderation-latest`. The default is `text-moderation-latest` which will be automatically - upgraded over time. This ensures you are always using our most accurate model. If you use - `text-moderation-stable`, we will provide advanced notice before updating the model. Accuracy - of `text-moderation-stable` may be slightly lower than for `text-moderation-latest`. - x-oaiTypeLabel: string - default: text-moderation-latest - CreateModerationResponse: + data: + type: array + items: + $ref: '#/components/schemas/OpenAIFile' + object: + type: string + enum: + - list + ListFineTuneEventsResponse: type: object required: - - id - - model - - results + - object + - data properties: - id: - type: string - description: The unique identifier for the moderation request. - model: + object: type: string - description: The model used to generate the moderation results. - results: + data: type: array items: - type: object - required: - - flagged - - categories - - category_scores - properties: - flagged: - type: boolean - description: Whether the content violates [OpenAI's usage policies](/policies/usage-policies). - categories: - type: object - description: A list of the categories, and whether they are flagged or not. - required: - - hate - - hate/threatening - - harassment - - harassment/threatening - - self-harm - - self-harm/intent - - self-harm/instructive - - sexual - - sexual/minors - - violence - - violence/graphic - properties: - hate: - type: boolean - description: |- - Content that expresses, incites, or promotes hate based on race, gender, ethnicity, - religion, nationality, sexual orientation, disability status, or caste. Hateful content - aimed at non-protected groups (e.g., chess players) is harrassment. - hate/threatening: - type: boolean - description: |- - Hateful content that also includes violence or serious harm towards the targeted group - based on race, gender, ethnicity, religion, nationality, sexual orientation, disability - status, or caste. - harassment: - type: boolean - description: Content that expresses, incites, or promotes harassing language towards any target. - harassment/threatening: - type: boolean - description: Harassment content that also includes violence or serious harm towards any target. - self-harm: - type: boolean - description: |- - Content that promotes, encourages, or depicts acts of self-harm, such as suicide, cutting, - and eating disorders. - self-harm/intent: - type: boolean - description: |- - Content where the speaker expresses that they are engaging or intend to engage in acts of - self-harm, such as suicide, cutting, and eating disorders. - self-harm/instructive: - type: boolean - description: |- - Content that encourages performing acts of self-harm, such as suicide, cutting, and eating - disorders, or that gives instructions or advice on how to commit such acts. - sexual: - type: boolean - description: |- - Content meant to arouse sexual excitement, such as the description of sexual activity, or - that promotes sexual services (excluding sex education and wellness). - sexual/minors: - type: boolean - description: Sexual content that includes an individual who is under 18 years old. - violence: - type: boolean - description: Content that depicts death, violence, or physical injury. - violence/graphic: - type: boolean - description: Content that depicts death, violence, or physical injury in graphic detail. - category_scores: - type: object - description: A list of the categories along with their scores as predicted by model. - required: - - hate - - hate/threatening - - harassment - - harassment/threatening - - self-harm - - self-harm/intent - - self-harm/instructive - - sexual - - sexual/minors - - violence - - violence/graphic - properties: - hate: - type: number - format: double - description: The score for the category 'hate'. - hate/threatening: - type: number - format: double - description: The score for the category 'hate/threatening'. - harassment: - type: number - format: double - description: The score for the category 'harassment'. - harassment/threatening: - type: number - format: double - description: The score for the category 'harassment/threatening'. - self-harm: - type: number - format: double - description: The score for the category 'self-harm'. - self-harm/intent: - type: number - format: double - description: The score for the category 'self-harm/intent'. - self-harm/instructive: - type: number - format: double - description: The score for the category 'self-harm/instructive'. - sexual: - type: number - format: double - description: The score for the category 'sexual'. - sexual/minors: - type: number - format: double - description: The score for the category 'sexual/minors'. - violence: - type: number - format: double - description: The score for the category 'violence'. - violence/graphic: - type: number - format: double - description: The score for the category 'violence/graphic'. - description: A list of moderation objects. - CreateTranscriptionRequest: + $ref: '#/components/schemas/FineTuneEvent' + ListFineTunesResponse: type: object required: - - file - - model + - object + - data properties: - file: + object: type: string - format: binary - description: |- - The audio file object (not file name) to transcribe, in one of these formats: flac, mp3, mp4, - mpeg, mpga, m4a, ogg, wav, or webm. - x-oaiTypeLabel: file - model: - anyOf: - - type: string - - type: string - enum: - - whisper-1 - description: ID of the model to use. Only `whisper-1` is currently available. - x-oaiTypeLabel: string - prompt: + data: + type: array + items: + $ref: '#/components/schemas/FineTune' + ListFineTuningJobEventsResponse: + type: object + required: + - object + - data + properties: + object: type: string - description: |- - An optional text to guide the model's style or continue a previous audio segment. The - [prompt](/docs/guides/speech-to-text/prompting) should match the audio language. - response_format: + data: + type: array + items: + $ref: '#/components/schemas/FineTuningJobEvent' + ListMessageFilesResponse: + type: object + required: + - object + - data + - first_id + - last_id + - has_more + properties: + object: type: string enum: - - json - - text - - srt - - verbose_json - - vtt - description: |- - The format of the transcript output, in one of these options: json, text, srt, verbose_json, or - vtt. - default: json - temperature: - type: number - format: double - description: |- - The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more - random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, - the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to - automatically increase the temperature until certain thresholds are hit. - minimum: 0 - maximum: 1 - default: 0 - language: + - list + data: + type: array + items: + $ref: '#/components/schemas/MessageFileObject' + first_id: type: string - description: |- - The language of the input audio. Supplying the input language in - [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) format will improve accuracy - and latency. - CreateTranscriptionResponse: + last_id: + type: string + has_more: + type: boolean + ListMessagesResponse: type: object required: - - text + - object + - data + - first_id + - last_id + - has_more properties: - text: + object: + type: string + enum: + - list + data: + type: array + items: + $ref: '#/components/schemas/MessageObject' + first_id: type: string - CreateTranslationRequest: + last_id: + type: string + has_more: + type: boolean + ListModelsResponse: type: object required: - - file - - model + - object + - data properties: - file: + object: type: string - format: binary - description: |- - The audio file object (not file name) to translate, in one of these formats: flac, mp3, mp4, - mpeg, mpga, m4a, ogg, wav, or webm. - x-oaiTypeLabel: file - model: - anyOf: - - type: string - - type: string - enum: - - whisper-1 - description: ID of the model to use. Only `whisper-1` is currently available. - x-oaiTypeLabel: string - prompt: + enum: + - list + data: + type: array + items: + $ref: '#/components/schemas/Model' + ListPaginatedFineTuningJobsResponse: + type: object + required: + - object + - data + - has_more + properties: + object: type: string - description: |- - An optional text to guide the model's style or continue a previous audio segment. The - [prompt](/docs/guides/speech-to-text/prompting) should match the audio language. - response_format: + data: + type: array + items: + $ref: '#/components/schemas/FineTuningJob' + has_more: + type: boolean + ListRunStepsResponse: + type: object + required: + - object + - data + - first_id + - last_id + - has_more + properties: + object: type: string enum: - - json - - text - - srt - - verbose_json - - vtt - description: |- - The format of the transcript output, in one of these options: json, text, srt, verbose_json, or - vtt. - default: json - temperature: - type: number - format: double - description: |- - The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more - random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, - the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to - automatically increase the temperature until certain thresholds are hit. - minimum: 0 - maximum: 1 - default: 0 - CreateTranslationResponse: + - list + data: + type: array + items: + $ref: '#/components/schemas/RunStepObject' + first_id: + type: string + last_id: + type: string + has_more: + type: boolean + ListRunsResponse: + type: object + required: + - object + - data + - first_id + - last_id + - has_more + properties: + object: + type: string + enum: + - list + data: + type: array + items: + $ref: '#/components/schemas/RunObject' + first_id: + type: string + last_id: + type: string + has_more: + type: boolean + MessageContentImageFileObject: + type: object + required: + - type + - image_file + properties: + type: + type: string + enum: + - image_file + description: Always `image_file`. + image_file: + type: object + properties: + file_id: + type: string + description: The [File](/docs/api-reference/files) ID of the image in the message content. + required: + - file_id + description: References an image [File](/docs/api-reference/files) in the content of a message. + MessageContentTextAnnotationsFileCitationObject: type: object required: + - type - text + - file_citation + - start_index + - end_index properties: + type: + type: string + enum: + - file_citation + description: Always `file_citation`. text: type: string - DeleteFileResponse: + description: The text in the message content that needs to be replaced. + file_citation: + type: object + properties: + file_id: + type: string + description: The ID of the specific File the citation is from. + quote: + type: string + description: The specific quote in the file. + required: + - file_id + - quote + start_index: + type: integer + format: int64 + minimum: 0 + end_index: + type: integer + format: int64 + minimum: 0 + description: |- + A citation within the message that points to a specific quote from a specific File associated + with the assistant or the message. Generated when the assistant uses the "retrieval" tool to + search files. + MessageContentTextAnnotationsFilePathObject: type: object required: - - id - - object - - deleted + - type + - text + - file_path + - start_index + - end_index properties: - id: + type: type: string - object: + enum: + - file_path + description: Always `file_path`. + text: type: string - deleted: - type: boolean - DeleteModelResponse: + description: The text in the message content that needs to be replaced. + file_path: + type: object + properties: + file_id: + type: string + description: The ID of the file that was generated. + required: + - file_id + start_index: + type: integer + format: int64 + minimum: 0 + end_index: + type: integer + format: int64 + minimum: 0 + description: |- + A URL for the file that's generated when the assistant used the `code_interpreter` tool to + generate a file. + MessageContentTextObject: + type: object + required: + - type + - text + properties: + type: + type: string + enum: + - text + - json_object + description: Always `text`. + text: + type: object + properties: + value: + type: string + description: The data that makes up the text. + annotations: + type: array + items: + $ref: '#/components/schemas/MessageContentTextObjectAnnotations' + required: + - value + - annotations + description: The text content that is part of a message. + MessageContentTextObjectAnnotations: + oneOf: + - $ref: '#/components/schemas/MessageContentTextAnnotationsFileCitationObject' + - $ref: '#/components/schemas/MessageContentTextAnnotationsFilePathObject' + x-oaiExpandable: true + MessageFileObject: type: object required: - id - object - - deleted + - created_at + - message_id properties: id: type: string + description: TThe identifier, which can be referenced in API endpoints. object: type: string - deleted: - type: boolean - EditN: - type: integer - format: int64 - minimum: 0 - maximum: 20 - Embedding: + enum: + - thread.message.file + description: The object type, which is always `thread.message.file`. + created_at: + type: integer + format: unixtime + description: The Unix timestamp (in seconds) for when the message file was created. + message_id: + type: string + description: The ID of the [message](/docs/api-reference/messages) that the [File](/docs/api-reference/files) is attached to. + description: A list of files attached to a `message`. + MessageObject: type: object - description: Represents an embedding vector returned by embedding endpoint. required: - - index + - id - object - - embedding + - created_at + - thread_id + - role + - content + - assistant_id + - run_id + - file_ids + - metadata properties: - index: - type: integer - format: int64 - description: The index of the embedding in the list of embeddings. + id: + type: string + description: The identifier, which can be referenced in API endpoints. object: type: string enum: - - embedding - description: The object type, which is always "embedding". - embedding: - type: array - items: - type: number - format: double - description: |- - The embedding vector, which is a list of floats. The length of vector depends on the model as\ - listed in the [embedding guide](/docs/guides/embeddings). - Error: - type: object - required: - - type - - message - - param - - code - properties: - type: + - thread.message + description: The object type, which is always `thread.message`. + created_at: + type: integer + format: unixtime + description: The Unix timestamp (in seconds) for when the message was created. + thread_id: type: string - message: + description: The [thread](/docs/api-reference/threads) ID that this message belongs to. + role: type: string - param: + enum: + - user + - assistant + description: The entity that produced the message. One of `user` or `assistant`. + content: + type: array + items: + $ref: '#/components/schemas/MessageObjectContent' + description: The content of the message in array of text and/or images. + assistant_id: type: string nullable: true - code: + description: |- + If applicable, the ID of the [assistant](/docs/api-reference/assistants) that authored this + message. + run_id: type: string nullable: true - ErrorResponse: - type: object - required: - - error - properties: - error: - $ref: '#/components/schemas/Error' - FineTune: + description: |- + If applicable, the ID of the [run](/docs/api-reference/runs) associated with the authoring of + this message. + file_ids: + type: array + items: + type: string + maxItems: 10 + description: |- + A list of [file](/docs/api-reference/files) IDs that the assistant should use. Useful for + tools like retrieval and code_interpreter that can access files. A maximum of 10 files can be + attached to a message. + default: [] + metadata: + type: object + additionalProperties: + type: string + nullable: true + description: |- + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + x-oaiTypeLabel: map + MessageObjectContent: + oneOf: + - $ref: '#/components/schemas/MessageContentImageFileObject' + - $ref: '#/components/schemas/MessageContentTextObject' + x-oaiExpandable: true + Model: type: object - description: The `FineTune` object represents a legacy fine-tune job that has been created through the API. required: - id + - created - object - - created_at - - updated_at - - model - - fine_tuned_model - - organization_id - - status - - hyperparams - - training_files - - validation_files - - result_files + - owned_by properties: id: type: string - description: The object identifier, which can be referenced in the API endpoints. + description: The model identifier, which can be referenced in the API endpoints. + created: + type: integer + format: unixtime + description: The Unix timestamp (in seconds) when the model was created. object: type: string enum: - - fine-tune - description: The object type, which is always "fine-tune". - created_at: - type: integer - format: unixtime - description: The Unix timestamp (in seconds) for when the fine-tuning job was created. - updated_at: - type: integer - format: unixtime - description: The Unix timestamp (in seconds) for when the fine-tuning job was last updated. + - model + description: The object type, which is always "model". + owned_by: + type: string + description: The organization that owns the model. + description: Describes an OpenAI model offering that can be used with the API. + ModifyAssistantRequest: + type: object + properties: model: type: string - description: The base model that is being fine-tuned. - fine_tuned_model: + description: |- + ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + see all of your available models, or see our [Model overview](/docs/models/overview) for + descriptions of them. + name: type: string nullable: true - description: The name of the fine-tuned model that is being created. - organization_id: + maxLength: 256 + description: The name of the assistant. The maximum length is 256 characters. + description: type: string - description: The organization that owns the fine-tuning job. - status: + nullable: true + maxLength: 512 + description: The description of the assistant. The maximum length is 512 characters. + instructions: type: string - enum: - - created - - running - - succeeded - - failed - - cancelled - description: |- - The current status of the fine-tuning job, which can be either `created`, `running`, - `succeeded`, `failed`, or `cancelled`. - hyperparams: - type: object + nullable: true + maxLength: 32768 + description: The system instructions that the assistant uses. The maximum length is 32768 characters. + tools: + allOf: + - $ref: '#/components/schemas/CreateAssistantRequestToolsItem' description: |- - The hyperparameters used for the fine-tuning job. See the - [fine-tuning guide](/docs/guides/legacy-fine-tuning/hyperparameters) for more details. - required: - - n_epochs - - batch_size - - prompt_loss_weight - - learning_rate_multiplier - properties: - n_epochs: - type: integer - format: int64 - description: |- - The number of epochs to train the model for. An epoch refers to one full cycle through the - training dataset. - batch_size: - type: integer - format: int64 - description: |- - The batch size to use for training. The batch size is the number of training examples used to - train a single forward and backward pass. - prompt_loss_weight: - type: number - format: double - description: The weight to use for loss on the prompt tokens. - learning_rate_multiplier: - type: number - format: double - description: The learning rate multiplier to use for training. - compute_classification_metrics: - type: boolean - description: The classification metrics to compute using the validation dataset at the end of every epoch. - classification_positive_class: - type: string - description: The positive class to use for computing classification metrics. - classification_n_classes: - type: integer - format: int64 - description: The number of classes to use for computing classification metrics. - training_files: - type: array - items: - $ref: '#/components/schemas/OpenAIFile' - description: The list of files used for training. - validation_files: - type: array - items: - $ref: '#/components/schemas/OpenAIFile' - description: The list of files used for validation. - result_files: - type: array - items: - $ref: '#/components/schemas/OpenAIFile' - description: The compiled results files for the fine-tuning job. - events: + A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. + Tools can be of types `code_interpreter`, `retrieval`, or `function`. + default: [] + file_ids: type: array items: - $ref: '#/components/schemas/FineTuneEvent' - description: The list of events that have been observed in the lifecycle of the FineTune job. - FineTuneEvent: + type: string + maxItems: 20 + description: |- + A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a + maximum of 20 files attached to the assistant. Files are ordered by their creation date in + ascending order. + default: [] + metadata: + type: object + additionalProperties: + type: string + nullable: true + description: |- + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + x-oaiTypeLabel: map + ModifyMessageRequest: type: object - required: - - object - - created_at - - level - - message properties: - object: - type: string - created_at: - type: integer - format: unixtime - level: - type: string - message: - type: string - FineTuningEvent: + metadata: + type: object + additionalProperties: + type: string + nullable: true + description: |- + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + x-oaiTypeLabel: map + ModifyRunRequest: + type: object + properties: + metadata: + type: object + additionalProperties: + type: string + nullable: true + description: |- + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + x-oaiTypeLabel: map + ModifyThreadRequest: + type: object + properties: + metadata: + type: object + additionalProperties: + type: string + nullable: true + description: |- + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + NEpochs: + type: integer + format: int64 + minimum: 1 + maximum: 50 + OpenAIFile: type: object required: - - object + - id + - bytes - created_at - - level - - message + - filename + - object + - purpose + - status properties: - object: + id: type: string + description: The file identifier, which can be referenced in the API endpoints. + bytes: + type: integer + format: int64 + description: The size of the file, in bytes. created_at: type: integer format: unixtime - level: + description: The Unix timestamp (in seconds) for when the file was created. + filename: type: string - message: + description: The name of the file. + object: type: string - data: - type: object - additionalProperties: {} - nullable: true - type: + enum: + - file + description: The object type, which is always "file". + purpose: type: string enum: - - message - - metrics - FineTuningJob: + - fine-tune + - fine-tune-results + - assistants + - assistants_output + description: |- + The intended purpose of the file. Supported values are `fine-tune`, `fine-tune-results`, + `assistants`, and `assistants_output`. + status: + type: string + enum: + - uploaded + - processed + - error + description: |- + Deprecated. The current status of the file, which can be either `uploaded`, `processed`, or + `error`. + deprecated: true + status_details: + type: string + description: |- + Deprecated. For details on why a fine-tuning training file failed validation, see the `error` + field on `fine_tuning.job`. + deprecated: true + description: The `File` object represents a document that has been uploaded to OpenAI. + Prompt: + oneOf: + - type: string + - type: array + items: + type: string + - $ref: '#/components/schemas/TokenArrayItem' + - $ref: '#/components/schemas/TokenArrayArray' + RunCompletionUsage: + type: object + required: + - completion_tokens + - prompt_tokens + - total_tokens + properties: + completion_tokens: + type: integer + format: int64 + description: Number of completion tokens used over the course of the run. + prompt_tokens: + type: integer + format: int64 + description: Number of prompt tokens used over the course of the run. + total_tokens: + type: integer + format: int64 + description: Total number of tokens used (prompt + completion). + description: |- + Usage statistics related to the run. This value will be `null` if the run is not in a terminal + state (i.e. `in_progress`, `queued`, etc.). + RunObject: type: object required: - id - object - created_at - - finished_at - - model - - fine_tuned_model - - organization_id + - thread_id + - assistant_id - status - - hyperparameters - - training_file - - validation_file - - result_files - - trained_tokens - - error + - required_action + - last_error + - expires_at + - started_at + - cancelled_at + - failed_at + - completed_at + - model + - instructions + - tools + - file_ids + - metadata + - usage properties: id: type: string - description: The object identifier, which can be referenced in the API endpoints. + description: The identifier, which can be referenced in API endpoints. object: type: string enum: - - fine_tuning.job - description: The object type, which is always "fine_tuning.job". + - thread.run + description: The object type, which is always `thread.run`. created_at: type: integer format: unixtime - description: The Unix timestamp (in seconds) for when the fine-tuning job was created. - finished_at: - type: string - format: date-time - nullable: true - description: |- - The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be - null if the fine-tuning job is still running. - model: - type: string - description: The base model that is being fine-tuned. - fine_tuned_model: + description: The Unix timestamp (in seconds) for when the run was created. + thread_id: type: string - nullable: true description: |- - The name of the fine-tuned model that is being created. The value will be null if the - fine-tuning job is still running. - organization_id: + The ID of the [thread](/docs/api-reference/threads) that was executed on as a part of this + run. + assistant_id: type: string - description: The organization that owns the fine-tuning job. + description: The ID of the [assistant](/docs/api-reference/assistants) used for execution of this run. status: type: string enum: - - created - - pending - - running - - succeeded - - failed + - queued + - in_progress + - requires_action + - cancelling - cancelled + - failed + - completed + - expired description: |- - The current status of the fine-tuning job, which can be either `created`, `pending`, `running`, - `succeeded`, `failed`, or `cancelled`. - hyperparameters: + The status of the run, which can be either `queued`, `in_progress`, `requires_action`, + `cancelling`, `cancelled`, `failed`, `completed`, or `expired`. + required_action: type: object - description: |- - The hyperparameters used for the fine-tuning job. See the - [fine-tuning guide](/docs/guides/fine-tuning) for more details. properties: - n_epochs: - anyOf: - - type: string - enum: - - auto - - $ref: '#/components/schemas/NEpochs' - description: |- - The number of epochs to train the model for. An epoch refers to one full cycle through the - training dataset. - - "Auto" decides the optimal number of epochs based on the size of the dataset. If setting the - number manually, we support any number between 1 and 50 epochs. - default: auto - training_file: - type: string - description: |- - The file ID used for training. You can retrieve the training data with the - [Files API](/docs/api-reference/files/retrieve-contents). - validation_file: - type: string - nullable: true - description: |- - The file ID used for validation. You can retrieve the validation results with the - [Files API](/docs/api-reference/files/retrieve-contents). - result_files: - type: array - items: - type: string - description: |- - The compiled results file ID(s) for the fine-tuning job. You can retrieve the results with the - [Files API](/docs/api-reference/files/retrieve-contents). - trained_tokens: - type: integer - format: int64 + type: + type: string + enum: + - submit_tool_outputs + description: For now, this is always `submit_tool_outputs`. + submit_tool_outputs: + type: object + properties: + tool_calls: + type: array + items: + $ref: '#/components/schemas/RunToolCallObject' + description: A list of the relevant tool calls. + required: + - tool_calls + description: Details on the tool outputs needed for this run to continue. + required: + - type + - submit_tool_outputs nullable: true description: |- - The total number of billable tokens processed by this fine tuning job. The value will be null - if the fine-tuning job is still running. - error: + Details on the action required to continue the run. Will be `null` if no action is + required. + last_error: type: object - description: |- - For fine-tuning jobs that have `failed`, this will contain more information on the cause of the - failure. properties: - message: - type: string - description: A human-readable error message. code: type: string - description: A machine-readable error code. - param: + enum: + - server_error + - rate_limit_exceeded + description: One of `server_error` or `rate_limit_exceeded`. + message: type: string - nullable: true - description: |- - The parameter that was invalid, usually `training_file` or `validation_file`. This field - will be null if the failure was not parameter-specific. + description: A human-readable description of the error. + required: + - code + - message nullable: true - FineTuningJobEvent: - type: object - required: - - id - - object - - created_at - - level - - message - properties: - id: - type: string - object: - type: string - created_at: + description: The last error associated with this run. Will be `null` if there are no errors. + expires_at: type: integer format: unixtime - level: + description: The Unix timestamp (in seconds) for when the run will expire. + started_at: type: string - enum: - - info - - warn - - error - message: + format: date-time + nullable: true + description: The Unix timestamp (in seconds) for when the run was started. + cancelled_at: type: string - Image: - type: object - description: Represents the url or the content of an image generated by the OpenAI API. - properties: - url: + format: date-time + nullable: true + description: The Unix timestamp (in seconds) for when the run was cancelled. + failed_at: type: string - format: uri - description: The URL of the generated image, if `response_format` is `url` (default). - b64_json: + format: date-time + nullable: true + description: The Unix timestamp (in seconds) for when the run failed. + completed_at: type: string - format: base64 - description: The base64-encoded JSON of the generated image, if `response_format` is `b64_json`. - ImagesN: - type: integer - format: int64 - minimum: 1 - maximum: 10 - ImagesResponse: + format: date-time + nullable: true + description: The Unix timestamp (in seconds) for when the run was completed. + model: + type: string + description: The model that the [assistant](/docs/api-reference/assistants) used for this run. + instructions: + type: string + description: The instructions that the [assistant](/docs/api-reference/assistants) used for this run. + tools: + allOf: + - $ref: '#/components/schemas/CreateRunRequestToolsItem' + description: The list of tools that the [assistant](/docs/api-reference/assistants) used for this run. + file_ids: + type: array + items: + type: string + description: |- + The list of [File](/docs/api-reference/files) IDs the + [assistant](/docs/api-reference/assistants) used for this run. + default: [] + metadata: + type: object + additionalProperties: + type: string + nullable: true + description: |- + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + x-oaiTypeLabel: map + usage: + type: object + allOf: + - $ref: '#/components/schemas/RunCompletionUsage' + nullable: true + description: Represents an execution run on a [thread](/docs/api-reference/threads). + RunStepCompletionUsage: type: object required: - - created - - data + - completion_tokens + - prompt_tokens + - total_tokens properties: - created: + completion_tokens: type: integer - format: unixtime - data: - type: array - items: - $ref: '#/components/schemas/Image' - ListFilesResponse: + format: int64 + description: Number of completion tokens used over the course of the run step. + prompt_tokens: + type: integer + format: int64 + description: Number of prompt tokens used over the course of the run step. + total_tokens: + type: integer + format: int64 + description: Total number of tokens used (prompt + completion). + description: |- + Usage statistics related to the run step. This value will be `null` while the run step's status + is `in_progress`. + RunStepDetails: + oneOf: + - $ref: '#/components/schemas/RunStepDetailsMessageCreationObject' + - $ref: '#/components/schemas/RunStepDetailsToolCallsObject' + x-oaiExpandable: true + RunStepDetailsMessageCreationObject: type: object required: - - object - - data - properties: - object: - type: string - data: - type: array - items: - $ref: '#/components/schemas/OpenAIFile' - ListFineTuneEventsResponse: + - type + - message_creation + properties: + type: + type: string + enum: + - message_creation + description: Details of the message creation by the run step. + message_creation: + type: object + properties: + message_id: + type: string + description: The ID of the message that was created by this run step. + required: + - message_id + description: Details of the message creation by the run step. + RunStepDetailsToolCallsCodeObject: type: object required: - - object - - data + - id + - type + - code_interpreter properties: - object: + id: type: string - data: - type: array - items: - $ref: '#/components/schemas/FineTuneEvent' - ListFineTunesResponse: + description: The ID of the tool call. + type: + type: string + enum: + - code_interpreter + description: |- + The type of tool call. This is always going to be `code_interpreter` for this type of tool + call. + code_interpreter: + type: object + properties: + input: + type: string + description: The input to the Code Interpreter tool call. + outputs: + allOf: + - $ref: '#/components/schemas/RunStepDetailsToolCallsCodeOutputs' + description: |- + The outputs from the Code Interpreter tool call. Code Interpreter can output one or more + items, including text (`logs`) or images (`image`). Each of these are represented by a + different object type. + required: + - input + - outputs + description: The Code Interpreter tool call definition. + description: Details of the Code Interpreter tool call the run step was involved in. + RunStepDetailsToolCallsCodeOutput: + oneOf: + - $ref: '#/components/schemas/RunStepDetailsToolCallsCodeOutputLogsObject' + - $ref: '#/components/schemas/RunStepDetailsToolCallsCodeOutputImageObject' + x-oaiExpandable: true + RunStepDetailsToolCallsCodeOutputImageObject: type: object required: - - object - - data + - type + - image properties: - object: + type: type: string - data: - type: array - items: - $ref: '#/components/schemas/FineTune' - ListFineTuningJobEventsResponse: + enum: + - image + description: Always `image`. + image: + type: object + properties: + file_id: + type: string + description: The [file](/docs/api-reference/files) ID of the image. + required: + - file_id + RunStepDetailsToolCallsCodeOutputLogsObject: type: object required: - - object - - data + - type + - logs properties: - object: + type: type: string - data: - type: array - items: - $ref: '#/components/schemas/FineTuningJobEvent' - ListModelsResponse: + enum: + - logs + description: Always `logs`. + logs: + type: string + description: The text output from the Code Interpreter tool call. + description: Text output from the Code Interpreter tool call as part of a run step. + RunStepDetailsToolCallsCodeOutputs: + type: array + items: + $ref: '#/components/schemas/RunStepDetailsToolCallsCodeOutput' + RunStepDetailsToolCallsFunctionObject: type: object required: - - object - - data + - id + - type + - function properties: - object: + id: type: string - data: - type: array - items: - $ref: '#/components/schemas/Model' - ListPaginatedFineTuningJobsResponse: + description: The ID of the tool call object. + type: + type: string + enum: + - function + description: The type of tool call. This is always going to be `function` for this type of tool call. + function: + type: object + properties: + name: + type: string + description: The name of the function. + arguments: + type: string + description: The arguments passed to the function. + output: + type: string + nullable: true + description: |- + The output of the function. This will be `null` if the outputs have not been + [submitted](/docs/api-reference/runs/submitToolOutputs) yet. + required: + - name + - arguments + - output + description: The definition of the function that was called. + RunStepDetailsToolCallsObject: type: object required: - - object - - data - - has_more + - type + - tool_calls properties: - object: + type: type: string - data: - type: array - items: - $ref: '#/components/schemas/FineTuningJob' - has_more: - type: boolean - MaxTokens: - type: integer - format: int64 - minimum: 0 - Model: + enum: + - tool_calls + description: Always `tool_calls`. + tool_calls: + allOf: + - $ref: '#/components/schemas/RunStepDetailsToolCallsObjectToolCallsItem' + description: |- + An array of tool calls the run step was involved in. These can be associated with one of three + types of tools: `code_interpreter`, `retrieval`, or `function`. + description: Details of the tool call. + RunStepDetailsToolCallsObjectToolCall: + oneOf: + - $ref: '#/components/schemas/RunStepDetailsToolCallsCodeObject' + - $ref: '#/components/schemas/RunStepDetailsToolCallsRetrievalObject' + - $ref: '#/components/schemas/RunStepDetailsToolCallsFunctionObject' + x-oaiExpandable: true + RunStepDetailsToolCallsObjectToolCallsItem: + type: array + items: + $ref: '#/components/schemas/RunStepDetailsToolCallsObjectToolCall' + RunStepDetailsToolCallsRetrievalObject: type: object - description: Describes an OpenAI model offering that can be used with the API. required: - id - - object - - created - - owned_by + - type + - retrieval properties: id: type: string - description: The model identifier, which can be referenced in the API endpoints. - object: + description: The ID of the tool call object. + type: type: string enum: - - model - description: The object type, which is always "model". - created: - type: integer - format: unixtime - description: The Unix timestamp (in seconds) when the model was created. - owned_by: - type: string - description: The organization that owns the model. - N: - type: integer - format: int64 - minimum: 1 - maximum: 128 - NEpochs: - type: integer - format: int64 - minimum: 1 - maximum: 50 - OpenAIFile: + - retrieval + description: The type of tool call. This is always going to be `retrieval` for this type of tool call. + retrieval: + type: object + description: For now, this is always going to be an empty object. + x-oaiTypeLabel: map + RunStepObject: type: object - description: The `File` object represents a document that has been uploaded to OpenAI. required: - id - object - - bytes - - createdAt - - filename - - purpose + - created_at + - assistant_id + - thread_id + - run_id + - type - status + - step_details + - last_error + - expires_at + - cancelled_at + - failed_at + - completed_at + - metadata + - usage properties: id: type: string - description: The file identifier, which can be referenced in the API endpoints. + description: The identifier of the run step, which can be referenced in API endpoints. object: type: string enum: - - file - description: The object type, which is always "file". - bytes: - type: integer - format: int64 - description: The size of the file in bytes. - createdAt: + - thread.run.step + description: The object type, which is always `thread.run.step`. + created_at: type: integer format: unixtime - description: The Unix timestamp (in seconds) for when the file was created. - filename: + description: The Unix timestamp (in seconds) for when the run step was created. + assistant_id: type: string - description: The name of the file. - purpose: + description: The ID of the [assistant](/docs/api-reference/assistants) associated with the run step. + thread_id: + type: string + description: The ID of the [thread](/docs/api-reference/threads) that was run. + run_id: + type: string + description: The ID of the [run](/docs/api-reference/runs) that this run step is a part of. + type: type: string - description: The intended purpose of the file. Currently, only "fine-tune" is supported. + enum: + - message_creation + - tool_calls + description: The type of run step, which can be either `message_creation` or `tool_calls`. status: type: string enum: - - uploaded - - processed - - pending - - error - - deleting - - deleted + - in_progress + - cancelled + - failed + - completed + - expired description: |- - The current status of the file, which can be either `uploaded`, `processed`, `pending`, - `error`, `deleting` or `deleted`. - status_details: + The status of the run step, which can be either `in_progress`, `cancelled`, `failed`, + `completed`, or `expired`. + step_details: + allOf: + - $ref: '#/components/schemas/RunStepDetails' + description: The details of the run step. + last_error: + type: object + properties: + code: + type: string + enum: + - server_error + - rate_limit_exceeded + description: One of `server_error` or `rate_limit_exceeded`. + message: + type: string + description: A human-readable description of the error. + required: + - code + - message + nullable: true + description: The last error associated with this run step. Will be `null` if there are no errors. + expires_at: type: string + format: date-time nullable: true description: |- - Additional details about the status of the file. If the file is in the `error` state, this will - include a message describing the error. - Penalty: - type: number - format: double - minimum: -2 - maximum: 2 - Prompt: - oneOf: - - type: string - - type: array - items: + The Unix timestamp (in seconds) for when the run step expired. A step is considered expired + if the parent run is expired. + cancelled_at: + type: string + format: date-time + nullable: true + description: The Unix timestamp (in seconds) for when the run step was cancelled. + failed_at: + type: string + format: date-time + nullable: true + description: The Unix timestamp (in seconds) for when the run step failed. + completed_at: + type: string + format: date-time + nullable: true + description: T The Unix timestamp (in seconds) for when the run step completed.. + metadata: + type: object + additionalProperties: type: string - - $ref: '#/components/schemas/TokenArray' - - $ref: '#/components/schemas/TokenArrayArray' - nullable: true + nullable: true + description: |- + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + x-oaiTypeLabel: map + usage: + type: object + allOf: + - $ref: '#/components/schemas/RunCompletionUsage' + nullable: true + description: Represents a step in execution of a run. + RunToolCallObject: + type: object + required: + - id + - type + - function + properties: + id: + type: string + description: |- + The ID of the tool call. This ID must be referenced when you submit the tool outputs in using + the [Submit tool outputs to run](/docs/api-reference/runs/submitToolOutputs) endpoint. + type: + type: string + enum: + - function + description: The type of tool call the output is required for. For now, this is always `function`. + function: + type: object + properties: + name: + type: string + description: The name of the function. + arguments: + type: string + description: The arguments that the model expects you to pass to the function. + required: + - name + - arguments + description: The function definition. + description: Tool call objects Stop: oneOf: - type: string - $ref: '#/components/schemas/StopSequences' - nullable: true StopSequences: type: array items: type: string minItems: 1 maxItems: 4 + SubmitToolOutputsRunRequest: + type: object + required: + - tool_outputs + properties: + tool_outputs: + type: object + properties: + tool_call_id: + type: string + description: |- + The ID of the tool call in the `required_action` object within the run object the output is + being submitted for. + output: + type: string + description: The output of the tool call to be submitted to continue the run. + description: A list of tools for which the outputs are being submitted. SuffixString: type: string minLength: 1 maxLength: 40 - Temperature: - type: number - format: double - minimum: 0 - maximum: 2 - TokenArray: + ThreadObject: + type: object + required: + - id + - object + - created_at + - metadata + properties: + id: + type: string + description: The identifier, which can be referenced in API endpoints. + object: + type: string + enum: + - thread + description: The object type, which is always `thread`. + created_at: + type: integer + format: unixtime + description: The Unix timestamp (in seconds) for when the thread was created. + metadata: + type: object + additionalProperties: + type: string + nullable: true + description: |- + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + x-oaiTypeLabel: map + description: Represents a thread that contains [messages](/docs/api-reference/messages). + TokenArrayArray: type: array items: - type: integer - format: int64 + $ref: '#/components/schemas/TokenArrayItem' minItems: 1 - TokenArrayArray: + TokenArrayItem: type: array items: - $ref: '#/components/schemas/TokenArray' + type: integer + format: int64 minItems: 1 - TopP: - type: number - format: double - minimum: 0 - maximum: 1 User: type: string securitySchemes: From 9733bb9eb3c679da241981d714700d87df4771de Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado Date: Wed, 7 Feb 2024 17:28:06 -0800 Subject: [PATCH 04/50] Remove duplicate readme --- README.md | 3 --- readme.md => readme2.md | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) delete mode 100644 README.md rename readme.md => readme2.md (90%) diff --git a/README.md b/README.md deleted file mode 100644 index 04bcd9be3..000000000 --- a/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# OpenAPI spec for the OpenAI API - -This repository contains an [OpenAPI](https://www.openapis.org/) specification for the [OpenAI API](https://platform.openai.com/docs/api-reference). diff --git a/readme.md b/readme2.md similarity index 90% rename from readme.md rename to readme2.md index b65856581..eff608de4 100644 --- a/readme.md +++ b/readme2.md @@ -1,10 +1,10 @@ -A conversion of the OpenAI OpenAPI to TypeSpec. +# A conversion of the OpenAI OpenAPI to TypeSpec Snapshot: https://raw.githubusercontent.com/openai/openai-openapi/b648b7823135e6fa5148ac9a303c16fdad050da6/openapi.yaml There are some deltas: -### Changes to API Semantics: +### Changes to API Semantics - Many things are missing defaults (mostly due to bug where we can't set null defaults) - Error responses have been added. From a952d4128be677bbf4e15e0896d2a89462d30169 Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado Date: Wed, 7 Feb 2024 17:28:41 -0800 Subject: [PATCH 05/50] Rename README --- readme2.md => README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename readme2.md => README.md (100%) diff --git a/readme2.md b/README.md similarity index 100% rename from readme2.md rename to README.md From 8eb95a03932094693b8fdce855d9f18af6748e22 Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado Date: Thu, 8 Feb 2024 14:00:51 -0800 Subject: [PATCH 06/50] Edit a couple of comments --- chat/models.tsp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chat/models.tsp b/chat/models.tsp index d0d19bc06..160afb122 100644 --- a/chat/models.tsp +++ b/chat/models.tsp @@ -359,6 +359,7 @@ model ChatCompletionRequestMessageContentPartImage { image_url: { /** Either a URL of the image or the base64 encoded image data. */ + // TODO: The original OpenAPI spec only describes this as a URL. url: url | string; /** @@ -373,7 +374,6 @@ model ChatCompletionRequestMessageContentPartImage { model ChatCompletionMessageToolCalls is ChatCompletionMessageToolCall[]; model ChatCompletionMessageToolCall { - // TODO: index included when streaming /** The ID of the tool call. */ id: string; From b6bfedfed72b52f2343d9f29c25219d8702a2aa3 Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado Date: Thu, 8 Feb 2024 14:15:30 -0800 Subject: [PATCH 07/50] Fix listAssistants name --- assistants/operations.tsp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assistants/operations.tsp b/assistants/operations.tsp index 2883342b1..350f68d7b 100644 --- a/assistants/operations.tsp +++ b/assistants/operations.tsp @@ -23,7 +23,7 @@ interface Assistants { @operationId("listAssistants") @tag("Assistants") @summary("Returns a list of assistants.") - listFiles( + listAssistants( /** * A limit on the number of objects to be returned. Limit can range between 1 and 100, and the * default is 20. From 11bb01fe71ab2b591aa86fbc851e3679b4048f22 Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado Date: Fri, 9 Feb 2024 10:23:06 -0800 Subject: [PATCH 08/50] Fix listRuns path --- runs/operations.tsp | 2 +- tsp-output/@typespec/openapi3/openapi.yaml | 141 ++++++++++----------- 2 files changed, 71 insertions(+), 72 deletions(-) diff --git a/runs/operations.tsp b/runs/operations.tsp index ae6f35778..8bf1f0df1 100644 --- a/runs/operations.tsp +++ b/runs/operations.tsp @@ -32,7 +32,7 @@ interface Runs { @body run: CreateRunRequest, ): RunObject | ErrorResponse; - @route("thread_id}/runs") + @route("{thread_id}/runs") @get @operationId("listRuns") @tag("Assistants") diff --git a/tsp-output/@typespec/openapi3/openapi.yaml b/tsp-output/@typespec/openapi3/openapi.yaml index f9d7b16a4..8f62d8667 100644 --- a/tsp-output/@typespec/openapi3/openapi.yaml +++ b/tsp-output/@typespec/openapi3/openapi.yaml @@ -1196,77 +1196,6 @@ paths: application/json: schema: $ref: '#/components/schemas/CreateThreadAndRunRequest' - /threads/thread_id}/runs/{thread_id}: - get: - tags: - - Assistants - operationId: listRuns - summary: Returns a list of runs belonging to a thread. - parameters: - - name: thread_id - in: path - required: true - description: The ID of the thread the run belongs to. - schema: - type: string - - name: limit - in: query - required: false - description: |- - A limit on the number of objects to be returned. Limit can range between 1 and 100, and the - default is 20. - schema: - type: integer - format: int32 - default: 20 - - name: order - in: query - required: false - description: |- - Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` - for descending order. - schema: - type: string - enum: - - asc - - desc - - desc - - desc - - desc - - desc - - desc - default: desc - - name: after - in: query - required: false - description: |- - A cursor for use in pagination. `after` is an object ID that defines your place in the list. - For instance, if you make a list request and receive 100 objects, ending with obj_foo, your - subsequent call can include after=obj_foo in order to fetch the next page of the list. - schema: - type: string - - name: before - in: query - required: false - description: |- - A cursor for use in pagination. `before` is an object ID that defines your place in the list. - For instance, if you make a list request and receive 100 objects, ending with obj_foo, your - subsequent call can include before=obj_foo in order to fetch the previous page of the list. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/ListRunsResponse' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' /threads/{thread_id}: get: tags: @@ -1667,6 +1596,76 @@ paths: application/json: schema: $ref: '#/components/schemas/CreateRunRequest' + get: + tags: + - Assistants + operationId: listRuns + summary: Returns a list of runs belonging to a thread. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the thread the run belongs to. + schema: + type: string + - name: limit + in: query + required: false + description: |- + A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + default is 20. + schema: + type: integer + format: int32 + default: 20 + - name: order + in: query + required: false + description: |- + Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + for descending order. + schema: + type: string + enum: + - asc + - desc + - desc + - desc + - desc + - desc + - desc + default: desc + - name: after + in: query + required: false + description: |- + A cursor for use in pagination. `after` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include after=obj_foo in order to fetch the next page of the list. + schema: + type: string + - name: before + in: query + required: false + description: |- + A cursor for use in pagination. `before` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include before=obj_foo in order to fetch the previous page of the list. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ListRunsResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' /threads/{thread_id}/runs/{run_id}: get: tags: From 4e9e7aa6963c616b48f74c51eb486d2ecbc626de Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado Date: Wed, 14 Feb 2024 16:56:35 -0800 Subject: [PATCH 09/50] Add initial .NET generated library --- .dotnet/OpenAI.sln | 50 + .dotnet/src/Generated/Assistants.cs | 1352 ++++ .dotnet/src/Generated/Audio.cs | 421 ++ .dotnet/src/Generated/Chat.cs | 183 + .dotnet/src/Generated/Completions.cs | 183 + .dotnet/src/Generated/Embeddings.cs | 183 + .dotnet/src/Generated/Files.cs | 683 ++ .dotnet/src/Generated/FineTunes.cs | 736 ++ .dotnet/src/Generated/FineTuning.cs | 55 + .dotnet/src/Generated/FineTuningJobs.cs | 710 ++ .dotnet/src/Generated/Images.cs | 421 ++ .dotnet/src/Generated/Messages.cs | 1037 +++ .../AssistantFileObject.Serialization.cs | 156 + .../Generated/Models/AssistantFileObject.cs | 91 + .../Models/AssistantFileObjectObject.cs | 45 + .../Models/AssistantObject.Serialization.cs | 302 + .../src/Generated/Models/AssistantObject.cs | 202 + .../Generated/Models/AssistantObjectObject.cs | 45 + .../Models/AudioSegment.Serialization.cs | 214 + .dotnet/src/Generated/Models/AudioSegment.cs | 147 + ...pletionFunctionCallOption.Serialization.cs | 132 + .../ChatCompletionFunctionCallOption.cs | 76 + .../ChatCompletionFunctions.Serialization.cs | 158 + .../Models/ChatCompletionFunctions.cs | 97 + ...CompletionMessageToolCall.Serialization.cs | 148 + .../Models/ChatCompletionMessageToolCall.cs | 85 + ...onMessageToolCallFunction.Serialization.cs | 140 + .../ChatCompletionMessageToolCallFunction.cs | 92 + .../ChatCompletionMessageToolCallType.cs | 45 + ...CompletionNamedToolChoice.Serialization.cs | 140 + .../Models/ChatCompletionNamedToolChoice.cs | 78 + ...onNamedToolChoiceFunction.Serialization.cs | 132 + .../ChatCompletionNamedToolChoiceFunction.cs | 73 + .../ChatCompletionNamedToolChoiceType.cs | 45 + ...CompletionResponseMessage.Serialization.cs | 192 + .../Models/ChatCompletionResponseMessage.cs | 84 + ...sponseMessageFunctionCall.Serialization.cs | 140 + ...atCompletionResponseMessageFunctionCall.cs | 92 + .../ChatCompletionResponseMessageRole.cs | 45 + ...hatCompletionTokenLogprob.Serialization.cs | 188 + .../Models/ChatCompletionTokenLogprob.cs | 117 + ...ionTokenLogprobTopLogprob.Serialization.cs | 170 + .../ChatCompletionTokenLogprobTopLogprob.cs | 101 + .../ChatCompletionTool.Serialization.cs | 140 + .../Generated/Models/ChatCompletionTool.cs | 78 + .../Models/ChatCompletionToolType.cs | 45 + .../Models/CompletionUsage.Serialization.cs | 148 + .../src/Generated/Models/CompletionUsage.cs | 81 + ...reateAssistantFileRequest.Serialization.cs | 132 + .../Models/CreateAssistantFileRequest.cs | 82 + .../CreateAssistantRequest.Serialization.cs | 303 + .../Models/CreateAssistantRequest.cs | 161 + ...eateChatCompletionRequest.Serialization.cs | 582 ++ .../Models/CreateChatCompletionRequest.cs | 512 ++ .../CreateChatCompletionRequestModel.cs | 90 + ...tionRequestResponseFormat.Serialization.cs | 139 + ...eateChatCompletionRequestResponseFormat.cs | 62 + ...ChatCompletionRequestResponseFormatType.cs | 48 + ...ateChatCompletionResponse.Serialization.cs | 200 + .../Models/CreateChatCompletionResponse.cs | 117 + ...tCompletionResponseChoice.Serialization.cs | 168 + .../CreateChatCompletionResponseChoice.cs | 109 + ...hatCompletionResponseChoiceFinishReason.cs | 57 + ...ionResponseChoiceLogprobs.Serialization.cs | 154 + ...ateChatCompletionResponseChoiceLogprobs.cs | 70 + .../CreateChatCompletionResponseObject.cs | 45 + .../CreateCompletionRequest.Serialization.cs | 509 ++ .../Models/CreateCompletionRequest.cs | 401 ++ .../Models/CreateCompletionRequestModel.cs | 51 + .../CreateCompletionResponse.Serialization.cs | 200 + .../Models/CreateCompletionResponse.cs | 120 + ...eCompletionResponseChoice.Serialization.cs | 168 + .../Models/CreateCompletionResponseChoice.cs | 109 + ...ateCompletionResponseChoiceFinishReason.cs | 51 + ...ionResponseChoiceLogprobs.Serialization.cs | 219 + .../CreateCompletionResponseChoiceLogprobs.cs | 95 + .../Models/CreateCompletionResponseObject.cs | 45 + .../CreateEmbeddingRequest.Serialization.cs | 188 + .../Models/CreateEmbeddingRequest.cs | 186 + .../CreateEmbeddingRequestEncodingFormat.cs | 48 + .../Models/CreateEmbeddingRequestModel.cs | 51 + .../CreateEmbeddingResponse.Serialization.cs | 166 + .../Models/CreateEmbeddingResponse.cs | 93 + .../Models/CreateEmbeddingResponseObject.cs | 45 + ...ateEmbeddingResponseUsage.Serialization.cs | 140 + .../Models/CreateEmbeddingResponseUsage.cs | 75 + .../Models/CreateFileRequest.Serialization.cs | 140 + .../src/Generated/Models/CreateFileRequest.cs | 109 + .../Models/CreateFileRequestPurpose.cs | 48 + .../CreateFineTuneRequest.Serialization.cs | 386 ++ .../Generated/Models/CreateFineTuneRequest.cs | 295 + .../Models/CreateFineTuneRequestModel.cs | 54 + ...reateFineTuningJobRequest.Serialization.cs | 201 + .../Models/CreateFineTuningJobRequest.cs | 159 + ...JobRequestHyperparameters.Serialization.cs | 146 + ...eateFineTuningJobRequestHyperparameters.cs | 106 + .../Models/CreateFineTuningJobRequestModel.cs | 51 + .../CreateImageEditRequest.Serialization.cs | 234 + .../Models/CreateImageEditRequest.cs | 153 + .../Models/CreateImageEditRequestModel.cs | 45 + .../CreateImageEditRequestResponseFormat.cs | 48 + .../Models/CreateImageEditRequestSize.cs | 51 + .../CreateImageRequest.Serialization.cs | 241 + .../Generated/Models/CreateImageRequest.cs | 142 + .../Models/CreateImageRequestModel.cs | 48 + .../Models/CreateImageRequestQuality.cs | 48 + .../CreateImageRequestResponseFormat.cs | 48 + .../Models/CreateImageRequestSize.cs | 57 + .../Models/CreateImageRequestStyle.cs | 48 + ...eateImageVariationRequest.Serialization.cs | 211 + .../Models/CreateImageVariationRequest.cs | 121 + .../CreateImageVariationRequestModel.cs | 45 + ...eateImageVariationRequestResponseFormat.cs | 48 + .../Models/CreateImageVariationRequestSize.cs | 51 + .../CreateMessageRequest.Serialization.cs | 198 + .../Generated/Models/CreateMessageRequest.cs | 104 + .../Models/CreateMessageRequestRole.cs | 45 + .../CreateModerationRequest.Serialization.cs | 154 + .../Models/CreateModerationRequest.cs | 129 + .../Models/CreateModerationRequestModel.cs | 48 + .../CreateModerationResponse.Serialization.cs | 158 + .../Models/CreateModerationResponse.cs | 88 + ...eModerationResponseResult.Serialization.cs | 148 + .../Models/CreateModerationResponseResult.cs | 86 + ...nResponseResultCategories.Serialization.cs | 212 + ...reateModerationResponseResultCategories.cs | 189 + ...ponseResultCategoryScores.Serialization.cs | 212 + ...eModerationResponseResultCategoryScores.cs | 129 + .../Models/CreateRunRequest.Serialization.cs | 285 + .../src/Generated/Models/CreateRunRequest.cs | 156 + .../CreateSpeechRequest.Serialization.cs | 178 + .../Generated/Models/CreateSpeechRequest.cs | 105 + .../Models/CreateSpeechRequestModel.cs | 48 + .../CreateSpeechRequestResponseFormat.cs | 54 + .../Models/CreateSpeechRequestVoice.cs | 60 + ...CreateThreadAndRunRequest.Serialization.cs | 277 + .../Models/CreateThreadAndRunRequest.cs | 150 + .../CreateThreadRequest.Serialization.cs | 182 + .../Generated/Models/CreateThreadRequest.cs | 77 + ...reateTranscriptionRequest.Serialization.cs | 192 + .../Models/CreateTranscriptionRequest.cs | 147 + .../Models/CreateTranscriptionRequestModel.cs | 45 + ...reateTranscriptionRequestResponseFormat.cs | 57 + ...eateTranscriptionResponse.Serialization.cs | 198 + .../Models/CreateTranscriptionResponse.cs | 96 + .../Models/CreateTranscriptionResponseTask.cs | 45 + .../CreateTranslationRequest.Serialization.cs | 181 + .../Models/CreateTranslationRequest.cs | 135 + .../Models/CreateTranslationRequestModel.cs | 45 + .../CreateTranslationRequestResponseFormat.cs | 57 + ...CreateTranslationResponse.Serialization.cs | 198 + .../Models/CreateTranslationResponse.cs | 96 + .../Models/CreateTranslationResponseTask.cs | 45 + ...leteAssistantFileResponse.Serialization.cs | 148 + .../Models/DeleteAssistantFileResponse.cs | 86 + .../DeleteAssistantFileResponseObject.cs | 45 + .../DeleteAssistantResponse.Serialization.cs | 148 + .../Models/DeleteAssistantResponse.cs | 83 + .../Models/DeleteAssistantResponseObject.cs | 45 + .../DeleteFileResponse.Serialization.cs | 148 + .../Generated/Models/DeleteFileResponse.cs | 84 + .../Models/DeleteFileResponseObject.cs | 45 + .../DeleteModelResponse.Serialization.cs | 148 + .../Generated/Models/DeleteModelResponse.cs | 83 + .../Models/DeleteModelResponseObject.cs | 45 + .../DeleteThreadResponse.Serialization.cs | 148 + .../Generated/Models/DeleteThreadResponse.cs | 83 + .../Models/DeleteThreadResponseObject.cs | 45 + .../Models/Embedding.Serialization.cs | 155 + .dotnet/src/Generated/Models/Embedding.cs | 130 + .../src/Generated/Models/EmbeddingObject.cs | 45 + .../Models/FineTune.Serialization.cs | 287 + .dotnet/src/Generated/Models/FineTune.cs | 169 + .../Models/FineTuneEvent.Serialization.cs | 156 + .dotnet/src/Generated/Models/FineTuneEvent.cs | 93 + .../FineTuneHyperparams.Serialization.cs | 197 + .../Generated/Models/FineTuneHyperparams.cs | 117 + .../src/Generated/Models/FineTuneObject.cs | 45 + .../src/Generated/Models/FineTuneStatus.cs | 57 + .../Models/FineTuningJob.Serialization.cs | 306 + .dotnet/src/Generated/Models/FineTuningJob.cs | 237 + .../FineTuningJobError.Serialization.cs | 169 + .../Generated/Models/FineTuningJobError.cs | 76 + .../FineTuningJobEvent.Serialization.cs | 164 + .../Generated/Models/FineTuningJobEvent.cs | 99 + .../Models/FineTuningJobEventLevel.cs | 51 + ...eTuningJobHyperparameters.Serialization.cs | 146 + .../Models/FineTuningJobHyperparameters.cs | 112 + .../Generated/Models/FineTuningJobObject.cs | 45 + .../Generated/Models/FineTuningJobStatus.cs | 60 + .../Models/FunctionObject.Serialization.cs | 158 + .../src/Generated/Models/FunctionObject.cs | 96 + .../FunctionParameters.Serialization.cs | 118 + .../Generated/Models/FunctionParameters.cs | 65 + .../Generated/Models/Image.Serialization.cs | 165 + .dotnet/src/Generated/Models/Image.cs | 85 + .../Models/ImagesResponse.Serialization.cs | 150 + .../src/Generated/Models/ImagesResponse.cs | 80 + ...istAssistantFilesResponse.Serialization.cs | 174 + .../Models/ListAssistantFilesResponse.cs | 99 + .../ListAssistantFilesResponseObject.cs | 45 + .../ListAssistantsResponse.Serialization.cs | 174 + .../Models/ListAssistantsResponse.cs | 99 + .../Models/ListAssistantsResponseObject.cs | 45 + .../Models/ListFilesResponse.Serialization.cs | 150 + .../src/Generated/Models/ListFilesResponse.cs | 78 + .../Models/ListFilesResponseObject.cs | 45 + ...istFineTuneEventsResponse.Serialization.cs | 150 + .../Models/ListFineTuneEventsResponse.cs | 81 + .../ListFineTunesResponse.Serialization.cs | 150 + .../Generated/Models/ListFineTunesResponse.cs | 81 + ...neTuningJobEventsResponse.Serialization.cs | 150 + .../Models/ListFineTuningJobEventsResponse.cs | 81 + .../ListMessageFilesResponse.Serialization.cs | 174 + .../Models/ListMessageFilesResponse.cs | 99 + .../Models/ListMessageFilesResponseObject.cs | 45 + .../ListMessagesResponse.Serialization.cs | 174 + .../Generated/Models/ListMessagesResponse.cs | 99 + .../Models/ListMessagesResponseObject.cs | 45 + .../ListModelsResponse.Serialization.cs | 150 + .../Generated/Models/ListModelsResponse.cs | 79 + .../Models/ListModelsResponseObject.cs | 45 + .dotnet/src/Generated/Models/ListOrder.cs | 47 + ...tedFineTuningJobsResponse.Serialization.cs | 158 + .../ListPaginatedFineTuningJobsResponse.cs | 87 + .../ListRunStepsResponse.Serialization.cs | 174 + .../Generated/Models/ListRunStepsResponse.cs | 99 + .../Models/ListRunStepsResponseObject.cs | 45 + .../Models/ListRunsResponse.Serialization.cs | 174 + .../src/Generated/Models/ListRunsResponse.cs | 99 + .../Models/ListRunsResponseObject.cs | 45 + .../Models/MessageFileObject.Serialization.cs | 156 + .../src/Generated/Models/MessageFileObject.cs | 91 + .../Models/MessageFileObjectObject.cs | 45 + .../Models/MessageObject.Serialization.cs | 290 + .dotnet/src/Generated/Models/MessageObject.cs | 201 + .../Generated/Models/MessageObjectObject.cs | 45 + .../src/Generated/Models/MessageObjectRole.cs | 48 + .../Generated/Models/Model.Serialization.cs | 156 + .dotnet/src/Generated/Models/Model.cs | 91 + .dotnet/src/Generated/Models/ModelObject.cs | 45 + .../ModifyAssistantRequest.Serialization.cs | 306 + .../Models/ModifyAssistantRequest.cs | 147 + .../ModifyMessageRequest.Serialization.cs | 157 + .../Generated/Models/ModifyMessageRequest.cs | 72 + .../Models/ModifyRunRequest.Serialization.cs | 157 + .../src/Generated/Models/ModifyRunRequest.cs | 72 + .../ModifyThreadRequest.Serialization.cs | 157 + .../Generated/Models/ModifyThreadRequest.cs | 72 + .../Models/OpenAIFile.Serialization.cs | 191 + .dotnet/src/Generated/Models/OpenAIFile.cs | 137 + .../src/Generated/Models/OpenAIFileObject.cs | 45 + .../src/Generated/Models/OpenAIFilePurpose.cs | 54 + .../src/Generated/Models/OpenAIFileStatus.cs | 51 + .../RunCompletionUsage.Serialization.cs | 148 + .../Generated/Models/RunCompletionUsage.cs | 84 + .../Models/RunObject.Serialization.cs | 422 ++ .dotnet/src/Generated/Models/RunObject.cs | 264 + .../RunObjectLastError.Serialization.cs | 140 + .../Generated/Models/RunObjectLastError.cs | 79 + .../Models/RunObjectLastErrorCode.cs | 48 + .../src/Generated/Models/RunObjectObject.cs | 45 + .../RunObjectRequiredAction.Serialization.cs | 140 + .../Models/RunObjectRequiredAction.cs | 78 + ...edActionSubmitToolOutputs.Serialization.cs | 142 + ...unObjectRequiredActionSubmitToolOutputs.cs | 74 + .../Models/RunObjectRequiredActionType.cs | 45 + .../src/Generated/Models/RunObjectStatus.cs | 66 + ...ailsMessageCreationObject.Serialization.cs | 140 + .../RunStepDetailsMessageCreationObject.cs | 78 + ...tionObjectMessageCreation.Serialization.cs | 132 + ...ilsMessageCreationObjectMessageCreation.cs | 73 + ...RunStepDetailsMessageCreationObjectType.cs | 45 + ...tepDetailsToolCallsObject.Serialization.cs | 169 + .../Models/RunStepDetailsToolCallsObject.cs | 115 + .../RunStepDetailsToolCallsObjectType.cs | 45 + .../Models/RunStepObject.Serialization.cs | 354 + .dotnet/src/Generated/Models/RunStepObject.cs | 236 + .../RunStepObjectLastError.Serialization.cs | 140 + .../Models/RunStepObjectLastError.cs | 79 + .../Models/RunStepObjectLastErrorCode.cs | 48 + .../Generated/Models/RunStepObjectObject.cs | 45 + .../Generated/Models/RunStepObjectStatus.cs | 57 + .../src/Generated/Models/RunStepObjectType.cs | 48 + .../Models/RunToolCallObject.Serialization.cs | 148 + .../src/Generated/Models/RunToolCallObject.cs | 94 + ...RunToolCallObjectFunction.Serialization.cs | 140 + .../Models/RunToolCallObjectFunction.cs | 80 + .../Generated/Models/RunToolCallObjectType.cs | 45 + ...bmitToolOutputsRunRequest.Serialization.cs | 132 + .../Models/SubmitToolOutputsRunRequest.cs | 73 + ...putsRunRequestToolOutputs.Serialization.cs | 146 + .../SubmitToolOutputsRunRequestToolOutputs.cs | 72 + .../Models/ThreadObject.Serialization.cs | 179 + .dotnet/src/Generated/Models/ThreadObject.cs | 102 + .../Generated/Models/ThreadObjectObject.cs | 45 + .dotnet/src/Generated/ModelsOps.cs | 419 ++ .dotnet/src/Generated/Moderations.cs | 183 + .dotnet/src/Generated/OpenAIClient.cs | 158 + .dotnet/src/Generated/OpenAIClientOptions.cs | 13 + .dotnet/src/Generated/OpenAIModelFactory.cs | 1769 +++++ .dotnet/src/Generated/Runs.cs | 1442 ++++ .dotnet/src/Generated/Threads.cs | 555 ++ .dotnet/src/OpenAI.csproj | 16 + .../tests/Generated/Tests/AssistantsTests.cs | 22 + .dotnet/tests/Generated/Tests/AudioTests.cs | 22 + .dotnet/tests/Generated/Tests/ChatTests.cs | 22 + .../tests/Generated/Tests/CompletionsTests.cs | 22 + .../tests/Generated/Tests/EmbeddingsTests.cs | 22 + .dotnet/tests/Generated/Tests/FilesTests.cs | 22 + .../Generated/Tests/FineTuningJobsTests.cs | 22 + .dotnet/tests/Generated/Tests/ImagesTests.cs | 22 + .../tests/Generated/Tests/MessagesTests.cs | 22 + .../tests/Generated/Tests/ModelsOpsTests.cs | 22 + .../tests/Generated/Tests/ModerationsTests.cs | 22 + .dotnet/tests/Generated/Tests/RunsTests.cs | 22 + .dotnet/tests/Generated/Tests/ThreadsTests.cs | 22 + .dotnet/tests/OpenAI.Tests.csproj | 18 + .../@typespec/openapi3/openapi.yaml | 6019 +++++++++++++++++ .gitignore | 178 + assistants/operations.tsp | 5 +- common/models.tsp | 5 + files/operations.tsp | 2 +- messages/operations.tsp | 5 +- runs/operations.tsp | 5 +- tsp-output/@typespec/openapi3/openapi.yaml | 72 +- tspconfig.yaml | 4 + 327 files changed, 51978 insertions(+), 66 deletions(-) create mode 100644 .dotnet/OpenAI.sln create mode 100644 .dotnet/src/Generated/Assistants.cs create mode 100644 .dotnet/src/Generated/Audio.cs create mode 100644 .dotnet/src/Generated/Chat.cs create mode 100644 .dotnet/src/Generated/Completions.cs create mode 100644 .dotnet/src/Generated/Embeddings.cs create mode 100644 .dotnet/src/Generated/Files.cs create mode 100644 .dotnet/src/Generated/FineTunes.cs create mode 100644 .dotnet/src/Generated/FineTuning.cs create mode 100644 .dotnet/src/Generated/FineTuningJobs.cs create mode 100644 .dotnet/src/Generated/Images.cs create mode 100644 .dotnet/src/Generated/Messages.cs create mode 100644 .dotnet/src/Generated/Models/AssistantFileObject.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/AssistantFileObject.cs create mode 100644 .dotnet/src/Generated/Models/AssistantFileObjectObject.cs create mode 100644 .dotnet/src/Generated/Models/AssistantObject.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/AssistantObject.cs create mode 100644 .dotnet/src/Generated/Models/AssistantObjectObject.cs create mode 100644 .dotnet/src/Generated/Models/AudioSegment.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/AudioSegment.cs create mode 100644 .dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.cs create mode 100644 .dotnet/src/Generated/Models/ChatCompletionFunctions.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ChatCompletionFunctions.cs create mode 100644 .dotnet/src/Generated/Models/ChatCompletionMessageToolCall.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ChatCompletionMessageToolCall.cs create mode 100644 .dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.cs create mode 100644 .dotnet/src/Generated/Models/ChatCompletionMessageToolCallType.cs create mode 100644 .dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.cs create mode 100644 .dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.cs create mode 100644 .dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceType.cs create mode 100644 .dotnet/src/Generated/Models/ChatCompletionResponseMessage.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ChatCompletionResponseMessage.cs create mode 100644 .dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.cs create mode 100644 .dotnet/src/Generated/Models/ChatCompletionResponseMessageRole.cs create mode 100644 .dotnet/src/Generated/Models/ChatCompletionTokenLogprob.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ChatCompletionTokenLogprob.cs create mode 100644 .dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.cs create mode 100644 .dotnet/src/Generated/Models/ChatCompletionTool.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ChatCompletionTool.cs create mode 100644 .dotnet/src/Generated/Models/ChatCompletionToolType.cs create mode 100644 .dotnet/src/Generated/Models/CompletionUsage.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CompletionUsage.cs create mode 100644 .dotnet/src/Generated/Models/CreateAssistantFileRequest.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateAssistantFileRequest.cs create mode 100644 .dotnet/src/Generated/Models/CreateAssistantRequest.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateAssistantRequest.cs create mode 100644 .dotnet/src/Generated/Models/CreateChatCompletionRequest.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateChatCompletionRequest.cs create mode 100644 .dotnet/src/Generated/Models/CreateChatCompletionRequestModel.cs create mode 100644 .dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.cs create mode 100644 .dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormatType.cs create mode 100644 .dotnet/src/Generated/Models/CreateChatCompletionResponse.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateChatCompletionResponse.cs create mode 100644 .dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.cs create mode 100644 .dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceFinishReason.cs create mode 100644 .dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.cs create mode 100644 .dotnet/src/Generated/Models/CreateChatCompletionResponseObject.cs create mode 100644 .dotnet/src/Generated/Models/CreateCompletionRequest.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateCompletionRequest.cs create mode 100644 .dotnet/src/Generated/Models/CreateCompletionRequestModel.cs create mode 100644 .dotnet/src/Generated/Models/CreateCompletionResponse.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateCompletionResponse.cs create mode 100644 .dotnet/src/Generated/Models/CreateCompletionResponseChoice.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateCompletionResponseChoice.cs create mode 100644 .dotnet/src/Generated/Models/CreateCompletionResponseChoiceFinishReason.cs create mode 100644 .dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.cs create mode 100644 .dotnet/src/Generated/Models/CreateCompletionResponseObject.cs create mode 100644 .dotnet/src/Generated/Models/CreateEmbeddingRequest.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateEmbeddingRequest.cs create mode 100644 .dotnet/src/Generated/Models/CreateEmbeddingRequestEncodingFormat.cs create mode 100644 .dotnet/src/Generated/Models/CreateEmbeddingRequestModel.cs create mode 100644 .dotnet/src/Generated/Models/CreateEmbeddingResponse.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateEmbeddingResponse.cs create mode 100644 .dotnet/src/Generated/Models/CreateEmbeddingResponseObject.cs create mode 100644 .dotnet/src/Generated/Models/CreateEmbeddingResponseUsage.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateEmbeddingResponseUsage.cs create mode 100644 .dotnet/src/Generated/Models/CreateFileRequest.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateFileRequest.cs create mode 100644 .dotnet/src/Generated/Models/CreateFileRequestPurpose.cs create mode 100644 .dotnet/src/Generated/Models/CreateFineTuneRequest.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateFineTuneRequest.cs create mode 100644 .dotnet/src/Generated/Models/CreateFineTuneRequestModel.cs create mode 100644 .dotnet/src/Generated/Models/CreateFineTuningJobRequest.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateFineTuningJobRequest.cs create mode 100644 .dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.cs create mode 100644 .dotnet/src/Generated/Models/CreateFineTuningJobRequestModel.cs create mode 100644 .dotnet/src/Generated/Models/CreateImageEditRequest.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateImageEditRequest.cs create mode 100644 .dotnet/src/Generated/Models/CreateImageEditRequestModel.cs create mode 100644 .dotnet/src/Generated/Models/CreateImageEditRequestResponseFormat.cs create mode 100644 .dotnet/src/Generated/Models/CreateImageEditRequestSize.cs create mode 100644 .dotnet/src/Generated/Models/CreateImageRequest.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateImageRequest.cs create mode 100644 .dotnet/src/Generated/Models/CreateImageRequestModel.cs create mode 100644 .dotnet/src/Generated/Models/CreateImageRequestQuality.cs create mode 100644 .dotnet/src/Generated/Models/CreateImageRequestResponseFormat.cs create mode 100644 .dotnet/src/Generated/Models/CreateImageRequestSize.cs create mode 100644 .dotnet/src/Generated/Models/CreateImageRequestStyle.cs create mode 100644 .dotnet/src/Generated/Models/CreateImageVariationRequest.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateImageVariationRequest.cs create mode 100644 .dotnet/src/Generated/Models/CreateImageVariationRequestModel.cs create mode 100644 .dotnet/src/Generated/Models/CreateImageVariationRequestResponseFormat.cs create mode 100644 .dotnet/src/Generated/Models/CreateImageVariationRequestSize.cs create mode 100644 .dotnet/src/Generated/Models/CreateMessageRequest.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateMessageRequest.cs create mode 100644 .dotnet/src/Generated/Models/CreateMessageRequestRole.cs create mode 100644 .dotnet/src/Generated/Models/CreateModerationRequest.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateModerationRequest.cs create mode 100644 .dotnet/src/Generated/Models/CreateModerationRequestModel.cs create mode 100644 .dotnet/src/Generated/Models/CreateModerationResponse.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateModerationResponse.cs create mode 100644 .dotnet/src/Generated/Models/CreateModerationResponseResult.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateModerationResponseResult.cs create mode 100644 .dotnet/src/Generated/Models/CreateModerationResponseResultCategories.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateModerationResponseResultCategories.cs create mode 100644 .dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.cs create mode 100644 .dotnet/src/Generated/Models/CreateRunRequest.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateRunRequest.cs create mode 100644 .dotnet/src/Generated/Models/CreateSpeechRequest.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateSpeechRequest.cs create mode 100644 .dotnet/src/Generated/Models/CreateSpeechRequestModel.cs create mode 100644 .dotnet/src/Generated/Models/CreateSpeechRequestResponseFormat.cs create mode 100644 .dotnet/src/Generated/Models/CreateSpeechRequestVoice.cs create mode 100644 .dotnet/src/Generated/Models/CreateThreadAndRunRequest.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateThreadAndRunRequest.cs create mode 100644 .dotnet/src/Generated/Models/CreateThreadRequest.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateThreadRequest.cs create mode 100644 .dotnet/src/Generated/Models/CreateTranscriptionRequest.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateTranscriptionRequest.cs create mode 100644 .dotnet/src/Generated/Models/CreateTranscriptionRequestModel.cs create mode 100644 .dotnet/src/Generated/Models/CreateTranscriptionRequestResponseFormat.cs create mode 100644 .dotnet/src/Generated/Models/CreateTranscriptionResponse.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateTranscriptionResponse.cs create mode 100644 .dotnet/src/Generated/Models/CreateTranscriptionResponseTask.cs create mode 100644 .dotnet/src/Generated/Models/CreateTranslationRequest.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateTranslationRequest.cs create mode 100644 .dotnet/src/Generated/Models/CreateTranslationRequestModel.cs create mode 100644 .dotnet/src/Generated/Models/CreateTranslationRequestResponseFormat.cs create mode 100644 .dotnet/src/Generated/Models/CreateTranslationResponse.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/CreateTranslationResponse.cs create mode 100644 .dotnet/src/Generated/Models/CreateTranslationResponseTask.cs create mode 100644 .dotnet/src/Generated/Models/DeleteAssistantFileResponse.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/DeleteAssistantFileResponse.cs create mode 100644 .dotnet/src/Generated/Models/DeleteAssistantFileResponseObject.cs create mode 100644 .dotnet/src/Generated/Models/DeleteAssistantResponse.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/DeleteAssistantResponse.cs create mode 100644 .dotnet/src/Generated/Models/DeleteAssistantResponseObject.cs create mode 100644 .dotnet/src/Generated/Models/DeleteFileResponse.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/DeleteFileResponse.cs create mode 100644 .dotnet/src/Generated/Models/DeleteFileResponseObject.cs create mode 100644 .dotnet/src/Generated/Models/DeleteModelResponse.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/DeleteModelResponse.cs create mode 100644 .dotnet/src/Generated/Models/DeleteModelResponseObject.cs create mode 100644 .dotnet/src/Generated/Models/DeleteThreadResponse.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/DeleteThreadResponse.cs create mode 100644 .dotnet/src/Generated/Models/DeleteThreadResponseObject.cs create mode 100644 .dotnet/src/Generated/Models/Embedding.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/Embedding.cs create mode 100644 .dotnet/src/Generated/Models/EmbeddingObject.cs create mode 100644 .dotnet/src/Generated/Models/FineTune.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/FineTune.cs create mode 100644 .dotnet/src/Generated/Models/FineTuneEvent.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/FineTuneEvent.cs create mode 100644 .dotnet/src/Generated/Models/FineTuneHyperparams.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/FineTuneHyperparams.cs create mode 100644 .dotnet/src/Generated/Models/FineTuneObject.cs create mode 100644 .dotnet/src/Generated/Models/FineTuneStatus.cs create mode 100644 .dotnet/src/Generated/Models/FineTuningJob.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/FineTuningJob.cs create mode 100644 .dotnet/src/Generated/Models/FineTuningJobError.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/FineTuningJobError.cs create mode 100644 .dotnet/src/Generated/Models/FineTuningJobEvent.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/FineTuningJobEvent.cs create mode 100644 .dotnet/src/Generated/Models/FineTuningJobEventLevel.cs create mode 100644 .dotnet/src/Generated/Models/FineTuningJobHyperparameters.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/FineTuningJobHyperparameters.cs create mode 100644 .dotnet/src/Generated/Models/FineTuningJobObject.cs create mode 100644 .dotnet/src/Generated/Models/FineTuningJobStatus.cs create mode 100644 .dotnet/src/Generated/Models/FunctionObject.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/FunctionObject.cs create mode 100644 .dotnet/src/Generated/Models/FunctionParameters.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/FunctionParameters.cs create mode 100644 .dotnet/src/Generated/Models/Image.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/Image.cs create mode 100644 .dotnet/src/Generated/Models/ImagesResponse.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ImagesResponse.cs create mode 100644 .dotnet/src/Generated/Models/ListAssistantFilesResponse.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ListAssistantFilesResponse.cs create mode 100644 .dotnet/src/Generated/Models/ListAssistantFilesResponseObject.cs create mode 100644 .dotnet/src/Generated/Models/ListAssistantsResponse.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ListAssistantsResponse.cs create mode 100644 .dotnet/src/Generated/Models/ListAssistantsResponseObject.cs create mode 100644 .dotnet/src/Generated/Models/ListFilesResponse.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ListFilesResponse.cs create mode 100644 .dotnet/src/Generated/Models/ListFilesResponseObject.cs create mode 100644 .dotnet/src/Generated/Models/ListFineTuneEventsResponse.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ListFineTuneEventsResponse.cs create mode 100644 .dotnet/src/Generated/Models/ListFineTunesResponse.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ListFineTunesResponse.cs create mode 100644 .dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.cs create mode 100644 .dotnet/src/Generated/Models/ListMessageFilesResponse.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ListMessageFilesResponse.cs create mode 100644 .dotnet/src/Generated/Models/ListMessageFilesResponseObject.cs create mode 100644 .dotnet/src/Generated/Models/ListMessagesResponse.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ListMessagesResponse.cs create mode 100644 .dotnet/src/Generated/Models/ListMessagesResponseObject.cs create mode 100644 .dotnet/src/Generated/Models/ListModelsResponse.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ListModelsResponse.cs create mode 100644 .dotnet/src/Generated/Models/ListModelsResponseObject.cs create mode 100644 .dotnet/src/Generated/Models/ListOrder.cs create mode 100644 .dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.cs create mode 100644 .dotnet/src/Generated/Models/ListRunStepsResponse.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ListRunStepsResponse.cs create mode 100644 .dotnet/src/Generated/Models/ListRunStepsResponseObject.cs create mode 100644 .dotnet/src/Generated/Models/ListRunsResponse.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ListRunsResponse.cs create mode 100644 .dotnet/src/Generated/Models/ListRunsResponseObject.cs create mode 100644 .dotnet/src/Generated/Models/MessageFileObject.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/MessageFileObject.cs create mode 100644 .dotnet/src/Generated/Models/MessageFileObjectObject.cs create mode 100644 .dotnet/src/Generated/Models/MessageObject.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/MessageObject.cs create mode 100644 .dotnet/src/Generated/Models/MessageObjectObject.cs create mode 100644 .dotnet/src/Generated/Models/MessageObjectRole.cs create mode 100644 .dotnet/src/Generated/Models/Model.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/Model.cs create mode 100644 .dotnet/src/Generated/Models/ModelObject.cs create mode 100644 .dotnet/src/Generated/Models/ModifyAssistantRequest.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ModifyAssistantRequest.cs create mode 100644 .dotnet/src/Generated/Models/ModifyMessageRequest.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ModifyMessageRequest.cs create mode 100644 .dotnet/src/Generated/Models/ModifyRunRequest.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ModifyRunRequest.cs create mode 100644 .dotnet/src/Generated/Models/ModifyThreadRequest.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ModifyThreadRequest.cs create mode 100644 .dotnet/src/Generated/Models/OpenAIFile.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/OpenAIFile.cs create mode 100644 .dotnet/src/Generated/Models/OpenAIFileObject.cs create mode 100644 .dotnet/src/Generated/Models/OpenAIFilePurpose.cs create mode 100644 .dotnet/src/Generated/Models/OpenAIFileStatus.cs create mode 100644 .dotnet/src/Generated/Models/RunCompletionUsage.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/RunCompletionUsage.cs create mode 100644 .dotnet/src/Generated/Models/RunObject.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/RunObject.cs create mode 100644 .dotnet/src/Generated/Models/RunObjectLastError.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/RunObjectLastError.cs create mode 100644 .dotnet/src/Generated/Models/RunObjectLastErrorCode.cs create mode 100644 .dotnet/src/Generated/Models/RunObjectObject.cs create mode 100644 .dotnet/src/Generated/Models/RunObjectRequiredAction.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/RunObjectRequiredAction.cs create mode 100644 .dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.cs create mode 100644 .dotnet/src/Generated/Models/RunObjectRequiredActionType.cs create mode 100644 .dotnet/src/Generated/Models/RunObjectStatus.cs create mode 100644 .dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.cs create mode 100644 .dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.cs create mode 100644 .dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectType.cs create mode 100644 .dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.cs create mode 100644 .dotnet/src/Generated/Models/RunStepDetailsToolCallsObjectType.cs create mode 100644 .dotnet/src/Generated/Models/RunStepObject.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/RunStepObject.cs create mode 100644 .dotnet/src/Generated/Models/RunStepObjectLastError.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/RunStepObjectLastError.cs create mode 100644 .dotnet/src/Generated/Models/RunStepObjectLastErrorCode.cs create mode 100644 .dotnet/src/Generated/Models/RunStepObjectObject.cs create mode 100644 .dotnet/src/Generated/Models/RunStepObjectStatus.cs create mode 100644 .dotnet/src/Generated/Models/RunStepObjectType.cs create mode 100644 .dotnet/src/Generated/Models/RunToolCallObject.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/RunToolCallObject.cs create mode 100644 .dotnet/src/Generated/Models/RunToolCallObjectFunction.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/RunToolCallObjectFunction.cs create mode 100644 .dotnet/src/Generated/Models/RunToolCallObjectType.cs create mode 100644 .dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.cs create mode 100644 .dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutputs.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutputs.cs create mode 100644 .dotnet/src/Generated/Models/ThreadObject.Serialization.cs create mode 100644 .dotnet/src/Generated/Models/ThreadObject.cs create mode 100644 .dotnet/src/Generated/Models/ThreadObjectObject.cs create mode 100644 .dotnet/src/Generated/ModelsOps.cs create mode 100644 .dotnet/src/Generated/Moderations.cs create mode 100644 .dotnet/src/Generated/OpenAIClient.cs create mode 100644 .dotnet/src/Generated/OpenAIClientOptions.cs create mode 100644 .dotnet/src/Generated/OpenAIModelFactory.cs create mode 100644 .dotnet/src/Generated/Runs.cs create mode 100644 .dotnet/src/Generated/Threads.cs create mode 100644 .dotnet/src/OpenAI.csproj create mode 100644 .dotnet/tests/Generated/Tests/AssistantsTests.cs create mode 100644 .dotnet/tests/Generated/Tests/AudioTests.cs create mode 100644 .dotnet/tests/Generated/Tests/ChatTests.cs create mode 100644 .dotnet/tests/Generated/Tests/CompletionsTests.cs create mode 100644 .dotnet/tests/Generated/Tests/EmbeddingsTests.cs create mode 100644 .dotnet/tests/Generated/Tests/FilesTests.cs create mode 100644 .dotnet/tests/Generated/Tests/FineTuningJobsTests.cs create mode 100644 .dotnet/tests/Generated/Tests/ImagesTests.cs create mode 100644 .dotnet/tests/Generated/Tests/MessagesTests.cs create mode 100644 .dotnet/tests/Generated/Tests/ModelsOpsTests.cs create mode 100644 .dotnet/tests/Generated/Tests/ModerationsTests.cs create mode 100644 .dotnet/tests/Generated/Tests/RunsTests.cs create mode 100644 .dotnet/tests/Generated/Tests/ThreadsTests.cs create mode 100644 .dotnet/tests/OpenAI.Tests.csproj create mode 100644 .dotnet/tsp-output/@typespec/openapi3/openapi.yaml create mode 100644 .gitignore create mode 100644 tspconfig.yaml diff --git a/.dotnet/OpenAI.sln b/.dotnet/OpenAI.sln new file mode 100644 index 000000000..5d1edd8c3 --- /dev/null +++ b/.dotnet/OpenAI.sln @@ -0,0 +1,50 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29709.97 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenAI", "src\OpenAI.csproj", "{28FF4005-4467-4E36-92E7-DEA27DEB1519}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenAI.Tests", "tests\OpenAI.Tests.csproj", "{1F1CD1D4-9932-4B73-99D8-C252A67D4B46}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B0C276D1-2930-4887-B29A-D1A33E7009A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B0C276D1-2930-4887-B29A-D1A33E7009A2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B0C276D1-2930-4887-B29A-D1A33E7009A2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B0C276D1-2930-4887-B29A-D1A33E7009A2}.Release|Any CPU.Build.0 = Release|Any CPU + {8E9A77AC-792A-4432-8320-ACFD46730401}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8E9A77AC-792A-4432-8320-ACFD46730401}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8E9A77AC-792A-4432-8320-ACFD46730401}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8E9A77AC-792A-4432-8320-ACFD46730401}.Release|Any CPU.Build.0 = Release|Any CPU + {A4241C1F-A53D-474C-9E4E-075054407E74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A4241C1F-A53D-474C-9E4E-075054407E74}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A4241C1F-A53D-474C-9E4E-075054407E74}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A4241C1F-A53D-474C-9E4E-075054407E74}.Release|Any CPU.Build.0 = Release|Any CPU + {FA8BD3F1-8616-47B6-974C-7576CDF4717E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FA8BD3F1-8616-47B6-974C-7576CDF4717E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FA8BD3F1-8616-47B6-974C-7576CDF4717E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FA8BD3F1-8616-47B6-974C-7576CDF4717E}.Release|Any CPU.Build.0 = Release|Any CPU + {85677AD3-C214-42FA-AE6E-49B956CAC8DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {85677AD3-C214-42FA-AE6E-49B956CAC8DC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {85677AD3-C214-42FA-AE6E-49B956CAC8DC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {85677AD3-C214-42FA-AE6E-49B956CAC8DC}.Release|Any CPU.Build.0 = Release|Any CPU + {28FF4005-4467-4E36-92E7-DEA27DEB1519}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {28FF4005-4467-4E36-92E7-DEA27DEB1519}.Debug|Any CPU.Build.0 = Debug|Any CPU + {28FF4005-4467-4E36-92E7-DEA27DEB1519}.Release|Any CPU.ActiveCfg = Release|Any CPU + {28FF4005-4467-4E36-92E7-DEA27DEB1519}.Release|Any CPU.Build.0 = Release|Any CPU + {1F1CD1D4-9932-4B73-99D8-C252A67D4B46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1F1CD1D4-9932-4B73-99D8-C252A67D4B46}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1F1CD1D4-9932-4B73-99D8-C252A67D4B46}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1F1CD1D4-9932-4B73-99D8-C252A67D4B46}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {A97F4B90-2591-4689-B1F8-5F21FE6D6CAE} + EndGlobalSection +EndGlobal diff --git a/.dotnet/src/Generated/Assistants.cs b/.dotnet/src/Generated/Assistants.cs new file mode 100644 index 000000000..748820476 --- /dev/null +++ b/.dotnet/src/Generated/Assistants.cs @@ -0,0 +1,1352 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.ClientModel.Primitives.Pipeline; +using System.Threading; +using System.Threading.Tasks; +using OpenAI.Models; + +namespace OpenAI +{ + // Data plane generated sub-client. + /// The Assistants sub-client. + public partial class Assistants + { + private const string AuthorizationHeader = "Authorization"; + private readonly KeyCredential _keyCredential; + private const string AuthorizationApiKeyPrefix = "Bearer"; + private readonly MessagePipeline _pipeline; + private readonly Uri _endpoint; + + /// The ClientDiagnostics is used to provide tracing support for the client library. + internal TelemetrySource ClientDiagnostics { get; } + + /// The HTTP pipeline for sending and receiving REST requests and responses. + public virtual MessagePipeline Pipeline => _pipeline; + + /// Initializes a new instance of Assistants for mocking. + protected Assistants() + { + } + + /// Initializes a new instance of Assistants. + /// The handler for diagnostic messaging in the client. + /// The HTTP pipeline for sending and receiving REST requests and responses. + /// The key credential to copy. + /// OpenAI Endpoint. + internal Assistants(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + { + ClientDiagnostics = clientDiagnostics; + _pipeline = pipeline; + _keyCredential = keyCredential; + _endpoint = endpoint; + } + + /// Create an assistant with a model and instructions. + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual async Task> CreateAssistantAsync(CreateAssistantRequest assistant, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(assistant, nameof(assistant)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = assistant.ToRequestBody(); + Result result = await CreateAssistantAsync(content, context).ConfigureAwait(false); + return Result.FromValue(AssistantObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Create an assistant with a model and instructions. + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual Result CreateAssistant(CreateAssistantRequest assistant, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(assistant, nameof(assistant)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = assistant.ToRequestBody(); + Result result = CreateAssistant(content, context); + return Result.FromValue(AssistantObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Create an assistant with a model and instructions. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task CreateAssistantAsync(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Assistants.CreateAssistant"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateAssistantRequest(content, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Create an assistant with a model and instructions. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result CreateAssistant(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Assistants.CreateAssistant"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateAssistantRequest(content, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Returns a list of assistants. + /// + /// A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + /// default is 20. + /// + /// + /// Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + /// for descending order. + /// + /// + /// A cursor for use in pagination. `after` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include after=obj_foo in order to fetch the next page of the list. + /// + /// + /// A cursor for use in pagination. `before` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. + /// + /// The cancellation token to use. + public virtual async Task> GetAssistantsAsync(int? limit = null, ListOrder? order = null, string after = null, string before = null, CancellationToken cancellationToken = default) + { + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await GetAssistantsAsync(limit, order?.ToString(), after, before, context).ConfigureAwait(false); + return Result.FromValue(ListAssistantsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Returns a list of assistants. + /// + /// A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + /// default is 20. + /// + /// + /// Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + /// for descending order. + /// + /// + /// A cursor for use in pagination. `after` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include after=obj_foo in order to fetch the next page of the list. + /// + /// + /// A cursor for use in pagination. `before` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. + /// + /// The cancellation token to use. + public virtual Result GetAssistants(int? limit = null, ListOrder? order = null, string after = null, string before = null, CancellationToken cancellationToken = default) + { + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = GetAssistants(limit, order?.ToString(), after, before, context); + return Result.FromValue(ListAssistantsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Returns a list of assistants. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// + /// A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + /// default is 20. + /// + /// + /// Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + /// for descending order. Allowed values: "asc" | "desc" + /// + /// + /// A cursor for use in pagination. `after` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include after=obj_foo in order to fetch the next page of the list. + /// + /// + /// A cursor for use in pagination. `before` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. + /// + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task GetAssistantsAsync(int? limit, string order, string after, string before, RequestOptions context) + { + using var scope = ClientDiagnostics.CreateSpan("Assistants.GetAssistants"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetAssistantsRequest(limit, order, after, before, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Returns a list of assistants. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// + /// A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + /// default is 20. + /// + /// + /// Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + /// for descending order. Allowed values: "asc" | "desc" + /// + /// + /// A cursor for use in pagination. `after` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include after=obj_foo in order to fetch the next page of the list. + /// + /// + /// A cursor for use in pagination. `before` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. + /// + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result GetAssistants(int? limit, string order, string after, string before, RequestOptions context) + { + using var scope = ClientDiagnostics.CreateSpan("Assistants.GetAssistants"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetAssistantsRequest(limit, order, after, before, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Retrieves an assistant. + /// The ID of the assistant to retrieve. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual async Task> GetAssistantAsync(string assistantId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await GetAssistantAsync(assistantId, context).ConfigureAwait(false); + return Result.FromValue(AssistantObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Retrieves an assistant. + /// The ID of the assistant to retrieve. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual Result GetAssistant(string assistantId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = GetAssistant(assistantId, context); + return Result.FromValue(AssistantObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Retrieves an assistant. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the assistant to retrieve. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task GetAssistantAsync(string assistantId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + + using var scope = ClientDiagnostics.CreateSpan("Assistants.GetAssistant"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetAssistantRequest(assistantId, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Retrieves an assistant. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the assistant to retrieve. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result GetAssistant(string assistantId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + + using var scope = ClientDiagnostics.CreateSpan("Assistants.GetAssistant"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetAssistantRequest(assistantId, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Modifies an assistant. + /// The ID of the assistant to modify. + /// The to use. + /// The cancellation token to use. + /// or is null. + /// is an empty string, and was expected to be non-empty. + public virtual async Task> ModifyAssistantAsync(string assistantId, ModifyAssistantRequest assistant, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + ClientUtilities.AssertNotNull(assistant, nameof(assistant)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = assistant.ToRequestBody(); + Result result = await ModifyAssistantAsync(assistantId, content, context).ConfigureAwait(false); + return Result.FromValue(AssistantObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Modifies an assistant. + /// The ID of the assistant to modify. + /// The to use. + /// The cancellation token to use. + /// or is null. + /// is an empty string, and was expected to be non-empty. + public virtual Result ModifyAssistant(string assistantId, ModifyAssistantRequest assistant, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + ClientUtilities.AssertNotNull(assistant, nameof(assistant)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = assistant.ToRequestBody(); + Result result = ModifyAssistant(assistantId, content, context); + return Result.FromValue(AssistantObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Modifies an assistant. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the assistant to modify. + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task ModifyAssistantAsync(string assistantId, RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Assistants.ModifyAssistant"); + scope.Start(); + try + { + using PipelineMessage message = CreateModifyAssistantRequest(assistantId, content, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Modifies an assistant. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the assistant to modify. + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result ModifyAssistant(string assistantId, RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Assistants.ModifyAssistant"); + scope.Start(); + try + { + using PipelineMessage message = CreateModifyAssistantRequest(assistantId, content, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Delete an assistant. + /// The ID of the assistant to delete. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual async Task> DeleteAssistantAsync(string assistantId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await DeleteAssistantAsync(assistantId, context).ConfigureAwait(false); + return Result.FromValue(DeleteAssistantResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Delete an assistant. + /// The ID of the assistant to delete. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual Result DeleteAssistant(string assistantId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = DeleteAssistant(assistantId, context); + return Result.FromValue(DeleteAssistantResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Delete an assistant. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the assistant to delete. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task DeleteAssistantAsync(string assistantId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + + using var scope = ClientDiagnostics.CreateSpan("Assistants.DeleteAssistant"); + scope.Start(); + try + { + using PipelineMessage message = CreateDeleteAssistantRequest(assistantId, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Delete an assistant. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the assistant to delete. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result DeleteAssistant(string assistantId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + + using var scope = ClientDiagnostics.CreateSpan("Assistants.DeleteAssistant"); + scope.Start(); + try + { + using PipelineMessage message = CreateDeleteAssistantRequest(assistantId, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// Create an assistant file by attaching a [File](/docs/api-reference/files) to a + /// [assistant](/docs/api-reference/assistants). + /// + /// The ID of the assistant for which to create a file. + /// The to use. + /// The cancellation token to use. + /// or is null. + /// is an empty string, and was expected to be non-empty. + public virtual async Task> CreateAssistantFileAsync(string assistantId, CreateAssistantFileRequest file, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + ClientUtilities.AssertNotNull(file, nameof(file)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = file.ToRequestBody(); + Result result = await CreateAssistantFileAsync(assistantId, content, context).ConfigureAwait(false); + return Result.FromValue(AssistantFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// Create an assistant file by attaching a [File](/docs/api-reference/files) to a + /// [assistant](/docs/api-reference/assistants). + /// + /// The ID of the assistant for which to create a file. + /// The to use. + /// The cancellation token to use. + /// or is null. + /// is an empty string, and was expected to be non-empty. + public virtual Result CreateAssistantFile(string assistantId, CreateAssistantFileRequest file, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + ClientUtilities.AssertNotNull(file, nameof(file)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = file.ToRequestBody(); + Result result = CreateAssistantFile(assistantId, content, context); + return Result.FromValue(AssistantFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Create an assistant file by attaching a [File](/docs/api-reference/files) to a + /// [assistant](/docs/api-reference/assistants). + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the assistant for which to create a file. + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task CreateAssistantFileAsync(string assistantId, RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Assistants.CreateAssistantFile"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateAssistantFileRequest(assistantId, content, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Create an assistant file by attaching a [File](/docs/api-reference/files) to a + /// [assistant](/docs/api-reference/assistants). + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the assistant for which to create a file. + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result CreateAssistantFile(string assistantId, RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Assistants.CreateAssistantFile"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateAssistantFileRequest(assistantId, content, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Returns a list of assistant files. + /// The ID of the assistant the file belongs to. + /// + /// A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + /// default is 20. + /// + /// + /// Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + /// for descending order. + /// + /// + /// A cursor for use in pagination. `after` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include after=obj_foo in order to fetch the next page of the list. + /// + /// + /// A cursor for use in pagination. `before` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. + /// + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual async Task> GetAssistantFilesAsync(string assistantId, int? limit = null, ListOrder? order = null, string after = null, string before = null, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await GetAssistantFilesAsync(assistantId, limit, order?.ToString(), after, before, context).ConfigureAwait(false); + return Result.FromValue(ListAssistantFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Returns a list of assistant files. + /// The ID of the assistant the file belongs to. + /// + /// A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + /// default is 20. + /// + /// + /// Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + /// for descending order. + /// + /// + /// A cursor for use in pagination. `after` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include after=obj_foo in order to fetch the next page of the list. + /// + /// + /// A cursor for use in pagination. `before` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. + /// + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual Result GetAssistantFiles(string assistantId, int? limit = null, ListOrder? order = null, string after = null, string before = null, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = GetAssistantFiles(assistantId, limit, order?.ToString(), after, before, context); + return Result.FromValue(ListAssistantFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Returns a list of assistant files. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the assistant the file belongs to. + /// + /// A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + /// default is 20. + /// + /// + /// Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + /// for descending order. Allowed values: "asc" | "desc" + /// + /// + /// A cursor for use in pagination. `after` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include after=obj_foo in order to fetch the next page of the list. + /// + /// + /// A cursor for use in pagination. `before` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. + /// + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task GetAssistantFilesAsync(string assistantId, int? limit, string order, string after, string before, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + + using var scope = ClientDiagnostics.CreateSpan("Assistants.GetAssistantFiles"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetAssistantFilesRequest(assistantId, limit, order, after, before, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Returns a list of assistant files. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the assistant the file belongs to. + /// + /// A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + /// default is 20. + /// + /// + /// Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + /// for descending order. Allowed values: "asc" | "desc" + /// + /// + /// A cursor for use in pagination. `after` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include after=obj_foo in order to fetch the next page of the list. + /// + /// + /// A cursor for use in pagination. `before` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. + /// + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result GetAssistantFiles(string assistantId, int? limit, string order, string after, string before, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + + using var scope = ClientDiagnostics.CreateSpan("Assistants.GetAssistantFiles"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetAssistantFilesRequest(assistantId, limit, order, after, before, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Retrieves an assistant file. + /// The ID of the assistant the file belongs to. + /// The ID of the file we're getting. + /// The cancellation token to use. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + public virtual async Task> GetAssistantFileAsync(string assistantId, string fileId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await GetAssistantFileAsync(assistantId, fileId, context).ConfigureAwait(false); + return Result.FromValue(AssistantFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Retrieves an assistant file. + /// The ID of the assistant the file belongs to. + /// The ID of the file we're getting. + /// The cancellation token to use. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + public virtual Result GetAssistantFile(string assistantId, string fileId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = GetAssistantFile(assistantId, fileId, context); + return Result.FromValue(AssistantFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Retrieves an assistant file. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the assistant the file belongs to. + /// The ID of the file we're getting. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task GetAssistantFileAsync(string assistantId, string fileId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + + using var scope = ClientDiagnostics.CreateSpan("Assistants.GetAssistantFile"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetAssistantFileRequest(assistantId, fileId, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Retrieves an assistant file. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the assistant the file belongs to. + /// The ID of the file we're getting. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result GetAssistantFile(string assistantId, string fileId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + + using var scope = ClientDiagnostics.CreateSpan("Assistants.GetAssistantFile"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetAssistantFileRequest(assistantId, fileId, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Delete an assistant file. + /// The ID of the assistant the file belongs to. + /// The ID of the file to delete. + /// The cancellation token to use. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + public virtual async Task> DeleteAssistantFileAsync(string assistantId, string fileId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await DeleteAssistantFileAsync(assistantId, fileId, context).ConfigureAwait(false); + return Result.FromValue(DeleteAssistantFileResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Delete an assistant file. + /// The ID of the assistant the file belongs to. + /// The ID of the file to delete. + /// The cancellation token to use. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + public virtual Result DeleteAssistantFile(string assistantId, string fileId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = DeleteAssistantFile(assistantId, fileId, context); + return Result.FromValue(DeleteAssistantFileResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Delete an assistant file. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the assistant the file belongs to. + /// The ID of the file to delete. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task DeleteAssistantFileAsync(string assistantId, string fileId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + + using var scope = ClientDiagnostics.CreateSpan("Assistants.DeleteAssistantFile"); + scope.Start(); + try + { + using PipelineMessage message = CreateDeleteAssistantFileRequest(assistantId, fileId, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Delete an assistant file. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the assistant the file belongs to. + /// The ID of the file to delete. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result DeleteAssistantFile(string assistantId, string fileId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + + using var scope = ClientDiagnostics.CreateSpan("Assistants.DeleteAssistantFile"); + scope.Start(); + try + { + using PipelineMessage message = CreateDeleteAssistantFileRequest(assistantId, fileId, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + internal PipelineMessage CreateCreateAssistantRequest(RequestBody content, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/assistants", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + request.SetHeaderValue("Content-Type", "application/json"); + request.Content = content; + return message; + } + + internal PipelineMessage CreateGetAssistantsRequest(int? limit, string order, string after, string before, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("GET"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/assistants", false); + if (limit != null) + { + uri.AppendQuery("limit", limit.Value, true); + } + if (order != null) + { + uri.AppendQuery("order", order, true); + } + if (after != null) + { + uri.AppendQuery("after", after, true); + } + if (before != null) + { + uri.AppendQuery("before", before, true); + } + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + internal PipelineMessage CreateGetAssistantRequest(string assistantId, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("GET"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/assistants/", false); + uri.AppendPath(assistantId, true); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + internal PipelineMessage CreateModifyAssistantRequest(string assistantId, RequestBody content, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/assistants/", false); + uri.AppendPath(assistantId, true); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + request.SetHeaderValue("Content-Type", "application/json"); + request.Content = content; + return message; + } + + internal PipelineMessage CreateDeleteAssistantRequest(string assistantId, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("DELETE"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/assistants/", false); + uri.AppendPath(assistantId, true); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + internal PipelineMessage CreateCreateAssistantFileRequest(string assistantId, RequestBody content, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/assistants/", false); + uri.AppendPath(assistantId, true); + uri.AppendPath("/files", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + request.SetHeaderValue("Content-Type", "application/json"); + request.Content = content; + return message; + } + + internal PipelineMessage CreateGetAssistantFilesRequest(string assistantId, int? limit, string order, string after, string before, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("GET"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/assistants/", false); + uri.AppendPath(assistantId, true); + uri.AppendPath("/files", false); + if (limit != null) + { + uri.AppendQuery("limit", limit.Value, true); + } + if (order != null) + { + uri.AppendQuery("order", order, true); + } + if (after != null) + { + uri.AppendQuery("after", after, true); + } + if (before != null) + { + uri.AppendQuery("before", before, true); + } + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + internal PipelineMessage CreateGetAssistantFileRequest(string assistantId, string fileId, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("GET"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/assistants/", false); + uri.AppendPath(assistantId, true); + uri.AppendPath("/files/", false); + uri.AppendPath(fileId, true); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + internal PipelineMessage CreateDeleteAssistantFileRequest(string assistantId, string fileId, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("DELETE"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/assistants/", false); + uri.AppendPath(assistantId, true); + uri.AppendPath("/files/", false); + uri.AppendPath(fileId, true); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + private static RequestOptions DefaultRequestContext = new RequestOptions(); + internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) + { + if (!cancellationToken.CanBeCanceled) + { + return DefaultRequestContext; + } + + return new RequestOptions() { CancellationToken = cancellationToken }; + } + + private static ResponseErrorClassifier _responseErrorClassifier200; + private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); + } +} diff --git a/.dotnet/src/Generated/Audio.cs b/.dotnet/src/Generated/Audio.cs new file mode 100644 index 000000000..6acfba501 --- /dev/null +++ b/.dotnet/src/Generated/Audio.cs @@ -0,0 +1,421 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.ClientModel.Primitives.Pipeline; +using System.Threading; +using System.Threading.Tasks; +using OpenAI.Models; + +namespace OpenAI +{ + // Data plane generated sub-client. + /// The Audio sub-client. + public partial class Audio + { + private const string AuthorizationHeader = "Authorization"; + private readonly KeyCredential _keyCredential; + private const string AuthorizationApiKeyPrefix = "Bearer"; + private readonly MessagePipeline _pipeline; + private readonly Uri _endpoint; + + /// The ClientDiagnostics is used to provide tracing support for the client library. + internal TelemetrySource ClientDiagnostics { get; } + + /// The HTTP pipeline for sending and receiving REST requests and responses. + public virtual MessagePipeline Pipeline => _pipeline; + + /// Initializes a new instance of Audio for mocking. + protected Audio() + { + } + + /// Initializes a new instance of Audio. + /// The handler for diagnostic messaging in the client. + /// The HTTP pipeline for sending and receiving REST requests and responses. + /// The key credential to copy. + /// OpenAI Endpoint. + internal Audio(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + { + ClientDiagnostics = clientDiagnostics; + _pipeline = pipeline; + _keyCredential = keyCredential; + _endpoint = endpoint; + } + + /// Generates audio from the input text. + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual async Task> CreateSpeechAsync(CreateSpeechRequest speech, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(speech, nameof(speech)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = speech.ToRequestBody(); + Result result = await CreateSpeechAsync(content, context).ConfigureAwait(false); + return Result.FromValue(result.GetRawResponse().Content, result.GetRawResponse()); + } + + /// Generates audio from the input text. + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual Result CreateSpeech(CreateSpeechRequest speech, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(speech, nameof(speech)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = speech.ToRequestBody(); + Result result = CreateSpeech(content, context); + return Result.FromValue(result.GetRawResponse().Content, result.GetRawResponse()); + } + + /// + /// [Protocol Method] Generates audio from the input text. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task CreateSpeechAsync(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Audio.CreateSpeech"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateSpeechRequest(content, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Generates audio from the input text. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result CreateSpeech(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Audio.CreateSpeech"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateSpeechRequest(content, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Transcribes audio into the input language. + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual async Task> CreateTranscriptionAsync(CreateTranscriptionRequest audio, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(audio, nameof(audio)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = audio.ToRequestBody(); + Result result = await CreateTranscriptionAsync(content, context).ConfigureAwait(false); + return Result.FromValue(CreateTranscriptionResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Transcribes audio into the input language. + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual Result CreateTranscription(CreateTranscriptionRequest audio, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(audio, nameof(audio)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = audio.ToRequestBody(); + Result result = CreateTranscription(content, context); + return Result.FromValue(CreateTranscriptionResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Transcribes audio into the input language. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task CreateTranscriptionAsync(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Audio.CreateTranscription"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateTranscriptionRequest(content, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Transcribes audio into the input language. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result CreateTranscription(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Audio.CreateTranscription"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateTranscriptionRequest(content, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Translates audio into English.. + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual async Task> CreateTranslationAsync(CreateTranslationRequest audio, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(audio, nameof(audio)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = audio.ToRequestBody(); + Result result = await CreateTranslationAsync(content, context).ConfigureAwait(false); + return Result.FromValue(CreateTranslationResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Translates audio into English.. + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual Result CreateTranslation(CreateTranslationRequest audio, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(audio, nameof(audio)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = audio.ToRequestBody(); + Result result = CreateTranslation(content, context); + return Result.FromValue(CreateTranslationResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Translates audio into English.. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task CreateTranslationAsync(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Audio.CreateTranslation"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateTranslationRequest(content, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Translates audio into English.. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result CreateTranslation(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Audio.CreateTranslation"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateTranslationRequest(content, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + internal PipelineMessage CreateCreateSpeechRequest(RequestBody content, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/audio/speech", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/octet-stream"); + request.SetHeaderValue("Content-Type", "application/json"); + request.Content = content; + return message; + } + + internal PipelineMessage CreateCreateTranscriptionRequest(RequestBody content, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/audio/transcriptions", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + request.SetHeaderValue("content-type", "multipart/form-data"); + request.Content = content; + return message; + } + + internal PipelineMessage CreateCreateTranslationRequest(RequestBody content, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/audio/translations", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + request.SetHeaderValue("content-type", "multipart/form-data"); + request.Content = content; + return message; + } + + private static RequestOptions DefaultRequestContext = new RequestOptions(); + internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) + { + if (!cancellationToken.CanBeCanceled) + { + return DefaultRequestContext; + } + + return new RequestOptions() { CancellationToken = cancellationToken }; + } + + private static ResponseErrorClassifier _responseErrorClassifier200; + private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); + } +} diff --git a/.dotnet/src/Generated/Chat.cs b/.dotnet/src/Generated/Chat.cs new file mode 100644 index 000000000..8c8e0546e --- /dev/null +++ b/.dotnet/src/Generated/Chat.cs @@ -0,0 +1,183 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.ClientModel.Primitives.Pipeline; +using System.Threading; +using System.Threading.Tasks; +using OpenAI.Models; + +namespace OpenAI +{ + // Data plane generated sub-client. + /// The Chat sub-client. + public partial class Chat + { + private const string AuthorizationHeader = "Authorization"; + private readonly KeyCredential _keyCredential; + private const string AuthorizationApiKeyPrefix = "Bearer"; + private readonly MessagePipeline _pipeline; + private readonly Uri _endpoint; + + /// The ClientDiagnostics is used to provide tracing support for the client library. + internal TelemetrySource ClientDiagnostics { get; } + + /// The HTTP pipeline for sending and receiving REST requests and responses. + public virtual MessagePipeline Pipeline => _pipeline; + + /// Initializes a new instance of Chat for mocking. + protected Chat() + { + } + + /// Initializes a new instance of Chat. + /// The handler for diagnostic messaging in the client. + /// The HTTP pipeline for sending and receiving REST requests and responses. + /// The key credential to copy. + /// OpenAI Endpoint. + internal Chat(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + { + ClientDiagnostics = clientDiagnostics; + _pipeline = pipeline; + _keyCredential = keyCredential; + _endpoint = endpoint; + } + + /// Creates a model response for the given chat conversation. + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual async Task> CreateChatCompletionAsync(CreateChatCompletionRequest createChatCompletionRequest, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(createChatCompletionRequest, nameof(createChatCompletionRequest)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = createChatCompletionRequest.ToRequestBody(); + Result result = await CreateChatCompletionAsync(content, context).ConfigureAwait(false); + return Result.FromValue(CreateChatCompletionResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Creates a model response for the given chat conversation. + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual Result CreateChatCompletion(CreateChatCompletionRequest createChatCompletionRequest, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(createChatCompletionRequest, nameof(createChatCompletionRequest)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = createChatCompletionRequest.ToRequestBody(); + Result result = CreateChatCompletion(content, context); + return Result.FromValue(CreateChatCompletionResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Creates a model response for the given chat conversation. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task CreateChatCompletionAsync(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Chat.CreateChatCompletion"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateChatCompletionRequest(content, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Creates a model response for the given chat conversation. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result CreateChatCompletion(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Chat.CreateChatCompletion"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateChatCompletionRequest(content, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + internal PipelineMessage CreateCreateChatCompletionRequest(RequestBody content, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/chat/completions", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + request.SetHeaderValue("Content-Type", "application/json"); + request.Content = content; + return message; + } + + private static RequestOptions DefaultRequestContext = new RequestOptions(); + internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) + { + if (!cancellationToken.CanBeCanceled) + { + return DefaultRequestContext; + } + + return new RequestOptions() { CancellationToken = cancellationToken }; + } + + private static ResponseErrorClassifier _responseErrorClassifier200; + private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); + } +} diff --git a/.dotnet/src/Generated/Completions.cs b/.dotnet/src/Generated/Completions.cs new file mode 100644 index 000000000..aaa1f585d --- /dev/null +++ b/.dotnet/src/Generated/Completions.cs @@ -0,0 +1,183 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.ClientModel.Primitives.Pipeline; +using System.Threading; +using System.Threading.Tasks; +using OpenAI.Models; + +namespace OpenAI +{ + // Data plane generated sub-client. + /// The Completions sub-client. + public partial class Completions + { + private const string AuthorizationHeader = "Authorization"; + private readonly KeyCredential _keyCredential; + private const string AuthorizationApiKeyPrefix = "Bearer"; + private readonly MessagePipeline _pipeline; + private readonly Uri _endpoint; + + /// The ClientDiagnostics is used to provide tracing support for the client library. + internal TelemetrySource ClientDiagnostics { get; } + + /// The HTTP pipeline for sending and receiving REST requests and responses. + public virtual MessagePipeline Pipeline => _pipeline; + + /// Initializes a new instance of Completions for mocking. + protected Completions() + { + } + + /// Initializes a new instance of Completions. + /// The handler for diagnostic messaging in the client. + /// The HTTP pipeline for sending and receiving REST requests and responses. + /// The key credential to copy. + /// OpenAI Endpoint. + internal Completions(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + { + ClientDiagnostics = clientDiagnostics; + _pipeline = pipeline; + _keyCredential = keyCredential; + _endpoint = endpoint; + } + + /// Creates a completion for the provided prompt and parameters. + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual async Task> CreateCompletionAsync(CreateCompletionRequest createCompletionRequest, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(createCompletionRequest, nameof(createCompletionRequest)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = createCompletionRequest.ToRequestBody(); + Result result = await CreateCompletionAsync(content, context).ConfigureAwait(false); + return Result.FromValue(CreateCompletionResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Creates a completion for the provided prompt and parameters. + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual Result CreateCompletion(CreateCompletionRequest createCompletionRequest, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(createCompletionRequest, nameof(createCompletionRequest)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = createCompletionRequest.ToRequestBody(); + Result result = CreateCompletion(content, context); + return Result.FromValue(CreateCompletionResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Creates a completion for the provided prompt and parameters. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task CreateCompletionAsync(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Completions.CreateCompletion"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateCompletionRequest(content, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Creates a completion for the provided prompt and parameters. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result CreateCompletion(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Completions.CreateCompletion"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateCompletionRequest(content, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + internal PipelineMessage CreateCreateCompletionRequest(RequestBody content, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/completions", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + request.SetHeaderValue("Content-Type", "application/json"); + request.Content = content; + return message; + } + + private static RequestOptions DefaultRequestContext = new RequestOptions(); + internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) + { + if (!cancellationToken.CanBeCanceled) + { + return DefaultRequestContext; + } + + return new RequestOptions() { CancellationToken = cancellationToken }; + } + + private static ResponseErrorClassifier _responseErrorClassifier200; + private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); + } +} diff --git a/.dotnet/src/Generated/Embeddings.cs b/.dotnet/src/Generated/Embeddings.cs new file mode 100644 index 000000000..d42141a8f --- /dev/null +++ b/.dotnet/src/Generated/Embeddings.cs @@ -0,0 +1,183 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.ClientModel.Primitives.Pipeline; +using System.Threading; +using System.Threading.Tasks; +using OpenAI.Models; + +namespace OpenAI +{ + // Data plane generated sub-client. + /// The Embeddings sub-client. + public partial class Embeddings + { + private const string AuthorizationHeader = "Authorization"; + private readonly KeyCredential _keyCredential; + private const string AuthorizationApiKeyPrefix = "Bearer"; + private readonly MessagePipeline _pipeline; + private readonly Uri _endpoint; + + /// The ClientDiagnostics is used to provide tracing support for the client library. + internal TelemetrySource ClientDiagnostics { get; } + + /// The HTTP pipeline for sending and receiving REST requests and responses. + public virtual MessagePipeline Pipeline => _pipeline; + + /// Initializes a new instance of Embeddings for mocking. + protected Embeddings() + { + } + + /// Initializes a new instance of Embeddings. + /// The handler for diagnostic messaging in the client. + /// The HTTP pipeline for sending and receiving REST requests and responses. + /// The key credential to copy. + /// OpenAI Endpoint. + internal Embeddings(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + { + ClientDiagnostics = clientDiagnostics; + _pipeline = pipeline; + _keyCredential = keyCredential; + _endpoint = endpoint; + } + + /// Creates an embedding vector representing the input text. + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual async Task> CreateEmbeddingAsync(CreateEmbeddingRequest embedding, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(embedding, nameof(embedding)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = embedding.ToRequestBody(); + Result result = await CreateEmbeddingAsync(content, context).ConfigureAwait(false); + return Result.FromValue(CreateEmbeddingResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Creates an embedding vector representing the input text. + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual Result CreateEmbedding(CreateEmbeddingRequest embedding, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(embedding, nameof(embedding)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = embedding.ToRequestBody(); + Result result = CreateEmbedding(content, context); + return Result.FromValue(CreateEmbeddingResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Creates an embedding vector representing the input text. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task CreateEmbeddingAsync(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Embeddings.CreateEmbedding"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateEmbeddingRequest(content, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Creates an embedding vector representing the input text. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result CreateEmbedding(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Embeddings.CreateEmbedding"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateEmbeddingRequest(content, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + internal PipelineMessage CreateCreateEmbeddingRequest(RequestBody content, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/embeddings", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + request.SetHeaderValue("Content-Type", "application/json"); + request.Content = content; + return message; + } + + private static RequestOptions DefaultRequestContext = new RequestOptions(); + internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) + { + if (!cancellationToken.CanBeCanceled) + { + return DefaultRequestContext; + } + + return new RequestOptions() { CancellationToken = cancellationToken }; + } + + private static ResponseErrorClassifier _responseErrorClassifier200; + private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); + } +} diff --git a/.dotnet/src/Generated/Files.cs b/.dotnet/src/Generated/Files.cs new file mode 100644 index 000000000..05aa7d834 --- /dev/null +++ b/.dotnet/src/Generated/Files.cs @@ -0,0 +1,683 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.ClientModel.Primitives.Pipeline; +using System.Threading; +using System.Threading.Tasks; +using OpenAI.Models; + +namespace OpenAI +{ + // Data plane generated sub-client. + /// The Files sub-client. + public partial class Files + { + private const string AuthorizationHeader = "Authorization"; + private readonly KeyCredential _keyCredential; + private const string AuthorizationApiKeyPrefix = "Bearer"; + private readonly MessagePipeline _pipeline; + private readonly Uri _endpoint; + + /// The ClientDiagnostics is used to provide tracing support for the client library. + internal TelemetrySource ClientDiagnostics { get; } + + /// The HTTP pipeline for sending and receiving REST requests and responses. + public virtual MessagePipeline Pipeline => _pipeline; + + /// Initializes a new instance of Files for mocking. + protected Files() + { + } + + /// Initializes a new instance of Files. + /// The handler for diagnostic messaging in the client. + /// The HTTP pipeline for sending and receiving REST requests and responses. + /// The key credential to copy. + /// OpenAI Endpoint. + internal Files(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + { + ClientDiagnostics = clientDiagnostics; + _pipeline = pipeline; + _keyCredential = keyCredential; + _endpoint = endpoint; + } + + /// + /// Upload a file that can be used across various endpoints. The size of all the files uploaded by + /// one organization can be up to 100 GB. + /// + /// The size of individual files can be a maximum of 512 MB or 2 million tokens for Assistants. See + /// the [Assistants Tools guide](/docs/assistants/tools) to learn more about the types of files + /// supported. The Fine-tuning API only supports `.jsonl` files. + /// + /// Please [contact us](https://help.openai.com/) if you need to increase these storage limits. + /// + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual async Task> CreateFileAsync(CreateFileRequest file, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(file, nameof(file)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = file.ToRequestBody(); + Result result = await CreateFileAsync(content, context).ConfigureAwait(false); + return Result.FromValue(OpenAIFile.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// Upload a file that can be used across various endpoints. The size of all the files uploaded by + /// one organization can be up to 100 GB. + /// + /// The size of individual files can be a maximum of 512 MB or 2 million tokens for Assistants. See + /// the [Assistants Tools guide](/docs/assistants/tools) to learn more about the types of files + /// supported. The Fine-tuning API only supports `.jsonl` files. + /// + /// Please [contact us](https://help.openai.com/) if you need to increase these storage limits. + /// + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual Result CreateFile(CreateFileRequest file, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(file, nameof(file)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = file.ToRequestBody(); + Result result = CreateFile(content, context); + return Result.FromValue(OpenAIFile.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Upload a file that can be used across various endpoints. The size of all the files uploaded by + /// one organization can be up to 100 GB. + /// + /// The size of individual files can be a maximum of 512 MB or 2 million tokens for Assistants. See + /// the [Assistants Tools guide](/docs/assistants/tools) to learn more about the types of files + /// supported. The Fine-tuning API only supports `.jsonl` files. + /// + /// Please [contact us](https://help.openai.com/) if you need to increase these storage limits. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task CreateFileAsync(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Files.CreateFile"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateFileRequest(content, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Upload a file that can be used across various endpoints. The size of all the files uploaded by + /// one organization can be up to 100 GB. + /// + /// The size of individual files can be a maximum of 512 MB or 2 million tokens for Assistants. See + /// the [Assistants Tools guide](/docs/assistants/tools) to learn more about the types of files + /// supported. The Fine-tuning API only supports `.jsonl` files. + /// + /// Please [contact us](https://help.openai.com/) if you need to increase these storage limits. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result CreateFile(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Files.CreateFile"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateFileRequest(content, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Returns a list of files that belong to the user's organization. + /// Only return files with the given purpose. + /// The cancellation token to use. + public virtual async Task> GetFilesAsync(string purpose = null, CancellationToken cancellationToken = default) + { + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await GetFilesAsync(purpose, context).ConfigureAwait(false); + return Result.FromValue(ListFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Returns a list of files that belong to the user's organization. + /// Only return files with the given purpose. + /// The cancellation token to use. + public virtual Result GetFiles(string purpose = null, CancellationToken cancellationToken = default) + { + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = GetFiles(purpose, context); + return Result.FromValue(ListFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Returns a list of files that belong to the user's organization. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// Only return files with the given purpose. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task GetFilesAsync(string purpose, RequestOptions context) + { + using var scope = ClientDiagnostics.CreateSpan("Files.GetFiles"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetFilesRequest(purpose, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Returns a list of files that belong to the user's organization. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// Only return files with the given purpose. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result GetFiles(string purpose, RequestOptions context) + { + using var scope = ClientDiagnostics.CreateSpan("Files.GetFiles"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetFilesRequest(purpose, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Returns information about a specific file. + /// The ID of the file to use for this request. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual async Task> RetrieveFileAsync(string fileId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await RetrieveFileAsync(fileId, context).ConfigureAwait(false); + return Result.FromValue(OpenAIFile.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Returns information about a specific file. + /// The ID of the file to use for this request. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual Result RetrieveFile(string fileId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = RetrieveFile(fileId, context); + return Result.FromValue(OpenAIFile.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Returns information about a specific file. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the file to use for this request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task RetrieveFileAsync(string fileId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + + using var scope = ClientDiagnostics.CreateSpan("Files.RetrieveFile"); + scope.Start(); + try + { + using PipelineMessage message = CreateRetrieveFileRequest(fileId, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Returns information about a specific file. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the file to use for this request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result RetrieveFile(string fileId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + + using var scope = ClientDiagnostics.CreateSpan("Files.RetrieveFile"); + scope.Start(); + try + { + using PipelineMessage message = CreateRetrieveFileRequest(fileId, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Delete a file. + /// The ID of the file to use for this request. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual async Task> DeleteFileAsync(string fileId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await DeleteFileAsync(fileId, context).ConfigureAwait(false); + return Result.FromValue(DeleteFileResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Delete a file. + /// The ID of the file to use for this request. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual Result DeleteFile(string fileId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = DeleteFile(fileId, context); + return Result.FromValue(DeleteFileResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Delete a file + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the file to use for this request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task DeleteFileAsync(string fileId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + + using var scope = ClientDiagnostics.CreateSpan("Files.DeleteFile"); + scope.Start(); + try + { + using PipelineMessage message = CreateDeleteFileRequest(fileId, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Delete a file + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the file to use for this request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result DeleteFile(string fileId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + + using var scope = ClientDiagnostics.CreateSpan("Files.DeleteFile"); + scope.Start(); + try + { + using PipelineMessage message = CreateDeleteFileRequest(fileId, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Returns the contents of the specified file. + /// The ID of the file to use for this request. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual async Task> DownloadFileAsync(string fileId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await DownloadFileAsync(fileId, context).ConfigureAwait(false); + return Result.FromValue(result.GetRawResponse().Content.ToObjectFromJson(), result.GetRawResponse()); + } + + /// Returns the contents of the specified file. + /// The ID of the file to use for this request. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual Result DownloadFile(string fileId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = DownloadFile(fileId, context); + return Result.FromValue(result.GetRawResponse().Content.ToObjectFromJson(), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Returns the contents of the specified file. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the file to use for this request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task DownloadFileAsync(string fileId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + + using var scope = ClientDiagnostics.CreateSpan("Files.DownloadFile"); + scope.Start(); + try + { + using PipelineMessage message = CreateDownloadFileRequest(fileId, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Returns the contents of the specified file. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the file to use for this request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result DownloadFile(string fileId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + + using var scope = ClientDiagnostics.CreateSpan("Files.DownloadFile"); + scope.Start(); + try + { + using PipelineMessage message = CreateDownloadFileRequest(fileId, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + internal PipelineMessage CreateCreateFileRequest(RequestBody content, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/files", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + request.SetHeaderValue("content-type", "multipart/form-data"); + request.Content = content; + return message; + } + + internal PipelineMessage CreateGetFilesRequest(string purpose, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("GET"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/files", false); + if (purpose != null) + { + uri.AppendQuery("purpose", purpose, true); + } + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + internal PipelineMessage CreateRetrieveFileRequest(string fileId, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("GET"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/files/", false); + uri.AppendPath(fileId, true); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + internal PipelineMessage CreateDeleteFileRequest(string fileId, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("DELETE"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/files/", false); + uri.AppendPath(fileId, true); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + internal PipelineMessage CreateDownloadFileRequest(string fileId, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("GET"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/files/", false); + uri.AppendPath(fileId, true); + uri.AppendPath("/content", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + private static RequestOptions DefaultRequestContext = new RequestOptions(); + internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) + { + if (!cancellationToken.CanBeCanceled) + { + return DefaultRequestContext; + } + + return new RequestOptions() { CancellationToken = cancellationToken }; + } + + private static ResponseErrorClassifier _responseErrorClassifier200; + private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); + } +} diff --git a/.dotnet/src/Generated/FineTunes.cs b/.dotnet/src/Generated/FineTunes.cs new file mode 100644 index 000000000..04c8bae74 --- /dev/null +++ b/.dotnet/src/Generated/FineTunes.cs @@ -0,0 +1,736 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.ClientModel.Primitives.Pipeline; +using System.Threading; +using System.Threading.Tasks; +using OpenAI.Models; + +namespace OpenAI +{ + // Data plane generated sub-client. + /// The FineTunes sub-client. + public partial class FineTunes + { + private const string AuthorizationHeader = "Authorization"; + private readonly KeyCredential _keyCredential; + private const string AuthorizationApiKeyPrefix = "Bearer"; + private readonly MessagePipeline _pipeline; + private readonly Uri _endpoint; + + /// The ClientDiagnostics is used to provide tracing support for the client library. + internal TelemetrySource ClientDiagnostics { get; } + + /// The HTTP pipeline for sending and receiving REST requests and responses. + public virtual MessagePipeline Pipeline => _pipeline; + + /// Initializes a new instance of FineTunes for mocking. + protected FineTunes() + { + } + + /// Initializes a new instance of FineTunes. + /// The handler for diagnostic messaging in the client. + /// The HTTP pipeline for sending and receiving REST requests and responses. + /// The key credential to copy. + /// OpenAI Endpoint. + internal FineTunes(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + { + ClientDiagnostics = clientDiagnostics; + _pipeline = pipeline; + _keyCredential = keyCredential; + _endpoint = endpoint; + } + + /// + /// Creates a job that fine-tunes a specified model from a given dataset. + /// + /// Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete. + /// + /// [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) + /// + /// The to use. + /// The cancellation token to use. + /// is null. + [Obsolete("deprecated")] + public virtual async Task> CreateFineTuneAsync(CreateFineTuneRequest fineTune, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(fineTune, nameof(fineTune)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = fineTune.ToRequestBody(); + Result result = await CreateFineTuneAsync(content, context).ConfigureAwait(false); + return Result.FromValue(FineTune.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// Creates a job that fine-tunes a specified model from a given dataset. + /// + /// Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete. + /// + /// [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) + /// + /// The to use. + /// The cancellation token to use. + /// is null. + [Obsolete("deprecated")] + public virtual Result CreateFineTune(CreateFineTuneRequest fineTune, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(fineTune, nameof(fineTune)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = fineTune.ToRequestBody(); + Result result = CreateFineTune(content, context); + return Result.FromValue(FineTune.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Creates a job that fine-tunes a specified model from a given dataset. + /// + /// Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete. + /// + /// [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + [Obsolete("deprecated")] + public virtual async Task CreateFineTuneAsync(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("FineTunes.CreateFineTune"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateFineTuneRequest(content, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Creates a job that fine-tunes a specified model from a given dataset. + /// + /// Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete. + /// + /// [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + [Obsolete("deprecated")] + public virtual Result CreateFineTune(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("FineTunes.CreateFineTune"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateFineTuneRequest(content, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// List your organization's fine-tuning jobs. + /// The cancellation token to use. + [Obsolete("deprecated")] + public virtual async Task> GetFineTunesAsync(CancellationToken cancellationToken = default) + { + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await GetFineTunesAsync(context).ConfigureAwait(false); + return Result.FromValue(ListFineTunesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// List your organization's fine-tuning jobs. + /// The cancellation token to use. + [Obsolete("deprecated")] + public virtual Result GetFineTunes(CancellationToken cancellationToken = default) + { + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = GetFineTunes(context); + return Result.FromValue(ListFineTunesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] List your organization's fine-tuning jobs + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// Service returned a non-success status code. + /// The response returned from the service. + [Obsolete("deprecated")] + public virtual async Task GetFineTunesAsync(RequestOptions context) + { + using var scope = ClientDiagnostics.CreateSpan("FineTunes.GetFineTunes"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetFineTunesRequest(context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] List your organization's fine-tuning jobs + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// Service returned a non-success status code. + /// The response returned from the service. + [Obsolete("deprecated")] + public virtual Result GetFineTunes(RequestOptions context) + { + using var scope = ClientDiagnostics.CreateSpan("FineTunes.GetFineTunes"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetFineTunesRequest(context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// Gets info about the fine-tune job. + /// + /// [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) + /// + /// The ID of the fine-tune job. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + [Obsolete("deprecated")] + public virtual async Task> RetrieveFineTuneAsync(string fineTuneId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuneId, nameof(fineTuneId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await RetrieveFineTuneAsync(fineTuneId, context).ConfigureAwait(false); + return Result.FromValue(FineTune.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// Gets info about the fine-tune job. + /// + /// [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) + /// + /// The ID of the fine-tune job. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + [Obsolete("deprecated")] + public virtual Result RetrieveFineTune(string fineTuneId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuneId, nameof(fineTuneId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = RetrieveFineTune(fineTuneId, context); + return Result.FromValue(FineTune.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Gets info about the fine-tune job. + /// + /// [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the fine-tune job. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + [Obsolete("deprecated")] + public virtual async Task RetrieveFineTuneAsync(string fineTuneId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuneId, nameof(fineTuneId)); + + using var scope = ClientDiagnostics.CreateSpan("FineTunes.RetrieveFineTune"); + scope.Start(); + try + { + using PipelineMessage message = CreateRetrieveFineTuneRequest(fineTuneId, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Gets info about the fine-tune job. + /// + /// [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the fine-tune job. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + [Obsolete("deprecated")] + public virtual Result RetrieveFineTune(string fineTuneId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuneId, nameof(fineTuneId)); + + using var scope = ClientDiagnostics.CreateSpan("FineTunes.RetrieveFineTune"); + scope.Start(); + try + { + using PipelineMessage message = CreateRetrieveFineTuneRequest(fineTuneId, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Get fine-grained status updates for a fine-tune job. + /// The ID of the fine-tune job to get events for. + /// + /// Whether to stream events for the fine-tune job. If set to true, events will be sent as + /// data-only + /// [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) + /// as they become available. The stream will terminate with a `data: [DONE]` message when the + /// job is finished (succeeded, cancelled, or failed). + /// + /// If set to false, only events generated so far will be returned. + /// + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + [Obsolete("deprecated")] + public virtual async Task> GetFineTuneEventsAsync(string fineTuneId, bool? stream = null, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuneId, nameof(fineTuneId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await GetFineTuneEventsAsync(fineTuneId, stream, context).ConfigureAwait(false); + return Result.FromValue(ListFineTuneEventsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Get fine-grained status updates for a fine-tune job. + /// The ID of the fine-tune job to get events for. + /// + /// Whether to stream events for the fine-tune job. If set to true, events will be sent as + /// data-only + /// [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) + /// as they become available. The stream will terminate with a `data: [DONE]` message when the + /// job is finished (succeeded, cancelled, or failed). + /// + /// If set to false, only events generated so far will be returned. + /// + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + [Obsolete("deprecated")] + public virtual Result GetFineTuneEvents(string fineTuneId, bool? stream = null, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuneId, nameof(fineTuneId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = GetFineTuneEvents(fineTuneId, stream, context); + return Result.FromValue(ListFineTuneEventsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Get fine-grained status updates for a fine-tune job. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the fine-tune job to get events for. + /// + /// Whether to stream events for the fine-tune job. If set to true, events will be sent as + /// data-only + /// [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) + /// as they become available. The stream will terminate with a `data: [DONE]` message when the + /// job is finished (succeeded, cancelled, or failed). + /// + /// If set to false, only events generated so far will be returned. + /// + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + [Obsolete("deprecated")] + public virtual async Task GetFineTuneEventsAsync(string fineTuneId, bool? stream, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuneId, nameof(fineTuneId)); + + using var scope = ClientDiagnostics.CreateSpan("FineTunes.GetFineTuneEvents"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetFineTuneEventsRequest(fineTuneId, stream, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Get fine-grained status updates for a fine-tune job. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the fine-tune job to get events for. + /// + /// Whether to stream events for the fine-tune job. If set to true, events will be sent as + /// data-only + /// [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) + /// as they become available. The stream will terminate with a `data: [DONE]` message when the + /// job is finished (succeeded, cancelled, or failed). + /// + /// If set to false, only events generated so far will be returned. + /// + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + [Obsolete("deprecated")] + public virtual Result GetFineTuneEvents(string fineTuneId, bool? stream, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuneId, nameof(fineTuneId)); + + using var scope = ClientDiagnostics.CreateSpan("FineTunes.GetFineTuneEvents"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetFineTuneEventsRequest(fineTuneId, stream, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Immediately cancel a fine-tune job. + /// The ID of the fine-tune job to cancel. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + [Obsolete("deprecated")] + public virtual async Task> CancelFineTuneAsync(string fineTuneId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuneId, nameof(fineTuneId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await CancelFineTuneAsync(fineTuneId, context).ConfigureAwait(false); + return Result.FromValue(FineTune.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Immediately cancel a fine-tune job. + /// The ID of the fine-tune job to cancel. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + [Obsolete("deprecated")] + public virtual Result CancelFineTune(string fineTuneId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuneId, nameof(fineTuneId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = CancelFineTune(fineTuneId, context); + return Result.FromValue(FineTune.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Immediately cancel a fine-tune job. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the fine-tune job to cancel. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + [Obsolete("deprecated")] + public virtual async Task CancelFineTuneAsync(string fineTuneId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuneId, nameof(fineTuneId)); + + using var scope = ClientDiagnostics.CreateSpan("FineTunes.CancelFineTune"); + scope.Start(); + try + { + using PipelineMessage message = CreateCancelFineTuneRequest(fineTuneId, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Immediately cancel a fine-tune job. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the fine-tune job to cancel. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + [Obsolete("deprecated")] + public virtual Result CancelFineTune(string fineTuneId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuneId, nameof(fineTuneId)); + + using var scope = ClientDiagnostics.CreateSpan("FineTunes.CancelFineTune"); + scope.Start(); + try + { + using PipelineMessage message = CreateCancelFineTuneRequest(fineTuneId, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + internal PipelineMessage CreateCreateFineTuneRequest(RequestBody content, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/fine-tunes", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + request.SetHeaderValue("Content-Type", "application/json"); + request.Content = content; + return message; + } + + internal PipelineMessage CreateGetFineTunesRequest(RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("GET"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/fine-tunes", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + internal PipelineMessage CreateRetrieveFineTuneRequest(string fineTuneId, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("GET"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/fine-tunes/", false); + uri.AppendPath(fineTuneId, true); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + internal PipelineMessage CreateGetFineTuneEventsRequest(string fineTuneId, bool? stream, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("GET"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/fine-tunes/", false); + uri.AppendPath(fineTuneId, true); + uri.AppendPath("/events", false); + if (stream != null) + { + uri.AppendQuery("stream", stream.Value, true); + } + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + internal PipelineMessage CreateCancelFineTuneRequest(string fineTuneId, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/fine-tunes/", false); + uri.AppendPath(fineTuneId, true); + uri.AppendPath("/cancel", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + private static RequestOptions DefaultRequestContext = new RequestOptions(); + internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) + { + if (!cancellationToken.CanBeCanceled) + { + return DefaultRequestContext; + } + + return new RequestOptions() { CancellationToken = cancellationToken }; + } + + private static ResponseErrorClassifier _responseErrorClassifier200; + private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); + } +} diff --git a/.dotnet/src/Generated/FineTuning.cs b/.dotnet/src/Generated/FineTuning.cs new file mode 100644 index 000000000..40f208a6e --- /dev/null +++ b/.dotnet/src/Generated/FineTuning.cs @@ -0,0 +1,55 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.ClientModel.Primitives.Pipeline; +using System.Threading; + +namespace OpenAI +{ + // Data plane generated sub-client. + /// The FineTuning sub-client. + public partial class FineTuning + { + private const string AuthorizationHeader = "Authorization"; + private readonly KeyCredential _keyCredential; + private const string AuthorizationApiKeyPrefix = "Bearer"; + private readonly MessagePipeline _pipeline; + private readonly Uri _endpoint; + + /// The ClientDiagnostics is used to provide tracing support for the client library. + internal TelemetrySource ClientDiagnostics { get; } + + /// The HTTP pipeline for sending and receiving REST requests and responses. + public virtual MessagePipeline Pipeline => _pipeline; + + /// Initializes a new instance of FineTuning for mocking. + protected FineTuning() + { + } + + /// Initializes a new instance of FineTuning. + /// The handler for diagnostic messaging in the client. + /// The HTTP pipeline for sending and receiving REST requests and responses. + /// The key credential to copy. + /// OpenAI Endpoint. + internal FineTuning(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + { + ClientDiagnostics = clientDiagnostics; + _pipeline = pipeline; + _keyCredential = keyCredential; + _endpoint = endpoint; + } + + private FineTuningJobs _cachedFineTuningJobs; + + /// Initializes a new instance of FineTuningJobs. + public virtual FineTuningJobs GetFineTuningJobsClient() + { + return Volatile.Read(ref _cachedFineTuningJobs) ?? Interlocked.CompareExchange(ref _cachedFineTuningJobs, new FineTuningJobs(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedFineTuningJobs; + } + } +} diff --git a/.dotnet/src/Generated/FineTuningJobs.cs b/.dotnet/src/Generated/FineTuningJobs.cs new file mode 100644 index 000000000..669480a3d --- /dev/null +++ b/.dotnet/src/Generated/FineTuningJobs.cs @@ -0,0 +1,710 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.ClientModel.Primitives.Pipeline; +using System.Threading; +using System.Threading.Tasks; +using OpenAI.Models; + +namespace OpenAI +{ + // Data plane generated sub-client. + /// The FineTuningJobs sub-client. + public partial class FineTuningJobs + { + private const string AuthorizationHeader = "Authorization"; + private readonly KeyCredential _keyCredential; + private const string AuthorizationApiKeyPrefix = "Bearer"; + private readonly MessagePipeline _pipeline; + private readonly Uri _endpoint; + + /// The ClientDiagnostics is used to provide tracing support for the client library. + internal TelemetrySource ClientDiagnostics { get; } + + /// The HTTP pipeline for sending and receiving REST requests and responses. + public virtual MessagePipeline Pipeline => _pipeline; + + /// Initializes a new instance of FineTuningJobs for mocking. + protected FineTuningJobs() + { + } + + /// Initializes a new instance of FineTuningJobs. + /// The handler for diagnostic messaging in the client. + /// The HTTP pipeline for sending and receiving REST requests and responses. + /// The key credential to copy. + /// OpenAI Endpoint. + internal FineTuningJobs(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + { + ClientDiagnostics = clientDiagnostics; + _pipeline = pipeline; + _keyCredential = keyCredential; + _endpoint = endpoint; + } + + /// + /// Creates a job that fine-tunes a specified model from a given dataset. + /// + /// Response includes details of the enqueued job including job status and the name of the + /// fine-tuned models once complete. + /// + /// [Learn more about fine-tuning](/docs/guides/fine-tuning) + /// + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual async Task> CreateFineTuningJobAsync(CreateFineTuningJobRequest job, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(job, nameof(job)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = job.ToRequestBody(); + Result result = await CreateFineTuningJobAsync(content, context).ConfigureAwait(false); + return Result.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// Creates a job that fine-tunes a specified model from a given dataset. + /// + /// Response includes details of the enqueued job including job status and the name of the + /// fine-tuned models once complete. + /// + /// [Learn more about fine-tuning](/docs/guides/fine-tuning) + /// + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual Result CreateFineTuningJob(CreateFineTuningJobRequest job, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(job, nameof(job)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = job.ToRequestBody(); + Result result = CreateFineTuningJob(content, context); + return Result.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Creates a job that fine-tunes a specified model from a given dataset. + /// + /// Response includes details of the enqueued job including job status and the name of the + /// fine-tuned models once complete. + /// + /// [Learn more about fine-tuning](/docs/guides/fine-tuning) + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task CreateFineTuningJobAsync(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("FineTuningJobs.CreateFineTuningJob"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateFineTuningJobRequest(content, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Creates a job that fine-tunes a specified model from a given dataset. + /// + /// Response includes details of the enqueued job including job status and the name of the + /// fine-tuned models once complete. + /// + /// [Learn more about fine-tuning](/docs/guides/fine-tuning) + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result CreateFineTuningJob(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("FineTuningJobs.CreateFineTuningJob"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateFineTuningJobRequest(content, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Identifier for the last job from the previous pagination request. + /// Number of fine-tuning jobs to retrieve. + /// The cancellation token to use. + public virtual async Task> GetPaginatedFineTuningJobsAsync(string after = null, long? limit = null, CancellationToken cancellationToken = default) + { + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await GetPaginatedFineTuningJobsAsync(after, limit, context).ConfigureAwait(false); + return Result.FromValue(ListPaginatedFineTuningJobsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Identifier for the last job from the previous pagination request. + /// Number of fine-tuning jobs to retrieve. + /// The cancellation token to use. + public virtual Result GetPaginatedFineTuningJobs(string after = null, long? limit = null, CancellationToken cancellationToken = default) + { + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = GetPaginatedFineTuningJobs(after, limit, context); + return Result.FromValue(ListPaginatedFineTuningJobsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// Identifier for the last job from the previous pagination request. + /// Number of fine-tuning jobs to retrieve. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task GetPaginatedFineTuningJobsAsync(string after, long? limit, RequestOptions context) + { + using var scope = ClientDiagnostics.CreateSpan("FineTuningJobs.GetPaginatedFineTuningJobs"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetPaginatedFineTuningJobsRequest(after, limit, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// Identifier for the last job from the previous pagination request. + /// Number of fine-tuning jobs to retrieve. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result GetPaginatedFineTuningJobs(string after, long? limit, RequestOptions context) + { + using var scope = ClientDiagnostics.CreateSpan("FineTuningJobs.GetPaginatedFineTuningJobs"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetPaginatedFineTuningJobsRequest(after, limit, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// Get info about a fine-tuning job. + /// + /// [Learn more about fine-tuning](/docs/guides/fine-tuning) + /// + /// The to use. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual async Task> RetrieveFineTuningJobAsync(string fineTuningJobId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await RetrieveFineTuningJobAsync(fineTuningJobId, context).ConfigureAwait(false); + return Result.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// Get info about a fine-tuning job. + /// + /// [Learn more about fine-tuning](/docs/guides/fine-tuning) + /// + /// The to use. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual Result RetrieveFineTuningJob(string fineTuningJobId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = RetrieveFineTuningJob(fineTuningJobId, context); + return Result.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Get info about a fine-tuning job. + /// + /// [Learn more about fine-tuning](/docs/guides/fine-tuning) + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The to use. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task RetrieveFineTuningJobAsync(string fineTuningJobId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + + using var scope = ClientDiagnostics.CreateSpan("FineTuningJobs.RetrieveFineTuningJob"); + scope.Start(); + try + { + using PipelineMessage message = CreateRetrieveFineTuningJobRequest(fineTuningJobId, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Get info about a fine-tuning job. + /// + /// [Learn more about fine-tuning](/docs/guides/fine-tuning) + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The to use. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result RetrieveFineTuningJob(string fineTuningJobId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + + using var scope = ClientDiagnostics.CreateSpan("FineTuningJobs.RetrieveFineTuningJob"); + scope.Start(); + try + { + using PipelineMessage message = CreateRetrieveFineTuningJobRequest(fineTuningJobId, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Get status updates for a fine-tuning job. + /// The ID of the fine-tuning job to get events for. + /// Identifier for the last event from the previous pagination request. + /// Number of events to retrieve. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual async Task> GetFineTuningEventsAsync(string fineTuningJobId, string after = null, int? limit = null, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await GetFineTuningEventsAsync(fineTuningJobId, after, limit, context).ConfigureAwait(false); + return Result.FromValue(ListFineTuningJobEventsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Get status updates for a fine-tuning job. + /// The ID of the fine-tuning job to get events for. + /// Identifier for the last event from the previous pagination request. + /// Number of events to retrieve. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual Result GetFineTuningEvents(string fineTuningJobId, string after = null, int? limit = null, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = GetFineTuningEvents(fineTuningJobId, after, limit, context); + return Result.FromValue(ListFineTuningJobEventsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Get status updates for a fine-tuning job. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the fine-tuning job to get events for. + /// Identifier for the last event from the previous pagination request. + /// Number of events to retrieve. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task GetFineTuningEventsAsync(string fineTuningJobId, string after, int? limit, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + + using var scope = ClientDiagnostics.CreateSpan("FineTuningJobs.GetFineTuningEvents"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetFineTuningEventsRequest(fineTuningJobId, after, limit, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Get status updates for a fine-tuning job. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the fine-tuning job to get events for. + /// Identifier for the last event from the previous pagination request. + /// Number of events to retrieve. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result GetFineTuningEvents(string fineTuningJobId, string after, int? limit, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + + using var scope = ClientDiagnostics.CreateSpan("FineTuningJobs.GetFineTuningEvents"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetFineTuningEventsRequest(fineTuningJobId, after, limit, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Immediately cancel a fine-tune job. + /// The ID of the fine-tuning job to cancel. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual async Task> CancelFineTuningJobAsync(string fineTuningJobId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await CancelFineTuningJobAsync(fineTuningJobId, context).ConfigureAwait(false); + return Result.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Immediately cancel a fine-tune job. + /// The ID of the fine-tuning job to cancel. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual Result CancelFineTuningJob(string fineTuningJobId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = CancelFineTuningJob(fineTuningJobId, context); + return Result.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Immediately cancel a fine-tune job. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the fine-tuning job to cancel. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task CancelFineTuningJobAsync(string fineTuningJobId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + + using var scope = ClientDiagnostics.CreateSpan("FineTuningJobs.CancelFineTuningJob"); + scope.Start(); + try + { + using PipelineMessage message = CreateCancelFineTuningJobRequest(fineTuningJobId, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Immediately cancel a fine-tune job. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the fine-tuning job to cancel. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result CancelFineTuningJob(string fineTuningJobId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + + using var scope = ClientDiagnostics.CreateSpan("FineTuningJobs.CancelFineTuningJob"); + scope.Start(); + try + { + using PipelineMessage message = CreateCancelFineTuningJobRequest(fineTuningJobId, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + internal PipelineMessage CreateCreateFineTuningJobRequest(RequestBody content, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/fine_tuning/jobs", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + request.SetHeaderValue("Content-Type", "application/json"); + request.Content = content; + return message; + } + + internal PipelineMessage CreateGetPaginatedFineTuningJobsRequest(string after, long? limit, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("GET"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/fine_tuning/jobs", false); + if (after != null) + { + uri.AppendQuery("after", after, true); + } + if (limit != null) + { + uri.AppendQuery("limit", limit.Value, true); + } + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + internal PipelineMessage CreateRetrieveFineTuningJobRequest(string fineTuningJobId, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("GET"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/fine_tuning/jobs/", false); + uri.AppendPath(fineTuningJobId, true); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + internal PipelineMessage CreateGetFineTuningEventsRequest(string fineTuningJobId, string after, int? limit, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("GET"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/fine_tuning/jobs/", false); + uri.AppendPath(fineTuningJobId, true); + uri.AppendPath("/events", false); + if (after != null) + { + uri.AppendQuery("after", after, true); + } + if (limit != null) + { + uri.AppendQuery("limit", limit.Value, true); + } + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + internal PipelineMessage CreateCancelFineTuningJobRequest(string fineTuningJobId, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/fine_tuning/jobs/", false); + uri.AppendPath(fineTuningJobId, true); + uri.AppendPath("/cancel", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + private static RequestOptions DefaultRequestContext = new RequestOptions(); + internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) + { + if (!cancellationToken.CanBeCanceled) + { + return DefaultRequestContext; + } + + return new RequestOptions() { CancellationToken = cancellationToken }; + } + + private static ResponseErrorClassifier _responseErrorClassifier200; + private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); + } +} diff --git a/.dotnet/src/Generated/Images.cs b/.dotnet/src/Generated/Images.cs new file mode 100644 index 000000000..a3de80e0b --- /dev/null +++ b/.dotnet/src/Generated/Images.cs @@ -0,0 +1,421 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.ClientModel.Primitives.Pipeline; +using System.Threading; +using System.Threading.Tasks; +using OpenAI.Models; + +namespace OpenAI +{ + // Data plane generated sub-client. + /// The Images sub-client. + public partial class Images + { + private const string AuthorizationHeader = "Authorization"; + private readonly KeyCredential _keyCredential; + private const string AuthorizationApiKeyPrefix = "Bearer"; + private readonly MessagePipeline _pipeline; + private readonly Uri _endpoint; + + /// The ClientDiagnostics is used to provide tracing support for the client library. + internal TelemetrySource ClientDiagnostics { get; } + + /// The HTTP pipeline for sending and receiving REST requests and responses. + public virtual MessagePipeline Pipeline => _pipeline; + + /// Initializes a new instance of Images for mocking. + protected Images() + { + } + + /// Initializes a new instance of Images. + /// The handler for diagnostic messaging in the client. + /// The HTTP pipeline for sending and receiving REST requests and responses. + /// The key credential to copy. + /// OpenAI Endpoint. + internal Images(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + { + ClientDiagnostics = clientDiagnostics; + _pipeline = pipeline; + _keyCredential = keyCredential; + _endpoint = endpoint; + } + + /// Creates an image given a prompt. + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual async Task> CreateImageAsync(CreateImageRequest image, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(image, nameof(image)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = image.ToRequestBody(); + Result result = await CreateImageAsync(content, context).ConfigureAwait(false); + return Result.FromValue(ImagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Creates an image given a prompt. + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual Result CreateImage(CreateImageRequest image, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(image, nameof(image)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = image.ToRequestBody(); + Result result = CreateImage(content, context); + return Result.FromValue(ImagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Creates an image given a prompt + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task CreateImageAsync(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Images.CreateImage"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateImageRequest(content, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Creates an image given a prompt + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result CreateImage(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Images.CreateImage"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateImageRequest(content, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Creates an edited or extended image given an original image and a prompt. + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual async Task> CreateImageEditAsync(CreateImageEditRequest image, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(image, nameof(image)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = image.ToRequestBody(); + Result result = await CreateImageEditAsync(content, context).ConfigureAwait(false); + return Result.FromValue(ImagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Creates an edited or extended image given an original image and a prompt. + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual Result CreateImageEdit(CreateImageEditRequest image, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(image, nameof(image)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = image.ToRequestBody(); + Result result = CreateImageEdit(content, context); + return Result.FromValue(ImagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Creates an edited or extended image given an original image and a prompt. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task CreateImageEditAsync(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Images.CreateImageEdit"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateImageEditRequest(content, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Creates an edited or extended image given an original image and a prompt. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result CreateImageEdit(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Images.CreateImageEdit"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateImageEditRequest(content, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Creates an edited or extended image given an original image and a prompt. + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual async Task> CreateImageVariationAsync(CreateImageVariationRequest image, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(image, nameof(image)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = image.ToRequestBody(); + Result result = await CreateImageVariationAsync(content, context).ConfigureAwait(false); + return Result.FromValue(ImagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Creates an edited or extended image given an original image and a prompt. + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual Result CreateImageVariation(CreateImageVariationRequest image, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(image, nameof(image)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = image.ToRequestBody(); + Result result = CreateImageVariation(content, context); + return Result.FromValue(ImagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Creates an edited or extended image given an original image and a prompt. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task CreateImageVariationAsync(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Images.CreateImageVariation"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateImageVariationRequest(content, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Creates an edited or extended image given an original image and a prompt. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result CreateImageVariation(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Images.CreateImageVariation"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateImageVariationRequest(content, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + internal PipelineMessage CreateCreateImageRequest(RequestBody content, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/images/generations", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + request.SetHeaderValue("Content-Type", "application/json"); + request.Content = content; + return message; + } + + internal PipelineMessage CreateCreateImageEditRequest(RequestBody content, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/images/edits", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + request.SetHeaderValue("content-type", "multipart/form-data"); + request.Content = content; + return message; + } + + internal PipelineMessage CreateCreateImageVariationRequest(RequestBody content, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/images/variations", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + request.SetHeaderValue("content-type", "multipart/form-data"); + request.Content = content; + return message; + } + + private static RequestOptions DefaultRequestContext = new RequestOptions(); + internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) + { + if (!cancellationToken.CanBeCanceled) + { + return DefaultRequestContext; + } + + return new RequestOptions() { CancellationToken = cancellationToken }; + } + + private static ResponseErrorClassifier _responseErrorClassifier200; + private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); + } +} diff --git a/.dotnet/src/Generated/Messages.cs b/.dotnet/src/Generated/Messages.cs new file mode 100644 index 000000000..1ca608801 --- /dev/null +++ b/.dotnet/src/Generated/Messages.cs @@ -0,0 +1,1037 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.ClientModel.Primitives.Pipeline; +using System.Threading; +using System.Threading.Tasks; +using OpenAI.Models; + +namespace OpenAI +{ + // Data plane generated sub-client. + /// The Messages sub-client. + public partial class Messages + { + private const string AuthorizationHeader = "Authorization"; + private readonly KeyCredential _keyCredential; + private const string AuthorizationApiKeyPrefix = "Bearer"; + private readonly MessagePipeline _pipeline; + private readonly Uri _endpoint; + + /// The ClientDiagnostics is used to provide tracing support for the client library. + internal TelemetrySource ClientDiagnostics { get; } + + /// The HTTP pipeline for sending and receiving REST requests and responses. + public virtual MessagePipeline Pipeline => _pipeline; + + /// Initializes a new instance of Messages for mocking. + protected Messages() + { + } + + /// Initializes a new instance of Messages. + /// The handler for diagnostic messaging in the client. + /// The HTTP pipeline for sending and receiving REST requests and responses. + /// The key credential to copy. + /// OpenAI Endpoint. + internal Messages(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + { + ClientDiagnostics = clientDiagnostics; + _pipeline = pipeline; + _keyCredential = keyCredential; + _endpoint = endpoint; + } + + /// Create a message. + /// The ID of the [thread](/docs/api-reference/threads) to create a message for. + /// The to use. + /// The cancellation token to use. + /// or is null. + /// is an empty string, and was expected to be non-empty. + public virtual async Task> CreateMessageAsync(string threadId, CreateMessageRequest message, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNull(message, nameof(message)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = message.ToRequestBody(); + Result result = await CreateMessageAsync(threadId, content, context).ConfigureAwait(false); + return Result.FromValue(MessageObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Create a message. + /// The ID of the [thread](/docs/api-reference/threads) to create a message for. + /// The to use. + /// The cancellation token to use. + /// or is null. + /// is an empty string, and was expected to be non-empty. + public virtual Result CreateMessage(string threadId, CreateMessageRequest message, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNull(message, nameof(message)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = message.ToRequestBody(); + Result result = CreateMessage(threadId, content, context); + return Result.FromValue(MessageObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Create a message. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the [thread](/docs/api-reference/threads) to create a message for. + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task CreateMessageAsync(string threadId, RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Messages.CreateMessage"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateMessageRequest(threadId, content, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Create a message. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the [thread](/docs/api-reference/threads) to create a message for. + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result CreateMessage(string threadId, RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Messages.CreateMessage"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateMessageRequest(threadId, content, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Returns a list of messages for a given thread. + /// The ID of the [thread](/docs/api-reference/threads) the messages belong to. + /// + /// A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + /// default is 20. + /// + /// + /// Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + /// for descending order. + /// + /// + /// A cursor for use in pagination. `after` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include after=obj_foo in order to fetch the next page of the list. + /// + /// + /// A cursor for use in pagination. `before` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. + /// + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual async Task> GetMessagesAsync(string threadId, int? limit = null, ListOrder? order = null, string after = null, string before = null, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await GetMessagesAsync(threadId, limit, order?.ToString(), after, before, context).ConfigureAwait(false); + return Result.FromValue(ListMessagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Returns a list of messages for a given thread. + /// The ID of the [thread](/docs/api-reference/threads) the messages belong to. + /// + /// A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + /// default is 20. + /// + /// + /// Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + /// for descending order. + /// + /// + /// A cursor for use in pagination. `after` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include after=obj_foo in order to fetch the next page of the list. + /// + /// + /// A cursor for use in pagination. `before` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. + /// + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual Result GetMessages(string threadId, int? limit = null, ListOrder? order = null, string after = null, string before = null, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = GetMessages(threadId, limit, order?.ToString(), after, before, context); + return Result.FromValue(ListMessagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Returns a list of messages for a given thread. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the [thread](/docs/api-reference/threads) the messages belong to. + /// + /// A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + /// default is 20. + /// + /// + /// Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + /// for descending order. Allowed values: "asc" | "desc" + /// + /// + /// A cursor for use in pagination. `after` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include after=obj_foo in order to fetch the next page of the list. + /// + /// + /// A cursor for use in pagination. `before` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. + /// + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task GetMessagesAsync(string threadId, int? limit, string order, string after, string before, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + + using var scope = ClientDiagnostics.CreateSpan("Messages.GetMessages"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetMessagesRequest(threadId, limit, order, after, before, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Returns a list of messages for a given thread. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the [thread](/docs/api-reference/threads) the messages belong to. + /// + /// A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + /// default is 20. + /// + /// + /// Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + /// for descending order. Allowed values: "asc" | "desc" + /// + /// + /// A cursor for use in pagination. `after` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include after=obj_foo in order to fetch the next page of the list. + /// + /// + /// A cursor for use in pagination. `before` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. + /// + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result GetMessages(string threadId, int? limit, string order, string after, string before, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + + using var scope = ClientDiagnostics.CreateSpan("Messages.GetMessages"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetMessagesRequest(threadId, limit, order, after, before, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Retrieve a message. + /// The ID of the [thread](/docs/api-reference/threads) to which this message belongs. + /// The ID of the message to retrieve. + /// The cancellation token to use. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + public virtual async Task> GetMessageAsync(string threadId, string messageId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await GetMessageAsync(threadId, messageId, context).ConfigureAwait(false); + return Result.FromValue(MessageObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Retrieve a message. + /// The ID of the [thread](/docs/api-reference/threads) to which this message belongs. + /// The ID of the message to retrieve. + /// The cancellation token to use. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + public virtual Result GetMessage(string threadId, string messageId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = GetMessage(threadId, messageId, context); + return Result.FromValue(MessageObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Retrieve a message. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the [thread](/docs/api-reference/threads) to which this message belongs. + /// The ID of the message to retrieve. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task GetMessageAsync(string threadId, string messageId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); + + using var scope = ClientDiagnostics.CreateSpan("Messages.GetMessage"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetMessageRequest(threadId, messageId, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Retrieve a message. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the [thread](/docs/api-reference/threads) to which this message belongs. + /// The ID of the message to retrieve. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result GetMessage(string threadId, string messageId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); + + using var scope = ClientDiagnostics.CreateSpan("Messages.GetMessage"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetMessageRequest(threadId, messageId, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Modifies a message. + /// The ID of the thread to which this message belongs. + /// The ID of the message to modify. + /// The to use. + /// The cancellation token to use. + /// , or is null. + /// or is an empty string, and was expected to be non-empty. + public virtual async Task> ModifyMessageAsync(string threadId, string messageId, ModifyMessageRequest message, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); + ClientUtilities.AssertNotNull(message, nameof(message)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = message.ToRequestBody(); + Result result = await ModifyMessageAsync(threadId, messageId, content, context).ConfigureAwait(false); + return Result.FromValue(MessageObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Modifies a message. + /// The ID of the thread to which this message belongs. + /// The ID of the message to modify. + /// The to use. + /// The cancellation token to use. + /// , or is null. + /// or is an empty string, and was expected to be non-empty. + public virtual Result ModifyMessage(string threadId, string messageId, ModifyMessageRequest message, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); + ClientUtilities.AssertNotNull(message, nameof(message)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = message.ToRequestBody(); + Result result = ModifyMessage(threadId, messageId, content, context); + return Result.FromValue(MessageObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Modifies a message. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the thread to which this message belongs. + /// The ID of the message to modify. + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// , or is null. + /// or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task ModifyMessageAsync(string threadId, string messageId, RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Messages.ModifyMessage"); + scope.Start(); + try + { + using PipelineMessage message = CreateModifyMessageRequest(threadId, messageId, content, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Modifies a message. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the thread to which this message belongs. + /// The ID of the message to modify. + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// , or is null. + /// or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result ModifyMessage(string threadId, string messageId, RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Messages.ModifyMessage"); + scope.Start(); + try + { + using PipelineMessage message = CreateModifyMessageRequest(threadId, messageId, content, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Returns a list of message files. + /// The ID of the thread that the message and files belong to. + /// The ID of the message that the files belongs to. + /// + /// A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + /// default is 20. + /// + /// + /// Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + /// for descending order. + /// + /// + /// A cursor for use in pagination. `after` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include after=obj_foo in order to fetch the next page of the list. + /// + /// + /// A cursor for use in pagination. `before` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. + /// + /// The cancellation token to use. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + public virtual async Task> GetMessageFilesAsync(string threadId, string messageId, int? limit = null, ListOrder? order = null, string after = null, string before = null, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await GetMessageFilesAsync(threadId, messageId, limit, order?.ToString(), after, before, context).ConfigureAwait(false); + return Result.FromValue(ListMessageFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Returns a list of message files. + /// The ID of the thread that the message and files belong to. + /// The ID of the message that the files belongs to. + /// + /// A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + /// default is 20. + /// + /// + /// Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + /// for descending order. + /// + /// + /// A cursor for use in pagination. `after` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include after=obj_foo in order to fetch the next page of the list. + /// + /// + /// A cursor for use in pagination. `before` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. + /// + /// The cancellation token to use. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + public virtual Result GetMessageFiles(string threadId, string messageId, int? limit = null, ListOrder? order = null, string after = null, string before = null, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = GetMessageFiles(threadId, messageId, limit, order?.ToString(), after, before, context); + return Result.FromValue(ListMessageFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Returns a list of message files. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the thread that the message and files belong to. + /// The ID of the message that the files belongs to. + /// + /// A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + /// default is 20. + /// + /// + /// Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + /// for descending order. Allowed values: "asc" | "desc" + /// + /// + /// A cursor for use in pagination. `after` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include after=obj_foo in order to fetch the next page of the list. + /// + /// + /// A cursor for use in pagination. `before` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. + /// + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task GetMessageFilesAsync(string threadId, string messageId, int? limit, string order, string after, string before, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); + + using var scope = ClientDiagnostics.CreateSpan("Messages.GetMessageFiles"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetMessageFilesRequest(threadId, messageId, limit, order, after, before, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Returns a list of message files. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the thread that the message and files belong to. + /// The ID of the message that the files belongs to. + /// + /// A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + /// default is 20. + /// + /// + /// Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + /// for descending order. Allowed values: "asc" | "desc" + /// + /// + /// A cursor for use in pagination. `after` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include after=obj_foo in order to fetch the next page of the list. + /// + /// + /// A cursor for use in pagination. `before` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. + /// + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result GetMessageFiles(string threadId, string messageId, int? limit, string order, string after, string before, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); + + using var scope = ClientDiagnostics.CreateSpan("Messages.GetMessageFiles"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetMessageFilesRequest(threadId, messageId, limit, order, after, before, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Retrieves a message file. + /// The ID of the thread to which the message and File belong. + /// The ID of the message the file belongs to. + /// The ID of the file being retrieved. + /// The cancellation token to use. + /// , or is null. + /// , or is an empty string, and was expected to be non-empty. + public virtual async Task> GetMessageFileAsync(string threadId, string messageId, string fileId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); + ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await GetMessageFileAsync(threadId, messageId, fileId, context).ConfigureAwait(false); + return Result.FromValue(MessageFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Retrieves a message file. + /// The ID of the thread to which the message and File belong. + /// The ID of the message the file belongs to. + /// The ID of the file being retrieved. + /// The cancellation token to use. + /// , or is null. + /// , or is an empty string, and was expected to be non-empty. + public virtual Result GetMessageFile(string threadId, string messageId, string fileId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); + ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = GetMessageFile(threadId, messageId, fileId, context); + return Result.FromValue(MessageFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Retrieves a message file. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the thread to which the message and File belong. + /// The ID of the message the file belongs to. + /// The ID of the file being retrieved. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// , or is null. + /// , or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task GetMessageFileAsync(string threadId, string messageId, string fileId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); + ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + + using var scope = ClientDiagnostics.CreateSpan("Messages.GetMessageFile"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetMessageFileRequest(threadId, messageId, fileId, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Retrieves a message file. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the thread to which the message and File belong. + /// The ID of the message the file belongs to. + /// The ID of the file being retrieved. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// , or is null. + /// , or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result GetMessageFile(string threadId, string messageId, string fileId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); + ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + + using var scope = ClientDiagnostics.CreateSpan("Messages.GetMessageFile"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetMessageFileRequest(threadId, messageId, fileId, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + internal PipelineMessage CreateCreateMessageRequest(string threadId, RequestBody content, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/threads/", false); + uri.AppendPath(threadId, true); + uri.AppendPath("/messages", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + request.SetHeaderValue("Content-Type", "application/json"); + request.Content = content; + return message; + } + + internal PipelineMessage CreateGetMessagesRequest(string threadId, int? limit, string order, string after, string before, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("GET"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/threads/", false); + uri.AppendPath(threadId, true); + uri.AppendPath("/messages", false); + if (limit != null) + { + uri.AppendQuery("limit", limit.Value, true); + } + if (order != null) + { + uri.AppendQuery("order", order, true); + } + if (after != null) + { + uri.AppendQuery("after", after, true); + } + if (before != null) + { + uri.AppendQuery("before", before, true); + } + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + internal PipelineMessage CreateGetMessageRequest(string threadId, string messageId, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("GET"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/threads/", false); + uri.AppendPath(threadId, true); + uri.AppendPath("/messages/", false); + uri.AppendPath(messageId, true); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + internal PipelineMessage CreateModifyMessageRequest(string threadId, string messageId, RequestBody content, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/threads/", false); + uri.AppendPath(threadId, true); + uri.AppendPath("/messages/", false); + uri.AppendPath(messageId, true); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + request.SetHeaderValue("Content-Type", "application/json"); + request.Content = content; + return message; + } + + internal PipelineMessage CreateGetMessageFilesRequest(string threadId, string messageId, int? limit, string order, string after, string before, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("GET"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/threads/", false); + uri.AppendPath(threadId, true); + uri.AppendPath("/messages/", false); + uri.AppendPath(messageId, true); + uri.AppendPath("/files", false); + if (limit != null) + { + uri.AppendQuery("limit", limit.Value, true); + } + if (order != null) + { + uri.AppendQuery("order", order, true); + } + if (after != null) + { + uri.AppendQuery("after", after, true); + } + if (before != null) + { + uri.AppendQuery("before", before, true); + } + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + internal PipelineMessage CreateGetMessageFileRequest(string threadId, string messageId, string fileId, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("GET"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/threads/", false); + uri.AppendPath(threadId, true); + uri.AppendPath("/messages/", false); + uri.AppendPath(messageId, true); + uri.AppendPath("/files/", false); + uri.AppendPath(fileId, true); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + private static RequestOptions DefaultRequestContext = new RequestOptions(); + internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) + { + if (!cancellationToken.CanBeCanceled) + { + return DefaultRequestContext; + } + + return new RequestOptions() { CancellationToken = cancellationToken }; + } + + private static ResponseErrorClassifier _responseErrorClassifier200; + private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); + } +} diff --git a/.dotnet/src/Generated/Models/AssistantFileObject.Serialization.cs b/.dotnet/src/Generated/Models/AssistantFileObject.Serialization.cs new file mode 100644 index 000000000..74ad1f256 --- /dev/null +++ b/.dotnet/src/Generated/Models/AssistantFileObject.Serialization.cs @@ -0,0 +1,156 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class AssistantFileObject : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(AssistantFileObject)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("id"u8); + writer.WriteStringValue(Id); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + writer.WritePropertyName("created_at"u8); + writer.WriteNumberValue(CreatedAt, "U"); + writer.WritePropertyName("assistant_id"u8); + writer.WriteStringValue(AssistantId); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + AssistantFileObject IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(AssistantFileObject)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeAssistantFileObject(document.RootElement, options); + } + + internal static AssistantFileObject DeserializeAssistantFileObject(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string id = default; + AssistantFileObjectObject @object = default; + DateTimeOffset createdAt = default; + string assistantId = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetString(); + continue; + } + if (property.NameEquals("object"u8)) + { + @object = new AssistantFileObjectObject(property.Value.GetString()); + continue; + } + if (property.NameEquals("created_at"u8)) + { + createdAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); + continue; + } + if (property.NameEquals("assistant_id"u8)) + { + assistantId = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new AssistantFileObject(id, @object, createdAt, assistantId, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(AssistantFileObject)} does not support '{options.Format}' format."); + } + } + + AssistantFileObject IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeAssistantFileObject(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(AssistantFileObject)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static AssistantFileObject FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeAssistantFileObject(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/AssistantFileObject.cs b/.dotnet/src/Generated/Models/AssistantFileObject.cs new file mode 100644 index 000000000..21aef1f7b --- /dev/null +++ b/.dotnet/src/Generated/Models/AssistantFileObject.cs @@ -0,0 +1,91 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// A list of [Files](/docs/api-reference/files) attached to an `assistant`. + public partial class AssistantFileObject + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The identifier, which can be referenced in API endpoints. + /// The Unix timestamp (in seconds) for when the assistant file was created. + /// The assistant ID that the file is attached to. + /// or is null. + internal AssistantFileObject(string id, DateTimeOffset createdAt, string assistantId) + { + ClientUtilities.AssertNotNull(id, nameof(id)); + ClientUtilities.AssertNotNull(assistantId, nameof(assistantId)); + + Id = id; + CreatedAt = createdAt; + AssistantId = assistantId; + } + + /// Initializes a new instance of . + /// The identifier, which can be referenced in API endpoints. + /// The object type, which is always `assistant.file`. + /// The Unix timestamp (in seconds) for when the assistant file was created. + /// The assistant ID that the file is attached to. + /// Keeps track of any properties unknown to the library. + internal AssistantFileObject(string id, AssistantFileObjectObject @object, DateTimeOffset createdAt, string assistantId, IDictionary serializedAdditionalRawData) + { + Id = id; + Object = @object; + CreatedAt = createdAt; + AssistantId = assistantId; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal AssistantFileObject() + { + } + + /// The identifier, which can be referenced in API endpoints. + public string Id { get; } + /// The object type, which is always `assistant.file`. + public AssistantFileObjectObject Object { get; } = AssistantFileObjectObject.AssistantFile; + + /// The Unix timestamp (in seconds) for when the assistant file was created. + public DateTimeOffset CreatedAt { get; } + /// The assistant ID that the file is attached to. + public string AssistantId { get; } + } +} diff --git a/.dotnet/src/Generated/Models/AssistantFileObjectObject.cs b/.dotnet/src/Generated/Models/AssistantFileObjectObject.cs new file mode 100644 index 000000000..d9b017682 --- /dev/null +++ b/.dotnet/src/Generated/Models/AssistantFileObjectObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The AssistantFileObject_object. + public readonly partial struct AssistantFileObjectObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public AssistantFileObjectObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string AssistantFileValue = "assistant.file"; + + /// assistant.file. + public static AssistantFileObjectObject AssistantFile { get; } = new AssistantFileObjectObject(AssistantFileValue); + /// Determines if two values are the same. + public static bool operator ==(AssistantFileObjectObject left, AssistantFileObjectObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(AssistantFileObjectObject left, AssistantFileObjectObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator AssistantFileObjectObject(string value) => new AssistantFileObjectObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is AssistantFileObjectObject other && Equals(other); + /// + public bool Equals(AssistantFileObjectObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/AssistantObject.Serialization.cs b/.dotnet/src/Generated/Models/AssistantObject.Serialization.cs new file mode 100644 index 000000000..3676fb26d --- /dev/null +++ b/.dotnet/src/Generated/Models/AssistantObject.Serialization.cs @@ -0,0 +1,302 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class AssistantObject : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(AssistantObject)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("id"u8); + writer.WriteStringValue(Id); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + writer.WritePropertyName("created_at"u8); + writer.WriteNumberValue(CreatedAt, "U"); + if (Name != null) + { + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + } + else + { + writer.WriteNull("name"); + } + if (Description != null) + { + writer.WritePropertyName("description"u8); + writer.WriteStringValue(Description); + } + else + { + writer.WriteNull("description"); + } + writer.WritePropertyName("model"u8); + writer.WriteStringValue(Model); + if (Instructions != null) + { + writer.WritePropertyName("instructions"u8); + writer.WriteStringValue(Instructions); + } + else + { + writer.WriteNull("instructions"); + } + writer.WritePropertyName("tools"u8); + writer.WriteStartArray(); + foreach (var item in Tools) + { + if (item == null) + { + writer.WriteNullValue(); + continue; + } +#if NET6_0_OR_GREATER + writer.WriteRawValue(item); +#else + using (JsonDocument document = JsonDocument.Parse(item)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + writer.WriteEndArray(); + writer.WritePropertyName("file_ids"u8); + writer.WriteStartArray(); + foreach (var item in FileIds) + { + writer.WriteStringValue(item); + } + writer.WriteEndArray(); + if (Metadata != null && OptionalProperty.IsCollectionDefined(Metadata)) + { + writer.WritePropertyName("metadata"u8); + writer.WriteStartObject(); + foreach (var item in Metadata) + { + writer.WritePropertyName(item.Key); + writer.WriteStringValue(item.Value); + } + writer.WriteEndObject(); + } + else + { + writer.WriteNull("metadata"); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + AssistantObject IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(AssistantObject)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeAssistantObject(document.RootElement, options); + } + + internal static AssistantObject DeserializeAssistantObject(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string id = default; + AssistantObjectObject @object = default; + DateTimeOffset createdAt = default; + string name = default; + string description = default; + string model = default; + string instructions = default; + IReadOnlyList tools = default; + IReadOnlyList fileIds = default; + IReadOnlyDictionary metadata = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetString(); + continue; + } + if (property.NameEquals("object"u8)) + { + @object = new AssistantObjectObject(property.Value.GetString()); + continue; + } + if (property.NameEquals("created_at"u8)) + { + createdAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); + continue; + } + if (property.NameEquals("name"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + name = null; + continue; + } + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("description"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + description = null; + continue; + } + description = property.Value.GetString(); + continue; + } + if (property.NameEquals("model"u8)) + { + model = property.Value.GetString(); + continue; + } + if (property.NameEquals("instructions"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + instructions = null; + continue; + } + instructions = property.Value.GetString(); + continue; + } + if (property.NameEquals("tools"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + if (item.ValueKind == JsonValueKind.Null) + { + array.Add(null); + } + else + { + array.Add(BinaryData.FromString(item.GetRawText())); + } + } + tools = array; + continue; + } + if (property.NameEquals("file_ids"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(item.GetString()); + } + fileIds = array; + continue; + } + if (property.NameEquals("metadata"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + metadata = new OptionalDictionary(); + continue; + } + Dictionary dictionary = new Dictionary(); + foreach (var property0 in property.Value.EnumerateObject()) + { + dictionary.Add(property0.Name, property0.Value.GetString()); + } + metadata = dictionary; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new AssistantObject(id, @object, createdAt, name, description, model, instructions, tools, fileIds, metadata, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(AssistantObject)} does not support '{options.Format}' format."); + } + } + + AssistantObject IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeAssistantObject(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(AssistantObject)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static AssistantObject FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeAssistantObject(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/AssistantObject.cs b/.dotnet/src/Generated/Models/AssistantObject.cs new file mode 100644 index 000000000..4816bc339 --- /dev/null +++ b/.dotnet/src/Generated/Models/AssistantObject.cs @@ -0,0 +1,202 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// Represents an `assistant` that can call the model and use tools. + public partial class AssistantObject + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The identifier, which can be referenced in API endpoints. + /// The Unix timestamp (in seconds) for when the assistant was created. + /// The name of the assistant. The maximum length is 256 characters. + /// The description of the assistant. The maximum length is 512 characters. + /// + /// ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + /// see all of your available models, or see our [Model overview](/docs/models/overview) for + /// descriptions of them. + /// + /// The system instructions that the assistant uses. The maximum length is 32768 characters. + /// + /// A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. + /// Tools can be of types `code_interpreter`, `retrieval`, or `function`. + /// + /// + /// A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a + /// maximum of 20 files attached to the assistant. Files are ordered by their creation date in + /// ascending order. + /// + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// , , or is null. + internal AssistantObject(string id, DateTimeOffset createdAt, string name, string description, string model, string instructions, IEnumerable tools, IEnumerable fileIds, IReadOnlyDictionary metadata) + { + ClientUtilities.AssertNotNull(id, nameof(id)); + ClientUtilities.AssertNotNull(model, nameof(model)); + ClientUtilities.AssertNotNull(tools, nameof(tools)); + ClientUtilities.AssertNotNull(fileIds, nameof(fileIds)); + + Id = id; + CreatedAt = createdAt; + Name = name; + Description = description; + Model = model; + Instructions = instructions; + Tools = tools.ToList(); + FileIds = fileIds.ToList(); + Metadata = metadata; + } + + /// Initializes a new instance of . + /// The identifier, which can be referenced in API endpoints. + /// The object type, which is always `assistant`. + /// The Unix timestamp (in seconds) for when the assistant was created. + /// The name of the assistant. The maximum length is 256 characters. + /// The description of the assistant. The maximum length is 512 characters. + /// + /// ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + /// see all of your available models, or see our [Model overview](/docs/models/overview) for + /// descriptions of them. + /// + /// The system instructions that the assistant uses. The maximum length is 32768 characters. + /// + /// A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. + /// Tools can be of types `code_interpreter`, `retrieval`, or `function`. + /// + /// + /// A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a + /// maximum of 20 files attached to the assistant. Files are ordered by their creation date in + /// ascending order. + /// + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// Keeps track of any properties unknown to the library. + internal AssistantObject(string id, AssistantObjectObject @object, DateTimeOffset createdAt, string name, string description, string model, string instructions, IReadOnlyList tools, IReadOnlyList fileIds, IReadOnlyDictionary metadata, IDictionary serializedAdditionalRawData) + { + Id = id; + Object = @object; + CreatedAt = createdAt; + Name = name; + Description = description; + Model = model; + Instructions = instructions; + Tools = tools; + FileIds = fileIds; + Metadata = metadata; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal AssistantObject() + { + } + + /// The identifier, which can be referenced in API endpoints. + public string Id { get; } + /// The object type, which is always `assistant`. + public AssistantObjectObject Object { get; } = AssistantObjectObject.Assistant; + + /// The Unix timestamp (in seconds) for when the assistant was created. + public DateTimeOffset CreatedAt { get; } + /// The name of the assistant. The maximum length is 256 characters. + public string Name { get; } + /// The description of the assistant. The maximum length is 512 characters. + public string Description { get; } + /// + /// ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + /// see all of your available models, or see our [Model overview](/docs/models/overview) for + /// descriptions of them. + /// + public string Model { get; } + /// The system instructions that the assistant uses. The maximum length is 32768 characters. + public string Instructions { get; } + /// + /// A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. + /// Tools can be of types `code_interpreter`, `retrieval`, or `function`. + /// + /// To assign an object to the element of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + public IReadOnlyList Tools { get; } + /// + /// A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a + /// maximum of 20 files attached to the assistant. Files are ordered by their creation date in + /// ascending order. + /// + public IReadOnlyList FileIds { get; } + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + public IReadOnlyDictionary Metadata { get; } + } +} diff --git a/.dotnet/src/Generated/Models/AssistantObjectObject.cs b/.dotnet/src/Generated/Models/AssistantObjectObject.cs new file mode 100644 index 000000000..9c8eb972f --- /dev/null +++ b/.dotnet/src/Generated/Models/AssistantObjectObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The AssistantObject_object. + public readonly partial struct AssistantObjectObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public AssistantObjectObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string AssistantValue = "assistant"; + + /// assistant. + public static AssistantObjectObject Assistant { get; } = new AssistantObjectObject(AssistantValue); + /// Determines if two values are the same. + public static bool operator ==(AssistantObjectObject left, AssistantObjectObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(AssistantObjectObject left, AssistantObjectObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator AssistantObjectObject(string value) => new AssistantObjectObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is AssistantObjectObject other && Equals(other); + /// + public bool Equals(AssistantObjectObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/AudioSegment.Serialization.cs b/.dotnet/src/Generated/Models/AudioSegment.Serialization.cs new file mode 100644 index 000000000..e114a09c0 --- /dev/null +++ b/.dotnet/src/Generated/Models/AudioSegment.Serialization.cs @@ -0,0 +1,214 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class AudioSegment : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(AudioSegment)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("id"u8); + writer.WriteNumberValue(Id); + writer.WritePropertyName("seek"u8); + writer.WriteNumberValue(Seek); + writer.WritePropertyName("start"u8); + writer.WriteNumberValue(Convert.ToInt32(Start.ToString("%s"))); + writer.WritePropertyName("end"u8); + writer.WriteNumberValue(Convert.ToInt32(End.ToString("%s"))); + writer.WritePropertyName("text"u8); + writer.WriteStringValue(Text); + writer.WritePropertyName("tokens"u8); + writer.WriteStartArray(); + foreach (var item in Tokens) + { + writer.WriteNumberValue(item); + } + writer.WriteEndArray(); + writer.WritePropertyName("temperature"u8); + writer.WriteNumberValue(Temperature); + writer.WritePropertyName("avg_logprob"u8); + writer.WriteNumberValue(AvgLogprob); + writer.WritePropertyName("compression_ratio"u8); + writer.WriteNumberValue(CompressionRatio); + writer.WritePropertyName("no_speech_prob"u8); + writer.WriteNumberValue(NoSpeechProb); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + AudioSegment IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(AudioSegment)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeAudioSegment(document.RootElement, options); + } + + internal static AudioSegment DeserializeAudioSegment(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + long id = default; + long seek = default; + TimeSpan start = default; + TimeSpan end = default; + string text = default; + IReadOnlyList tokens = default; + double temperature = default; + double avgLogprob = default; + double compressionRatio = default; + double noSpeechProb = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("seek"u8)) + { + seek = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("start"u8)) + { + start = TimeSpan.FromSeconds(property.Value.GetInt32()); + continue; + } + if (property.NameEquals("end"u8)) + { + end = TimeSpan.FromSeconds(property.Value.GetInt32()); + continue; + } + if (property.NameEquals("text"u8)) + { + text = property.Value.GetString(); + continue; + } + if (property.NameEquals("tokens"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(item.GetInt64()); + } + tokens = array; + continue; + } + if (property.NameEquals("temperature"u8)) + { + temperature = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("avg_logprob"u8)) + { + avgLogprob = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("compression_ratio"u8)) + { + compressionRatio = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("no_speech_prob"u8)) + { + noSpeechProb = property.Value.GetDouble(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new AudioSegment(id, seek, start, end, text, tokens, temperature, avgLogprob, compressionRatio, noSpeechProb, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(AudioSegment)} does not support '{options.Format}' format."); + } + } + + AudioSegment IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeAudioSegment(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(AudioSegment)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static AudioSegment FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeAudioSegment(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/AudioSegment.cs b/.dotnet/src/Generated/Models/AudioSegment.cs new file mode 100644 index 000000000..d44bf8dc7 --- /dev/null +++ b/.dotnet/src/Generated/Models/AudioSegment.cs @@ -0,0 +1,147 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// The AudioSegment. + public partial class AudioSegment + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The zero-based index of this segment. + /// + /// The seek position associated with the processing of this audio segment. Seek positions are + /// expressed as hundredths of seconds. The model may process several segments from a single seek + /// position, so while the seek position will never represent a later time than the segment's + /// start, the segment's start may represent a significantly later time than the segment's + /// associated seek position. + /// + /// The time at which this segment started relative to the beginning of the audio. + /// The time at which this segment ended relative to the beginning of the audio. + /// The text that was part of this audio segment. + /// The token IDs matching the text in this audio segment. + /// The temperature score associated with this audio segment. + /// The average log probability associated with this audio segment. + /// The compression ratio of this audio segment. + /// The probability of no speech detection within this audio segment. + /// or is null. + internal AudioSegment(long id, long seek, TimeSpan start, TimeSpan end, string text, IEnumerable tokens, double temperature, double avgLogprob, double compressionRatio, double noSpeechProb) + { + ClientUtilities.AssertNotNull(text, nameof(text)); + ClientUtilities.AssertNotNull(tokens, nameof(tokens)); + + Id = id; + Seek = seek; + Start = start; + End = end; + Text = text; + Tokens = tokens.ToList(); + Temperature = temperature; + AvgLogprob = avgLogprob; + CompressionRatio = compressionRatio; + NoSpeechProb = noSpeechProb; + } + + /// Initializes a new instance of . + /// The zero-based index of this segment. + /// + /// The seek position associated with the processing of this audio segment. Seek positions are + /// expressed as hundredths of seconds. The model may process several segments from a single seek + /// position, so while the seek position will never represent a later time than the segment's + /// start, the segment's start may represent a significantly later time than the segment's + /// associated seek position. + /// + /// The time at which this segment started relative to the beginning of the audio. + /// The time at which this segment ended relative to the beginning of the audio. + /// The text that was part of this audio segment. + /// The token IDs matching the text in this audio segment. + /// The temperature score associated with this audio segment. + /// The average log probability associated with this audio segment. + /// The compression ratio of this audio segment. + /// The probability of no speech detection within this audio segment. + /// Keeps track of any properties unknown to the library. + internal AudioSegment(long id, long seek, TimeSpan start, TimeSpan end, string text, IReadOnlyList tokens, double temperature, double avgLogprob, double compressionRatio, double noSpeechProb, IDictionary serializedAdditionalRawData) + { + Id = id; + Seek = seek; + Start = start; + End = end; + Text = text; + Tokens = tokens; + Temperature = temperature; + AvgLogprob = avgLogprob; + CompressionRatio = compressionRatio; + NoSpeechProb = noSpeechProb; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal AudioSegment() + { + } + + /// The zero-based index of this segment. + public long Id { get; } + /// + /// The seek position associated with the processing of this audio segment. Seek positions are + /// expressed as hundredths of seconds. The model may process several segments from a single seek + /// position, so while the seek position will never represent a later time than the segment's + /// start, the segment's start may represent a significantly later time than the segment's + /// associated seek position. + /// + public long Seek { get; } + /// The time at which this segment started relative to the beginning of the audio. + public TimeSpan Start { get; } + /// The time at which this segment ended relative to the beginning of the audio. + public TimeSpan End { get; } + /// The text that was part of this audio segment. + public string Text { get; } + /// The token IDs matching the text in this audio segment. + public IReadOnlyList Tokens { get; } + /// The temperature score associated with this audio segment. + public double Temperature { get; } + /// The average log probability associated with this audio segment. + public double AvgLogprob { get; } + /// The compression ratio of this audio segment. + public double CompressionRatio { get; } + /// The probability of no speech detection within this audio segment. + public double NoSpeechProb { get; } + } +} diff --git a/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.Serialization.cs new file mode 100644 index 000000000..c85718f98 --- /dev/null +++ b/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.Serialization.cs @@ -0,0 +1,132 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + internal partial class ChatCompletionFunctionCallOption : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ChatCompletionFunctionCallOption)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ChatCompletionFunctionCallOption IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ChatCompletionFunctionCallOption)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeChatCompletionFunctionCallOption(document.RootElement, options); + } + + internal static ChatCompletionFunctionCallOption DeserializeChatCompletionFunctionCallOption(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string name = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ChatCompletionFunctionCallOption(name, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ChatCompletionFunctionCallOption)} does not support '{options.Format}' format."); + } + } + + ChatCompletionFunctionCallOption IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeChatCompletionFunctionCallOption(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ChatCompletionFunctionCallOption)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ChatCompletionFunctionCallOption FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeChatCompletionFunctionCallOption(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.cs b/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.cs new file mode 100644 index 000000000..268efaf1a --- /dev/null +++ b/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.cs @@ -0,0 +1,76 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// + /// Specifying a particular function via `{"name": "my_function"}` forces the model to call that + /// function. + /// + internal partial class ChatCompletionFunctionCallOption + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The name of the function to call. + /// is null. + public ChatCompletionFunctionCallOption(string name) + { + ClientUtilities.AssertNotNull(name, nameof(name)); + + Name = name; + } + + /// Initializes a new instance of . + /// The name of the function to call. + /// Keeps track of any properties unknown to the library. + internal ChatCompletionFunctionCallOption(string name, IDictionary serializedAdditionalRawData) + { + Name = name; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal ChatCompletionFunctionCallOption() + { + } + + /// The name of the function to call. + public string Name { get; } + } +} diff --git a/.dotnet/src/Generated/Models/ChatCompletionFunctions.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionFunctions.Serialization.cs new file mode 100644 index 000000000..119be9a51 --- /dev/null +++ b/.dotnet/src/Generated/Models/ChatCompletionFunctions.Serialization.cs @@ -0,0 +1,158 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class ChatCompletionFunctions : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ChatCompletionFunctions)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + if (OptionalProperty.IsDefined(Description)) + { + writer.WritePropertyName("description"u8); + writer.WriteStringValue(Description); + } + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + if (OptionalProperty.IsDefined(Parameters)) + { + writer.WritePropertyName("parameters"u8); + writer.WriteObjectValue(Parameters); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ChatCompletionFunctions IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ChatCompletionFunctions)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeChatCompletionFunctions(document.RootElement, options); + } + + internal static ChatCompletionFunctions DeserializeChatCompletionFunctions(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + OptionalProperty description = default; + string name = default; + OptionalProperty parameters = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("description"u8)) + { + description = property.Value.GetString(); + continue; + } + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("parameters"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + parameters = FunctionParameters.DeserializeFunctionParameters(property.Value); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ChatCompletionFunctions(description.Value, name, parameters.Value, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ChatCompletionFunctions)} does not support '{options.Format}' format."); + } + } + + ChatCompletionFunctions IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeChatCompletionFunctions(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ChatCompletionFunctions)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ChatCompletionFunctions FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeChatCompletionFunctions(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ChatCompletionFunctions.cs b/.dotnet/src/Generated/Models/ChatCompletionFunctions.cs new file mode 100644 index 000000000..d1bbfa718 --- /dev/null +++ b/.dotnet/src/Generated/Models/ChatCompletionFunctions.cs @@ -0,0 +1,97 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The ChatCompletionFunctions. + [Obsolete("deprecated")] + public partial class ChatCompletionFunctions + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and + /// dashes, with a maximum length of 64. + /// + /// is null. + public ChatCompletionFunctions(string name) + { + ClientUtilities.AssertNotNull(name, nameof(name)); + + Name = name; + } + + /// Initializes a new instance of . + /// + /// A description of what the function does, used by the model to choose when and how to call the + /// function. + /// + /// + /// The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and + /// dashes, with a maximum length of 64. + /// + /// + /// Keeps track of any properties unknown to the library. + internal ChatCompletionFunctions(string description, string name, FunctionParameters parameters, IDictionary serializedAdditionalRawData) + { + Description = description; + Name = name; + Parameters = parameters; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal ChatCompletionFunctions() + { + } + + /// + /// A description of what the function does, used by the model to choose when and how to call the + /// function. + /// + public string Description { get; set; } + /// + /// The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and + /// dashes, with a maximum length of 64. + /// + public string Name { get; } + /// Gets or sets the parameters. + public FunctionParameters Parameters { get; set; } + } +} diff --git a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.Serialization.cs new file mode 100644 index 000000000..e3d872da2 --- /dev/null +++ b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.Serialization.cs @@ -0,0 +1,148 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class ChatCompletionMessageToolCall : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ChatCompletionMessageToolCall)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("id"u8); + writer.WriteStringValue(Id); + writer.WritePropertyName("type"u8); + writer.WriteStringValue(Type.ToString()); + writer.WritePropertyName("function"u8); + writer.WriteObjectValue(Function); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ChatCompletionMessageToolCall IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ChatCompletionMessageToolCall)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeChatCompletionMessageToolCall(document.RootElement, options); + } + + internal static ChatCompletionMessageToolCall DeserializeChatCompletionMessageToolCall(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string id = default; + ChatCompletionMessageToolCallType type = default; + ChatCompletionMessageToolCallFunction function = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetString(); + continue; + } + if (property.NameEquals("type"u8)) + { + type = new ChatCompletionMessageToolCallType(property.Value.GetString()); + continue; + } + if (property.NameEquals("function"u8)) + { + function = ChatCompletionMessageToolCallFunction.DeserializeChatCompletionMessageToolCallFunction(property.Value); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ChatCompletionMessageToolCall(id, type, function, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ChatCompletionMessageToolCall)} does not support '{options.Format}' format."); + } + } + + ChatCompletionMessageToolCall IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeChatCompletionMessageToolCall(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ChatCompletionMessageToolCall)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ChatCompletionMessageToolCall FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeChatCompletionMessageToolCall(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.cs b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.cs new file mode 100644 index 000000000..e5249dafc --- /dev/null +++ b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.cs @@ -0,0 +1,85 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The ChatCompletionMessageToolCall. + public partial class ChatCompletionMessageToolCall + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The ID of the tool call. + /// The function that the model called. + /// or is null. + public ChatCompletionMessageToolCall(string id, ChatCompletionMessageToolCallFunction function) + { + ClientUtilities.AssertNotNull(id, nameof(id)); + ClientUtilities.AssertNotNull(function, nameof(function)); + + Id = id; + Function = function; + } + + /// Initializes a new instance of . + /// The ID of the tool call. + /// The type of the tool. Currently, only `function` is supported. + /// The function that the model called. + /// Keeps track of any properties unknown to the library. + internal ChatCompletionMessageToolCall(string id, ChatCompletionMessageToolCallType type, ChatCompletionMessageToolCallFunction function, IDictionary serializedAdditionalRawData) + { + Id = id; + Type = type; + Function = function; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal ChatCompletionMessageToolCall() + { + } + + /// The ID of the tool call. + public string Id { get; set; } + /// The type of the tool. Currently, only `function` is supported. + public ChatCompletionMessageToolCallType Type { get; } = ChatCompletionMessageToolCallType.Function; + + /// The function that the model called. + public ChatCompletionMessageToolCallFunction Function { get; set; } + } +} diff --git a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.Serialization.cs new file mode 100644 index 000000000..ca4e609d1 --- /dev/null +++ b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.Serialization.cs @@ -0,0 +1,140 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class ChatCompletionMessageToolCallFunction : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ChatCompletionMessageToolCallFunction)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + writer.WritePropertyName("arguments"u8); + writer.WriteStringValue(Arguments); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ChatCompletionMessageToolCallFunction IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ChatCompletionMessageToolCallFunction)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeChatCompletionMessageToolCallFunction(document.RootElement, options); + } + + internal static ChatCompletionMessageToolCallFunction DeserializeChatCompletionMessageToolCallFunction(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string name = default; + string arguments = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("arguments"u8)) + { + arguments = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ChatCompletionMessageToolCallFunction(name, arguments, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ChatCompletionMessageToolCallFunction)} does not support '{options.Format}' format."); + } + } + + ChatCompletionMessageToolCallFunction IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeChatCompletionMessageToolCallFunction(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ChatCompletionMessageToolCallFunction)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ChatCompletionMessageToolCallFunction FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeChatCompletionMessageToolCallFunction(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.cs b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.cs new file mode 100644 index 000000000..92b945f4c --- /dev/null +++ b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.cs @@ -0,0 +1,92 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The ChatCompletionMessageToolCallFunction. + public partial class ChatCompletionMessageToolCallFunction + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The name of the function to call. + /// + /// The arguments to call the function with, as generated by the model in JSON format. Note that + /// the model does not always generate valid JSON, and may hallucinate parameters not defined by + /// your function schema. Validate the arguments in your code before calling your function. + /// + /// or is null. + public ChatCompletionMessageToolCallFunction(string name, string arguments) + { + ClientUtilities.AssertNotNull(name, nameof(name)); + ClientUtilities.AssertNotNull(arguments, nameof(arguments)); + + Name = name; + Arguments = arguments; + } + + /// Initializes a new instance of . + /// The name of the function to call. + /// + /// The arguments to call the function with, as generated by the model in JSON format. Note that + /// the model does not always generate valid JSON, and may hallucinate parameters not defined by + /// your function schema. Validate the arguments in your code before calling your function. + /// + /// Keeps track of any properties unknown to the library. + internal ChatCompletionMessageToolCallFunction(string name, string arguments, IDictionary serializedAdditionalRawData) + { + Name = name; + Arguments = arguments; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal ChatCompletionMessageToolCallFunction() + { + } + + /// The name of the function to call. + public string Name { get; set; } + /// + /// The arguments to call the function with, as generated by the model in JSON format. Note that + /// the model does not always generate valid JSON, and may hallucinate parameters not defined by + /// your function schema. Validate the arguments in your code before calling your function. + /// + public string Arguments { get; set; } + } +} diff --git a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallType.cs b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallType.cs new file mode 100644 index 000000000..e6c9dff53 --- /dev/null +++ b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallType.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The ChatCompletionMessageToolCall_type. + public readonly partial struct ChatCompletionMessageToolCallType : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public ChatCompletionMessageToolCallType(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string FunctionValue = "function"; + + /// function. + public static ChatCompletionMessageToolCallType Function { get; } = new ChatCompletionMessageToolCallType(FunctionValue); + /// Determines if two values are the same. + public static bool operator ==(ChatCompletionMessageToolCallType left, ChatCompletionMessageToolCallType right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(ChatCompletionMessageToolCallType left, ChatCompletionMessageToolCallType right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator ChatCompletionMessageToolCallType(string value) => new ChatCompletionMessageToolCallType(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is ChatCompletionMessageToolCallType other && Equals(other); + /// + public bool Equals(ChatCompletionMessageToolCallType other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.Serialization.cs new file mode 100644 index 000000000..7ec5a3aeb --- /dev/null +++ b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.Serialization.cs @@ -0,0 +1,140 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + internal partial class ChatCompletionNamedToolChoice : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ChatCompletionNamedToolChoice)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("type"u8); + writer.WriteStringValue(Type.ToString()); + writer.WritePropertyName("function"u8); + writer.WriteObjectValue(Function); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ChatCompletionNamedToolChoice IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ChatCompletionNamedToolChoice)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeChatCompletionNamedToolChoice(document.RootElement, options); + } + + internal static ChatCompletionNamedToolChoice DeserializeChatCompletionNamedToolChoice(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + ChatCompletionNamedToolChoiceType type = default; + ChatCompletionNamedToolChoiceFunction function = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("type"u8)) + { + type = new ChatCompletionNamedToolChoiceType(property.Value.GetString()); + continue; + } + if (property.NameEquals("function"u8)) + { + function = ChatCompletionNamedToolChoiceFunction.DeserializeChatCompletionNamedToolChoiceFunction(property.Value); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ChatCompletionNamedToolChoice(type, function, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ChatCompletionNamedToolChoice)} does not support '{options.Format}' format."); + } + } + + ChatCompletionNamedToolChoice IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeChatCompletionNamedToolChoice(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ChatCompletionNamedToolChoice)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ChatCompletionNamedToolChoice FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeChatCompletionNamedToolChoice(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.cs b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.cs new file mode 100644 index 000000000..da8b10edb --- /dev/null +++ b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.cs @@ -0,0 +1,78 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// Specifies a tool the model should use. Use to force the model to call a specific function. + internal partial class ChatCompletionNamedToolChoice + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// is null. + public ChatCompletionNamedToolChoice(ChatCompletionNamedToolChoiceFunction function) + { + ClientUtilities.AssertNotNull(function, nameof(function)); + + Function = function; + } + + /// Initializes a new instance of . + /// The type of the tool. Currently, only `function` is supported. + /// + /// Keeps track of any properties unknown to the library. + internal ChatCompletionNamedToolChoice(ChatCompletionNamedToolChoiceType type, ChatCompletionNamedToolChoiceFunction function, IDictionary serializedAdditionalRawData) + { + Type = type; + Function = function; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal ChatCompletionNamedToolChoice() + { + } + + /// The type of the tool. Currently, only `function` is supported. + public ChatCompletionNamedToolChoiceType Type { get; } = ChatCompletionNamedToolChoiceType.Function; + + /// Gets the function. + public ChatCompletionNamedToolChoiceFunction Function { get; } + } +} diff --git a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.Serialization.cs new file mode 100644 index 000000000..654aa4f90 --- /dev/null +++ b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.Serialization.cs @@ -0,0 +1,132 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + internal partial class ChatCompletionNamedToolChoiceFunction : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ChatCompletionNamedToolChoiceFunction)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ChatCompletionNamedToolChoiceFunction IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ChatCompletionNamedToolChoiceFunction)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeChatCompletionNamedToolChoiceFunction(document.RootElement, options); + } + + internal static ChatCompletionNamedToolChoiceFunction DeserializeChatCompletionNamedToolChoiceFunction(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string name = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ChatCompletionNamedToolChoiceFunction(name, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ChatCompletionNamedToolChoiceFunction)} does not support '{options.Format}' format."); + } + } + + ChatCompletionNamedToolChoiceFunction IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeChatCompletionNamedToolChoiceFunction(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ChatCompletionNamedToolChoiceFunction)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ChatCompletionNamedToolChoiceFunction FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeChatCompletionNamedToolChoiceFunction(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.cs b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.cs new file mode 100644 index 000000000..383fceef2 --- /dev/null +++ b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.cs @@ -0,0 +1,73 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The ChatCompletionNamedToolChoiceFunction. + internal partial class ChatCompletionNamedToolChoiceFunction + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The name of the function to call. + /// is null. + public ChatCompletionNamedToolChoiceFunction(string name) + { + ClientUtilities.AssertNotNull(name, nameof(name)); + + Name = name; + } + + /// Initializes a new instance of . + /// The name of the function to call. + /// Keeps track of any properties unknown to the library. + internal ChatCompletionNamedToolChoiceFunction(string name, IDictionary serializedAdditionalRawData) + { + Name = name; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal ChatCompletionNamedToolChoiceFunction() + { + } + + /// The name of the function to call. + public string Name { get; } + } +} diff --git a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceType.cs b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceType.cs new file mode 100644 index 000000000..8f94a2674 --- /dev/null +++ b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceType.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The ChatCompletionNamedToolChoice_type. + internal readonly partial struct ChatCompletionNamedToolChoiceType : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public ChatCompletionNamedToolChoiceType(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string FunctionValue = "function"; + + /// function. + public static ChatCompletionNamedToolChoiceType Function { get; } = new ChatCompletionNamedToolChoiceType(FunctionValue); + /// Determines if two values are the same. + public static bool operator ==(ChatCompletionNamedToolChoiceType left, ChatCompletionNamedToolChoiceType right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(ChatCompletionNamedToolChoiceType left, ChatCompletionNamedToolChoiceType right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator ChatCompletionNamedToolChoiceType(string value) => new ChatCompletionNamedToolChoiceType(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is ChatCompletionNamedToolChoiceType other && Equals(other); + /// + public bool Equals(ChatCompletionNamedToolChoiceType other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.Serialization.cs new file mode 100644 index 000000000..b467eb421 --- /dev/null +++ b/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.Serialization.cs @@ -0,0 +1,192 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class ChatCompletionResponseMessage : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ChatCompletionResponseMessage)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + if (Content != null) + { + writer.WritePropertyName("content"u8); + writer.WriteStringValue(Content); + } + else + { + writer.WriteNull("content"); + } + if (OptionalProperty.IsCollectionDefined(ToolCalls)) + { + writer.WritePropertyName("tool_calls"u8); + writer.WriteStartArray(); + foreach (var item in ToolCalls) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + } + writer.WritePropertyName("role"u8); + writer.WriteStringValue(Role.ToString()); + if (OptionalProperty.IsDefined(FunctionCall)) + { + writer.WritePropertyName("function_call"u8); + writer.WriteObjectValue(FunctionCall); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ChatCompletionResponseMessage IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ChatCompletionResponseMessage)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeChatCompletionResponseMessage(document.RootElement, options); + } + + internal static ChatCompletionResponseMessage DeserializeChatCompletionResponseMessage(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string content = default; + OptionalProperty> toolCalls = default; + ChatCompletionResponseMessageRole role = default; + OptionalProperty functionCall = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("content"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + content = null; + continue; + } + content = property.Value.GetString(); + continue; + } + if (property.NameEquals("tool_calls"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(ChatCompletionMessageToolCall.DeserializeChatCompletionMessageToolCall(item)); + } + toolCalls = array; + continue; + } + if (property.NameEquals("role"u8)) + { + role = new ChatCompletionResponseMessageRole(property.Value.GetString()); + continue; + } + if (property.NameEquals("function_call"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + functionCall = ChatCompletionResponseMessageFunctionCall.DeserializeChatCompletionResponseMessageFunctionCall(property.Value); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ChatCompletionResponseMessage(content, OptionalProperty.ToList(toolCalls), role, functionCall.Value, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ChatCompletionResponseMessage)} does not support '{options.Format}' format."); + } + } + + ChatCompletionResponseMessage IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeChatCompletionResponseMessage(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ChatCompletionResponseMessage)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ChatCompletionResponseMessage FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeChatCompletionResponseMessage(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.cs b/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.cs new file mode 100644 index 000000000..709a705ff --- /dev/null +++ b/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.cs @@ -0,0 +1,84 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The ChatCompletionResponseMessage. + public partial class ChatCompletionResponseMessage + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The contents of the message. + internal ChatCompletionResponseMessage(string content) + { + Content = content; + ToolCalls = new OptionalList(); + } + + /// Initializes a new instance of . + /// The contents of the message. + /// + /// The role of the author of this message. + /// Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model. + /// Keeps track of any properties unknown to the library. + internal ChatCompletionResponseMessage(string content, IReadOnlyList toolCalls, ChatCompletionResponseMessageRole role, ChatCompletionResponseMessageFunctionCall functionCall, IDictionary serializedAdditionalRawData) + { + Content = content; + ToolCalls = toolCalls; + Role = role; + FunctionCall = functionCall; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal ChatCompletionResponseMessage() + { + } + + /// The contents of the message. + public string Content { get; } + /// Gets the tool calls. + public IReadOnlyList ToolCalls { get; } + /// The role of the author of this message. + public ChatCompletionResponseMessageRole Role { get; } = ChatCompletionResponseMessageRole.Assistant; + + /// Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model. + public ChatCompletionResponseMessageFunctionCall FunctionCall { get; } + } +} diff --git a/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.Serialization.cs new file mode 100644 index 000000000..98aac4cd5 --- /dev/null +++ b/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.Serialization.cs @@ -0,0 +1,140 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class ChatCompletionResponseMessageFunctionCall : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ChatCompletionResponseMessageFunctionCall)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("arguments"u8); + writer.WriteStringValue(Arguments); + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ChatCompletionResponseMessageFunctionCall IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ChatCompletionResponseMessageFunctionCall)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeChatCompletionResponseMessageFunctionCall(document.RootElement, options); + } + + internal static ChatCompletionResponseMessageFunctionCall DeserializeChatCompletionResponseMessageFunctionCall(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string arguments = default; + string name = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("arguments"u8)) + { + arguments = property.Value.GetString(); + continue; + } + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ChatCompletionResponseMessageFunctionCall(arguments, name, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ChatCompletionResponseMessageFunctionCall)} does not support '{options.Format}' format."); + } + } + + ChatCompletionResponseMessageFunctionCall IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeChatCompletionResponseMessageFunctionCall(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ChatCompletionResponseMessageFunctionCall)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ChatCompletionResponseMessageFunctionCall FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeChatCompletionResponseMessageFunctionCall(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.cs b/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.cs new file mode 100644 index 000000000..7f9e8549c --- /dev/null +++ b/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.cs @@ -0,0 +1,92 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The ChatCompletionResponseMessageFunctionCall. + public partial class ChatCompletionResponseMessageFunctionCall + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// The arguments to call the function with, as generated by the model in JSON format. Note that + /// the model does not always generate valid JSON, and may hallucinate parameters not defined by + /// your function schema. Validate the arguments in your code before calling your function. + /// + /// The name of the function to call. + /// or is null. + internal ChatCompletionResponseMessageFunctionCall(string arguments, string name) + { + ClientUtilities.AssertNotNull(arguments, nameof(arguments)); + ClientUtilities.AssertNotNull(name, nameof(name)); + + Arguments = arguments; + Name = name; + } + + /// Initializes a new instance of . + /// + /// The arguments to call the function with, as generated by the model in JSON format. Note that + /// the model does not always generate valid JSON, and may hallucinate parameters not defined by + /// your function schema. Validate the arguments in your code before calling your function. + /// + /// The name of the function to call. + /// Keeps track of any properties unknown to the library. + internal ChatCompletionResponseMessageFunctionCall(string arguments, string name, IDictionary serializedAdditionalRawData) + { + Arguments = arguments; + Name = name; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal ChatCompletionResponseMessageFunctionCall() + { + } + + /// + /// The arguments to call the function with, as generated by the model in JSON format. Note that + /// the model does not always generate valid JSON, and may hallucinate parameters not defined by + /// your function schema. Validate the arguments in your code before calling your function. + /// + public string Arguments { get; } + /// The name of the function to call. + public string Name { get; } + } +} diff --git a/.dotnet/src/Generated/Models/ChatCompletionResponseMessageRole.cs b/.dotnet/src/Generated/Models/ChatCompletionResponseMessageRole.cs new file mode 100644 index 000000000..ee43ccb40 --- /dev/null +++ b/.dotnet/src/Generated/Models/ChatCompletionResponseMessageRole.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The ChatCompletionResponseMessage_role. + public readonly partial struct ChatCompletionResponseMessageRole : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public ChatCompletionResponseMessageRole(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string AssistantValue = "assistant"; + + /// assistant. + public static ChatCompletionResponseMessageRole Assistant { get; } = new ChatCompletionResponseMessageRole(AssistantValue); + /// Determines if two values are the same. + public static bool operator ==(ChatCompletionResponseMessageRole left, ChatCompletionResponseMessageRole right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(ChatCompletionResponseMessageRole left, ChatCompletionResponseMessageRole right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator ChatCompletionResponseMessageRole(string value) => new ChatCompletionResponseMessageRole(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is ChatCompletionResponseMessageRole other && Equals(other); + /// + public bool Equals(ChatCompletionResponseMessageRole other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.Serialization.cs new file mode 100644 index 000000000..b80e2c44a --- /dev/null +++ b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.Serialization.cs @@ -0,0 +1,188 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class ChatCompletionTokenLogprob : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ChatCompletionTokenLogprob)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("token"u8); + writer.WriteStringValue(Token); + writer.WritePropertyName("logprob"u8); + writer.WriteNumberValue(Logprob); + if (Bytes != null && OptionalProperty.IsCollectionDefined(Bytes)) + { + writer.WritePropertyName("bytes"u8); + writer.WriteStartArray(); + foreach (var item in Bytes) + { + writer.WriteNumberValue(item); + } + writer.WriteEndArray(); + } + else + { + writer.WriteNull("bytes"); + } + writer.WritePropertyName("top_logprobs"u8); + writer.WriteStartArray(); + foreach (var item in TopLogprobs) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ChatCompletionTokenLogprob IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ChatCompletionTokenLogprob)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeChatCompletionTokenLogprob(document.RootElement, options); + } + + internal static ChatCompletionTokenLogprob DeserializeChatCompletionTokenLogprob(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string token = default; + double logprob = default; + IReadOnlyList bytes = default; + IReadOnlyList topLogprobs = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("token"u8)) + { + token = property.Value.GetString(); + continue; + } + if (property.NameEquals("logprob"u8)) + { + logprob = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("bytes"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + bytes = new OptionalList(); + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(item.GetInt64()); + } + bytes = array; + continue; + } + if (property.NameEquals("top_logprobs"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(ChatCompletionTokenLogprobTopLogprob.DeserializeChatCompletionTokenLogprobTopLogprob(item)); + } + topLogprobs = array; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ChatCompletionTokenLogprob(token, logprob, bytes, topLogprobs, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ChatCompletionTokenLogprob)} does not support '{options.Format}' format."); + } + } + + ChatCompletionTokenLogprob IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeChatCompletionTokenLogprob(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ChatCompletionTokenLogprob)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ChatCompletionTokenLogprob FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeChatCompletionTokenLogprob(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.cs b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.cs new file mode 100644 index 000000000..6e487ac5c --- /dev/null +++ b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.cs @@ -0,0 +1,117 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// The ChatCompletionTokenLogprob. + public partial class ChatCompletionTokenLogprob + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The token. + /// The log probability of this token. + /// + /// A list of integers representing the UTF-8 bytes representation of the token. Useful in + /// instances where characters are represented by multiple tokens and their byte representations + /// must be combined to generate the correct text representation. Can be `null` if there is no + /// bytes representation for the token. + /// + /// + /// List of the most likely tokens and their log probability, at this token position. In rare + /// cases, there may be fewer than the number of requested `top_logprobs` returned. + /// + /// or is null. + internal ChatCompletionTokenLogprob(string token, double logprob, IEnumerable bytes, IEnumerable topLogprobs) + { + ClientUtilities.AssertNotNull(token, nameof(token)); + ClientUtilities.AssertNotNull(topLogprobs, nameof(topLogprobs)); + + Token = token; + Logprob = logprob; + Bytes = bytes?.ToList(); + TopLogprobs = topLogprobs.ToList(); + } + + /// Initializes a new instance of . + /// The token. + /// The log probability of this token. + /// + /// A list of integers representing the UTF-8 bytes representation of the token. Useful in + /// instances where characters are represented by multiple tokens and their byte representations + /// must be combined to generate the correct text representation. Can be `null` if there is no + /// bytes representation for the token. + /// + /// + /// List of the most likely tokens and their log probability, at this token position. In rare + /// cases, there may be fewer than the number of requested `top_logprobs` returned. + /// + /// Keeps track of any properties unknown to the library. + internal ChatCompletionTokenLogprob(string token, double logprob, IReadOnlyList bytes, IReadOnlyList topLogprobs, IDictionary serializedAdditionalRawData) + { + Token = token; + Logprob = logprob; + Bytes = bytes; + TopLogprobs = topLogprobs; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal ChatCompletionTokenLogprob() + { + } + + /// The token. + public string Token { get; } + /// The log probability of this token. + public double Logprob { get; } + /// + /// A list of integers representing the UTF-8 bytes representation of the token. Useful in + /// instances where characters are represented by multiple tokens and their byte representations + /// must be combined to generate the correct text representation. Can be `null` if there is no + /// bytes representation for the token. + /// + public IReadOnlyList Bytes { get; } + /// + /// List of the most likely tokens and their log probability, at this token position. In rare + /// cases, there may be fewer than the number of requested `top_logprobs` returned. + /// + public IReadOnlyList TopLogprobs { get; } + } +} diff --git a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.Serialization.cs new file mode 100644 index 000000000..ab6b52872 --- /dev/null +++ b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.Serialization.cs @@ -0,0 +1,170 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class ChatCompletionTokenLogprobTopLogprob : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ChatCompletionTokenLogprobTopLogprob)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("token"u8); + writer.WriteStringValue(Token); + writer.WritePropertyName("logprob"u8); + writer.WriteNumberValue(Logprob); + if (Bytes != null && OptionalProperty.IsCollectionDefined(Bytes)) + { + writer.WritePropertyName("bytes"u8); + writer.WriteStartArray(); + foreach (var item in Bytes) + { + writer.WriteNumberValue(item); + } + writer.WriteEndArray(); + } + else + { + writer.WriteNull("bytes"); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ChatCompletionTokenLogprobTopLogprob IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ChatCompletionTokenLogprobTopLogprob)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeChatCompletionTokenLogprobTopLogprob(document.RootElement, options); + } + + internal static ChatCompletionTokenLogprobTopLogprob DeserializeChatCompletionTokenLogprobTopLogprob(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string token = default; + double logprob = default; + IReadOnlyList bytes = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("token"u8)) + { + token = property.Value.GetString(); + continue; + } + if (property.NameEquals("logprob"u8)) + { + logprob = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("bytes"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + bytes = new OptionalList(); + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(item.GetInt64()); + } + bytes = array; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ChatCompletionTokenLogprobTopLogprob(token, logprob, bytes, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ChatCompletionTokenLogprobTopLogprob)} does not support '{options.Format}' format."); + } + } + + ChatCompletionTokenLogprobTopLogprob IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeChatCompletionTokenLogprobTopLogprob(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ChatCompletionTokenLogprobTopLogprob)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ChatCompletionTokenLogprobTopLogprob FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeChatCompletionTokenLogprobTopLogprob(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.cs b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.cs new file mode 100644 index 000000000..f0a7c191b --- /dev/null +++ b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.cs @@ -0,0 +1,101 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// The ChatCompletionTokenLogprobTopLogprob. + public partial class ChatCompletionTokenLogprobTopLogprob + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The token. + /// The log probability of this token. + /// + /// A list of integers representing the UTF-8 bytes representation of the token. Useful in + /// instances where characters are represented by multiple tokens and their byte representations + /// must be combined to generate the correct text representation. Can be `null` if there is no + /// bytes representation for the token. + /// + /// is null. + internal ChatCompletionTokenLogprobTopLogprob(string token, double logprob, IEnumerable bytes) + { + ClientUtilities.AssertNotNull(token, nameof(token)); + + Token = token; + Logprob = logprob; + Bytes = bytes?.ToList(); + } + + /// Initializes a new instance of . + /// The token. + /// The log probability of this token. + /// + /// A list of integers representing the UTF-8 bytes representation of the token. Useful in + /// instances where characters are represented by multiple tokens and their byte representations + /// must be combined to generate the correct text representation. Can be `null` if there is no + /// bytes representation for the token. + /// + /// Keeps track of any properties unknown to the library. + internal ChatCompletionTokenLogprobTopLogprob(string token, double logprob, IReadOnlyList bytes, IDictionary serializedAdditionalRawData) + { + Token = token; + Logprob = logprob; + Bytes = bytes; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal ChatCompletionTokenLogprobTopLogprob() + { + } + + /// The token. + public string Token { get; } + /// The log probability of this token. + public double Logprob { get; } + /// + /// A list of integers representing the UTF-8 bytes representation of the token. Useful in + /// instances where characters are represented by multiple tokens and their byte representations + /// must be combined to generate the correct text representation. Can be `null` if there is no + /// bytes representation for the token. + /// + public IReadOnlyList Bytes { get; } + } +} diff --git a/.dotnet/src/Generated/Models/ChatCompletionTool.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionTool.Serialization.cs new file mode 100644 index 000000000..4f0233034 --- /dev/null +++ b/.dotnet/src/Generated/Models/ChatCompletionTool.Serialization.cs @@ -0,0 +1,140 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class ChatCompletionTool : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ChatCompletionTool)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("type"u8); + writer.WriteStringValue(Type.ToString()); + writer.WritePropertyName("function"u8); + writer.WriteObjectValue(Function); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ChatCompletionTool IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ChatCompletionTool)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeChatCompletionTool(document.RootElement, options); + } + + internal static ChatCompletionTool DeserializeChatCompletionTool(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + ChatCompletionToolType type = default; + FunctionObject function = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("type"u8)) + { + type = new ChatCompletionToolType(property.Value.GetString()); + continue; + } + if (property.NameEquals("function"u8)) + { + function = FunctionObject.DeserializeFunctionObject(property.Value); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ChatCompletionTool(type, function, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ChatCompletionTool)} does not support '{options.Format}' format."); + } + } + + ChatCompletionTool IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeChatCompletionTool(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ChatCompletionTool)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ChatCompletionTool FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeChatCompletionTool(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ChatCompletionTool.cs b/.dotnet/src/Generated/Models/ChatCompletionTool.cs new file mode 100644 index 000000000..c03dc4647 --- /dev/null +++ b/.dotnet/src/Generated/Models/ChatCompletionTool.cs @@ -0,0 +1,78 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The ChatCompletionTool. + public partial class ChatCompletionTool + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// is null. + public ChatCompletionTool(FunctionObject function) + { + ClientUtilities.AssertNotNull(function, nameof(function)); + + Function = function; + } + + /// Initializes a new instance of . + /// The type of the tool. Currently, only `function` is supported. + /// + /// Keeps track of any properties unknown to the library. + internal ChatCompletionTool(ChatCompletionToolType type, FunctionObject function, IDictionary serializedAdditionalRawData) + { + Type = type; + Function = function; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal ChatCompletionTool() + { + } + + /// The type of the tool. Currently, only `function` is supported. + public ChatCompletionToolType Type { get; } = ChatCompletionToolType.Function; + + /// Gets the function. + public FunctionObject Function { get; } + } +} diff --git a/.dotnet/src/Generated/Models/ChatCompletionToolType.cs b/.dotnet/src/Generated/Models/ChatCompletionToolType.cs new file mode 100644 index 000000000..f1a96376c --- /dev/null +++ b/.dotnet/src/Generated/Models/ChatCompletionToolType.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The ChatCompletionTool_type. + public readonly partial struct ChatCompletionToolType : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public ChatCompletionToolType(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string FunctionValue = "function"; + + /// function. + public static ChatCompletionToolType Function { get; } = new ChatCompletionToolType(FunctionValue); + /// Determines if two values are the same. + public static bool operator ==(ChatCompletionToolType left, ChatCompletionToolType right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(ChatCompletionToolType left, ChatCompletionToolType right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator ChatCompletionToolType(string value) => new ChatCompletionToolType(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is ChatCompletionToolType other && Equals(other); + /// + public bool Equals(ChatCompletionToolType other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CompletionUsage.Serialization.cs b/.dotnet/src/Generated/Models/CompletionUsage.Serialization.cs new file mode 100644 index 000000000..ffaa5adcb --- /dev/null +++ b/.dotnet/src/Generated/Models/CompletionUsage.Serialization.cs @@ -0,0 +1,148 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CompletionUsage : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CompletionUsage)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("prompt_tokens"u8); + writer.WriteNumberValue(PromptTokens); + writer.WritePropertyName("completion_tokens"u8); + writer.WriteNumberValue(CompletionTokens); + writer.WritePropertyName("total_tokens"u8); + writer.WriteNumberValue(TotalTokens); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CompletionUsage IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CompletionUsage)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCompletionUsage(document.RootElement, options); + } + + internal static CompletionUsage DeserializeCompletionUsage(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + long promptTokens = default; + long completionTokens = default; + long totalTokens = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("prompt_tokens"u8)) + { + promptTokens = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("completion_tokens"u8)) + { + completionTokens = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("total_tokens"u8)) + { + totalTokens = property.Value.GetInt64(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CompletionUsage(promptTokens, completionTokens, totalTokens, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CompletionUsage)} does not support '{options.Format}' format."); + } + } + + CompletionUsage IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCompletionUsage(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CompletionUsage)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CompletionUsage FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCompletionUsage(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CompletionUsage.cs b/.dotnet/src/Generated/Models/CompletionUsage.cs new file mode 100644 index 000000000..07f38ee8b --- /dev/null +++ b/.dotnet/src/Generated/Models/CompletionUsage.cs @@ -0,0 +1,81 @@ +// + +#nullable disable + +using System; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// Usage statistics for the completion request. + public partial class CompletionUsage + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// Number of tokens in the prompt. + /// Number of tokens in the generated completion. + /// Total number of tokens used in the request (prompt + completion). + internal CompletionUsage(long promptTokens, long completionTokens, long totalTokens) + { + PromptTokens = promptTokens; + CompletionTokens = completionTokens; + TotalTokens = totalTokens; + } + + /// Initializes a new instance of . + /// Number of tokens in the prompt. + /// Number of tokens in the generated completion. + /// Total number of tokens used in the request (prompt + completion). + /// Keeps track of any properties unknown to the library. + internal CompletionUsage(long promptTokens, long completionTokens, long totalTokens, IDictionary serializedAdditionalRawData) + { + PromptTokens = promptTokens; + CompletionTokens = completionTokens; + TotalTokens = totalTokens; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CompletionUsage() + { + } + + /// Number of tokens in the prompt. + public long PromptTokens { get; } + /// Number of tokens in the generated completion. + public long CompletionTokens { get; } + /// Total number of tokens used in the request (prompt + completion). + public long TotalTokens { get; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateAssistantFileRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateAssistantFileRequest.Serialization.cs new file mode 100644 index 000000000..ae5a3b32e --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateAssistantFileRequest.Serialization.cs @@ -0,0 +1,132 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateAssistantFileRequest : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateAssistantFileRequest)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("file_id"u8); + writer.WriteStringValue(FileId); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateAssistantFileRequest IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateAssistantFileRequest)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateAssistantFileRequest(document.RootElement, options); + } + + internal static CreateAssistantFileRequest DeserializeCreateAssistantFileRequest(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string fileId = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("file_id"u8)) + { + fileId = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateAssistantFileRequest(fileId, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateAssistantFileRequest)} does not support '{options.Format}' format."); + } + } + + CreateAssistantFileRequest IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateAssistantFileRequest(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateAssistantFileRequest)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateAssistantFileRequest FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateAssistantFileRequest(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateAssistantFileRequest.cs b/.dotnet/src/Generated/Models/CreateAssistantFileRequest.cs new file mode 100644 index 000000000..8c11246d1 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateAssistantFileRequest.cs @@ -0,0 +1,82 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateAssistantFileRequest. + public partial class CreateAssistantFileRequest + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// A [File](/docs/api-reference/files) ID (with `purpose="assistants"`) that the assistant should + /// use. Useful for tools like `retrieval` and `code_interpreter` that can access files. + /// + /// is null. + public CreateAssistantFileRequest(string fileId) + { + ClientUtilities.AssertNotNull(fileId, nameof(fileId)); + + FileId = fileId; + } + + /// Initializes a new instance of . + /// + /// A [File](/docs/api-reference/files) ID (with `purpose="assistants"`) that the assistant should + /// use. Useful for tools like `retrieval` and `code_interpreter` that can access files. + /// + /// Keeps track of any properties unknown to the library. + internal CreateAssistantFileRequest(string fileId, IDictionary serializedAdditionalRawData) + { + FileId = fileId; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateAssistantFileRequest() + { + } + + /// + /// A [File](/docs/api-reference/files) ID (with `purpose="assistants"`) that the assistant should + /// use. Useful for tools like `retrieval` and `code_interpreter` that can access files. + /// + public string FileId { get; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateAssistantRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateAssistantRequest.Serialization.cs new file mode 100644 index 000000000..8aaa22372 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateAssistantRequest.Serialization.cs @@ -0,0 +1,303 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateAssistantRequest : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateAssistantRequest)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("model"u8); + writer.WriteStringValue(Model); + if (OptionalProperty.IsDefined(Name)) + { + if (Name != null) + { + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + } + else + { + writer.WriteNull("name"); + } + } + if (OptionalProperty.IsDefined(Description)) + { + if (Description != null) + { + writer.WritePropertyName("description"u8); + writer.WriteStringValue(Description); + } + else + { + writer.WriteNull("description"); + } + } + if (OptionalProperty.IsDefined(Instructions)) + { + if (Instructions != null) + { + writer.WritePropertyName("instructions"u8); + writer.WriteStringValue(Instructions); + } + else + { + writer.WriteNull("instructions"); + } + } + if (OptionalProperty.IsCollectionDefined(Tools)) + { + writer.WritePropertyName("tools"u8); + writer.WriteStartArray(); + foreach (var item in Tools) + { + if (item == null) + { + writer.WriteNullValue(); + continue; + } +#if NET6_0_OR_GREATER + writer.WriteRawValue(item); +#else + using (JsonDocument document = JsonDocument.Parse(item)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + writer.WriteEndArray(); + } + if (OptionalProperty.IsCollectionDefined(FileIds)) + { + writer.WritePropertyName("file_ids"u8); + writer.WriteStartArray(); + foreach (var item in FileIds) + { + writer.WriteStringValue(item); + } + writer.WriteEndArray(); + } + if (OptionalProperty.IsCollectionDefined(Metadata)) + { + if (Metadata != null) + { + writer.WritePropertyName("metadata"u8); + writer.WriteStartObject(); + foreach (var item in Metadata) + { + writer.WritePropertyName(item.Key); + writer.WriteStringValue(item.Value); + } + writer.WriteEndObject(); + } + else + { + writer.WriteNull("metadata"); + } + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateAssistantRequest IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateAssistantRequest)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateAssistantRequest(document.RootElement, options); + } + + internal static CreateAssistantRequest DeserializeCreateAssistantRequest(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string model = default; + OptionalProperty name = default; + OptionalProperty description = default; + OptionalProperty instructions = default; + OptionalProperty> tools = default; + OptionalProperty> fileIds = default; + OptionalProperty> metadata = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("model"u8)) + { + model = property.Value.GetString(); + continue; + } + if (property.NameEquals("name"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + name = null; + continue; + } + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("description"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + description = null; + continue; + } + description = property.Value.GetString(); + continue; + } + if (property.NameEquals("instructions"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + instructions = null; + continue; + } + instructions = property.Value.GetString(); + continue; + } + if (property.NameEquals("tools"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + if (item.ValueKind == JsonValueKind.Null) + { + array.Add(null); + } + else + { + array.Add(BinaryData.FromString(item.GetRawText())); + } + } + tools = array; + continue; + } + if (property.NameEquals("file_ids"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(item.GetString()); + } + fileIds = array; + continue; + } + if (property.NameEquals("metadata"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + Dictionary dictionary = new Dictionary(); + foreach (var property0 in property.Value.EnumerateObject()) + { + dictionary.Add(property0.Name, property0.Value.GetString()); + } + metadata = dictionary; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateAssistantRequest(model, name.Value, description.Value, instructions.Value, OptionalProperty.ToList(tools), OptionalProperty.ToList(fileIds), OptionalProperty.ToDictionary(metadata), serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateAssistantRequest)} does not support '{options.Format}' format."); + } + } + + CreateAssistantRequest IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateAssistantRequest(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateAssistantRequest)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateAssistantRequest FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateAssistantRequest(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateAssistantRequest.cs b/.dotnet/src/Generated/Models/CreateAssistantRequest.cs new file mode 100644 index 000000000..115fbc0d9 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateAssistantRequest.cs @@ -0,0 +1,161 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateAssistantRequest. + public partial class CreateAssistantRequest + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + /// see all of your available models, or see our [Model overview](/docs/models/overview) for + /// descriptions of them. + /// + /// is null. + public CreateAssistantRequest(string model) + { + ClientUtilities.AssertNotNull(model, nameof(model)); + + Model = model; + Tools = new OptionalList(); + FileIds = new OptionalList(); + Metadata = new OptionalDictionary(); + } + + /// Initializes a new instance of . + /// + /// ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + /// see all of your available models, or see our [Model overview](/docs/models/overview) for + /// descriptions of them. + /// + /// The name of the assistant. The maximum length is 256 characters. + /// The description of the assistant. The maximum length is 512 characters. + /// The system instructions that the assistant uses. The maximum length is 32768 characters. + /// + /// A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. + /// Tools can be of types `code_interpreter`, `retrieval`, or `function`. + /// + /// + /// A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a + /// maximum of 20 files attached to the assistant. Files are ordered by their creation date in + /// ascending order. + /// + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// Keeps track of any properties unknown to the library. + internal CreateAssistantRequest(string model, string name, string description, string instructions, IList tools, IList fileIds, IDictionary metadata, IDictionary serializedAdditionalRawData) + { + Model = model; + Name = name; + Description = description; + Instructions = instructions; + Tools = tools; + FileIds = fileIds; + Metadata = metadata; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateAssistantRequest() + { + } + + /// + /// ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + /// see all of your available models, or see our [Model overview](/docs/models/overview) for + /// descriptions of them. + /// + public string Model { get; } + /// The name of the assistant. The maximum length is 256 characters. + public string Name { get; set; } + /// The description of the assistant. The maximum length is 512 characters. + public string Description { get; set; } + /// The system instructions that the assistant uses. The maximum length is 32768 characters. + public string Instructions { get; set; } + /// + /// A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. + /// Tools can be of types `code_interpreter`, `retrieval`, or `function`. + /// + /// To assign an object to the element of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + public IList Tools { get; } + /// + /// A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a + /// maximum of 20 files attached to the assistant. Files are ordered by their creation date in + /// ascending order. + /// + public IList FileIds { get; } + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + public IDictionary Metadata { get; set; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateChatCompletionRequest.Serialization.cs new file mode 100644 index 000000000..66c50785a --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateChatCompletionRequest.Serialization.cs @@ -0,0 +1,582 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateChatCompletionRequest : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateChatCompletionRequest)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("messages"u8); + writer.WriteStartArray(); + foreach (var item in Messages) + { + if (item == null) + { + writer.WriteNullValue(); + continue; + } +#if NET6_0_OR_GREATER + writer.WriteRawValue(item); +#else + using (JsonDocument document = JsonDocument.Parse(item)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + writer.WriteEndArray(); + writer.WritePropertyName("model"u8); + writer.WriteStringValue(Model.ToString()); + if (OptionalProperty.IsDefined(FrequencyPenalty)) + { + if (FrequencyPenalty != null) + { + writer.WritePropertyName("frequency_penalty"u8); + writer.WriteNumberValue(FrequencyPenalty.Value); + } + else + { + writer.WriteNull("frequency_penalty"); + } + } + if (OptionalProperty.IsCollectionDefined(LogitBias)) + { + if (LogitBias != null) + { + writer.WritePropertyName("logit_bias"u8); + writer.WriteStartObject(); + foreach (var item in LogitBias) + { + writer.WritePropertyName(item.Key); + writer.WriteNumberValue(item.Value); + } + writer.WriteEndObject(); + } + else + { + writer.WriteNull("logit_bias"); + } + } + if (OptionalProperty.IsDefined(Logprobs)) + { + if (Logprobs != null) + { + writer.WritePropertyName("logprobs"u8); + writer.WriteBooleanValue(Logprobs.Value); + } + else + { + writer.WriteNull("logprobs"); + } + } + if (OptionalProperty.IsDefined(TopLogprobs)) + { + if (TopLogprobs != null) + { + writer.WritePropertyName("top_logprobs"u8); + writer.WriteNumberValue(TopLogprobs.Value); + } + else + { + writer.WriteNull("top_logprobs"); + } + } + if (OptionalProperty.IsDefined(MaxTokens)) + { + if (MaxTokens != null) + { + writer.WritePropertyName("max_tokens"u8); + writer.WriteNumberValue(MaxTokens.Value); + } + else + { + writer.WriteNull("max_tokens"); + } + } + if (OptionalProperty.IsDefined(N)) + { + if (N != null) + { + writer.WritePropertyName("n"u8); + writer.WriteNumberValue(N.Value); + } + else + { + writer.WriteNull("n"); + } + } + if (OptionalProperty.IsDefined(PresencePenalty)) + { + if (PresencePenalty != null) + { + writer.WritePropertyName("presence_penalty"u8); + writer.WriteNumberValue(PresencePenalty.Value); + } + else + { + writer.WriteNull("presence_penalty"); + } + } + if (OptionalProperty.IsDefined(ResponseFormat)) + { + writer.WritePropertyName("response_format"u8); + writer.WriteObjectValue(ResponseFormat); + } + if (OptionalProperty.IsDefined(Seed)) + { + if (Seed != null) + { + writer.WritePropertyName("seed"u8); + writer.WriteNumberValue(Seed.Value); + } + else + { + writer.WriteNull("seed"); + } + } + if (OptionalProperty.IsDefined(Stop)) + { + if (Stop != null) + { + writer.WritePropertyName("stop"u8); +#if NET6_0_OR_GREATER + writer.WriteRawValue(Stop); +#else + using (JsonDocument document = JsonDocument.Parse(Stop)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + else + { + writer.WriteNull("stop"); + } + } + if (OptionalProperty.IsDefined(Stream)) + { + if (Stream != null) + { + writer.WritePropertyName("stream"u8); + writer.WriteBooleanValue(Stream.Value); + } + else + { + writer.WriteNull("stream"); + } + } + if (OptionalProperty.IsDefined(Temperature)) + { + if (Temperature != null) + { + writer.WritePropertyName("temperature"u8); + writer.WriteNumberValue(Temperature.Value); + } + else + { + writer.WriteNull("temperature"); + } + } + if (OptionalProperty.IsDefined(TopP)) + { + if (TopP != null) + { + writer.WritePropertyName("top_p"u8); + writer.WriteNumberValue(TopP.Value); + } + else + { + writer.WriteNull("top_p"); + } + } + if (OptionalProperty.IsCollectionDefined(Tools)) + { + writer.WritePropertyName("tools"u8); + writer.WriteStartArray(); + foreach (var item in Tools) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + } + if (OptionalProperty.IsDefined(ToolChoice)) + { + writer.WritePropertyName("tool_choice"u8); +#if NET6_0_OR_GREATER + writer.WriteRawValue(ToolChoice); +#else + using (JsonDocument document = JsonDocument.Parse(ToolChoice)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + if (OptionalProperty.IsDefined(User)) + { + writer.WritePropertyName("user"u8); + writer.WriteStringValue(User); + } + if (OptionalProperty.IsDefined(FunctionCall)) + { + writer.WritePropertyName("function_call"u8); +#if NET6_0_OR_GREATER + writer.WriteRawValue(FunctionCall); +#else + using (JsonDocument document = JsonDocument.Parse(FunctionCall)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + if (OptionalProperty.IsCollectionDefined(Functions)) + { + writer.WritePropertyName("functions"u8); + writer.WriteStartArray(); + foreach (var item in Functions) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateChatCompletionRequest IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateChatCompletionRequest)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateChatCompletionRequest(document.RootElement, options); + } + + internal static CreateChatCompletionRequest DeserializeCreateChatCompletionRequest(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + IList messages = default; + CreateChatCompletionRequestModel model = default; + OptionalProperty frequencyPenalty = default; + OptionalProperty> logitBias = default; + OptionalProperty logprobs = default; + OptionalProperty topLogprobs = default; + OptionalProperty maxTokens = default; + OptionalProperty n = default; + OptionalProperty presencePenalty = default; + OptionalProperty responseFormat = default; + OptionalProperty seed = default; + OptionalProperty stop = default; + OptionalProperty stream = default; + OptionalProperty temperature = default; + OptionalProperty topP = default; + OptionalProperty> tools = default; + OptionalProperty toolChoice = default; + OptionalProperty user = default; + OptionalProperty functionCall = default; + OptionalProperty> functions = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("messages"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + if (item.ValueKind == JsonValueKind.Null) + { + array.Add(null); + } + else + { + array.Add(BinaryData.FromString(item.GetRawText())); + } + } + messages = array; + continue; + } + if (property.NameEquals("model"u8)) + { + model = new CreateChatCompletionRequestModel(property.Value.GetString()); + continue; + } + if (property.NameEquals("frequency_penalty"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + frequencyPenalty = null; + continue; + } + frequencyPenalty = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("logit_bias"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + Dictionary dictionary = new Dictionary(); + foreach (var property0 in property.Value.EnumerateObject()) + { + dictionary.Add(property0.Name, property0.Value.GetInt64()); + } + logitBias = dictionary; + continue; + } + if (property.NameEquals("logprobs"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + logprobs = null; + continue; + } + logprobs = property.Value.GetBoolean(); + continue; + } + if (property.NameEquals("top_logprobs"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + topLogprobs = null; + continue; + } + topLogprobs = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("max_tokens"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + maxTokens = null; + continue; + } + maxTokens = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("n"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + n = null; + continue; + } + n = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("presence_penalty"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + presencePenalty = null; + continue; + } + presencePenalty = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("response_format"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + responseFormat = CreateChatCompletionRequestResponseFormat.DeserializeCreateChatCompletionRequestResponseFormat(property.Value); + continue; + } + if (property.NameEquals("seed"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + seed = null; + continue; + } + seed = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("stop"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + stop = null; + continue; + } + stop = BinaryData.FromString(property.Value.GetRawText()); + continue; + } + if (property.NameEquals("stream"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + stream = null; + continue; + } + stream = property.Value.GetBoolean(); + continue; + } + if (property.NameEquals("temperature"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + temperature = null; + continue; + } + temperature = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("top_p"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + topP = null; + continue; + } + topP = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("tools"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(ChatCompletionTool.DeserializeChatCompletionTool(item)); + } + tools = array; + continue; + } + if (property.NameEquals("tool_choice"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + toolChoice = BinaryData.FromString(property.Value.GetRawText()); + continue; + } + if (property.NameEquals("user"u8)) + { + user = property.Value.GetString(); + continue; + } + if (property.NameEquals("function_call"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + functionCall = BinaryData.FromString(property.Value.GetRawText()); + continue; + } + if (property.NameEquals("functions"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(ChatCompletionFunctions.DeserializeChatCompletionFunctions(item)); + } + functions = array; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateChatCompletionRequest(messages, model, OptionalProperty.ToNullable(frequencyPenalty), OptionalProperty.ToDictionary(logitBias), OptionalProperty.ToNullable(logprobs), OptionalProperty.ToNullable(topLogprobs), OptionalProperty.ToNullable(maxTokens), OptionalProperty.ToNullable(n), OptionalProperty.ToNullable(presencePenalty), responseFormat.Value, OptionalProperty.ToNullable(seed), stop.Value, OptionalProperty.ToNullable(stream), OptionalProperty.ToNullable(temperature), OptionalProperty.ToNullable(topP), OptionalProperty.ToList(tools), toolChoice.Value, user.Value, functionCall.Value, OptionalProperty.ToList(functions), serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateChatCompletionRequest)} does not support '{options.Format}' format."); + } + } + + CreateChatCompletionRequest IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateChatCompletionRequest(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateChatCompletionRequest)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateChatCompletionRequest FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateChatCompletionRequest(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionRequest.cs b/.dotnet/src/Generated/Models/CreateChatCompletionRequest.cs new file mode 100644 index 000000000..c773e9297 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateChatCompletionRequest.cs @@ -0,0 +1,512 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// The CreateChatCompletionRequest. + public partial class CreateChatCompletionRequest + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// A list of messages comprising the conversation so far. + /// [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb). + /// + /// + /// ID of the model to use. See the [model endpoint compatibility](/docs/models/model-endpoint-compatibility) + /// table for details on which models work with the Chat API. + /// + /// is null. + public CreateChatCompletionRequest(IEnumerable messages, CreateChatCompletionRequestModel model) + { + ClientUtilities.AssertNotNull(messages, nameof(messages)); + + Messages = messages.ToList(); + Model = model; + LogitBias = new OptionalDictionary(); + Tools = new OptionalList(); + Functions = new OptionalList(); + } + + /// Initializes a new instance of . + /// + /// A list of messages comprising the conversation so far. + /// [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb). + /// + /// + /// ID of the model to use. See the [model endpoint compatibility](/docs/models/model-endpoint-compatibility) + /// table for details on which models work with the Chat API. + /// + /// + /// Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing + /// frequency in the text so far, decreasing the model's likelihood to repeat the same line + /// verbatim. + /// + /// [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) + /// + /// + /// Modify the likelihood of specified tokens appearing in the completion. + /// + /// Accepts a JSON object that maps tokens (specified by their token ID in the tokenizer) to an + /// associated bias value from -100 to 100. Mathematically, the bias is added to the logits + /// generated by the model prior to sampling. The exact effect will vary per model, but values + /// between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 + /// should result in a ban or exclusive selection of the relevant token. + /// + /// + /// Whether to return log probabilities of the output tokens or not. If true, returns the log + /// probabilities of each output token returned in the `content` of `message`. This option is + /// currently not available on the `gpt-4-vision-preview` model. + /// + /// + /// An integer between 0 and 5 specifying the number of most likely tokens to return at each token + /// position, each with an associated log probability. `logprobs` must be set to `true` if this + /// parameter is used. + /// + /// + /// The maximum number of [tokens](/tokenizer) that can be generated in the chat completion. + /// + /// The total length of input tokens and generated tokens is limited by the model's context length. + /// [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) + /// for counting tokens. + /// + /// + /// How many chat completion choices to generate for each input message. Note that you will be + /// charged based on the number of generated tokens across all of the choices. Keep `n` as `1` to + /// minimize costs. + /// + /// + /// Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear + /// in the text so far, increasing the model's likelihood to talk about new topics. + /// + /// [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) + /// + /// + /// An object specifying the format that the model must output. Compatible with + /// [GPT-4 Turbo](/docs/models/gpt-4-and-gpt-4-turbo) and `gpt-3.5-turbo-1106`. + /// + /// 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. + /// + /// + /// This feature is in Beta. + /// + /// If specified, our system will make a best effort to sample deterministically, such that + /// repeated requests with the same `seed` and parameters should return the same result. + /// + /// Determinism is not guaranteed, and you should refer to the `system_fingerprint` response + /// parameter to monitor changes in the backend. + /// + /// Up to 4 sequences where the API will stop generating further tokens. + /// + /// If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only + /// [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) + /// as they become available, with the stream terminated by a `data: [DONE]` message. + /// [Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions). + /// + /// + /// What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output + /// more random, while lower values like 0.2 will make it more focused and deterministic. + /// + /// We generally recommend altering this or `top_p` but not both. + /// + /// + /// An alternative to sampling with temperature, called nucleus sampling, where the model considers + /// the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising + /// the top 10% probability mass are considered. + /// + /// We generally recommend altering this or `temperature` but not both. + /// + /// + /// A list of tools the model may call. Currently, only functions are supported as a tool. Use this + /// to provide a list of functions the model may generate JSON inputs for. + /// + /// + /// + /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect + /// abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + /// + /// + /// Deprecated in favor of `tool_choice`. + /// + /// Controls which (if any) function is called by the model. `none` means the model will not call a + /// function and instead generates a message. `auto` means the model can pick between generating a + /// message or calling a function. Specifying a particular function via `{"name": "my_function"}` + /// forces the model to call that function. + /// + /// `none` is the default when no functions are present. `auto` is the default if functions are + /// present. + /// + /// + /// Deprecated in favor of `tools`. + /// + /// A list of functions the model may generate JSON inputs for. + /// + /// Keeps track of any properties unknown to the library. + internal CreateChatCompletionRequest(IList messages, CreateChatCompletionRequestModel model, double? frequencyPenalty, IDictionary logitBias, bool? logprobs, long? topLogprobs, long? maxTokens, long? n, double? presencePenalty, CreateChatCompletionRequestResponseFormat responseFormat, long? seed, BinaryData stop, bool? stream, double? temperature, double? topP, IList tools, BinaryData toolChoice, string user, BinaryData functionCall, IList functions, IDictionary serializedAdditionalRawData) + { + Messages = messages; + Model = model; + FrequencyPenalty = frequencyPenalty; + LogitBias = logitBias; + Logprobs = logprobs; + TopLogprobs = topLogprobs; + MaxTokens = maxTokens; + N = n; + PresencePenalty = presencePenalty; + ResponseFormat = responseFormat; + Seed = seed; + Stop = stop; + Stream = stream; + Temperature = temperature; + TopP = topP; + Tools = tools; + ToolChoice = toolChoice; + User = user; + FunctionCall = functionCall; + Functions = functions; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateChatCompletionRequest() + { + } + + /// + /// A list of messages comprising the conversation so far. + /// [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb). + /// + /// To assign an object to the element of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + public IList Messages { get; } + /// + /// ID of the model to use. See the [model endpoint compatibility](/docs/models/model-endpoint-compatibility) + /// table for details on which models work with the Chat API. + /// + public CreateChatCompletionRequestModel Model { get; } + /// + /// Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing + /// frequency in the text so far, decreasing the model's likelihood to repeat the same line + /// verbatim. + /// + /// [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) + /// + public double? FrequencyPenalty { get; set; } + /// + /// Modify the likelihood of specified tokens appearing in the completion. + /// + /// Accepts a JSON object that maps tokens (specified by their token ID in the tokenizer) to an + /// associated bias value from -100 to 100. Mathematically, the bias is added to the logits + /// generated by the model prior to sampling. The exact effect will vary per model, but values + /// between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 + /// should result in a ban or exclusive selection of the relevant token. + /// + public IDictionary LogitBias { get; set; } + /// + /// Whether to return log probabilities of the output tokens or not. If true, returns the log + /// probabilities of each output token returned in the `content` of `message`. This option is + /// currently not available on the `gpt-4-vision-preview` model. + /// + public bool? Logprobs { get; set; } + /// + /// An integer between 0 and 5 specifying the number of most likely tokens to return at each token + /// position, each with an associated log probability. `logprobs` must be set to `true` if this + /// parameter is used. + /// + public long? TopLogprobs { get; set; } + /// + /// The maximum number of [tokens](/tokenizer) that can be generated in the chat completion. + /// + /// The total length of input tokens and generated tokens is limited by the model's context length. + /// [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) + /// for counting tokens. + /// + public long? MaxTokens { get; set; } + /// + /// How many chat completion choices to generate for each input message. Note that you will be + /// charged based on the number of generated tokens across all of the choices. Keep `n` as `1` to + /// minimize costs. + /// + public long? N { get; set; } + /// + /// Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear + /// in the text so far, increasing the model's likelihood to talk about new topics. + /// + /// [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) + /// + public double? PresencePenalty { get; set; } + /// + /// An object specifying the format that the model must output. Compatible with + /// [GPT-4 Turbo](/docs/models/gpt-4-and-gpt-4-turbo) and `gpt-3.5-turbo-1106`. + /// + /// 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. + /// + public CreateChatCompletionRequestResponseFormat ResponseFormat { get; set; } + /// + /// This feature is in Beta. + /// + /// If specified, our system will make a best effort to sample deterministically, such that + /// repeated requests with the same `seed` and parameters should return the same result. + /// + /// Determinism is not guaranteed, and you should refer to the `system_fingerprint` response + /// parameter to monitor changes in the backend. + /// + public long? Seed { get; set; } + /// + /// Up to 4 sequences where the API will stop generating further tokens. + /// + /// To assign an object to this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// + /// Supported types: + /// + /// + /// + /// + /// + /// where T is of type + /// + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + public BinaryData Stop { get; set; } + /// + /// If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only + /// [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) + /// as they become available, with the stream terminated by a `data: [DONE]` message. + /// [Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions). + /// + public bool? Stream { get; set; } + /// + /// What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output + /// more random, while lower values like 0.2 will make it more focused and deterministic. + /// + /// We generally recommend altering this or `top_p` but not both. + /// + public double? Temperature { get; set; } + /// + /// An alternative to sampling with temperature, called nucleus sampling, where the model considers + /// the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising + /// the top 10% probability mass are considered. + /// + /// We generally recommend altering this or `temperature` but not both. + /// + public double? TopP { get; set; } + /// + /// A list of tools the model may call. Currently, only functions are supported as a tool. Use this + /// to provide a list of functions the model may generate JSON inputs for. + /// + public IList Tools { get; } + /// + /// Gets or sets the tool choice + /// + /// To assign an object to this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// + /// Supported types: + /// + /// + /// "none" + /// + /// + /// "auto" + /// + /// + /// + /// + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + public BinaryData ToolChoice { get; set; } + /// + /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect + /// abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + /// + public string User { get; set; } + /// + /// Deprecated in favor of `tool_choice`. + /// + /// Controls which (if any) function is called by the model. `none` means the model will not call a + /// function and instead generates a message. `auto` means the model can pick between generating a + /// message or calling a function. Specifying a particular function via `{"name": "my_function"}` + /// forces the model to call that function. + /// + /// `none` is the default when no functions are present. `auto` is the default if functions are + /// present. + /// + /// To assign an object to this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// + /// Supported types: + /// + /// + /// "none" + /// + /// + /// "auto" + /// + /// + /// + /// + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + public BinaryData FunctionCall { get; set; } + /// + /// Deprecated in favor of `tools`. + /// + /// A list of functions the model may generate JSON inputs for. + /// + public IList Functions { get; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionRequestModel.cs b/.dotnet/src/Generated/Models/CreateChatCompletionRequestModel.cs new file mode 100644 index 000000000..a0c497c47 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateChatCompletionRequestModel.cs @@ -0,0 +1,90 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for model in CreateChatCompletionRequest. + public readonly partial struct CreateChatCompletionRequestModel : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateChatCompletionRequestModel(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string Gpt40125PreviewValue = "gpt-4-0125-preview"; + private const string Gpt4TurboPreviewValue = "gpt-4-turbo-preview"; + private const string Gpt41106PreviewValue = "gpt-4-1106-preview"; + private const string Gpt4VisionPreviewValue = "gpt-4-vision-preview"; + private const string Gpt4Value = "gpt-4"; + private const string Gpt40314Value = "gpt-4-0314"; + private const string Gpt40613Value = "gpt-4-0613"; + private const string Gpt432kValue = "gpt-4-32k"; + private const string Gpt432k0314Value = "gpt-4-32k-0314"; + private const string Gpt432k0613Value = "gpt-4-32k-0613"; + private const string Gpt35TurboValue = "gpt-3.5-turbo"; + private const string Gpt35Turbo16kValue = "gpt-3.5-turbo-16k"; + private const string Gpt35Turbo0301Value = "gpt-3.5-turbo-0301"; + private const string Gpt35Turbo0613Value = "gpt-3.5-turbo-0613"; + private const string Gpt35Turbo1106Value = "gpt-3.5-turbo-1106"; + private const string Gpt35Turbo16k0613Value = "gpt-3.5-turbo-16k-0613"; + + /// gpt-4-0125-preview. + public static CreateChatCompletionRequestModel Gpt40125Preview { get; } = new CreateChatCompletionRequestModel(Gpt40125PreviewValue); + /// gpt-4-turbo-preview. + public static CreateChatCompletionRequestModel Gpt4TurboPreview { get; } = new CreateChatCompletionRequestModel(Gpt4TurboPreviewValue); + /// gpt-4-1106-preview. + public static CreateChatCompletionRequestModel Gpt41106Preview { get; } = new CreateChatCompletionRequestModel(Gpt41106PreviewValue); + /// gpt-4-vision-preview. + public static CreateChatCompletionRequestModel Gpt4VisionPreview { get; } = new CreateChatCompletionRequestModel(Gpt4VisionPreviewValue); + /// gpt-4. + public static CreateChatCompletionRequestModel Gpt4 { get; } = new CreateChatCompletionRequestModel(Gpt4Value); + /// gpt-4-0314. + public static CreateChatCompletionRequestModel Gpt40314 { get; } = new CreateChatCompletionRequestModel(Gpt40314Value); + /// gpt-4-0613. + public static CreateChatCompletionRequestModel Gpt40613 { get; } = new CreateChatCompletionRequestModel(Gpt40613Value); + /// gpt-4-32k. + public static CreateChatCompletionRequestModel Gpt432k { get; } = new CreateChatCompletionRequestModel(Gpt432kValue); + /// gpt-4-32k-0314. + public static CreateChatCompletionRequestModel Gpt432k0314 { get; } = new CreateChatCompletionRequestModel(Gpt432k0314Value); + /// gpt-4-32k-0613. + public static CreateChatCompletionRequestModel Gpt432k0613 { get; } = new CreateChatCompletionRequestModel(Gpt432k0613Value); + /// gpt-3.5-turbo. + public static CreateChatCompletionRequestModel Gpt35Turbo { get; } = new CreateChatCompletionRequestModel(Gpt35TurboValue); + /// gpt-3.5-turbo-16k. + public static CreateChatCompletionRequestModel Gpt35Turbo16k { get; } = new CreateChatCompletionRequestModel(Gpt35Turbo16kValue); + /// gpt-3.5-turbo-0301. + public static CreateChatCompletionRequestModel Gpt35Turbo0301 { get; } = new CreateChatCompletionRequestModel(Gpt35Turbo0301Value); + /// gpt-3.5-turbo-0613. + public static CreateChatCompletionRequestModel Gpt35Turbo0613 { get; } = new CreateChatCompletionRequestModel(Gpt35Turbo0613Value); + /// gpt-3.5-turbo-1106. + public static CreateChatCompletionRequestModel Gpt35Turbo1106 { get; } = new CreateChatCompletionRequestModel(Gpt35Turbo1106Value); + /// gpt-3.5-turbo-16k-0613. + public static CreateChatCompletionRequestModel Gpt35Turbo16k0613 { get; } = new CreateChatCompletionRequestModel(Gpt35Turbo16k0613Value); + /// Determines if two values are the same. + public static bool operator ==(CreateChatCompletionRequestModel left, CreateChatCompletionRequestModel right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateChatCompletionRequestModel left, CreateChatCompletionRequestModel right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateChatCompletionRequestModel(string value) => new CreateChatCompletionRequestModel(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateChatCompletionRequestModel other && Equals(other); + /// + public bool Equals(CreateChatCompletionRequestModel other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.Serialization.cs b/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.Serialization.cs new file mode 100644 index 000000000..ecd0ac9b1 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.Serialization.cs @@ -0,0 +1,139 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateChatCompletionRequestResponseFormat : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateChatCompletionRequestResponseFormat)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + if (OptionalProperty.IsDefined(Type)) + { + writer.WritePropertyName("type"u8); + writer.WriteStringValue(Type.Value.ToString()); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateChatCompletionRequestResponseFormat IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateChatCompletionRequestResponseFormat)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateChatCompletionRequestResponseFormat(document.RootElement, options); + } + + internal static CreateChatCompletionRequestResponseFormat DeserializeCreateChatCompletionRequestResponseFormat(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + OptionalProperty type = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("type"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + type = new CreateChatCompletionRequestResponseFormatType(property.Value.GetString()); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateChatCompletionRequestResponseFormat(OptionalProperty.ToNullable(type), serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateChatCompletionRequestResponseFormat)} does not support '{options.Format}' format."); + } + } + + CreateChatCompletionRequestResponseFormat IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateChatCompletionRequestResponseFormat(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateChatCompletionRequestResponseFormat)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateChatCompletionRequestResponseFormat FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateChatCompletionRequestResponseFormat(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.cs b/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.cs new file mode 100644 index 000000000..5c8f4c2c0 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.cs @@ -0,0 +1,62 @@ +// + +#nullable disable + +using System; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateChatCompletionRequestResponseFormat. + public partial class CreateChatCompletionRequestResponseFormat + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + public CreateChatCompletionRequestResponseFormat() + { + } + + /// Initializes a new instance of . + /// Must be one of `text` or `json_object`. + /// Keeps track of any properties unknown to the library. + internal CreateChatCompletionRequestResponseFormat(CreateChatCompletionRequestResponseFormatType? type, IDictionary serializedAdditionalRawData) + { + Type = type; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Must be one of `text` or `json_object`. + public CreateChatCompletionRequestResponseFormatType? Type { get; set; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormatType.cs b/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormatType.cs new file mode 100644 index 000000000..d0332868f --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormatType.cs @@ -0,0 +1,48 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for type in CreateChatCompletionRequestResponseFormat. + public readonly partial struct CreateChatCompletionRequestResponseFormatType : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateChatCompletionRequestResponseFormatType(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string TextValue = "text"; + private const string JsonObjectValue = "json_object"; + + /// text. + public static CreateChatCompletionRequestResponseFormatType Text { get; } = new CreateChatCompletionRequestResponseFormatType(TextValue); + /// json_object. + public static CreateChatCompletionRequestResponseFormatType JsonObject { get; } = new CreateChatCompletionRequestResponseFormatType(JsonObjectValue); + /// Determines if two values are the same. + public static bool operator ==(CreateChatCompletionRequestResponseFormatType left, CreateChatCompletionRequestResponseFormatType right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateChatCompletionRequestResponseFormatType left, CreateChatCompletionRequestResponseFormatType right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateChatCompletionRequestResponseFormatType(string value) => new CreateChatCompletionRequestResponseFormatType(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateChatCompletionRequestResponseFormatType other && Equals(other); + /// + public bool Equals(CreateChatCompletionRequestResponseFormatType other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponse.Serialization.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponse.Serialization.cs new file mode 100644 index 000000000..c560aa105 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponse.Serialization.cs @@ -0,0 +1,200 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateChatCompletionResponse : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateChatCompletionResponse)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("id"u8); + writer.WriteStringValue(Id); + writer.WritePropertyName("choices"u8); + writer.WriteStartArray(); + foreach (var item in Choices) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + writer.WritePropertyName("created"u8); + writer.WriteNumberValue(Created, "U"); + writer.WritePropertyName("model"u8); + writer.WriteStringValue(Model); + if (OptionalProperty.IsDefined(SystemFingerprint)) + { + writer.WritePropertyName("system_fingerprint"u8); + writer.WriteStringValue(SystemFingerprint); + } + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + if (OptionalProperty.IsDefined(Usage)) + { + writer.WritePropertyName("usage"u8); + writer.WriteObjectValue(Usage); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateChatCompletionResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateChatCompletionResponse)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateChatCompletionResponse(document.RootElement, options); + } + + internal static CreateChatCompletionResponse DeserializeCreateChatCompletionResponse(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string id = default; + IReadOnlyList choices = default; + DateTimeOffset created = default; + string model = default; + OptionalProperty systemFingerprint = default; + CreateChatCompletionResponseObject @object = default; + OptionalProperty usage = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetString(); + continue; + } + if (property.NameEquals("choices"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(CreateChatCompletionResponseChoice.DeserializeCreateChatCompletionResponseChoice(item)); + } + choices = array; + continue; + } + if (property.NameEquals("created"u8)) + { + created = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); + continue; + } + if (property.NameEquals("model"u8)) + { + model = property.Value.GetString(); + continue; + } + if (property.NameEquals("system_fingerprint"u8)) + { + systemFingerprint = property.Value.GetString(); + continue; + } + if (property.NameEquals("object"u8)) + { + @object = new CreateChatCompletionResponseObject(property.Value.GetString()); + continue; + } + if (property.NameEquals("usage"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + usage = CompletionUsage.DeserializeCompletionUsage(property.Value); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateChatCompletionResponse(id, choices, created, model, systemFingerprint.Value, @object, usage.Value, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateChatCompletionResponse)} does not support '{options.Format}' format."); + } + } + + CreateChatCompletionResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateChatCompletionResponse(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateChatCompletionResponse)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateChatCompletionResponse FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateChatCompletionResponse(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponse.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponse.cs new file mode 100644 index 000000000..cc16880d8 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponse.cs @@ -0,0 +1,117 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// Represents a chat completion response returned by model, based on the provided input. + public partial class CreateChatCompletionResponse + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// A unique identifier for the chat completion. + /// A list of chat completion choices. Can be more than one if `n` is greater than 1. + /// The Unix timestamp (in seconds) of when the chat completion was created. + /// The model used for the chat completion. + /// , or is null. + internal CreateChatCompletionResponse(string id, IEnumerable choices, DateTimeOffset created, string model) + { + ClientUtilities.AssertNotNull(id, nameof(id)); + ClientUtilities.AssertNotNull(choices, nameof(choices)); + ClientUtilities.AssertNotNull(model, nameof(model)); + + Id = id; + Choices = choices.ToList(); + Created = created; + Model = model; + } + + /// Initializes a new instance of . + /// A unique identifier for the chat completion. + /// A list of chat completion choices. Can be more than one if `n` is greater than 1. + /// The Unix timestamp (in seconds) of when the chat completion was created. + /// The model used for the chat completion. + /// + /// 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. + /// + /// The object type, which is always `chat.completion`. + /// + /// Keeps track of any properties unknown to the library. + internal CreateChatCompletionResponse(string id, IReadOnlyList choices, DateTimeOffset created, string model, string systemFingerprint, CreateChatCompletionResponseObject @object, CompletionUsage usage, IDictionary serializedAdditionalRawData) + { + Id = id; + Choices = choices; + Created = created; + Model = model; + SystemFingerprint = systemFingerprint; + Object = @object; + Usage = usage; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateChatCompletionResponse() + { + } + + /// A unique identifier for the chat completion. + public string Id { get; } + /// A list of chat completion choices. Can be more than one if `n` is greater than 1. + public IReadOnlyList Choices { get; } + /// The Unix timestamp (in seconds) of when the chat completion was created. + public DateTimeOffset Created { get; } + /// The model used for the chat completion. + public string Model { get; } + /// + /// 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. + /// + public string SystemFingerprint { get; } + /// The object type, which is always `chat.completion`. + public CreateChatCompletionResponseObject Object { get; } = CreateChatCompletionResponseObject.ChatCompletion; + + /// Gets the usage. + public CompletionUsage Usage { get; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.Serialization.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.Serialization.cs new file mode 100644 index 000000000..8663dced6 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.Serialization.cs @@ -0,0 +1,168 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateChatCompletionResponseChoice : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateChatCompletionResponseChoice)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("finish_reason"u8); + writer.WriteStringValue(FinishReason.ToString()); + writer.WritePropertyName("index"u8); + writer.WriteNumberValue(Index); + writer.WritePropertyName("message"u8); + writer.WriteObjectValue(Message); + if (Logprobs != null) + { + writer.WritePropertyName("logprobs"u8); + writer.WriteObjectValue(Logprobs); + } + else + { + writer.WriteNull("logprobs"); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateChatCompletionResponseChoice IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateChatCompletionResponseChoice)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateChatCompletionResponseChoice(document.RootElement, options); + } + + internal static CreateChatCompletionResponseChoice DeserializeCreateChatCompletionResponseChoice(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + CreateChatCompletionResponseChoiceFinishReason finishReason = default; + long index = default; + ChatCompletionResponseMessage message = default; + CreateChatCompletionResponseChoiceLogprobs logprobs = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("finish_reason"u8)) + { + finishReason = new CreateChatCompletionResponseChoiceFinishReason(property.Value.GetString()); + continue; + } + if (property.NameEquals("index"u8)) + { + index = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("message"u8)) + { + message = ChatCompletionResponseMessage.DeserializeChatCompletionResponseMessage(property.Value); + continue; + } + if (property.NameEquals("logprobs"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + logprobs = null; + continue; + } + logprobs = CreateChatCompletionResponseChoiceLogprobs.DeserializeCreateChatCompletionResponseChoiceLogprobs(property.Value); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateChatCompletionResponseChoice(finishReason, index, message, logprobs, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateChatCompletionResponseChoice)} does not support '{options.Format}' format."); + } + } + + CreateChatCompletionResponseChoice IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateChatCompletionResponseChoice(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateChatCompletionResponseChoice)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateChatCompletionResponseChoice FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateChatCompletionResponseChoice(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.cs new file mode 100644 index 000000000..7a5b8c5c9 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.cs @@ -0,0 +1,109 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateChatCompletionResponseChoice. + public partial class CreateChatCompletionResponseChoice + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// The reason the model stopped generating tokens. This will be `stop` if the model hit a + /// natural stop point or a provided stop sequence, `length` if the maximum number of tokens + /// specified in the request was reached, `content_filter` if content was omitted due to a flag + /// from our content filters, `tool_calls` if the model called a tool, or `function_call` + /// (deprecated) if the model called a function. + /// + /// The index of the choice in the list of choices. + /// + /// Log probability information for the choice. + /// is null. + internal CreateChatCompletionResponseChoice(CreateChatCompletionResponseChoiceFinishReason finishReason, long index, ChatCompletionResponseMessage message, CreateChatCompletionResponseChoiceLogprobs logprobs) + { + ClientUtilities.AssertNotNull(message, nameof(message)); + + FinishReason = finishReason; + Index = index; + Message = message; + Logprobs = logprobs; + } + + /// Initializes a new instance of . + /// + /// The reason the model stopped generating tokens. This will be `stop` if the model hit a + /// natural stop point or a provided stop sequence, `length` if the maximum number of tokens + /// specified in the request was reached, `content_filter` if content was omitted due to a flag + /// from our content filters, `tool_calls` if the model called a tool, or `function_call` + /// (deprecated) if the model called a function. + /// + /// The index of the choice in the list of choices. + /// + /// Log probability information for the choice. + /// Keeps track of any properties unknown to the library. + internal CreateChatCompletionResponseChoice(CreateChatCompletionResponseChoiceFinishReason finishReason, long index, ChatCompletionResponseMessage message, CreateChatCompletionResponseChoiceLogprobs logprobs, IDictionary serializedAdditionalRawData) + { + FinishReason = finishReason; + Index = index; + Message = message; + Logprobs = logprobs; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateChatCompletionResponseChoice() + { + } + + /// + /// The reason the model stopped generating tokens. This will be `stop` if the model hit a + /// natural stop point or a provided stop sequence, `length` if the maximum number of tokens + /// specified in the request was reached, `content_filter` if content was omitted due to a flag + /// from our content filters, `tool_calls` if the model called a tool, or `function_call` + /// (deprecated) if the model called a function. + /// + public CreateChatCompletionResponseChoiceFinishReason FinishReason { get; } + /// The index of the choice in the list of choices. + public long Index { get; } + /// Gets the message. + public ChatCompletionResponseMessage Message { get; } + /// Log probability information for the choice. + public CreateChatCompletionResponseChoiceLogprobs Logprobs { get; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceFinishReason.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceFinishReason.cs new file mode 100644 index 000000000..65e41895b --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceFinishReason.cs @@ -0,0 +1,57 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for finish_reason in CreateChatCompletionResponseChoice. + public readonly partial struct CreateChatCompletionResponseChoiceFinishReason : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateChatCompletionResponseChoiceFinishReason(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string StopValue = "stop"; + private const string LengthValue = "length"; + private const string ToolCallsValue = "tool_calls"; + private const string ContentFilterValue = "content_filter"; + private const string FunctionCallValue = "function_call"; + + /// stop. + public static CreateChatCompletionResponseChoiceFinishReason Stop { get; } = new CreateChatCompletionResponseChoiceFinishReason(StopValue); + /// length. + public static CreateChatCompletionResponseChoiceFinishReason Length { get; } = new CreateChatCompletionResponseChoiceFinishReason(LengthValue); + /// tool_calls. + public static CreateChatCompletionResponseChoiceFinishReason ToolCalls { get; } = new CreateChatCompletionResponseChoiceFinishReason(ToolCallsValue); + /// content_filter. + public static CreateChatCompletionResponseChoiceFinishReason ContentFilter { get; } = new CreateChatCompletionResponseChoiceFinishReason(ContentFilterValue); + /// function_call. + public static CreateChatCompletionResponseChoiceFinishReason FunctionCall { get; } = new CreateChatCompletionResponseChoiceFinishReason(FunctionCallValue); + /// Determines if two values are the same. + public static bool operator ==(CreateChatCompletionResponseChoiceFinishReason left, CreateChatCompletionResponseChoiceFinishReason right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateChatCompletionResponseChoiceFinishReason left, CreateChatCompletionResponseChoiceFinishReason right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateChatCompletionResponseChoiceFinishReason(string value) => new CreateChatCompletionResponseChoiceFinishReason(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateChatCompletionResponseChoiceFinishReason other && Equals(other); + /// + public bool Equals(CreateChatCompletionResponseChoiceFinishReason other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.Serialization.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.Serialization.cs new file mode 100644 index 000000000..8893ed290 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.Serialization.cs @@ -0,0 +1,154 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateChatCompletionResponseChoiceLogprobs : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateChatCompletionResponseChoiceLogprobs)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + if (Content != null && OptionalProperty.IsCollectionDefined(Content)) + { + writer.WritePropertyName("content"u8); + writer.WriteStartArray(); + foreach (var item in Content) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + } + else + { + writer.WriteNull("content"); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateChatCompletionResponseChoiceLogprobs IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateChatCompletionResponseChoiceLogprobs)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateChatCompletionResponseChoiceLogprobs(document.RootElement, options); + } + + internal static CreateChatCompletionResponseChoiceLogprobs DeserializeCreateChatCompletionResponseChoiceLogprobs(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + IReadOnlyList content = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("content"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + content = new OptionalList(); + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(ChatCompletionTokenLogprob.DeserializeChatCompletionTokenLogprob(item)); + } + content = array; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateChatCompletionResponseChoiceLogprobs(content, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateChatCompletionResponseChoiceLogprobs)} does not support '{options.Format}' format."); + } + } + + CreateChatCompletionResponseChoiceLogprobs IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateChatCompletionResponseChoiceLogprobs(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateChatCompletionResponseChoiceLogprobs)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateChatCompletionResponseChoiceLogprobs FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateChatCompletionResponseChoiceLogprobs(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.cs new file mode 100644 index 000000000..36cc66621 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.cs @@ -0,0 +1,70 @@ +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// The CreateChatCompletionResponseChoiceLogprobs. + public partial class CreateChatCompletionResponseChoiceLogprobs + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + internal CreateChatCompletionResponseChoiceLogprobs(IEnumerable content) + { + Content = content?.ToList(); + } + + /// Initializes a new instance of . + /// + /// Keeps track of any properties unknown to the library. + internal CreateChatCompletionResponseChoiceLogprobs(IReadOnlyList content, IDictionary serializedAdditionalRawData) + { + Content = content; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateChatCompletionResponseChoiceLogprobs() + { + } + + /// Gets the content. + public IReadOnlyList Content { get; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponseObject.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponseObject.cs new file mode 100644 index 000000000..3e2747865 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponseObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The CreateChatCompletionResponse_object. + public readonly partial struct CreateChatCompletionResponseObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateChatCompletionResponseObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string ChatCompletionValue = "chat.completion"; + + /// chat.completion. + public static CreateChatCompletionResponseObject ChatCompletion { get; } = new CreateChatCompletionResponseObject(ChatCompletionValue); + /// Determines if two values are the same. + public static bool operator ==(CreateChatCompletionResponseObject left, CreateChatCompletionResponseObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateChatCompletionResponseObject left, CreateChatCompletionResponseObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateChatCompletionResponseObject(string value) => new CreateChatCompletionResponseObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateChatCompletionResponseObject other && Equals(other); + /// + public bool Equals(CreateChatCompletionResponseObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateCompletionRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateCompletionRequest.Serialization.cs new file mode 100644 index 000000000..9d1be276a --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateCompletionRequest.Serialization.cs @@ -0,0 +1,509 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateCompletionRequest : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateCompletionRequest)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("model"u8); + writer.WriteStringValue(Model.ToString()); + if (Prompt != null) + { + writer.WritePropertyName("prompt"u8); +#if NET6_0_OR_GREATER + writer.WriteRawValue(Prompt); +#else + using (JsonDocument document = JsonDocument.Parse(Prompt)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + else + { + writer.WriteNull("prompt"); + } + if (OptionalProperty.IsDefined(BestOf)) + { + if (BestOf != null) + { + writer.WritePropertyName("best_of"u8); + writer.WriteNumberValue(BestOf.Value); + } + else + { + writer.WriteNull("best_of"); + } + } + if (OptionalProperty.IsDefined(Echo)) + { + if (Echo != null) + { + writer.WritePropertyName("echo"u8); + writer.WriteBooleanValue(Echo.Value); + } + else + { + writer.WriteNull("echo"); + } + } + if (OptionalProperty.IsDefined(FrequencyPenalty)) + { + if (FrequencyPenalty != null) + { + writer.WritePropertyName("frequency_penalty"u8); + writer.WriteNumberValue(FrequencyPenalty.Value); + } + else + { + writer.WriteNull("frequency_penalty"); + } + } + if (OptionalProperty.IsCollectionDefined(LogitBias)) + { + if (LogitBias != null) + { + writer.WritePropertyName("logit_bias"u8); + writer.WriteStartObject(); + foreach (var item in LogitBias) + { + writer.WritePropertyName(item.Key); + writer.WriteNumberValue(item.Value); + } + writer.WriteEndObject(); + } + else + { + writer.WriteNull("logit_bias"); + } + } + if (OptionalProperty.IsDefined(Logprobs)) + { + if (Logprobs != null) + { + writer.WritePropertyName("logprobs"u8); + writer.WriteNumberValue(Logprobs.Value); + } + else + { + writer.WriteNull("logprobs"); + } + } + if (OptionalProperty.IsDefined(MaxTokens)) + { + if (MaxTokens != null) + { + writer.WritePropertyName("max_tokens"u8); + writer.WriteNumberValue(MaxTokens.Value); + } + else + { + writer.WriteNull("max_tokens"); + } + } + if (OptionalProperty.IsDefined(N)) + { + if (N != null) + { + writer.WritePropertyName("n"u8); + writer.WriteNumberValue(N.Value); + } + else + { + writer.WriteNull("n"); + } + } + if (OptionalProperty.IsDefined(PresencePenalty)) + { + if (PresencePenalty != null) + { + writer.WritePropertyName("presence_penalty"u8); + writer.WriteNumberValue(PresencePenalty.Value); + } + else + { + writer.WriteNull("presence_penalty"); + } + } + if (OptionalProperty.IsDefined(Seed)) + { + if (Seed != null) + { + writer.WritePropertyName("seed"u8); + writer.WriteNumberValue(Seed.Value); + } + else + { + writer.WriteNull("seed"); + } + } + if (OptionalProperty.IsDefined(Stop)) + { + if (Stop != null) + { + writer.WritePropertyName("stop"u8); +#if NET6_0_OR_GREATER + writer.WriteRawValue(Stop); +#else + using (JsonDocument document = JsonDocument.Parse(Stop)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + else + { + writer.WriteNull("stop"); + } + } + if (OptionalProperty.IsDefined(Stream)) + { + if (Stream != null) + { + writer.WritePropertyName("stream"u8); + writer.WriteBooleanValue(Stream.Value); + } + else + { + writer.WriteNull("stream"); + } + } + if (OptionalProperty.IsDefined(Suffix)) + { + if (Suffix != null) + { + writer.WritePropertyName("suffix"u8); + writer.WriteStringValue(Suffix); + } + else + { + writer.WriteNull("suffix"); + } + } + if (OptionalProperty.IsDefined(Temperature)) + { + if (Temperature != null) + { + writer.WritePropertyName("temperature"u8); + writer.WriteNumberValue(Temperature.Value); + } + else + { + writer.WriteNull("temperature"); + } + } + if (OptionalProperty.IsDefined(TopP)) + { + if (TopP != null) + { + writer.WritePropertyName("top_p"u8); + writer.WriteNumberValue(TopP.Value); + } + else + { + writer.WriteNull("top_p"); + } + } + if (OptionalProperty.IsDefined(User)) + { + writer.WritePropertyName("user"u8); + writer.WriteStringValue(User); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateCompletionRequest IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateCompletionRequest)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateCompletionRequest(document.RootElement, options); + } + + internal static CreateCompletionRequest DeserializeCreateCompletionRequest(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + CreateCompletionRequestModel model = default; + BinaryData prompt = default; + OptionalProperty bestOf = default; + OptionalProperty echo = default; + OptionalProperty frequencyPenalty = default; + OptionalProperty> logitBias = default; + OptionalProperty logprobs = default; + OptionalProperty maxTokens = default; + OptionalProperty n = default; + OptionalProperty presencePenalty = default; + OptionalProperty seed = default; + OptionalProperty stop = default; + OptionalProperty stream = default; + OptionalProperty suffix = default; + OptionalProperty temperature = default; + OptionalProperty topP = default; + OptionalProperty user = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("model"u8)) + { + model = new CreateCompletionRequestModel(property.Value.GetString()); + continue; + } + if (property.NameEquals("prompt"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + prompt = null; + continue; + } + prompt = BinaryData.FromString(property.Value.GetRawText()); + continue; + } + if (property.NameEquals("best_of"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + bestOf = null; + continue; + } + bestOf = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("echo"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + echo = null; + continue; + } + echo = property.Value.GetBoolean(); + continue; + } + if (property.NameEquals("frequency_penalty"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + frequencyPenalty = null; + continue; + } + frequencyPenalty = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("logit_bias"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + Dictionary dictionary = new Dictionary(); + foreach (var property0 in property.Value.EnumerateObject()) + { + dictionary.Add(property0.Name, property0.Value.GetInt64()); + } + logitBias = dictionary; + continue; + } + if (property.NameEquals("logprobs"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + logprobs = null; + continue; + } + logprobs = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("max_tokens"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + maxTokens = null; + continue; + } + maxTokens = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("n"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + n = null; + continue; + } + n = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("presence_penalty"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + presencePenalty = null; + continue; + } + presencePenalty = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("seed"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + seed = null; + continue; + } + seed = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("stop"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + stop = null; + continue; + } + stop = BinaryData.FromString(property.Value.GetRawText()); + continue; + } + if (property.NameEquals("stream"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + stream = null; + continue; + } + stream = property.Value.GetBoolean(); + continue; + } + if (property.NameEquals("suffix"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + suffix = null; + continue; + } + suffix = property.Value.GetString(); + continue; + } + if (property.NameEquals("temperature"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + temperature = null; + continue; + } + temperature = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("top_p"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + topP = null; + continue; + } + topP = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("user"u8)) + { + user = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateCompletionRequest(model, prompt, OptionalProperty.ToNullable(bestOf), OptionalProperty.ToNullable(echo), OptionalProperty.ToNullable(frequencyPenalty), OptionalProperty.ToDictionary(logitBias), OptionalProperty.ToNullable(logprobs), OptionalProperty.ToNullable(maxTokens), OptionalProperty.ToNullable(n), OptionalProperty.ToNullable(presencePenalty), OptionalProperty.ToNullable(seed), stop.Value, OptionalProperty.ToNullable(stream), suffix.Value, OptionalProperty.ToNullable(temperature), OptionalProperty.ToNullable(topP), user.Value, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateCompletionRequest)} does not support '{options.Format}' format."); + } + } + + CreateCompletionRequest IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateCompletionRequest(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateCompletionRequest)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateCompletionRequest FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateCompletionRequest(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateCompletionRequest.cs b/.dotnet/src/Generated/Models/CreateCompletionRequest.cs new file mode 100644 index 000000000..7797fb2a3 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateCompletionRequest.cs @@ -0,0 +1,401 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateCompletionRequest. + public partial class CreateCompletionRequest + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + /// see all of your available models, or see our [Model overview](/docs/models/overview) for + /// descriptions of them. + /// + /// + /// The prompt(s) to generate completions for, encoded as a string, array of strings, array of + /// tokens, or array of token arrays. + /// + /// Note that <|endoftext|> is the document separator that the model sees during training, so if a + /// prompt is not specified the model will generate as if from the beginning of a new document. + /// + public CreateCompletionRequest(CreateCompletionRequestModel model, BinaryData prompt) + { + Model = model; + Prompt = prompt; + LogitBias = new OptionalDictionary(); + } + + /// Initializes a new instance of . + /// + /// ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + /// see all of your available models, or see our [Model overview](/docs/models/overview) for + /// descriptions of them. + /// + /// + /// The prompt(s) to generate completions for, encoded as a string, array of strings, array of + /// tokens, or array of token arrays. + /// + /// Note that <|endoftext|> is the document separator that the model sees during training, so if a + /// prompt is not specified the model will generate as if from the beginning of a new document. + /// + /// + /// Generates `best_of` completions server-side and returns the "best" (the one with the highest + /// log probability per token). Results cannot be streamed. + /// + /// When used with `n`, `best_of` controls the number of candidate completions and `n` specifies + /// how many to return – `best_of` must be greater than `n`. + /// + /// **Note:** Because this parameter generates many completions, it can quickly consume your token + /// quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. + /// + /// Echo back the prompt in addition to the completion. + /// + /// Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing + /// frequency in the text so far, decreasing the model's likelihood to repeat the same line + /// verbatim. + /// + /// [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) + /// + /// + /// Modify the likelihood of specified tokens appearing in the completion. + /// + /// Accepts a JSON object that maps tokens (specified by their token ID in the GPT tokenizer) to an + /// associated bias value from -100 to 100. You can use this [tokenizer tool](/tokenizer?view=bpe) + /// to convert text to token IDs. Mathematically, the bias is added to the logits generated by the + /// model prior to sampling. The exact effect will vary per model, but values between -1 and 1 + /// should decrease or increase likelihood of selection; values like -100 or 100 should result in a + /// ban or exclusive selection of the relevant token. + /// + /// As an example, you can pass `{"50256": -100}` to prevent the <|endoftext|> token from being + /// generated. + /// + /// + /// Include the log probabilities on the `logprobs` most likely tokens, as well the chosen tokens. + /// For example, if `logprobs` is 5, the API will return a list of the 5 most likely tokens. The + /// API will always return the `logprob` of the sampled token, so there may be up to `logprobs+1` + /// elements in the response. + /// + /// The maximum value for `logprobs` is 5. + /// + /// + /// The maximum number of [tokens](/tokenizer) to generate in the completion. + /// + /// The token count of your prompt plus `max_tokens` cannot exceed the model's context length. + /// [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) + /// for counting tokens. + /// + /// + /// How many completions to generate for each prompt. + /// + /// **Note:** Because this parameter generates many completions, it can quickly consume your token + /// quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. + /// + /// + /// Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear + /// in the text so far, increasing the model's likelihood to talk about new topics. + /// + /// [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) + /// + /// + /// If specified, our system will make a best effort to sample deterministically, such that + /// repeated requests with the same `seed` and parameters should return the same result. + /// + /// Determinism is not guaranteed, and you should refer to the `system_fingerprint` response + /// parameter to monitor changes in the backend. + /// + /// Up to 4 sequences where the API will stop generating further tokens. + /// + /// If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only + /// [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) + /// as they become available, with the stream terminated by a `data: [DONE]` message. + /// [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_stream_completions.ipynb). + /// + /// The suffix that comes after a completion of inserted text. + /// + /// What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output + /// more random, while lower values like 0.2 will make it more focused and deterministic. + /// + /// We generally recommend altering this or `top_p` but not both. + /// + /// + /// An alternative to sampling with temperature, called nucleus sampling, where the model considers + /// the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising + /// the top 10% probability mass are considered. + /// + /// We generally recommend altering this or `temperature` but not both. + /// + /// + /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect + /// abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + /// + /// Keeps track of any properties unknown to the library. + internal CreateCompletionRequest(CreateCompletionRequestModel model, BinaryData prompt, long? bestOf, bool? echo, double? frequencyPenalty, IDictionary logitBias, long? logprobs, long? maxTokens, long? n, double? presencePenalty, long? seed, BinaryData stop, bool? stream, string suffix, double? temperature, double? topP, string user, IDictionary serializedAdditionalRawData) + { + Model = model; + Prompt = prompt; + BestOf = bestOf; + Echo = echo; + FrequencyPenalty = frequencyPenalty; + LogitBias = logitBias; + Logprobs = logprobs; + MaxTokens = maxTokens; + N = n; + PresencePenalty = presencePenalty; + Seed = seed; + Stop = stop; + Stream = stream; + Suffix = suffix; + Temperature = temperature; + TopP = topP; + User = user; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateCompletionRequest() + { + } + + /// + /// ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + /// see all of your available models, or see our [Model overview](/docs/models/overview) for + /// descriptions of them. + /// + public CreateCompletionRequestModel Model { get; } + /// + /// The prompt(s) to generate completions for, encoded as a string, array of strings, array of + /// tokens, or array of token arrays. + /// + /// Note that <|endoftext|> is the document separator that the model sees during training, so if a + /// prompt is not specified the model will generate as if from the beginning of a new document. + /// + /// To assign an object to this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// + /// Supported types: + /// + /// + /// + /// + /// + /// where T is of type + /// + /// + /// where T is of type + /// + /// + /// where T is of type IList{long} + /// + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + public BinaryData Prompt { get; } + /// + /// Generates `best_of` completions server-side and returns the "best" (the one with the highest + /// log probability per token). Results cannot be streamed. + /// + /// When used with `n`, `best_of` controls the number of candidate completions and `n` specifies + /// how many to return – `best_of` must be greater than `n`. + /// + /// **Note:** Because this parameter generates many completions, it can quickly consume your token + /// quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. + /// + public long? BestOf { get; set; } + /// Echo back the prompt in addition to the completion. + public bool? Echo { get; set; } + /// + /// Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing + /// frequency in the text so far, decreasing the model's likelihood to repeat the same line + /// verbatim. + /// + /// [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) + /// + public double? FrequencyPenalty { get; set; } + /// + /// Modify the likelihood of specified tokens appearing in the completion. + /// + /// Accepts a JSON object that maps tokens (specified by their token ID in the GPT tokenizer) to an + /// associated bias value from -100 to 100. You can use this [tokenizer tool](/tokenizer?view=bpe) + /// to convert text to token IDs. Mathematically, the bias is added to the logits generated by the + /// model prior to sampling. The exact effect will vary per model, but values between -1 and 1 + /// should decrease or increase likelihood of selection; values like -100 or 100 should result in a + /// ban or exclusive selection of the relevant token. + /// + /// As an example, you can pass `{"50256": -100}` to prevent the <|endoftext|> token from being + /// generated. + /// + public IDictionary LogitBias { get; set; } + /// + /// Include the log probabilities on the `logprobs` most likely tokens, as well the chosen tokens. + /// For example, if `logprobs` is 5, the API will return a list of the 5 most likely tokens. The + /// API will always return the `logprob` of the sampled token, so there may be up to `logprobs+1` + /// elements in the response. + /// + /// The maximum value for `logprobs` is 5. + /// + public long? Logprobs { get; set; } + /// + /// The maximum number of [tokens](/tokenizer) to generate in the completion. + /// + /// The token count of your prompt plus `max_tokens` cannot exceed the model's context length. + /// [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) + /// for counting tokens. + /// + public long? MaxTokens { get; set; } + /// + /// How many completions to generate for each prompt. + /// + /// **Note:** Because this parameter generates many completions, it can quickly consume your token + /// quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. + /// + public long? N { get; set; } + /// + /// Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear + /// in the text so far, increasing the model's likelihood to talk about new topics. + /// + /// [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) + /// + public double? PresencePenalty { get; set; } + /// + /// If specified, our system will make a best effort to sample deterministically, such that + /// repeated requests with the same `seed` and parameters should return the same result. + /// + /// Determinism is not guaranteed, and you should refer to the `system_fingerprint` response + /// parameter to monitor changes in the backend. + /// + public long? Seed { get; set; } + /// + /// Up to 4 sequences where the API will stop generating further tokens. + /// + /// To assign an object to this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// + /// Supported types: + /// + /// + /// + /// + /// + /// where T is of type + /// + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + public BinaryData Stop { get; set; } + /// + /// If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only + /// [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) + /// as they become available, with the stream terminated by a `data: [DONE]` message. + /// [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_stream_completions.ipynb). + /// + public bool? Stream { get; set; } + /// The suffix that comes after a completion of inserted text. + public string Suffix { get; set; } + /// + /// What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output + /// more random, while lower values like 0.2 will make it more focused and deterministic. + /// + /// We generally recommend altering this or `top_p` but not both. + /// + public double? Temperature { get; set; } + /// + /// An alternative to sampling with temperature, called nucleus sampling, where the model considers + /// the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising + /// the top 10% probability mass are considered. + /// + /// We generally recommend altering this or `temperature` but not both. + /// + public double? TopP { get; set; } + /// + /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect + /// abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + /// + public string User { get; set; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateCompletionRequestModel.cs b/.dotnet/src/Generated/Models/CreateCompletionRequestModel.cs new file mode 100644 index 000000000..885dde0a4 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateCompletionRequestModel.cs @@ -0,0 +1,51 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for model in CreateCompletionRequest. + public readonly partial struct CreateCompletionRequestModel : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateCompletionRequestModel(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string Gpt35TurboInstructValue = "gpt-3.5-turbo-instruct"; + private const string Davinci002Value = "davinci-002"; + private const string Babbage002Value = "babbage-002"; + + /// gpt-3.5-turbo-instruct. + public static CreateCompletionRequestModel Gpt35TurboInstruct { get; } = new CreateCompletionRequestModel(Gpt35TurboInstructValue); + /// davinci-002. + public static CreateCompletionRequestModel Davinci002 { get; } = new CreateCompletionRequestModel(Davinci002Value); + /// babbage-002. + public static CreateCompletionRequestModel Babbage002 { get; } = new CreateCompletionRequestModel(Babbage002Value); + /// Determines if two values are the same. + public static bool operator ==(CreateCompletionRequestModel left, CreateCompletionRequestModel right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateCompletionRequestModel left, CreateCompletionRequestModel right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateCompletionRequestModel(string value) => new CreateCompletionRequestModel(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateCompletionRequestModel other && Equals(other); + /// + public bool Equals(CreateCompletionRequestModel other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponse.Serialization.cs b/.dotnet/src/Generated/Models/CreateCompletionResponse.Serialization.cs new file mode 100644 index 000000000..3afa5cb8c --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateCompletionResponse.Serialization.cs @@ -0,0 +1,200 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateCompletionResponse : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateCompletionResponse)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("id"u8); + writer.WriteStringValue(Id); + writer.WritePropertyName("choices"u8); + writer.WriteStartArray(); + foreach (var item in Choices) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + writer.WritePropertyName("created"u8); + writer.WriteNumberValue(Created, "U"); + writer.WritePropertyName("model"u8); + writer.WriteStringValue(Model); + if (OptionalProperty.IsDefined(SystemFingerprint)) + { + writer.WritePropertyName("system_fingerprint"u8); + writer.WriteStringValue(SystemFingerprint); + } + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + if (OptionalProperty.IsDefined(Usage)) + { + writer.WritePropertyName("usage"u8); + writer.WriteObjectValue(Usage); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateCompletionResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateCompletionResponse)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateCompletionResponse(document.RootElement, options); + } + + internal static CreateCompletionResponse DeserializeCreateCompletionResponse(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string id = default; + IReadOnlyList choices = default; + DateTimeOffset created = default; + string model = default; + OptionalProperty systemFingerprint = default; + CreateCompletionResponseObject @object = default; + OptionalProperty usage = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetString(); + continue; + } + if (property.NameEquals("choices"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(CreateCompletionResponseChoice.DeserializeCreateCompletionResponseChoice(item)); + } + choices = array; + continue; + } + if (property.NameEquals("created"u8)) + { + created = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); + continue; + } + if (property.NameEquals("model"u8)) + { + model = property.Value.GetString(); + continue; + } + if (property.NameEquals("system_fingerprint"u8)) + { + systemFingerprint = property.Value.GetString(); + continue; + } + if (property.NameEquals("object"u8)) + { + @object = new CreateCompletionResponseObject(property.Value.GetString()); + continue; + } + if (property.NameEquals("usage"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + usage = CompletionUsage.DeserializeCompletionUsage(property.Value); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateCompletionResponse(id, choices, created, model, systemFingerprint.Value, @object, usage.Value, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateCompletionResponse)} does not support '{options.Format}' format."); + } + } + + CreateCompletionResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateCompletionResponse(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateCompletionResponse)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateCompletionResponse FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateCompletionResponse(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponse.cs b/.dotnet/src/Generated/Models/CreateCompletionResponse.cs new file mode 100644 index 000000000..0d47cab50 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateCompletionResponse.cs @@ -0,0 +1,120 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// + /// Represents a completion response from the API. Note: both the streamed and non-streamed response + /// objects share the same shape (unlike the chat endpoint). + /// + public partial class CreateCompletionResponse + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// A unique identifier for the completion. + /// The list of completion choices the model generated for the input. + /// The Unix timestamp (in seconds) of when the completion was created. + /// The model used for the completion. + /// , or is null. + internal CreateCompletionResponse(string id, IEnumerable choices, DateTimeOffset created, string model) + { + ClientUtilities.AssertNotNull(id, nameof(id)); + ClientUtilities.AssertNotNull(choices, nameof(choices)); + ClientUtilities.AssertNotNull(model, nameof(model)); + + Id = id; + Choices = choices.ToList(); + Created = created; + Model = model; + } + + /// Initializes a new instance of . + /// A unique identifier for the completion. + /// The list of completion choices the model generated for the input. + /// The Unix timestamp (in seconds) of when the completion was created. + /// The model used for the completion. + /// + /// 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. + /// + /// The object type, which is always `text_completion`. + /// Usage statistics for the completion request. + /// Keeps track of any properties unknown to the library. + internal CreateCompletionResponse(string id, IReadOnlyList choices, DateTimeOffset created, string model, string systemFingerprint, CreateCompletionResponseObject @object, CompletionUsage usage, IDictionary serializedAdditionalRawData) + { + Id = id; + Choices = choices; + Created = created; + Model = model; + SystemFingerprint = systemFingerprint; + Object = @object; + Usage = usage; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateCompletionResponse() + { + } + + /// A unique identifier for the completion. + public string Id { get; } + /// The list of completion choices the model generated for the input. + public IReadOnlyList Choices { get; } + /// The Unix timestamp (in seconds) of when the completion was created. + public DateTimeOffset Created { get; } + /// The model used for the completion. + public string Model { get; } + /// + /// 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. + /// + public string SystemFingerprint { get; } + /// The object type, which is always `text_completion`. + public CreateCompletionResponseObject Object { get; } = CreateCompletionResponseObject.TextCompletion; + + /// Usage statistics for the completion request. + public CompletionUsage Usage { get; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.Serialization.cs b/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.Serialization.cs new file mode 100644 index 000000000..d9f0caf93 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.Serialization.cs @@ -0,0 +1,168 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateCompletionResponseChoice : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateCompletionResponseChoice)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("index"u8); + writer.WriteNumberValue(Index); + writer.WritePropertyName("text"u8); + writer.WriteStringValue(Text); + if (Logprobs != null) + { + writer.WritePropertyName("logprobs"u8); + writer.WriteObjectValue(Logprobs); + } + else + { + writer.WriteNull("logprobs"); + } + writer.WritePropertyName("finish_reason"u8); + writer.WriteStringValue(FinishReason.ToString()); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateCompletionResponseChoice IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateCompletionResponseChoice)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateCompletionResponseChoice(document.RootElement, options); + } + + internal static CreateCompletionResponseChoice DeserializeCreateCompletionResponseChoice(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + long index = default; + string text = default; + CreateCompletionResponseChoiceLogprobs logprobs = default; + CreateCompletionResponseChoiceFinishReason finishReason = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("index"u8)) + { + index = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("text"u8)) + { + text = property.Value.GetString(); + continue; + } + if (property.NameEquals("logprobs"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + logprobs = null; + continue; + } + logprobs = CreateCompletionResponseChoiceLogprobs.DeserializeCreateCompletionResponseChoiceLogprobs(property.Value); + continue; + } + if (property.NameEquals("finish_reason"u8)) + { + finishReason = new CreateCompletionResponseChoiceFinishReason(property.Value.GetString()); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateCompletionResponseChoice(index, text, logprobs, finishReason, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateCompletionResponseChoice)} does not support '{options.Format}' format."); + } + } + + CreateCompletionResponseChoice IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateCompletionResponseChoice(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateCompletionResponseChoice)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateCompletionResponseChoice FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateCompletionResponseChoice(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.cs b/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.cs new file mode 100644 index 000000000..b38455976 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.cs @@ -0,0 +1,109 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateCompletionResponseChoice. + public partial class CreateCompletionResponseChoice + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// + /// + /// + /// The reason the model stopped generating tokens. This will be `stop` if the model hit a + /// natural stop point or a provided stop sequence, or `content_filter` if content was omitted + /// due to a flag from our content filters, `length` if the maximum number of tokens specified + /// in the request was reached, or `content_filter` if content was omitted due to a flag from our + /// content filters. + /// + /// is null. + internal CreateCompletionResponseChoice(long index, string text, CreateCompletionResponseChoiceLogprobs logprobs, CreateCompletionResponseChoiceFinishReason finishReason) + { + ClientUtilities.AssertNotNull(text, nameof(text)); + + Index = index; + Text = text; + Logprobs = logprobs; + FinishReason = finishReason; + } + + /// Initializes a new instance of . + /// + /// + /// + /// + /// The reason the model stopped generating tokens. This will be `stop` if the model hit a + /// natural stop point or a provided stop sequence, or `content_filter` if content was omitted + /// due to a flag from our content filters, `length` if the maximum number of tokens specified + /// in the request was reached, or `content_filter` if content was omitted due to a flag from our + /// content filters. + /// + /// Keeps track of any properties unknown to the library. + internal CreateCompletionResponseChoice(long index, string text, CreateCompletionResponseChoiceLogprobs logprobs, CreateCompletionResponseChoiceFinishReason finishReason, IDictionary serializedAdditionalRawData) + { + Index = index; + Text = text; + Logprobs = logprobs; + FinishReason = finishReason; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateCompletionResponseChoice() + { + } + + /// Gets the index. + public long Index { get; } + /// Gets the text. + public string Text { get; } + /// Gets the logprobs. + public CreateCompletionResponseChoiceLogprobs Logprobs { get; } + /// + /// The reason the model stopped generating tokens. This will be `stop` if the model hit a + /// natural stop point or a provided stop sequence, or `content_filter` if content was omitted + /// due to a flag from our content filters, `length` if the maximum number of tokens specified + /// in the request was reached, or `content_filter` if content was omitted due to a flag from our + /// content filters. + /// + public CreateCompletionResponseChoiceFinishReason FinishReason { get; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceFinishReason.cs b/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceFinishReason.cs new file mode 100644 index 000000000..5071c4a7a --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceFinishReason.cs @@ -0,0 +1,51 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for finish_reason in CreateCompletionResponseChoice. + public readonly partial struct CreateCompletionResponseChoiceFinishReason : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateCompletionResponseChoiceFinishReason(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string StopValue = "stop"; + private const string LengthValue = "length"; + private const string ContentFilterValue = "content_filter"; + + /// stop. + public static CreateCompletionResponseChoiceFinishReason Stop { get; } = new CreateCompletionResponseChoiceFinishReason(StopValue); + /// length. + public static CreateCompletionResponseChoiceFinishReason Length { get; } = new CreateCompletionResponseChoiceFinishReason(LengthValue); + /// content_filter. + public static CreateCompletionResponseChoiceFinishReason ContentFilter { get; } = new CreateCompletionResponseChoiceFinishReason(ContentFilterValue); + /// Determines if two values are the same. + public static bool operator ==(CreateCompletionResponseChoiceFinishReason left, CreateCompletionResponseChoiceFinishReason right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateCompletionResponseChoiceFinishReason left, CreateCompletionResponseChoiceFinishReason right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateCompletionResponseChoiceFinishReason(string value) => new CreateCompletionResponseChoiceFinishReason(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateCompletionResponseChoiceFinishReason other && Equals(other); + /// + public bool Equals(CreateCompletionResponseChoiceFinishReason other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.Serialization.cs b/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.Serialization.cs new file mode 100644 index 000000000..89dcafec8 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.Serialization.cs @@ -0,0 +1,219 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateCompletionResponseChoiceLogprobs : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateCompletionResponseChoiceLogprobs)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("tokens"u8); + writer.WriteStartArray(); + foreach (var item in Tokens) + { + writer.WriteStringValue(item); + } + writer.WriteEndArray(); + writer.WritePropertyName("token_logprobs"u8); + writer.WriteStartArray(); + foreach (var item in TokenLogprobs) + { + writer.WriteNumberValue(item); + } + writer.WriteEndArray(); + writer.WritePropertyName("top_logprobs"u8); + writer.WriteStartArray(); + foreach (var item in TopLogprobs) + { + if (item == null) + { + writer.WriteNullValue(); + continue; + } + writer.WriteStartObject(); + foreach (var item0 in item) + { + writer.WritePropertyName(item0.Key); + writer.WriteNumberValue(item0.Value); + } + writer.WriteEndObject(); + } + writer.WriteEndArray(); + writer.WritePropertyName("text_offset"u8); + writer.WriteStartArray(); + foreach (var item in TextOffset) + { + writer.WriteNumberValue(item); + } + writer.WriteEndArray(); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateCompletionResponseChoiceLogprobs IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateCompletionResponseChoiceLogprobs)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateCompletionResponseChoiceLogprobs(document.RootElement, options); + } + + internal static CreateCompletionResponseChoiceLogprobs DeserializeCreateCompletionResponseChoiceLogprobs(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + IReadOnlyList tokens = default; + IReadOnlyList tokenLogprobs = default; + IReadOnlyList> topLogprobs = default; + IReadOnlyList textOffset = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("tokens"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(item.GetString()); + } + tokens = array; + continue; + } + if (property.NameEquals("token_logprobs"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(item.GetDouble()); + } + tokenLogprobs = array; + continue; + } + if (property.NameEquals("top_logprobs"u8)) + { + List> array = new List>(); + foreach (var item in property.Value.EnumerateArray()) + { + if (item.ValueKind == JsonValueKind.Null) + { + array.Add(null); + } + else + { + Dictionary dictionary = new Dictionary(); + foreach (var property0 in item.EnumerateObject()) + { + dictionary.Add(property0.Name, property0.Value.GetInt64()); + } + array.Add(dictionary); + } + } + topLogprobs = array; + continue; + } + if (property.NameEquals("text_offset"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(item.GetInt64()); + } + textOffset = array; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateCompletionResponseChoiceLogprobs(tokens, tokenLogprobs, topLogprobs, textOffset, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateCompletionResponseChoiceLogprobs)} does not support '{options.Format}' format."); + } + } + + CreateCompletionResponseChoiceLogprobs IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateCompletionResponseChoiceLogprobs(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateCompletionResponseChoiceLogprobs)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateCompletionResponseChoiceLogprobs FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateCompletionResponseChoiceLogprobs(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.cs b/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.cs new file mode 100644 index 000000000..5b88d866b --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.cs @@ -0,0 +1,95 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// The CreateCompletionResponseChoiceLogprobs. + public partial class CreateCompletionResponseChoiceLogprobs + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// + /// + /// + /// , , or is null. + internal CreateCompletionResponseChoiceLogprobs(IEnumerable tokens, IEnumerable tokenLogprobs, IEnumerable> topLogprobs, IEnumerable textOffset) + { + ClientUtilities.AssertNotNull(tokens, nameof(tokens)); + ClientUtilities.AssertNotNull(tokenLogprobs, nameof(tokenLogprobs)); + ClientUtilities.AssertNotNull(topLogprobs, nameof(topLogprobs)); + ClientUtilities.AssertNotNull(textOffset, nameof(textOffset)); + + Tokens = tokens.ToList(); + TokenLogprobs = tokenLogprobs.ToList(); + TopLogprobs = topLogprobs.ToList(); + TextOffset = textOffset.ToList(); + } + + /// Initializes a new instance of . + /// + /// + /// + /// + /// Keeps track of any properties unknown to the library. + internal CreateCompletionResponseChoiceLogprobs(IReadOnlyList tokens, IReadOnlyList tokenLogprobs, IReadOnlyList> topLogprobs, IReadOnlyList textOffset, IDictionary serializedAdditionalRawData) + { + Tokens = tokens; + TokenLogprobs = tokenLogprobs; + TopLogprobs = topLogprobs; + TextOffset = textOffset; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateCompletionResponseChoiceLogprobs() + { + } + + /// Gets the tokens. + public IReadOnlyList Tokens { get; } + /// Gets the token logprobs. + public IReadOnlyList TokenLogprobs { get; } + /// Gets the top logprobs. + public IReadOnlyList> TopLogprobs { get; } + /// Gets the text offset. + public IReadOnlyList TextOffset { get; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponseObject.cs b/.dotnet/src/Generated/Models/CreateCompletionResponseObject.cs new file mode 100644 index 000000000..3185d279a --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateCompletionResponseObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The CreateCompletionResponse_object. + public readonly partial struct CreateCompletionResponseObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateCompletionResponseObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string TextCompletionValue = "text_completion"; + + /// text_completion. + public static CreateCompletionResponseObject TextCompletion { get; } = new CreateCompletionResponseObject(TextCompletionValue); + /// Determines if two values are the same. + public static bool operator ==(CreateCompletionResponseObject left, CreateCompletionResponseObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateCompletionResponseObject left, CreateCompletionResponseObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateCompletionResponseObject(string value) => new CreateCompletionResponseObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateCompletionResponseObject other && Equals(other); + /// + public bool Equals(CreateCompletionResponseObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateEmbeddingRequest.Serialization.cs new file mode 100644 index 000000000..4601bcc63 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateEmbeddingRequest.Serialization.cs @@ -0,0 +1,188 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateEmbeddingRequest : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateEmbeddingRequest)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("input"u8); +#if NET6_0_OR_GREATER + writer.WriteRawValue(Input); +#else + using (JsonDocument document = JsonDocument.Parse(Input)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + writer.WritePropertyName("model"u8); + writer.WriteStringValue(Model.ToString()); + if (OptionalProperty.IsDefined(EncodingFormat)) + { + writer.WritePropertyName("encoding_format"u8); + writer.WriteStringValue(EncodingFormat.Value.ToString()); + } + if (OptionalProperty.IsDefined(Dimensions)) + { + writer.WritePropertyName("dimensions"u8); + writer.WriteNumberValue(Dimensions.Value); + } + if (OptionalProperty.IsDefined(User)) + { + writer.WritePropertyName("user"u8); + writer.WriteStringValue(User); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateEmbeddingRequest IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateEmbeddingRequest)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateEmbeddingRequest(document.RootElement, options); + } + + internal static CreateEmbeddingRequest DeserializeCreateEmbeddingRequest(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + BinaryData input = default; + CreateEmbeddingRequestModel model = default; + OptionalProperty encodingFormat = default; + OptionalProperty dimensions = default; + OptionalProperty user = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("input"u8)) + { + input = BinaryData.FromString(property.Value.GetRawText()); + continue; + } + if (property.NameEquals("model"u8)) + { + model = new CreateEmbeddingRequestModel(property.Value.GetString()); + continue; + } + if (property.NameEquals("encoding_format"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + encodingFormat = new CreateEmbeddingRequestEncodingFormat(property.Value.GetString()); + continue; + } + if (property.NameEquals("dimensions"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + dimensions = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("user"u8)) + { + user = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateEmbeddingRequest(input, model, OptionalProperty.ToNullable(encodingFormat), OptionalProperty.ToNullable(dimensions), user.Value, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateEmbeddingRequest)} does not support '{options.Format}' format."); + } + } + + CreateEmbeddingRequest IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateEmbeddingRequest(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateEmbeddingRequest)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateEmbeddingRequest FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateEmbeddingRequest(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingRequest.cs b/.dotnet/src/Generated/Models/CreateEmbeddingRequest.cs new file mode 100644 index 000000000..770cc70db --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateEmbeddingRequest.cs @@ -0,0 +1,186 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateEmbeddingRequest. + public partial class CreateEmbeddingRequest + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a + /// single request, pass an array of strings or array of token arrays. Each input must not exceed + /// the max input tokens for the model (8191 tokens for `text-embedding-ada-002`) and cannot be an + /// empty string. + /// [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) + /// for counting tokens. + /// + /// + /// ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + /// see all of your available models, or see our [Model overview](/docs/models/overview) for + /// descriptions of them. + /// + /// is null. + public CreateEmbeddingRequest(BinaryData input, CreateEmbeddingRequestModel model) + { + ClientUtilities.AssertNotNull(input, nameof(input)); + + Input = input; + Model = model; + } + + /// Initializes a new instance of . + /// + /// Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a + /// single request, pass an array of strings or array of token arrays. Each input must not exceed + /// the max input tokens for the model (8191 tokens for `text-embedding-ada-002`) and cannot be an + /// empty string. + /// [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) + /// for counting tokens. + /// + /// + /// ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + /// see all of your available models, or see our [Model overview](/docs/models/overview) for + /// descriptions of them. + /// + /// + /// The format to return the embeddings in. Can be either `float` or + /// [`base64`](https://pypi.org/project/pybase64/). + /// + /// + /// The number of dimensions the resulting output embeddings should have. Only supported in + /// `text-embedding-3` and later models. + /// + /// + /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect + /// abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + /// + /// Keeps track of any properties unknown to the library. + internal CreateEmbeddingRequest(BinaryData input, CreateEmbeddingRequestModel model, CreateEmbeddingRequestEncodingFormat? encodingFormat, long? dimensions, string user, IDictionary serializedAdditionalRawData) + { + Input = input; + Model = model; + EncodingFormat = encodingFormat; + Dimensions = dimensions; + User = user; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateEmbeddingRequest() + { + } + + /// + /// Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a + /// single request, pass an array of strings or array of token arrays. Each input must not exceed + /// the max input tokens for the model (8191 tokens for `text-embedding-ada-002`) and cannot be an + /// empty string. + /// [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) + /// for counting tokens. + /// + /// To assign an object to this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// + /// Supported types: + /// + /// + /// + /// + /// + /// where T is of type + /// + /// + /// where T is of type + /// + /// + /// where T is of type IList{long} + /// + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + public BinaryData Input { get; } + /// + /// ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + /// see all of your available models, or see our [Model overview](/docs/models/overview) for + /// descriptions of them. + /// + public CreateEmbeddingRequestModel Model { get; } + /// + /// The format to return the embeddings in. Can be either `float` or + /// [`base64`](https://pypi.org/project/pybase64/). + /// + public CreateEmbeddingRequestEncodingFormat? EncodingFormat { get; set; } + /// + /// The number of dimensions the resulting output embeddings should have. Only supported in + /// `text-embedding-3` and later models. + /// + public long? Dimensions { get; set; } + /// + /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect + /// abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + /// + public string User { get; set; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingRequestEncodingFormat.cs b/.dotnet/src/Generated/Models/CreateEmbeddingRequestEncodingFormat.cs new file mode 100644 index 000000000..23debf648 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateEmbeddingRequestEncodingFormat.cs @@ -0,0 +1,48 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for encoding_format in CreateEmbeddingRequest. + public readonly partial struct CreateEmbeddingRequestEncodingFormat : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateEmbeddingRequestEncodingFormat(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string FloatValue = "float"; + private const string Base64Value = "base64"; + + /// float. + public static CreateEmbeddingRequestEncodingFormat Float { get; } = new CreateEmbeddingRequestEncodingFormat(FloatValue); + /// base64. + public static CreateEmbeddingRequestEncodingFormat Base64 { get; } = new CreateEmbeddingRequestEncodingFormat(Base64Value); + /// Determines if two values are the same. + public static bool operator ==(CreateEmbeddingRequestEncodingFormat left, CreateEmbeddingRequestEncodingFormat right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateEmbeddingRequestEncodingFormat left, CreateEmbeddingRequestEncodingFormat right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateEmbeddingRequestEncodingFormat(string value) => new CreateEmbeddingRequestEncodingFormat(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateEmbeddingRequestEncodingFormat other && Equals(other); + /// + public bool Equals(CreateEmbeddingRequestEncodingFormat other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingRequestModel.cs b/.dotnet/src/Generated/Models/CreateEmbeddingRequestModel.cs new file mode 100644 index 000000000..1b65ef4e0 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateEmbeddingRequestModel.cs @@ -0,0 +1,51 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for model in CreateEmbeddingRequest. + public readonly partial struct CreateEmbeddingRequestModel : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateEmbeddingRequestModel(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string TextEmbeddingAda002Value = "text-embedding-ada-002"; + private const string TextEmbedding3SmallValue = "text-embedding-3-small"; + private const string TextEmbedding3LargeValue = "text-embedding-3-large"; + + /// text-embedding-ada-002. + public static CreateEmbeddingRequestModel TextEmbeddingAda002 { get; } = new CreateEmbeddingRequestModel(TextEmbeddingAda002Value); + /// text-embedding-3-small. + public static CreateEmbeddingRequestModel TextEmbedding3Small { get; } = new CreateEmbeddingRequestModel(TextEmbedding3SmallValue); + /// text-embedding-3-large. + public static CreateEmbeddingRequestModel TextEmbedding3Large { get; } = new CreateEmbeddingRequestModel(TextEmbedding3LargeValue); + /// Determines if two values are the same. + public static bool operator ==(CreateEmbeddingRequestModel left, CreateEmbeddingRequestModel right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateEmbeddingRequestModel left, CreateEmbeddingRequestModel right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateEmbeddingRequestModel(string value) => new CreateEmbeddingRequestModel(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateEmbeddingRequestModel other && Equals(other); + /// + public bool Equals(CreateEmbeddingRequestModel other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingResponse.Serialization.cs b/.dotnet/src/Generated/Models/CreateEmbeddingResponse.Serialization.cs new file mode 100644 index 000000000..78595eb7e --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateEmbeddingResponse.Serialization.cs @@ -0,0 +1,166 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateEmbeddingResponse : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateEmbeddingResponse)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("data"u8); + writer.WriteStartArray(); + foreach (var item in Data) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + writer.WritePropertyName("model"u8); + writer.WriteStringValue(Model); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + writer.WritePropertyName("usage"u8); + writer.WriteObjectValue(Usage); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateEmbeddingResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateEmbeddingResponse)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateEmbeddingResponse(document.RootElement, options); + } + + internal static CreateEmbeddingResponse DeserializeCreateEmbeddingResponse(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + IReadOnlyList data = default; + string model = default; + CreateEmbeddingResponseObject @object = default; + CreateEmbeddingResponseUsage usage = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("data"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(Embedding.DeserializeEmbedding(item)); + } + data = array; + continue; + } + if (property.NameEquals("model"u8)) + { + model = property.Value.GetString(); + continue; + } + if (property.NameEquals("object"u8)) + { + @object = new CreateEmbeddingResponseObject(property.Value.GetString()); + continue; + } + if (property.NameEquals("usage"u8)) + { + usage = CreateEmbeddingResponseUsage.DeserializeCreateEmbeddingResponseUsage(property.Value); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateEmbeddingResponse(data, model, @object, usage, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateEmbeddingResponse)} does not support '{options.Format}' format."); + } + } + + CreateEmbeddingResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateEmbeddingResponse(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateEmbeddingResponse)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateEmbeddingResponse FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateEmbeddingResponse(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingResponse.cs b/.dotnet/src/Generated/Models/CreateEmbeddingResponse.cs new file mode 100644 index 000000000..bf7e741ca --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateEmbeddingResponse.cs @@ -0,0 +1,93 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// The CreateEmbeddingResponse. + public partial class CreateEmbeddingResponse + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The list of embeddings generated by the model. + /// The name of the model used to generate the embedding. + /// The usage information for the request. + /// , or is null. + internal CreateEmbeddingResponse(IEnumerable data, string model, CreateEmbeddingResponseUsage usage) + { + ClientUtilities.AssertNotNull(data, nameof(data)); + ClientUtilities.AssertNotNull(model, nameof(model)); + ClientUtilities.AssertNotNull(usage, nameof(usage)); + + Data = data.ToList(); + Model = model; + Usage = usage; + } + + /// Initializes a new instance of . + /// The list of embeddings generated by the model. + /// The name of the model used to generate the embedding. + /// The object type, which is always "list". + /// The usage information for the request. + /// Keeps track of any properties unknown to the library. + internal CreateEmbeddingResponse(IReadOnlyList data, string model, CreateEmbeddingResponseObject @object, CreateEmbeddingResponseUsage usage, IDictionary serializedAdditionalRawData) + { + Data = data; + Model = model; + Object = @object; + Usage = usage; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateEmbeddingResponse() + { + } + + /// The list of embeddings generated by the model. + public IReadOnlyList Data { get; } + /// The name of the model used to generate the embedding. + public string Model { get; } + /// The object type, which is always "list". + public CreateEmbeddingResponseObject Object { get; } = CreateEmbeddingResponseObject.List; + + /// The usage information for the request. + public CreateEmbeddingResponseUsage Usage { get; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingResponseObject.cs b/.dotnet/src/Generated/Models/CreateEmbeddingResponseObject.cs new file mode 100644 index 000000000..82ba92eec --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateEmbeddingResponseObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The CreateEmbeddingResponse_object. + public readonly partial struct CreateEmbeddingResponseObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateEmbeddingResponseObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string ListValue = "list"; + + /// list. + public static CreateEmbeddingResponseObject List { get; } = new CreateEmbeddingResponseObject(ListValue); + /// Determines if two values are the same. + public static bool operator ==(CreateEmbeddingResponseObject left, CreateEmbeddingResponseObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateEmbeddingResponseObject left, CreateEmbeddingResponseObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateEmbeddingResponseObject(string value) => new CreateEmbeddingResponseObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateEmbeddingResponseObject other && Equals(other); + /// + public bool Equals(CreateEmbeddingResponseObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingResponseUsage.Serialization.cs b/.dotnet/src/Generated/Models/CreateEmbeddingResponseUsage.Serialization.cs new file mode 100644 index 000000000..c662893ed --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateEmbeddingResponseUsage.Serialization.cs @@ -0,0 +1,140 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateEmbeddingResponseUsage : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateEmbeddingResponseUsage)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("prompt_tokens"u8); + writer.WriteNumberValue(PromptTokens); + writer.WritePropertyName("total_tokens"u8); + writer.WriteNumberValue(TotalTokens); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateEmbeddingResponseUsage IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateEmbeddingResponseUsage)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateEmbeddingResponseUsage(document.RootElement, options); + } + + internal static CreateEmbeddingResponseUsage DeserializeCreateEmbeddingResponseUsage(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + long promptTokens = default; + long totalTokens = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("prompt_tokens"u8)) + { + promptTokens = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("total_tokens"u8)) + { + totalTokens = property.Value.GetInt64(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateEmbeddingResponseUsage(promptTokens, totalTokens, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateEmbeddingResponseUsage)} does not support '{options.Format}' format."); + } + } + + CreateEmbeddingResponseUsage IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateEmbeddingResponseUsage(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateEmbeddingResponseUsage)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateEmbeddingResponseUsage FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateEmbeddingResponseUsage(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingResponseUsage.cs b/.dotnet/src/Generated/Models/CreateEmbeddingResponseUsage.cs new file mode 100644 index 000000000..d21b5b9e9 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateEmbeddingResponseUsage.cs @@ -0,0 +1,75 @@ +// + +#nullable disable + +using System; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateEmbeddingResponseUsage. + public partial class CreateEmbeddingResponseUsage + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The number of tokens used by the prompt. + /// The total number of tokens used by the request. + internal CreateEmbeddingResponseUsage(long promptTokens, long totalTokens) + { + PromptTokens = promptTokens; + TotalTokens = totalTokens; + } + + /// Initializes a new instance of . + /// The number of tokens used by the prompt. + /// The total number of tokens used by the request. + /// Keeps track of any properties unknown to the library. + internal CreateEmbeddingResponseUsage(long promptTokens, long totalTokens, IDictionary serializedAdditionalRawData) + { + PromptTokens = promptTokens; + TotalTokens = totalTokens; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateEmbeddingResponseUsage() + { + } + + /// The number of tokens used by the prompt. + public long PromptTokens { get; } + /// The total number of tokens used by the request. + public long TotalTokens { get; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateFileRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateFileRequest.Serialization.cs new file mode 100644 index 000000000..6f2012c20 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateFileRequest.Serialization.cs @@ -0,0 +1,140 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateFileRequest : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateFileRequest)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("file"u8); + writer.WriteBase64StringValue(File.ToArray(), "D"); + writer.WritePropertyName("purpose"u8); + writer.WriteStringValue(Purpose.ToString()); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateFileRequest IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateFileRequest)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateFileRequest(document.RootElement, options); + } + + internal static CreateFileRequest DeserializeCreateFileRequest(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + BinaryData file = default; + CreateFileRequestPurpose purpose = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("file"u8)) + { + file = BinaryData.FromBytes(property.Value.GetBytesFromBase64("D")); + continue; + } + if (property.NameEquals("purpose"u8)) + { + purpose = new CreateFileRequestPurpose(property.Value.GetString()); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateFileRequest(file, purpose, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateFileRequest)} does not support '{options.Format}' format."); + } + } + + CreateFileRequest IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateFileRequest(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateFileRequest)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateFileRequest FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateFileRequest(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateFileRequest.cs b/.dotnet/src/Generated/Models/CreateFileRequest.cs new file mode 100644 index 000000000..9e10579a6 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateFileRequest.cs @@ -0,0 +1,109 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateFileRequest. + public partial class CreateFileRequest + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The file object (not file name) to be uploaded. + /// + /// The intended purpose of the uploaded file. Use "fine-tune" for + /// [Fine-tuning](/docs/api-reference/fine-tuning) and "assistants" for + /// [Assistants](/docs/api-reference/assistants) and [Messages](/docs/api-reference/messages). This + /// allows us to validate the format of the uploaded file is correct for fine-tuning. + /// + /// is null. + public CreateFileRequest(BinaryData file, CreateFileRequestPurpose purpose) + { + ClientUtilities.AssertNotNull(file, nameof(file)); + + File = file; + Purpose = purpose; + } + + /// Initializes a new instance of . + /// The file object (not file name) to be uploaded. + /// + /// The intended purpose of the uploaded file. Use "fine-tune" for + /// [Fine-tuning](/docs/api-reference/fine-tuning) and "assistants" for + /// [Assistants](/docs/api-reference/assistants) and [Messages](/docs/api-reference/messages). This + /// allows us to validate the format of the uploaded file is correct for fine-tuning. + /// + /// Keeps track of any properties unknown to the library. + internal CreateFileRequest(BinaryData file, CreateFileRequestPurpose purpose, IDictionary serializedAdditionalRawData) + { + File = file; + Purpose = purpose; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateFileRequest() + { + } + + /// + /// The file object (not file name) to be uploaded. + /// + /// To assign a byte[] to this property use . + /// The byte[] will be serialized to a Base64 encoded string. + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromBytes(new byte[] { 1, 2, 3 }) + /// Creates a payload of "AQID". + /// + /// + /// + /// + public BinaryData File { get; } + /// + /// The intended purpose of the uploaded file. Use "fine-tune" for + /// [Fine-tuning](/docs/api-reference/fine-tuning) and "assistants" for + /// [Assistants](/docs/api-reference/assistants) and [Messages](/docs/api-reference/messages). This + /// allows us to validate the format of the uploaded file is correct for fine-tuning. + /// + public CreateFileRequestPurpose Purpose { get; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateFileRequestPurpose.cs b/.dotnet/src/Generated/Models/CreateFileRequestPurpose.cs new file mode 100644 index 000000000..866087c3b --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateFileRequestPurpose.cs @@ -0,0 +1,48 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for purpose in CreateFileRequest. + public readonly partial struct CreateFileRequestPurpose : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateFileRequestPurpose(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string FineTuneValue = "fine-tune"; + private const string AssistantsValue = "assistants"; + + /// fine-tune. + public static CreateFileRequestPurpose FineTune { get; } = new CreateFileRequestPurpose(FineTuneValue); + /// assistants. + public static CreateFileRequestPurpose Assistants { get; } = new CreateFileRequestPurpose(AssistantsValue); + /// Determines if two values are the same. + public static bool operator ==(CreateFileRequestPurpose left, CreateFileRequestPurpose right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateFileRequestPurpose left, CreateFileRequestPurpose right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateFileRequestPurpose(string value) => new CreateFileRequestPurpose(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateFileRequestPurpose other && Equals(other); + /// + public bool Equals(CreateFileRequestPurpose other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateFineTuneRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateFineTuneRequest.Serialization.cs new file mode 100644 index 000000000..c83a0246a --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateFineTuneRequest.Serialization.cs @@ -0,0 +1,386 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateFineTuneRequest : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateFineTuneRequest)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("training_file"u8); + writer.WriteStringValue(TrainingFile); + if (OptionalProperty.IsDefined(ValidationFile)) + { + if (ValidationFile != null) + { + writer.WritePropertyName("validation_file"u8); + writer.WriteStringValue(ValidationFile); + } + else + { + writer.WriteNull("validation_file"); + } + } + if (OptionalProperty.IsDefined(Model)) + { + writer.WritePropertyName("model"u8); + writer.WriteStringValue(Model.Value.ToString()); + } + if (OptionalProperty.IsDefined(NEpochs)) + { + if (NEpochs != null) + { + writer.WritePropertyName("n_epochs"u8); + writer.WriteNumberValue(NEpochs.Value); + } + else + { + writer.WriteNull("n_epochs"); + } + } + if (OptionalProperty.IsDefined(BatchSize)) + { + if (BatchSize != null) + { + writer.WritePropertyName("batch_size"u8); + writer.WriteNumberValue(BatchSize.Value); + } + else + { + writer.WriteNull("batch_size"); + } + } + if (OptionalProperty.IsDefined(LearningRateMultiplier)) + { + if (LearningRateMultiplier != null) + { + writer.WritePropertyName("learning_rate_multiplier"u8); + writer.WriteNumberValue(LearningRateMultiplier.Value); + } + else + { + writer.WriteNull("learning_rate_multiplier"); + } + } + if (OptionalProperty.IsDefined(PromptLossRate)) + { + if (PromptLossRate != null) + { + writer.WritePropertyName("prompt_loss_rate"u8); + writer.WriteNumberValue(PromptLossRate.Value); + } + else + { + writer.WriteNull("prompt_loss_rate"); + } + } + if (OptionalProperty.IsDefined(ComputeClassificationMetrics)) + { + if (ComputeClassificationMetrics != null) + { + writer.WritePropertyName("compute_classification_metrics"u8); + writer.WriteBooleanValue(ComputeClassificationMetrics.Value); + } + else + { + writer.WriteNull("compute_classification_metrics"); + } + } + if (OptionalProperty.IsDefined(ClassificationNClasses)) + { + if (ClassificationNClasses != null) + { + writer.WritePropertyName("classification_n_classes"u8); + writer.WriteNumberValue(ClassificationNClasses.Value); + } + else + { + writer.WriteNull("classification_n_classes"); + } + } + if (OptionalProperty.IsDefined(ClassificationPositiveClass)) + { + if (ClassificationPositiveClass != null) + { + writer.WritePropertyName("classification_positive_class"u8); + writer.WriteStringValue(ClassificationPositiveClass); + } + else + { + writer.WriteNull("classification_positive_class"); + } + } + if (OptionalProperty.IsCollectionDefined(ClassificationBetas)) + { + if (ClassificationBetas != null) + { + writer.WritePropertyName("classification_betas"u8); + writer.WriteStartArray(); + foreach (var item in ClassificationBetas) + { + writer.WriteNumberValue(item); + } + writer.WriteEndArray(); + } + else + { + writer.WriteNull("classification_betas"); + } + } + if (OptionalProperty.IsDefined(Suffix)) + { + if (Suffix != null) + { + writer.WritePropertyName("suffix"u8); + writer.WriteStringValue(Suffix); + } + else + { + writer.WriteNull("suffix"); + } + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateFineTuneRequest IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateFineTuneRequest)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateFineTuneRequest(document.RootElement, options); + } + + internal static CreateFineTuneRequest DeserializeCreateFineTuneRequest(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string trainingFile = default; + OptionalProperty validationFile = default; + OptionalProperty model = default; + OptionalProperty nEpochs = default; + OptionalProperty batchSize = default; + OptionalProperty learningRateMultiplier = default; + OptionalProperty promptLossRate = default; + OptionalProperty computeClassificationMetrics = default; + OptionalProperty classificationNClasses = default; + OptionalProperty classificationPositiveClass = default; + OptionalProperty> classificationBetas = default; + OptionalProperty suffix = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("training_file"u8)) + { + trainingFile = property.Value.GetString(); + continue; + } + if (property.NameEquals("validation_file"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + validationFile = null; + continue; + } + validationFile = property.Value.GetString(); + continue; + } + if (property.NameEquals("model"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + model = new CreateFineTuneRequestModel(property.Value.GetString()); + continue; + } + if (property.NameEquals("n_epochs"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + nEpochs = null; + continue; + } + nEpochs = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("batch_size"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + batchSize = null; + continue; + } + batchSize = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("learning_rate_multiplier"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + learningRateMultiplier = null; + continue; + } + learningRateMultiplier = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("prompt_loss_rate"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + promptLossRate = null; + continue; + } + promptLossRate = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("compute_classification_metrics"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + computeClassificationMetrics = null; + continue; + } + computeClassificationMetrics = property.Value.GetBoolean(); + continue; + } + if (property.NameEquals("classification_n_classes"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + classificationNClasses = null; + continue; + } + classificationNClasses = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("classification_positive_class"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + classificationPositiveClass = null; + continue; + } + classificationPositiveClass = property.Value.GetString(); + continue; + } + if (property.NameEquals("classification_betas"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(item.GetDouble()); + } + classificationBetas = array; + continue; + } + if (property.NameEquals("suffix"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + suffix = null; + continue; + } + suffix = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateFineTuneRequest(trainingFile, validationFile.Value, OptionalProperty.ToNullable(model), OptionalProperty.ToNullable(nEpochs), OptionalProperty.ToNullable(batchSize), OptionalProperty.ToNullable(learningRateMultiplier), OptionalProperty.ToNullable(promptLossRate), OptionalProperty.ToNullable(computeClassificationMetrics), OptionalProperty.ToNullable(classificationNClasses), classificationPositiveClass.Value, OptionalProperty.ToList(classificationBetas), suffix.Value, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateFineTuneRequest)} does not support '{options.Format}' format."); + } + } + + CreateFineTuneRequest IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateFineTuneRequest(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateFineTuneRequest)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateFineTuneRequest FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateFineTuneRequest(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateFineTuneRequest.cs b/.dotnet/src/Generated/Models/CreateFineTuneRequest.cs new file mode 100644 index 000000000..31b410dcb --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateFineTuneRequest.cs @@ -0,0 +1,295 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateFineTuneRequest. + public partial class CreateFineTuneRequest + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// The ID of an uploaded file that contains training data. + /// + /// See [upload file](/docs/api-reference/files/upload) for how to upload a file. + /// + /// Your dataset must be formatted as a JSONL file, where each training example is a JSON object + /// with the keys "prompt" and "completion". Additionally, you must upload your file with the + /// purpose `fine-tune`. + /// + /// See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more + /// details. + /// + /// is null. + public CreateFineTuneRequest(string trainingFile) + { + ClientUtilities.AssertNotNull(trainingFile, nameof(trainingFile)); + + TrainingFile = trainingFile; + ClassificationBetas = new OptionalList(); + } + + /// Initializes a new instance of . + /// + /// The ID of an uploaded file that contains training data. + /// + /// See [upload file](/docs/api-reference/files/upload) for how to upload a file. + /// + /// Your dataset must be formatted as a JSONL file, where each training example is a JSON object + /// with the keys "prompt" and "completion". Additionally, you must upload your file with the + /// purpose `fine-tune`. + /// + /// See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more + /// details. + /// + /// + /// The ID of an uploaded file that contains validation data. + /// + /// If you provide this file, the data is used to generate validation metrics periodically during + /// fine-tuning. These metrics can be viewed in the + /// [fine-tuning results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model). + /// Your train and validation data should be mutually exclusive. + /// + /// Your dataset must be formatted as a JSONL file, where each validation example is a JSON object + /// with the keys "prompt" and "completion". Additionally, you must upload your file with the + /// purpose `fine-tune`. + /// + /// See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more + /// details. + /// + /// + /// The name of the base model to fine-tune. You can select one of "ada", "babbage", "curie", + /// "davinci", or a fine-tuned model created after 2022-04-21 and before 2023-08-22. To learn more + /// about these models, see the [Models](/docs/models) documentation. + /// + /// + /// The number of epochs to train the model for. An epoch refers to one full cycle through the + /// training dataset. + /// + /// + /// The batch size to use for training. The batch size is the number of training examples used to + /// train a single forward and backward pass. + /// + /// By default, the batch size will be dynamically configured to be ~0.2% of the number of examples + /// in the training set, capped at 256 - in general, we've found that larger batch sizes tend to + /// work better for larger datasets. + /// + /// + /// The learning rate multiplier to use for training. The fine-tuning learning rate is the original + /// learning rate used for pretraining multiplied by this value. + /// + /// By default, the learning rate multiplier is the 0.05, 0.1, or 0.2 depending on final + /// `batch_size` (larger learning rates tend to perform better with larger batch sizes). We + /// recommend experimenting with values in the range 0.02 to 0.2 to see what produces the best + /// results. + /// + /// + /// The weight to use for loss on the prompt tokens. This controls how much the model tries to + /// learn to generate the prompt (as compared to the completion which always has a weight of 1.0), + /// and can add a stabilizing effect to training when completions are short. + /// + /// If prompts are extremely long (relative to completions), it may make sense to reduce this + /// weight so as to avoid over-prioritizing learning the prompt. + /// + /// + /// If set, we calculate classification-specific metrics such as accuracy and F-1 score using the + /// validation set at the end of every epoch. These metrics can be viewed in the + /// [results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model). + /// + /// In order to compute classification metrics, you must provide a `validation_file`. Additionally, + /// you must specify `classification_n_classes` for multiclass classification or + /// `classification_positive_class` for binary classification. + /// + /// + /// The number of classes in a classification task. + /// + /// This parameter is required for multiclass classification. + /// + /// + /// The positive class in binary classification. + /// + /// This parameter is needed to generate precision, recall, and F1 metrics when doing binary + /// classification. + /// + /// + /// If this is provided, we calculate F-beta scores at the specified beta values. The F-beta score + /// is a generalization of F-1 score. This is only used for binary classification. + /// + /// With a beta of 1 (i.e. the F-1 score), precision and recall are given the same weight. A larger + /// beta score puts more weight on recall and less on precision. A smaller beta score puts more + /// weight on precision and less on recall. + /// + /// + /// 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 + /// `ada:ft-your-org:custom-model-name-2022-02-15-04-21-04`. + /// + /// Keeps track of any properties unknown to the library. + internal CreateFineTuneRequest(string trainingFile, string validationFile, CreateFineTuneRequestModel? model, long? nEpochs, long? batchSize, double? learningRateMultiplier, double? promptLossRate, bool? computeClassificationMetrics, long? classificationNClasses, string classificationPositiveClass, IList classificationBetas, string suffix, IDictionary serializedAdditionalRawData) + { + TrainingFile = trainingFile; + ValidationFile = validationFile; + Model = model; + NEpochs = nEpochs; + BatchSize = batchSize; + LearningRateMultiplier = learningRateMultiplier; + PromptLossRate = promptLossRate; + ComputeClassificationMetrics = computeClassificationMetrics; + ClassificationNClasses = classificationNClasses; + ClassificationPositiveClass = classificationPositiveClass; + ClassificationBetas = classificationBetas; + Suffix = suffix; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateFineTuneRequest() + { + } + + /// + /// The ID of an uploaded file that contains training data. + /// + /// See [upload file](/docs/api-reference/files/upload) for how to upload a file. + /// + /// Your dataset must be formatted as a JSONL file, where each training example is a JSON object + /// with the keys "prompt" and "completion". Additionally, you must upload your file with the + /// purpose `fine-tune`. + /// + /// See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more + /// details. + /// + public string TrainingFile { get; } + /// + /// The ID of an uploaded file that contains validation data. + /// + /// If you provide this file, the data is used to generate validation metrics periodically during + /// fine-tuning. These metrics can be viewed in the + /// [fine-tuning results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model). + /// Your train and validation data should be mutually exclusive. + /// + /// Your dataset must be formatted as a JSONL file, where each validation example is a JSON object + /// with the keys "prompt" and "completion". Additionally, you must upload your file with the + /// purpose `fine-tune`. + /// + /// See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more + /// details. + /// + public string ValidationFile { get; set; } + /// + /// The name of the base model to fine-tune. You can select one of "ada", "babbage", "curie", + /// "davinci", or a fine-tuned model created after 2022-04-21 and before 2023-08-22. To learn more + /// about these models, see the [Models](/docs/models) documentation. + /// + public CreateFineTuneRequestModel? Model { get; set; } + /// + /// The number of epochs to train the model for. An epoch refers to one full cycle through the + /// training dataset. + /// + public long? NEpochs { get; set; } + /// + /// The batch size to use for training. The batch size is the number of training examples used to + /// train a single forward and backward pass. + /// + /// By default, the batch size will be dynamically configured to be ~0.2% of the number of examples + /// in the training set, capped at 256 - in general, we've found that larger batch sizes tend to + /// work better for larger datasets. + /// + public long? BatchSize { get; set; } + /// + /// The learning rate multiplier to use for training. The fine-tuning learning rate is the original + /// learning rate used for pretraining multiplied by this value. + /// + /// By default, the learning rate multiplier is the 0.05, 0.1, or 0.2 depending on final + /// `batch_size` (larger learning rates tend to perform better with larger batch sizes). We + /// recommend experimenting with values in the range 0.02 to 0.2 to see what produces the best + /// results. + /// + public double? LearningRateMultiplier { get; set; } + /// + /// The weight to use for loss on the prompt tokens. This controls how much the model tries to + /// learn to generate the prompt (as compared to the completion which always has a weight of 1.0), + /// and can add a stabilizing effect to training when completions are short. + /// + /// If prompts are extremely long (relative to completions), it may make sense to reduce this + /// weight so as to avoid over-prioritizing learning the prompt. + /// + public double? PromptLossRate { get; set; } + /// + /// If set, we calculate classification-specific metrics such as accuracy and F-1 score using the + /// validation set at the end of every epoch. These metrics can be viewed in the + /// [results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model). + /// + /// In order to compute classification metrics, you must provide a `validation_file`. Additionally, + /// you must specify `classification_n_classes` for multiclass classification or + /// `classification_positive_class` for binary classification. + /// + public bool? ComputeClassificationMetrics { get; set; } + /// + /// The number of classes in a classification task. + /// + /// This parameter is required for multiclass classification. + /// + public long? ClassificationNClasses { get; set; } + /// + /// The positive class in binary classification. + /// + /// This parameter is needed to generate precision, recall, and F1 metrics when doing binary + /// classification. + /// + public string ClassificationPositiveClass { get; set; } + /// + /// If this is provided, we calculate F-beta scores at the specified beta values. The F-beta score + /// is a generalization of F-1 score. This is only used for binary classification. + /// + /// With a beta of 1 (i.e. the F-1 score), precision and recall are given the same weight. A larger + /// beta score puts more weight on recall and less on precision. A smaller beta score puts more + /// weight on precision and less on recall. + /// + public IList ClassificationBetas { get; set; } + /// + /// 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 + /// `ada:ft-your-org:custom-model-name-2022-02-15-04-21-04`. + /// + public string Suffix { get; set; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateFineTuneRequestModel.cs b/.dotnet/src/Generated/Models/CreateFineTuneRequestModel.cs new file mode 100644 index 000000000..de5b6f368 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateFineTuneRequestModel.cs @@ -0,0 +1,54 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for model in CreateFineTuneRequest. + public readonly partial struct CreateFineTuneRequestModel : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateFineTuneRequestModel(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string AdaValue = "ada"; + private const string BabbageValue = "babbage"; + private const string CurieValue = "curie"; + private const string DavinciValue = "davinci"; + + /// ada. + public static CreateFineTuneRequestModel Ada { get; } = new CreateFineTuneRequestModel(AdaValue); + /// babbage. + public static CreateFineTuneRequestModel Babbage { get; } = new CreateFineTuneRequestModel(BabbageValue); + /// curie. + public static CreateFineTuneRequestModel Curie { get; } = new CreateFineTuneRequestModel(CurieValue); + /// davinci. + public static CreateFineTuneRequestModel Davinci { get; } = new CreateFineTuneRequestModel(DavinciValue); + /// Determines if two values are the same. + public static bool operator ==(CreateFineTuneRequestModel left, CreateFineTuneRequestModel right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateFineTuneRequestModel left, CreateFineTuneRequestModel right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateFineTuneRequestModel(string value) => new CreateFineTuneRequestModel(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateFineTuneRequestModel other && Equals(other); + /// + public bool Equals(CreateFineTuneRequestModel other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.Serialization.cs new file mode 100644 index 000000000..6d26b67fc --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.Serialization.cs @@ -0,0 +1,201 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateFineTuningJobRequest : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateFineTuningJobRequest)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("training_file"u8); + writer.WriteStringValue(TrainingFile); + if (OptionalProperty.IsDefined(ValidationFile)) + { + if (ValidationFile != null) + { + writer.WritePropertyName("validation_file"u8); + writer.WriteStringValue(ValidationFile); + } + else + { + writer.WriteNull("validation_file"); + } + } + writer.WritePropertyName("model"u8); + writer.WriteStringValue(Model.ToString()); + if (OptionalProperty.IsDefined(Hyperparameters)) + { + writer.WritePropertyName("hyperparameters"u8); + writer.WriteObjectValue(Hyperparameters); + } + if (OptionalProperty.IsDefined(Suffix)) + { + if (Suffix != null) + { + writer.WritePropertyName("suffix"u8); + writer.WriteStringValue(Suffix); + } + else + { + writer.WriteNull("suffix"); + } + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateFineTuningJobRequest IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateFineTuningJobRequest)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateFineTuningJobRequest(document.RootElement, options); + } + + internal static CreateFineTuningJobRequest DeserializeCreateFineTuningJobRequest(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string trainingFile = default; + OptionalProperty validationFile = default; + CreateFineTuningJobRequestModel model = default; + OptionalProperty hyperparameters = default; + OptionalProperty suffix = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("training_file"u8)) + { + trainingFile = property.Value.GetString(); + continue; + } + if (property.NameEquals("validation_file"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + validationFile = null; + continue; + } + validationFile = property.Value.GetString(); + continue; + } + if (property.NameEquals("model"u8)) + { + model = new CreateFineTuningJobRequestModel(property.Value.GetString()); + continue; + } + if (property.NameEquals("hyperparameters"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + hyperparameters = CreateFineTuningJobRequestHyperparameters.DeserializeCreateFineTuningJobRequestHyperparameters(property.Value); + continue; + } + if (property.NameEquals("suffix"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + suffix = null; + continue; + } + suffix = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateFineTuningJobRequest(trainingFile, validationFile.Value, model, hyperparameters.Value, suffix.Value, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateFineTuningJobRequest)} does not support '{options.Format}' format."); + } + } + + CreateFineTuningJobRequest IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateFineTuningJobRequest(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateFineTuningJobRequest)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateFineTuningJobRequest FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateFineTuningJobRequest(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.cs b/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.cs new file mode 100644 index 000000000..7157e813c --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.cs @@ -0,0 +1,159 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateFineTuningJobRequest. + public partial class CreateFineTuningJobRequest + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// The ID of an uploaded file that contains training data. + /// + /// See [upload file](/docs/api-reference/files/upload) for how to upload a file. + /// + /// Your dataset must be formatted as a JSONL file. Additionally, you must upload your file with + /// the purpose `fine-tune`. + /// + /// See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. + /// + /// + /// The name of the model to fine-tune. You can select one of the + /// [supported models](/docs/guides/fine-tuning/what-models-can-be-fine-tuned). + /// + /// is null. + public CreateFineTuningJobRequest(string trainingFile, CreateFineTuningJobRequestModel model) + { + ClientUtilities.AssertNotNull(trainingFile, nameof(trainingFile)); + + TrainingFile = trainingFile; + Model = model; + } + + /// Initializes a new instance of . + /// + /// The ID of an uploaded file that contains training data. + /// + /// See [upload file](/docs/api-reference/files/upload) for how to upload a file. + /// + /// Your dataset must be formatted as a JSONL file. Additionally, you must upload your file with + /// the purpose `fine-tune`. + /// + /// See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. + /// + /// + /// The ID of an uploaded file that contains validation data. + /// + /// If you provide this file, the data is used to generate validation metrics periodically during + /// fine-tuning. These metrics can be viewed in the fine-tuning results file. The same data should + /// not be present in both train and validation files. + /// + /// Your dataset must be formatted as a JSONL file. You must upload your file with the purpose + /// `fine-tune`. + /// + /// See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. + /// + /// + /// The name of the model to fine-tune. You can select one of the + /// [supported models](/docs/guides/fine-tuning/what-models-can-be-fine-tuned). + /// + /// The hyperparameters used for the fine-tuning job. + /// + /// 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`. + /// + /// Keeps track of any properties unknown to the library. + internal CreateFineTuningJobRequest(string trainingFile, string validationFile, CreateFineTuningJobRequestModel model, CreateFineTuningJobRequestHyperparameters hyperparameters, string suffix, IDictionary serializedAdditionalRawData) + { + TrainingFile = trainingFile; + ValidationFile = validationFile; + Model = model; + Hyperparameters = hyperparameters; + Suffix = suffix; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateFineTuningJobRequest() + { + } + + /// + /// The ID of an uploaded file that contains training data. + /// + /// See [upload file](/docs/api-reference/files/upload) for how to upload a file. + /// + /// Your dataset must be formatted as a JSONL file. Additionally, you must upload your file with + /// the purpose `fine-tune`. + /// + /// See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. + /// + public string TrainingFile { get; } + /// + /// The ID of an uploaded file that contains validation data. + /// + /// If you provide this file, the data is used to generate validation metrics periodically during + /// fine-tuning. These metrics can be viewed in the fine-tuning results file. The same data should + /// not be present in both train and validation files. + /// + /// Your dataset must be formatted as a JSONL file. You must upload your file with the purpose + /// `fine-tune`. + /// + /// See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. + /// + public string ValidationFile { get; set; } + /// + /// The name of the model to fine-tune. You can select one of the + /// [supported models](/docs/guides/fine-tuning/what-models-can-be-fine-tuned). + /// + public CreateFineTuningJobRequestModel Model { get; } + /// The hyperparameters used for the fine-tuning job. + public CreateFineTuningJobRequestHyperparameters Hyperparameters { get; set; } + /// + /// 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`. + /// + public string Suffix { get; set; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.Serialization.cs b/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.Serialization.cs new file mode 100644 index 000000000..de057600c --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.Serialization.cs @@ -0,0 +1,146 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateFineTuningJobRequestHyperparameters : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateFineTuningJobRequestHyperparameters)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + if (OptionalProperty.IsDefined(NEpochs)) + { + writer.WritePropertyName("n_epochs"u8); +#if NET6_0_OR_GREATER + writer.WriteRawValue(NEpochs); +#else + using (JsonDocument document = JsonDocument.Parse(NEpochs)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateFineTuningJobRequestHyperparameters IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateFineTuningJobRequestHyperparameters)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateFineTuningJobRequestHyperparameters(document.RootElement, options); + } + + internal static CreateFineTuningJobRequestHyperparameters DeserializeCreateFineTuningJobRequestHyperparameters(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + OptionalProperty nEpochs = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("n_epochs"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + nEpochs = BinaryData.FromString(property.Value.GetRawText()); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateFineTuningJobRequestHyperparameters(nEpochs.Value, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateFineTuningJobRequestHyperparameters)} does not support '{options.Format}' format."); + } + } + + CreateFineTuningJobRequestHyperparameters IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateFineTuningJobRequestHyperparameters(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateFineTuningJobRequestHyperparameters)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateFineTuningJobRequestHyperparameters FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateFineTuningJobRequestHyperparameters(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.cs b/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.cs new file mode 100644 index 000000000..258881cb0 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.cs @@ -0,0 +1,106 @@ +// + +#nullable disable + +using System; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateFineTuningJobRequestHyperparameters. + public partial class CreateFineTuningJobRequestHyperparameters + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + public CreateFineTuningJobRequestHyperparameters() + { + } + + /// Initializes a new instance of . + /// + /// The number of epochs to train the model for. An epoch refers to one full cycle through the + /// training dataset. + /// + /// Keeps track of any properties unknown to the library. + internal CreateFineTuningJobRequestHyperparameters(BinaryData nEpochs, IDictionary serializedAdditionalRawData) + { + NEpochs = nEpochs; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// + /// The number of epochs to train the model for. An epoch refers to one full cycle through the + /// training dataset. + /// + /// To assign an object to this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// + /// Supported types: + /// + /// + /// "auto" + /// + /// + /// + /// + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + public BinaryData NEpochs { get; set; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateFineTuningJobRequestModel.cs b/.dotnet/src/Generated/Models/CreateFineTuningJobRequestModel.cs new file mode 100644 index 000000000..ef3c6ec0c --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateFineTuningJobRequestModel.cs @@ -0,0 +1,51 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for model in CreateFineTuningJobRequest. + public readonly partial struct CreateFineTuningJobRequestModel : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateFineTuningJobRequestModel(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string Babbage002Value = "babbage-002"; + private const string Davinci002Value = "davinci-002"; + private const string Gpt35TurboValue = "gpt-3.5-turbo"; + + /// babbage-002. + public static CreateFineTuningJobRequestModel Babbage002 { get; } = new CreateFineTuningJobRequestModel(Babbage002Value); + /// davinci-002. + public static CreateFineTuningJobRequestModel Davinci002 { get; } = new CreateFineTuningJobRequestModel(Davinci002Value); + /// gpt-3.5-turbo. + public static CreateFineTuningJobRequestModel Gpt35Turbo { get; } = new CreateFineTuningJobRequestModel(Gpt35TurboValue); + /// Determines if two values are the same. + public static bool operator ==(CreateFineTuningJobRequestModel left, CreateFineTuningJobRequestModel right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateFineTuningJobRequestModel left, CreateFineTuningJobRequestModel right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateFineTuningJobRequestModel(string value) => new CreateFineTuningJobRequestModel(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateFineTuningJobRequestModel other && Equals(other); + /// + public bool Equals(CreateFineTuningJobRequestModel other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateImageEditRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateImageEditRequest.Serialization.cs new file mode 100644 index 000000000..cc8938c1f --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateImageEditRequest.Serialization.cs @@ -0,0 +1,234 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateImageEditRequest : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateImageEditRequest)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("image"u8); + writer.WriteBase64StringValue(Image.ToArray(), "D"); + writer.WritePropertyName("prompt"u8); + writer.WriteStringValue(Prompt); + if (OptionalProperty.IsDefined(Mask)) + { + writer.WritePropertyName("mask"u8); + writer.WriteBase64StringValue(Mask.ToArray(), "D"); + } + if (OptionalProperty.IsDefined(Model)) + { + writer.WritePropertyName("model"u8); + writer.WriteStringValue(Model.Value.ToString()); + } + if (OptionalProperty.IsDefined(N)) + { + if (N != null) + { + writer.WritePropertyName("n"u8); + writer.WriteNumberValue(N.Value); + } + else + { + writer.WriteNull("n"); + } + } + if (OptionalProperty.IsDefined(Size)) + { + writer.WritePropertyName("size"u8); + writer.WriteStringValue(Size.Value.ToString()); + } + if (OptionalProperty.IsDefined(ResponseFormat)) + { + writer.WritePropertyName("response_format"u8); + writer.WriteStringValue(ResponseFormat.Value.ToString()); + } + if (OptionalProperty.IsDefined(User)) + { + writer.WritePropertyName("user"u8); + writer.WriteStringValue(User); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateImageEditRequest IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateImageEditRequest)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateImageEditRequest(document.RootElement, options); + } + + internal static CreateImageEditRequest DeserializeCreateImageEditRequest(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + BinaryData image = default; + string prompt = default; + OptionalProperty mask = default; + OptionalProperty model = default; + OptionalProperty n = default; + OptionalProperty size = default; + OptionalProperty responseFormat = default; + OptionalProperty user = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("image"u8)) + { + image = BinaryData.FromBytes(property.Value.GetBytesFromBase64("D")); + continue; + } + if (property.NameEquals("prompt"u8)) + { + prompt = property.Value.GetString(); + continue; + } + if (property.NameEquals("mask"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + mask = BinaryData.FromBytes(property.Value.GetBytesFromBase64("D")); + continue; + } + if (property.NameEquals("model"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + model = new CreateImageEditRequestModel(property.Value.GetString()); + continue; + } + if (property.NameEquals("n"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + n = null; + continue; + } + n = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("size"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + size = new CreateImageEditRequestSize(property.Value.GetString()); + continue; + } + if (property.NameEquals("response_format"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + responseFormat = new CreateImageEditRequestResponseFormat(property.Value.GetString()); + continue; + } + if (property.NameEquals("user"u8)) + { + user = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateImageEditRequest(image, prompt, mask.Value, OptionalProperty.ToNullable(model), OptionalProperty.ToNullable(n), OptionalProperty.ToNullable(size), OptionalProperty.ToNullable(responseFormat), user.Value, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateImageEditRequest)} does not support '{options.Format}' format."); + } + } + + CreateImageEditRequest IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateImageEditRequest(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateImageEditRequest)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateImageEditRequest FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateImageEditRequest(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateImageEditRequest.cs b/.dotnet/src/Generated/Models/CreateImageEditRequest.cs new file mode 100644 index 000000000..12f245f91 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateImageEditRequest.cs @@ -0,0 +1,153 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateImageEditRequest. + public partial class CreateImageEditRequest + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// The image to edit. Must be a valid PNG file, less than 4MB, and square. If mask is not + /// provided, image must have transparency, which will be used as the mask. + /// + /// A text description of the desired image(s). The maximum length is 1000 characters. + /// or is null. + public CreateImageEditRequest(BinaryData image, string prompt) + { + ClientUtilities.AssertNotNull(image, nameof(image)); + ClientUtilities.AssertNotNull(prompt, nameof(prompt)); + + Image = image; + Prompt = prompt; + } + + /// Initializes a new instance of . + /// + /// The image to edit. Must be a valid PNG file, less than 4MB, and square. If mask is not + /// provided, image must have transparency, which will be used as the mask. + /// + /// A text description of the desired image(s). The maximum length is 1000 characters. + /// + /// An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where + /// `image` should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions + /// as `image`. + /// + /// The model to use for image generation. Only `dall-e-2` is supported at this time. + /// The number of images to generate. Must be between 1 and 10. + /// The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`. + /// The format in which the generated images are returned. Must be one of `url` or `b64_json`. + /// + /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect + /// abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + /// + /// Keeps track of any properties unknown to the library. + internal CreateImageEditRequest(BinaryData image, string prompt, BinaryData mask, CreateImageEditRequestModel? model, long? n, CreateImageEditRequestSize? size, CreateImageEditRequestResponseFormat? responseFormat, string user, IDictionary serializedAdditionalRawData) + { + Image = image; + Prompt = prompt; + Mask = mask; + Model = model; + N = n; + Size = size; + ResponseFormat = responseFormat; + User = user; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateImageEditRequest() + { + } + + /// + /// The image to edit. Must be a valid PNG file, less than 4MB, and square. If mask is not + /// provided, image must have transparency, which will be used as the mask. + /// + /// To assign a byte[] to this property use . + /// The byte[] will be serialized to a Base64 encoded string. + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromBytes(new byte[] { 1, 2, 3 }) + /// Creates a payload of "AQID". + /// + /// + /// + /// + public BinaryData Image { get; } + /// A text description of the desired image(s). The maximum length is 1000 characters. + public string Prompt { get; } + /// + /// An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where + /// `image` should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions + /// as `image`. + /// + /// To assign a byte[] to this property use . + /// The byte[] will be serialized to a Base64 encoded string. + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromBytes(new byte[] { 1, 2, 3 }) + /// Creates a payload of "AQID". + /// + /// + /// + /// + public BinaryData Mask { get; set; } + /// The model to use for image generation. Only `dall-e-2` is supported at this time. + public CreateImageEditRequestModel? Model { get; set; } + /// The number of images to generate. Must be between 1 and 10. + public long? N { get; set; } + /// The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`. + public CreateImageEditRequestSize? Size { get; set; } + /// The format in which the generated images are returned. Must be one of `url` or `b64_json`. + public CreateImageEditRequestResponseFormat? ResponseFormat { get; set; } + /// + /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect + /// abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + /// + public string User { get; set; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateImageEditRequestModel.cs b/.dotnet/src/Generated/Models/CreateImageEditRequestModel.cs new file mode 100644 index 000000000..152466ce3 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateImageEditRequestModel.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for model in CreateImageEditRequest. + public readonly partial struct CreateImageEditRequestModel : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateImageEditRequestModel(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string DallE2Value = "dall-e-2"; + + /// dall-e-2. + public static CreateImageEditRequestModel DallE2 { get; } = new CreateImageEditRequestModel(DallE2Value); + /// Determines if two values are the same. + public static bool operator ==(CreateImageEditRequestModel left, CreateImageEditRequestModel right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateImageEditRequestModel left, CreateImageEditRequestModel right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateImageEditRequestModel(string value) => new CreateImageEditRequestModel(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateImageEditRequestModel other && Equals(other); + /// + public bool Equals(CreateImageEditRequestModel other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateImageEditRequestResponseFormat.cs b/.dotnet/src/Generated/Models/CreateImageEditRequestResponseFormat.cs new file mode 100644 index 000000000..2dfc96644 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateImageEditRequestResponseFormat.cs @@ -0,0 +1,48 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for response_format in CreateImageEditRequest. + public readonly partial struct CreateImageEditRequestResponseFormat : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateImageEditRequestResponseFormat(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string UrlValue = "url"; + private const string B64JsonValue = "b64_json"; + + /// url. + public static CreateImageEditRequestResponseFormat Url { get; } = new CreateImageEditRequestResponseFormat(UrlValue); + /// b64_json. + public static CreateImageEditRequestResponseFormat B64Json { get; } = new CreateImageEditRequestResponseFormat(B64JsonValue); + /// Determines if two values are the same. + public static bool operator ==(CreateImageEditRequestResponseFormat left, CreateImageEditRequestResponseFormat right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateImageEditRequestResponseFormat left, CreateImageEditRequestResponseFormat right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateImageEditRequestResponseFormat(string value) => new CreateImageEditRequestResponseFormat(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateImageEditRequestResponseFormat other && Equals(other); + /// + public bool Equals(CreateImageEditRequestResponseFormat other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateImageEditRequestSize.cs b/.dotnet/src/Generated/Models/CreateImageEditRequestSize.cs new file mode 100644 index 000000000..01c9a4c45 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateImageEditRequestSize.cs @@ -0,0 +1,51 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for size in CreateImageEditRequest. + public readonly partial struct CreateImageEditRequestSize : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateImageEditRequestSize(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string _256x256Value = "256x256"; + private const string _512x512Value = "512x512"; + private const string _1024x1024Value = "1024x1024"; + + /// 256x256. + public static CreateImageEditRequestSize _256x256 { get; } = new CreateImageEditRequestSize(_256x256Value); + /// 512x512. + public static CreateImageEditRequestSize _512x512 { get; } = new CreateImageEditRequestSize(_512x512Value); + /// 1024x1024. + public static CreateImageEditRequestSize _1024x1024 { get; } = new CreateImageEditRequestSize(_1024x1024Value); + /// Determines if two values are the same. + public static bool operator ==(CreateImageEditRequestSize left, CreateImageEditRequestSize right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateImageEditRequestSize left, CreateImageEditRequestSize right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateImageEditRequestSize(string value) => new CreateImageEditRequestSize(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateImageEditRequestSize other && Equals(other); + /// + public bool Equals(CreateImageEditRequestSize other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateImageRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateImageRequest.Serialization.cs new file mode 100644 index 000000000..f790166ff --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateImageRequest.Serialization.cs @@ -0,0 +1,241 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateImageRequest : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateImageRequest)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("prompt"u8); + writer.WriteStringValue(Prompt); + if (OptionalProperty.IsDefined(Model)) + { + writer.WritePropertyName("model"u8); + writer.WriteStringValue(Model.Value.ToString()); + } + if (OptionalProperty.IsDefined(N)) + { + if (N != null) + { + writer.WritePropertyName("n"u8); + writer.WriteNumberValue(N.Value); + } + else + { + writer.WriteNull("n"); + } + } + if (OptionalProperty.IsDefined(Quality)) + { + writer.WritePropertyName("quality"u8); + writer.WriteStringValue(Quality.Value.ToString()); + } + if (OptionalProperty.IsDefined(ResponseFormat)) + { + writer.WritePropertyName("response_format"u8); + writer.WriteStringValue(ResponseFormat.Value.ToString()); + } + if (OptionalProperty.IsDefined(Size)) + { + writer.WritePropertyName("size"u8); + writer.WriteStringValue(Size.Value.ToString()); + } + if (OptionalProperty.IsDefined(Style)) + { + writer.WritePropertyName("style"u8); + writer.WriteStringValue(Style.Value.ToString()); + } + if (OptionalProperty.IsDefined(User)) + { + writer.WritePropertyName("user"u8); + writer.WriteStringValue(User); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateImageRequest IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateImageRequest)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateImageRequest(document.RootElement, options); + } + + internal static CreateImageRequest DeserializeCreateImageRequest(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string prompt = default; + OptionalProperty model = default; + OptionalProperty n = default; + OptionalProperty quality = default; + OptionalProperty responseFormat = default; + OptionalProperty size = default; + OptionalProperty style = default; + OptionalProperty user = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("prompt"u8)) + { + prompt = property.Value.GetString(); + continue; + } + if (property.NameEquals("model"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + model = new CreateImageRequestModel(property.Value.GetString()); + continue; + } + if (property.NameEquals("n"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + n = null; + continue; + } + n = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("quality"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + quality = new CreateImageRequestQuality(property.Value.GetString()); + continue; + } + if (property.NameEquals("response_format"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + responseFormat = new CreateImageRequestResponseFormat(property.Value.GetString()); + continue; + } + if (property.NameEquals("size"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + size = new CreateImageRequestSize(property.Value.GetString()); + continue; + } + if (property.NameEquals("style"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + style = new CreateImageRequestStyle(property.Value.GetString()); + continue; + } + if (property.NameEquals("user"u8)) + { + user = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateImageRequest(prompt, OptionalProperty.ToNullable(model), OptionalProperty.ToNullable(n), OptionalProperty.ToNullable(quality), OptionalProperty.ToNullable(responseFormat), OptionalProperty.ToNullable(size), OptionalProperty.ToNullable(style), user.Value, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateImageRequest)} does not support '{options.Format}' format."); + } + } + + CreateImageRequest IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateImageRequest(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateImageRequest)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateImageRequest FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateImageRequest(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateImageRequest.cs b/.dotnet/src/Generated/Models/CreateImageRequest.cs new file mode 100644 index 000000000..bde1c78ba --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateImageRequest.cs @@ -0,0 +1,142 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateImageRequest. + public partial class CreateImageRequest + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// A text description of the desired image(s). The maximum length is 1000 characters for + /// `dall-e-2` and 4000 characters for `dall-e-3`. + /// + /// is null. + public CreateImageRequest(string prompt) + { + ClientUtilities.AssertNotNull(prompt, nameof(prompt)); + + Prompt = prompt; + } + + /// Initializes a new instance of . + /// + /// A text description of the desired image(s). The maximum length is 1000 characters for + /// `dall-e-2` and 4000 characters for `dall-e-3`. + /// + /// The model to use for image generation. + /// + /// The number of images to generate. Must be between 1 and 10. For `dall-e-3`, only `n=1` is + /// supported. + /// + /// + /// The quality of the image that will be generated. `hd` creates images with finer details and + /// greater consistency across the image. This param is only supported for `dall-e-3`. + /// + /// The format in which the generated images are returned. Must be one of `url` or `b64_json`. + /// + /// 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. + /// + /// + /// The style of the generated images. Must be one of `vivid` or `natural`. Vivid causes the model + /// to lean towards generating hyper-real and dramatic images. Natural causes the model to produce + /// more natural, less hyper-real looking images. This param is only supported for `dall-e-3`. + /// + /// + /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect + /// abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + /// + /// Keeps track of any properties unknown to the library. + internal CreateImageRequest(string prompt, CreateImageRequestModel? model, long? n, CreateImageRequestQuality? quality, CreateImageRequestResponseFormat? responseFormat, CreateImageRequestSize? size, CreateImageRequestStyle? style, string user, IDictionary serializedAdditionalRawData) + { + Prompt = prompt; + Model = model; + N = n; + Quality = quality; + ResponseFormat = responseFormat; + Size = size; + Style = style; + User = user; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateImageRequest() + { + } + + /// + /// A text description of the desired image(s). The maximum length is 1000 characters for + /// `dall-e-2` and 4000 characters for `dall-e-3`. + /// + public string Prompt { get; } + /// The model to use for image generation. + public CreateImageRequestModel? Model { get; set; } + /// + /// The number of images to generate. Must be between 1 and 10. For `dall-e-3`, only `n=1` is + /// supported. + /// + public long? N { get; set; } + /// + /// The quality of the image that will be generated. `hd` creates images with finer details and + /// greater consistency across the image. This param is only supported for `dall-e-3`. + /// + public CreateImageRequestQuality? Quality { get; set; } + /// The format in which the generated images are returned. Must be one of `url` or `b64_json`. + public CreateImageRequestResponseFormat? ResponseFormat { get; set; } + /// + /// 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. + /// + public CreateImageRequestSize? Size { get; set; } + /// + /// The style of the generated images. Must be one of `vivid` or `natural`. Vivid causes the model + /// to lean towards generating hyper-real and dramatic images. Natural causes the model to produce + /// more natural, less hyper-real looking images. This param is only supported for `dall-e-3`. + /// + public CreateImageRequestStyle? Style { get; set; } + /// + /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect + /// abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + /// + public string User { get; set; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateImageRequestModel.cs b/.dotnet/src/Generated/Models/CreateImageRequestModel.cs new file mode 100644 index 000000000..46d224028 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateImageRequestModel.cs @@ -0,0 +1,48 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for model in CreateImageRequest. + public readonly partial struct CreateImageRequestModel : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateImageRequestModel(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string DallE2Value = "dall-e-2"; + private const string DallE3Value = "dall-e-3"; + + /// dall-e-2. + public static CreateImageRequestModel DallE2 { get; } = new CreateImageRequestModel(DallE2Value); + /// dall-e-3. + public static CreateImageRequestModel DallE3 { get; } = new CreateImageRequestModel(DallE3Value); + /// Determines if two values are the same. + public static bool operator ==(CreateImageRequestModel left, CreateImageRequestModel right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateImageRequestModel left, CreateImageRequestModel right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateImageRequestModel(string value) => new CreateImageRequestModel(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateImageRequestModel other && Equals(other); + /// + public bool Equals(CreateImageRequestModel other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateImageRequestQuality.cs b/.dotnet/src/Generated/Models/CreateImageRequestQuality.cs new file mode 100644 index 000000000..e3a737c23 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateImageRequestQuality.cs @@ -0,0 +1,48 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for quality in CreateImageRequest. + public readonly partial struct CreateImageRequestQuality : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateImageRequestQuality(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string StandardValue = "standard"; + private const string HdValue = "hd"; + + /// standard. + public static CreateImageRequestQuality Standard { get; } = new CreateImageRequestQuality(StandardValue); + /// hd. + public static CreateImageRequestQuality Hd { get; } = new CreateImageRequestQuality(HdValue); + /// Determines if two values are the same. + public static bool operator ==(CreateImageRequestQuality left, CreateImageRequestQuality right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateImageRequestQuality left, CreateImageRequestQuality right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateImageRequestQuality(string value) => new CreateImageRequestQuality(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateImageRequestQuality other && Equals(other); + /// + public bool Equals(CreateImageRequestQuality other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateImageRequestResponseFormat.cs b/.dotnet/src/Generated/Models/CreateImageRequestResponseFormat.cs new file mode 100644 index 000000000..5990ab315 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateImageRequestResponseFormat.cs @@ -0,0 +1,48 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for response_format in CreateImageRequest. + public readonly partial struct CreateImageRequestResponseFormat : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateImageRequestResponseFormat(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string UrlValue = "url"; + private const string B64JsonValue = "b64_json"; + + /// url. + public static CreateImageRequestResponseFormat Url { get; } = new CreateImageRequestResponseFormat(UrlValue); + /// b64_json. + public static CreateImageRequestResponseFormat B64Json { get; } = new CreateImageRequestResponseFormat(B64JsonValue); + /// Determines if two values are the same. + public static bool operator ==(CreateImageRequestResponseFormat left, CreateImageRequestResponseFormat right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateImageRequestResponseFormat left, CreateImageRequestResponseFormat right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateImageRequestResponseFormat(string value) => new CreateImageRequestResponseFormat(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateImageRequestResponseFormat other && Equals(other); + /// + public bool Equals(CreateImageRequestResponseFormat other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateImageRequestSize.cs b/.dotnet/src/Generated/Models/CreateImageRequestSize.cs new file mode 100644 index 000000000..df73f6aac --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateImageRequestSize.cs @@ -0,0 +1,57 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for size in CreateImageRequest. + public readonly partial struct CreateImageRequestSize : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateImageRequestSize(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string _256x256Value = "256x256"; + private const string _512x512Value = "512x512"; + private const string _1024x1024Value = "1024x1024"; + private const string _1792x1024Value = "1792x1024"; + private const string _1024x1792Value = "1024x1792"; + + /// 256x256. + public static CreateImageRequestSize _256x256 { get; } = new CreateImageRequestSize(_256x256Value); + /// 512x512. + public static CreateImageRequestSize _512x512 { get; } = new CreateImageRequestSize(_512x512Value); + /// 1024x1024. + public static CreateImageRequestSize _1024x1024 { get; } = new CreateImageRequestSize(_1024x1024Value); + /// 1792x1024. + public static CreateImageRequestSize _1792x1024 { get; } = new CreateImageRequestSize(_1792x1024Value); + /// 1024x1792. + public static CreateImageRequestSize _1024x1792 { get; } = new CreateImageRequestSize(_1024x1792Value); + /// Determines if two values are the same. + public static bool operator ==(CreateImageRequestSize left, CreateImageRequestSize right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateImageRequestSize left, CreateImageRequestSize right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateImageRequestSize(string value) => new CreateImageRequestSize(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateImageRequestSize other && Equals(other); + /// + public bool Equals(CreateImageRequestSize other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateImageRequestStyle.cs b/.dotnet/src/Generated/Models/CreateImageRequestStyle.cs new file mode 100644 index 000000000..a711e0635 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateImageRequestStyle.cs @@ -0,0 +1,48 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for style in CreateImageRequest. + public readonly partial struct CreateImageRequestStyle : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateImageRequestStyle(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string VividValue = "vivid"; + private const string NaturalValue = "natural"; + + /// vivid. + public static CreateImageRequestStyle Vivid { get; } = new CreateImageRequestStyle(VividValue); + /// natural. + public static CreateImageRequestStyle Natural { get; } = new CreateImageRequestStyle(NaturalValue); + /// Determines if two values are the same. + public static bool operator ==(CreateImageRequestStyle left, CreateImageRequestStyle right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateImageRequestStyle left, CreateImageRequestStyle right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateImageRequestStyle(string value) => new CreateImageRequestStyle(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateImageRequestStyle other && Equals(other); + /// + public bool Equals(CreateImageRequestStyle other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateImageVariationRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateImageVariationRequest.Serialization.cs new file mode 100644 index 000000000..bd3a103fb --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateImageVariationRequest.Serialization.cs @@ -0,0 +1,211 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateImageVariationRequest : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateImageVariationRequest)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("image"u8); + writer.WriteBase64StringValue(Image.ToArray(), "D"); + if (OptionalProperty.IsDefined(Model)) + { + writer.WritePropertyName("model"u8); + writer.WriteStringValue(Model.Value.ToString()); + } + if (OptionalProperty.IsDefined(N)) + { + if (N != null) + { + writer.WritePropertyName("n"u8); + writer.WriteNumberValue(N.Value); + } + else + { + writer.WriteNull("n"); + } + } + if (OptionalProperty.IsDefined(ResponseFormat)) + { + writer.WritePropertyName("response_format"u8); + writer.WriteStringValue(ResponseFormat.Value.ToString()); + } + if (OptionalProperty.IsDefined(Size)) + { + writer.WritePropertyName("size"u8); + writer.WriteStringValue(Size.Value.ToString()); + } + if (OptionalProperty.IsDefined(User)) + { + writer.WritePropertyName("user"u8); + writer.WriteStringValue(User); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateImageVariationRequest IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateImageVariationRequest)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateImageVariationRequest(document.RootElement, options); + } + + internal static CreateImageVariationRequest DeserializeCreateImageVariationRequest(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + BinaryData image = default; + OptionalProperty model = default; + OptionalProperty n = default; + OptionalProperty responseFormat = default; + OptionalProperty size = default; + OptionalProperty user = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("image"u8)) + { + image = BinaryData.FromBytes(property.Value.GetBytesFromBase64("D")); + continue; + } + if (property.NameEquals("model"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + model = new CreateImageVariationRequestModel(property.Value.GetString()); + continue; + } + if (property.NameEquals("n"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + n = null; + continue; + } + n = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("response_format"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + responseFormat = new CreateImageVariationRequestResponseFormat(property.Value.GetString()); + continue; + } + if (property.NameEquals("size"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + size = new CreateImageVariationRequestSize(property.Value.GetString()); + continue; + } + if (property.NameEquals("user"u8)) + { + user = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateImageVariationRequest(image, OptionalProperty.ToNullable(model), OptionalProperty.ToNullable(n), OptionalProperty.ToNullable(responseFormat), OptionalProperty.ToNullable(size), user.Value, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateImageVariationRequest)} does not support '{options.Format}' format."); + } + } + + CreateImageVariationRequest IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateImageVariationRequest(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateImageVariationRequest)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateImageVariationRequest FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateImageVariationRequest(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateImageVariationRequest.cs b/.dotnet/src/Generated/Models/CreateImageVariationRequest.cs new file mode 100644 index 000000000..f1c52762f --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateImageVariationRequest.cs @@ -0,0 +1,121 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateImageVariationRequest. + public partial class CreateImageVariationRequest + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// The image to use as the basis for the variation(s). Must be a valid PNG file, less than 4MB, + /// and square. + /// + /// is null. + public CreateImageVariationRequest(BinaryData image) + { + ClientUtilities.AssertNotNull(image, nameof(image)); + + Image = image; + } + + /// Initializes a new instance of . + /// + /// The image to use as the basis for the variation(s). Must be a valid PNG file, less than 4MB, + /// and square. + /// + /// The model to use for image generation. Only `dall-e-2` is supported at this time. + /// The number of images to generate. Must be between 1 and 10. + /// The format in which the generated images are returned. Must be one of `url` or `b64_json`. + /// The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`. + /// + /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect + /// abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + /// + /// Keeps track of any properties unknown to the library. + internal CreateImageVariationRequest(BinaryData image, CreateImageVariationRequestModel? model, long? n, CreateImageVariationRequestResponseFormat? responseFormat, CreateImageVariationRequestSize? size, string user, IDictionary serializedAdditionalRawData) + { + Image = image; + Model = model; + N = n; + ResponseFormat = responseFormat; + Size = size; + User = user; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateImageVariationRequest() + { + } + + /// + /// The image to use as the basis for the variation(s). Must be a valid PNG file, less than 4MB, + /// and square. + /// + /// To assign a byte[] to this property use . + /// The byte[] will be serialized to a Base64 encoded string. + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromBytes(new byte[] { 1, 2, 3 }) + /// Creates a payload of "AQID". + /// + /// + /// + /// + public BinaryData Image { get; } + /// The model to use for image generation. Only `dall-e-2` is supported at this time. + public CreateImageVariationRequestModel? Model { get; set; } + /// The number of images to generate. Must be between 1 and 10. + public long? N { get; set; } + /// The format in which the generated images are returned. Must be one of `url` or `b64_json`. + public CreateImageVariationRequestResponseFormat? ResponseFormat { get; set; } + /// The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`. + public CreateImageVariationRequestSize? Size { get; set; } + /// + /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect + /// abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + /// + public string User { get; set; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateImageVariationRequestModel.cs b/.dotnet/src/Generated/Models/CreateImageVariationRequestModel.cs new file mode 100644 index 000000000..e1fb70037 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateImageVariationRequestModel.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for model in CreateImageVariationRequest. + public readonly partial struct CreateImageVariationRequestModel : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateImageVariationRequestModel(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string DallE2Value = "dall-e-2"; + + /// dall-e-2. + public static CreateImageVariationRequestModel DallE2 { get; } = new CreateImageVariationRequestModel(DallE2Value); + /// Determines if two values are the same. + public static bool operator ==(CreateImageVariationRequestModel left, CreateImageVariationRequestModel right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateImageVariationRequestModel left, CreateImageVariationRequestModel right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateImageVariationRequestModel(string value) => new CreateImageVariationRequestModel(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateImageVariationRequestModel other && Equals(other); + /// + public bool Equals(CreateImageVariationRequestModel other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateImageVariationRequestResponseFormat.cs b/.dotnet/src/Generated/Models/CreateImageVariationRequestResponseFormat.cs new file mode 100644 index 000000000..2c384bb1f --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateImageVariationRequestResponseFormat.cs @@ -0,0 +1,48 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for response_format in CreateImageVariationRequest. + public readonly partial struct CreateImageVariationRequestResponseFormat : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateImageVariationRequestResponseFormat(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string UrlValue = "url"; + private const string B64JsonValue = "b64_json"; + + /// url. + public static CreateImageVariationRequestResponseFormat Url { get; } = new CreateImageVariationRequestResponseFormat(UrlValue); + /// b64_json. + public static CreateImageVariationRequestResponseFormat B64Json { get; } = new CreateImageVariationRequestResponseFormat(B64JsonValue); + /// Determines if two values are the same. + public static bool operator ==(CreateImageVariationRequestResponseFormat left, CreateImageVariationRequestResponseFormat right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateImageVariationRequestResponseFormat left, CreateImageVariationRequestResponseFormat right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateImageVariationRequestResponseFormat(string value) => new CreateImageVariationRequestResponseFormat(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateImageVariationRequestResponseFormat other && Equals(other); + /// + public bool Equals(CreateImageVariationRequestResponseFormat other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateImageVariationRequestSize.cs b/.dotnet/src/Generated/Models/CreateImageVariationRequestSize.cs new file mode 100644 index 000000000..50f61d60c --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateImageVariationRequestSize.cs @@ -0,0 +1,51 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for size in CreateImageVariationRequest. + public readonly partial struct CreateImageVariationRequestSize : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateImageVariationRequestSize(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string _256x256Value = "256x256"; + private const string _512x512Value = "512x512"; + private const string _1024x1024Value = "1024x1024"; + + /// 256x256. + public static CreateImageVariationRequestSize _256x256 { get; } = new CreateImageVariationRequestSize(_256x256Value); + /// 512x512. + public static CreateImageVariationRequestSize _512x512 { get; } = new CreateImageVariationRequestSize(_512x512Value); + /// 1024x1024. + public static CreateImageVariationRequestSize _1024x1024 { get; } = new CreateImageVariationRequestSize(_1024x1024Value); + /// Determines if two values are the same. + public static bool operator ==(CreateImageVariationRequestSize left, CreateImageVariationRequestSize right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateImageVariationRequestSize left, CreateImageVariationRequestSize right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateImageVariationRequestSize(string value) => new CreateImageVariationRequestSize(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateImageVariationRequestSize other && Equals(other); + /// + public bool Equals(CreateImageVariationRequestSize other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateMessageRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateMessageRequest.Serialization.cs new file mode 100644 index 000000000..f8cdabd45 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateMessageRequest.Serialization.cs @@ -0,0 +1,198 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateMessageRequest : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateMessageRequest)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("role"u8); + writer.WriteStringValue(Role.ToString()); + writer.WritePropertyName("content"u8); + writer.WriteStringValue(Content); + if (OptionalProperty.IsCollectionDefined(FileIds)) + { + writer.WritePropertyName("file_ids"u8); + writer.WriteStartArray(); + foreach (var item in FileIds) + { + writer.WriteStringValue(item); + } + writer.WriteEndArray(); + } + if (OptionalProperty.IsCollectionDefined(Metadata)) + { + if (Metadata != null) + { + writer.WritePropertyName("metadata"u8); + writer.WriteStartObject(); + foreach (var item in Metadata) + { + writer.WritePropertyName(item.Key); + writer.WriteStringValue(item.Value); + } + writer.WriteEndObject(); + } + else + { + writer.WriteNull("metadata"); + } + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateMessageRequest IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateMessageRequest)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateMessageRequest(document.RootElement, options); + } + + internal static CreateMessageRequest DeserializeCreateMessageRequest(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + CreateMessageRequestRole role = default; + string content = default; + OptionalProperty> fileIds = default; + OptionalProperty> metadata = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("role"u8)) + { + role = new CreateMessageRequestRole(property.Value.GetString()); + continue; + } + if (property.NameEquals("content"u8)) + { + content = property.Value.GetString(); + continue; + } + if (property.NameEquals("file_ids"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(item.GetString()); + } + fileIds = array; + continue; + } + if (property.NameEquals("metadata"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + Dictionary dictionary = new Dictionary(); + foreach (var property0 in property.Value.EnumerateObject()) + { + dictionary.Add(property0.Name, property0.Value.GetString()); + } + metadata = dictionary; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateMessageRequest(role, content, OptionalProperty.ToList(fileIds), OptionalProperty.ToDictionary(metadata), serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateMessageRequest)} does not support '{options.Format}' format."); + } + } + + CreateMessageRequest IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateMessageRequest(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateMessageRequest)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateMessageRequest FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateMessageRequest(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateMessageRequest.cs b/.dotnet/src/Generated/Models/CreateMessageRequest.cs new file mode 100644 index 000000000..63200e048 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateMessageRequest.cs @@ -0,0 +1,104 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateMessageRequest. + public partial class CreateMessageRequest + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The content of the message. + /// is null. + public CreateMessageRequest(string content) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + Content = content; + FileIds = new OptionalList(); + Metadata = new OptionalDictionary(); + } + + /// Initializes a new instance of . + /// The role of the entity that is creating the message. Currently only `user` is supported. + /// The content of the message. + /// + /// A list of [File](/docs/api-reference/files) IDs that the message should use. There can be a + /// maximum of 10 files attached to a message. Useful for tools like `retrieval` and + /// `code_interpreter` that can access and use files. + /// + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// Keeps track of any properties unknown to the library. + internal CreateMessageRequest(CreateMessageRequestRole role, string content, IList fileIds, IDictionary metadata, IDictionary serializedAdditionalRawData) + { + Role = role; + Content = content; + FileIds = fileIds; + Metadata = metadata; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateMessageRequest() + { + } + + /// The role of the entity that is creating the message. Currently only `user` is supported. + public CreateMessageRequestRole Role { get; } = CreateMessageRequestRole.User; + + /// The content of the message. + public string Content { get; } + /// + /// A list of [File](/docs/api-reference/files) IDs that the message should use. There can be a + /// maximum of 10 files attached to a message. Useful for tools like `retrieval` and + /// `code_interpreter` that can access and use files. + /// + public IList FileIds { get; } + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + public IDictionary Metadata { get; set; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateMessageRequestRole.cs b/.dotnet/src/Generated/Models/CreateMessageRequestRole.cs new file mode 100644 index 000000000..2f7ae075a --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateMessageRequestRole.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The CreateMessageRequest_role. + public readonly partial struct CreateMessageRequestRole : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateMessageRequestRole(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string UserValue = "user"; + + /// user. + public static CreateMessageRequestRole User { get; } = new CreateMessageRequestRole(UserValue); + /// Determines if two values are the same. + public static bool operator ==(CreateMessageRequestRole left, CreateMessageRequestRole right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateMessageRequestRole left, CreateMessageRequestRole right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateMessageRequestRole(string value) => new CreateMessageRequestRole(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateMessageRequestRole other && Equals(other); + /// + public bool Equals(CreateMessageRequestRole other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateModerationRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateModerationRequest.Serialization.cs new file mode 100644 index 000000000..d7d7cac14 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateModerationRequest.Serialization.cs @@ -0,0 +1,154 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateModerationRequest : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateModerationRequest)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("input"u8); +#if NET6_0_OR_GREATER + writer.WriteRawValue(Input); +#else + using (JsonDocument document = JsonDocument.Parse(Input)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + if (OptionalProperty.IsDefined(Model)) + { + writer.WritePropertyName("model"u8); + writer.WriteStringValue(Model.Value.ToString()); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateModerationRequest IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateModerationRequest)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateModerationRequest(document.RootElement, options); + } + + internal static CreateModerationRequest DeserializeCreateModerationRequest(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + BinaryData input = default; + OptionalProperty model = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("input"u8)) + { + input = BinaryData.FromString(property.Value.GetRawText()); + continue; + } + if (property.NameEquals("model"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + model = new CreateModerationRequestModel(property.Value.GetString()); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateModerationRequest(input, OptionalProperty.ToNullable(model), serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateModerationRequest)} does not support '{options.Format}' format."); + } + } + + CreateModerationRequest IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateModerationRequest(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateModerationRequest)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateModerationRequest FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateModerationRequest(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateModerationRequest.cs b/.dotnet/src/Generated/Models/CreateModerationRequest.cs new file mode 100644 index 000000000..3192ceea7 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateModerationRequest.cs @@ -0,0 +1,129 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateModerationRequest. + public partial class CreateModerationRequest + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The input text to classify. + /// is null. + public CreateModerationRequest(BinaryData input) + { + ClientUtilities.AssertNotNull(input, nameof(input)); + + Input = input; + } + + /// Initializes a new instance of . + /// The input text to classify. + /// + /// Two content moderations models are available: `text-moderation-stable` and + /// `text-moderation-latest`. The default is `text-moderation-latest` which will be automatically + /// upgraded over time. This ensures you are always using our most accurate model. If you use + /// `text-moderation-stable`, we will provide advanced notice before updating the model. Accuracy + /// of `text-moderation-stable` may be slightly lower than for `text-moderation-latest`. + /// + /// Keeps track of any properties unknown to the library. + internal CreateModerationRequest(BinaryData input, CreateModerationRequestModel? model, IDictionary serializedAdditionalRawData) + { + Input = input; + Model = model; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateModerationRequest() + { + } + + /// + /// The input text to classify + /// + /// To assign an object to this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// + /// Supported types: + /// + /// + /// + /// + /// + /// where T is of type + /// + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + public BinaryData Input { get; } + /// + /// Two content moderations models are available: `text-moderation-stable` and + /// `text-moderation-latest`. The default is `text-moderation-latest` which will be automatically + /// upgraded over time. This ensures you are always using our most accurate model. If you use + /// `text-moderation-stable`, we will provide advanced notice before updating the model. Accuracy + /// of `text-moderation-stable` may be slightly lower than for `text-moderation-latest`. + /// + public CreateModerationRequestModel? Model { get; set; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateModerationRequestModel.cs b/.dotnet/src/Generated/Models/CreateModerationRequestModel.cs new file mode 100644 index 000000000..fcc067e02 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateModerationRequestModel.cs @@ -0,0 +1,48 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for model in CreateModerationRequest. + public readonly partial struct CreateModerationRequestModel : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateModerationRequestModel(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string TextModerationLatestValue = "text-moderation-latest"; + private const string TextModerationStableValue = "text-moderation-stable"; + + /// text-moderation-latest. + public static CreateModerationRequestModel TextModerationLatest { get; } = new CreateModerationRequestModel(TextModerationLatestValue); + /// text-moderation-stable. + public static CreateModerationRequestModel TextModerationStable { get; } = new CreateModerationRequestModel(TextModerationStableValue); + /// Determines if two values are the same. + public static bool operator ==(CreateModerationRequestModel left, CreateModerationRequestModel right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateModerationRequestModel left, CreateModerationRequestModel right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateModerationRequestModel(string value) => new CreateModerationRequestModel(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateModerationRequestModel other && Equals(other); + /// + public bool Equals(CreateModerationRequestModel other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateModerationResponse.Serialization.cs b/.dotnet/src/Generated/Models/CreateModerationResponse.Serialization.cs new file mode 100644 index 000000000..95902ce14 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateModerationResponse.Serialization.cs @@ -0,0 +1,158 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateModerationResponse : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateModerationResponse)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("id"u8); + writer.WriteStringValue(Id); + writer.WritePropertyName("model"u8); + writer.WriteStringValue(Model); + writer.WritePropertyName("results"u8); + writer.WriteStartArray(); + foreach (var item in Results) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateModerationResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateModerationResponse)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateModerationResponse(document.RootElement, options); + } + + internal static CreateModerationResponse DeserializeCreateModerationResponse(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string id = default; + string model = default; + IReadOnlyList results = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetString(); + continue; + } + if (property.NameEquals("model"u8)) + { + model = property.Value.GetString(); + continue; + } + if (property.NameEquals("results"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(CreateModerationResponseResult.DeserializeCreateModerationResponseResult(item)); + } + results = array; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateModerationResponse(id, model, results, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateModerationResponse)} does not support '{options.Format}' format."); + } + } + + CreateModerationResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateModerationResponse(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateModerationResponse)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateModerationResponse FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateModerationResponse(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateModerationResponse.cs b/.dotnet/src/Generated/Models/CreateModerationResponse.cs new file mode 100644 index 000000000..7fe06f011 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateModerationResponse.cs @@ -0,0 +1,88 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// Represents policy compliance report by OpenAI's content moderation model against a given input. + public partial class CreateModerationResponse + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The unique identifier for the moderation request. + /// The model used to generate the moderation results. + /// A list of moderation objects. + /// , or is null. + internal CreateModerationResponse(string id, string model, IEnumerable results) + { + ClientUtilities.AssertNotNull(id, nameof(id)); + ClientUtilities.AssertNotNull(model, nameof(model)); + ClientUtilities.AssertNotNull(results, nameof(results)); + + Id = id; + Model = model; + Results = results.ToList(); + } + + /// Initializes a new instance of . + /// The unique identifier for the moderation request. + /// The model used to generate the moderation results. + /// A list of moderation objects. + /// Keeps track of any properties unknown to the library. + internal CreateModerationResponse(string id, string model, IReadOnlyList results, IDictionary serializedAdditionalRawData) + { + Id = id; + Model = model; + Results = results; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateModerationResponse() + { + } + + /// The unique identifier for the moderation request. + public string Id { get; } + /// The model used to generate the moderation results. + public string Model { get; } + /// A list of moderation objects. + public IReadOnlyList Results { get; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateModerationResponseResult.Serialization.cs b/.dotnet/src/Generated/Models/CreateModerationResponseResult.Serialization.cs new file mode 100644 index 000000000..6c56b94e2 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateModerationResponseResult.Serialization.cs @@ -0,0 +1,148 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateModerationResponseResult : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateModerationResponseResult)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("flagged"u8); + writer.WriteBooleanValue(Flagged); + writer.WritePropertyName("categories"u8); + writer.WriteObjectValue(Categories); + writer.WritePropertyName("category_scores"u8); + writer.WriteObjectValue(CategoryScores); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateModerationResponseResult IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateModerationResponseResult)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateModerationResponseResult(document.RootElement, options); + } + + internal static CreateModerationResponseResult DeserializeCreateModerationResponseResult(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + bool flagged = default; + CreateModerationResponseResultCategories categories = default; + CreateModerationResponseResultCategoryScores categoryScores = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("flagged"u8)) + { + flagged = property.Value.GetBoolean(); + continue; + } + if (property.NameEquals("categories"u8)) + { + categories = CreateModerationResponseResultCategories.DeserializeCreateModerationResponseResultCategories(property.Value); + continue; + } + if (property.NameEquals("category_scores"u8)) + { + categoryScores = CreateModerationResponseResultCategoryScores.DeserializeCreateModerationResponseResultCategoryScores(property.Value); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateModerationResponseResult(flagged, categories, categoryScores, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateModerationResponseResult)} does not support '{options.Format}' format."); + } + } + + CreateModerationResponseResult IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateModerationResponseResult(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateModerationResponseResult)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateModerationResponseResult FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateModerationResponseResult(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateModerationResponseResult.cs b/.dotnet/src/Generated/Models/CreateModerationResponseResult.cs new file mode 100644 index 000000000..3842b8365 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateModerationResponseResult.cs @@ -0,0 +1,86 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateModerationResponseResult. + public partial class CreateModerationResponseResult + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// Whether the content violates [OpenAI's usage policies](/policies/usage-policies). + /// A list of the categories, and whether they are flagged or not. + /// A list of the categories along with their scores as predicted by model. + /// or is null. + internal CreateModerationResponseResult(bool flagged, CreateModerationResponseResultCategories categories, CreateModerationResponseResultCategoryScores categoryScores) + { + ClientUtilities.AssertNotNull(categories, nameof(categories)); + ClientUtilities.AssertNotNull(categoryScores, nameof(categoryScores)); + + Flagged = flagged; + Categories = categories; + CategoryScores = categoryScores; + } + + /// Initializes a new instance of . + /// Whether the content violates [OpenAI's usage policies](/policies/usage-policies). + /// A list of the categories, and whether they are flagged or not. + /// A list of the categories along with their scores as predicted by model. + /// Keeps track of any properties unknown to the library. + internal CreateModerationResponseResult(bool flagged, CreateModerationResponseResultCategories categories, CreateModerationResponseResultCategoryScores categoryScores, IDictionary serializedAdditionalRawData) + { + Flagged = flagged; + Categories = categories; + CategoryScores = categoryScores; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateModerationResponseResult() + { + } + + /// Whether the content violates [OpenAI's usage policies](/policies/usage-policies). + public bool Flagged { get; } + /// A list of the categories, and whether they are flagged or not. + public CreateModerationResponseResultCategories Categories { get; } + /// A list of the categories along with their scores as predicted by model. + public CreateModerationResponseResultCategoryScores CategoryScores { get; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateModerationResponseResultCategories.Serialization.cs b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategories.Serialization.cs new file mode 100644 index 000000000..53595dc4a --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategories.Serialization.cs @@ -0,0 +1,212 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateModerationResponseResultCategories : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateModerationResponseResultCategories)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("hate"u8); + writer.WriteBooleanValue(Hate); + writer.WritePropertyName("hate/threatening"u8); + writer.WriteBooleanValue(HateThreatening); + writer.WritePropertyName("harassment"u8); + writer.WriteBooleanValue(Harassment); + writer.WritePropertyName("harassment/threatening"u8); + writer.WriteBooleanValue(HarassmentThreatening); + writer.WritePropertyName("self-harm"u8); + writer.WriteBooleanValue(SelfHarm); + writer.WritePropertyName("self-harm/intent"u8); + writer.WriteBooleanValue(SelfHarmIntent); + writer.WritePropertyName("self-harm/instructions"u8); + writer.WriteBooleanValue(SelfHarmInstructions); + writer.WritePropertyName("sexual"u8); + writer.WriteBooleanValue(Sexual); + writer.WritePropertyName("sexual/minors"u8); + writer.WriteBooleanValue(SexualMinors); + writer.WritePropertyName("violence"u8); + writer.WriteBooleanValue(Violence); + writer.WritePropertyName("violence/graphic"u8); + writer.WriteBooleanValue(ViolenceGraphic); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateModerationResponseResultCategories IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateModerationResponseResultCategories)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateModerationResponseResultCategories(document.RootElement, options); + } + + internal static CreateModerationResponseResultCategories DeserializeCreateModerationResponseResultCategories(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + bool hate = default; + bool hateThreatening = default; + bool harassment = default; + bool harassmentThreatening = default; + bool selfHarm = default; + bool selfHarmIntent = default; + bool selfHarmInstructions = default; + bool sexual = default; + bool sexualMinors = default; + bool violence = default; + bool violenceGraphic = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("hate"u8)) + { + hate = property.Value.GetBoolean(); + continue; + } + if (property.NameEquals("hate/threatening"u8)) + { + hateThreatening = property.Value.GetBoolean(); + continue; + } + if (property.NameEquals("harassment"u8)) + { + harassment = property.Value.GetBoolean(); + continue; + } + if (property.NameEquals("harassment/threatening"u8)) + { + harassmentThreatening = property.Value.GetBoolean(); + continue; + } + if (property.NameEquals("self-harm"u8)) + { + selfHarm = property.Value.GetBoolean(); + continue; + } + if (property.NameEquals("self-harm/intent"u8)) + { + selfHarmIntent = property.Value.GetBoolean(); + continue; + } + if (property.NameEquals("self-harm/instructions"u8)) + { + selfHarmInstructions = property.Value.GetBoolean(); + continue; + } + if (property.NameEquals("sexual"u8)) + { + sexual = property.Value.GetBoolean(); + continue; + } + if (property.NameEquals("sexual/minors"u8)) + { + sexualMinors = property.Value.GetBoolean(); + continue; + } + if (property.NameEquals("violence"u8)) + { + violence = property.Value.GetBoolean(); + continue; + } + if (property.NameEquals("violence/graphic"u8)) + { + violenceGraphic = property.Value.GetBoolean(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateModerationResponseResultCategories(hate, hateThreatening, harassment, harassmentThreatening, selfHarm, selfHarmIntent, selfHarmInstructions, sexual, sexualMinors, violence, violenceGraphic, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateModerationResponseResultCategories)} does not support '{options.Format}' format."); + } + } + + CreateModerationResponseResultCategories IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateModerationResponseResultCategories(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateModerationResponseResultCategories)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateModerationResponseResultCategories FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateModerationResponseResultCategories(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateModerationResponseResultCategories.cs b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategories.cs new file mode 100644 index 000000000..fdb93fb6c --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategories.cs @@ -0,0 +1,189 @@ +// + +#nullable disable + +using System; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateModerationResponseResultCategories. + public partial class CreateModerationResponseResultCategories + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// Content that expresses, incites, or promotes hate based on race, gender, ethnicity, + /// religion, nationality, sexual orientation, disability status, or caste. Hateful content + /// aimed at non-protected groups (e.g., chess players) is harrassment. + /// + /// + /// Hateful content that also includes violence or serious harm towards the targeted group + /// based on race, gender, ethnicity, religion, nationality, sexual orientation, disability + /// status, or caste. + /// + /// Content that expresses, incites, or promotes harassing language towards any target. + /// Harassment content that also includes violence or serious harm towards any target. + /// + /// Content that promotes, encourages, or depicts acts of self-harm, such as suicide, cutting, + /// and eating disorders. + /// + /// + /// Content where the speaker expresses that they are engaging or intend to engage in acts of + /// self-harm, such as suicide, cutting, and eating disorders. + /// + /// + /// Content that encourages performing acts of self-harm, such as suicide, cutting, and eating + /// disorders, or that gives instructions or advice on how to commit such acts. + /// + /// + /// Content meant to arouse sexual excitement, such as the description of sexual activity, or + /// that promotes sexual services (excluding sex education and wellness). + /// + /// Sexual content that includes an individual who is under 18 years old. + /// Content that depicts death, violence, or physical injury. + /// Content that depicts death, violence, or physical injury in graphic detail. + internal CreateModerationResponseResultCategories(bool hate, bool hateThreatening, bool harassment, bool harassmentThreatening, bool selfHarm, bool selfHarmIntent, bool selfHarmInstructions, bool sexual, bool sexualMinors, bool violence, bool violenceGraphic) + { + Hate = hate; + HateThreatening = hateThreatening; + Harassment = harassment; + HarassmentThreatening = harassmentThreatening; + SelfHarm = selfHarm; + SelfHarmIntent = selfHarmIntent; + SelfHarmInstructions = selfHarmInstructions; + Sexual = sexual; + SexualMinors = sexualMinors; + Violence = violence; + ViolenceGraphic = violenceGraphic; + } + + /// Initializes a new instance of . + /// + /// Content that expresses, incites, or promotes hate based on race, gender, ethnicity, + /// religion, nationality, sexual orientation, disability status, or caste. Hateful content + /// aimed at non-protected groups (e.g., chess players) is harrassment. + /// + /// + /// Hateful content that also includes violence or serious harm towards the targeted group + /// based on race, gender, ethnicity, religion, nationality, sexual orientation, disability + /// status, or caste. + /// + /// Content that expresses, incites, or promotes harassing language towards any target. + /// Harassment content that also includes violence or serious harm towards any target. + /// + /// Content that promotes, encourages, or depicts acts of self-harm, such as suicide, cutting, + /// and eating disorders. + /// + /// + /// Content where the speaker expresses that they are engaging or intend to engage in acts of + /// self-harm, such as suicide, cutting, and eating disorders. + /// + /// + /// Content that encourages performing acts of self-harm, such as suicide, cutting, and eating + /// disorders, or that gives instructions or advice on how to commit such acts. + /// + /// + /// Content meant to arouse sexual excitement, such as the description of sexual activity, or + /// that promotes sexual services (excluding sex education and wellness). + /// + /// Sexual content that includes an individual who is under 18 years old. + /// Content that depicts death, violence, or physical injury. + /// Content that depicts death, violence, or physical injury in graphic detail. + /// Keeps track of any properties unknown to the library. + internal CreateModerationResponseResultCategories(bool hate, bool hateThreatening, bool harassment, bool harassmentThreatening, bool selfHarm, bool selfHarmIntent, bool selfHarmInstructions, bool sexual, bool sexualMinors, bool violence, bool violenceGraphic, IDictionary serializedAdditionalRawData) + { + Hate = hate; + HateThreatening = hateThreatening; + Harassment = harassment; + HarassmentThreatening = harassmentThreatening; + SelfHarm = selfHarm; + SelfHarmIntent = selfHarmIntent; + SelfHarmInstructions = selfHarmInstructions; + Sexual = sexual; + SexualMinors = sexualMinors; + Violence = violence; + ViolenceGraphic = violenceGraphic; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateModerationResponseResultCategories() + { + } + + /// + /// Content that expresses, incites, or promotes hate based on race, gender, ethnicity, + /// religion, nationality, sexual orientation, disability status, or caste. Hateful content + /// aimed at non-protected groups (e.g., chess players) is harrassment. + /// + public bool Hate { get; } + /// + /// Hateful content that also includes violence or serious harm towards the targeted group + /// based on race, gender, ethnicity, religion, nationality, sexual orientation, disability + /// status, or caste. + /// + public bool HateThreatening { get; } + /// Content that expresses, incites, or promotes harassing language towards any target. + public bool Harassment { get; } + /// Harassment content that also includes violence or serious harm towards any target. + public bool HarassmentThreatening { get; } + /// + /// Content that promotes, encourages, or depicts acts of self-harm, such as suicide, cutting, + /// and eating disorders. + /// + public bool SelfHarm { get; } + /// + /// Content where the speaker expresses that they are engaging or intend to engage in acts of + /// self-harm, such as suicide, cutting, and eating disorders. + /// + public bool SelfHarmIntent { get; } + /// + /// Content that encourages performing acts of self-harm, such as suicide, cutting, and eating + /// disorders, or that gives instructions or advice on how to commit such acts. + /// + public bool SelfHarmInstructions { get; } + /// + /// Content meant to arouse sexual excitement, such as the description of sexual activity, or + /// that promotes sexual services (excluding sex education and wellness). + /// + public bool Sexual { get; } + /// Sexual content that includes an individual who is under 18 years old. + public bool SexualMinors { get; } + /// Content that depicts death, violence, or physical injury. + public bool Violence { get; } + /// Content that depicts death, violence, or physical injury in graphic detail. + public bool ViolenceGraphic { get; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.Serialization.cs b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.Serialization.cs new file mode 100644 index 000000000..2c169bdec --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.Serialization.cs @@ -0,0 +1,212 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateModerationResponseResultCategoryScores : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateModerationResponseResultCategoryScores)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("hate"u8); + writer.WriteNumberValue(Hate); + writer.WritePropertyName("hate/threatening"u8); + writer.WriteNumberValue(HateThreatening); + writer.WritePropertyName("harassment"u8); + writer.WriteNumberValue(Harassment); + writer.WritePropertyName("harassment/threatening"u8); + writer.WriteNumberValue(HarassmentThreatening); + writer.WritePropertyName("self-harm"u8); + writer.WriteNumberValue(SelfHarm); + writer.WritePropertyName("self-harm/intent"u8); + writer.WriteNumberValue(SelfHarmIntent); + writer.WritePropertyName("self-harm/instructions"u8); + writer.WriteNumberValue(SelfHarmInstructions); + writer.WritePropertyName("sexual"u8); + writer.WriteNumberValue(Sexual); + writer.WritePropertyName("sexual/minors"u8); + writer.WriteNumberValue(SexualMinors); + writer.WritePropertyName("violence"u8); + writer.WriteNumberValue(Violence); + writer.WritePropertyName("violence/graphic"u8); + writer.WriteNumberValue(ViolenceGraphic); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateModerationResponseResultCategoryScores IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateModerationResponseResultCategoryScores)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateModerationResponseResultCategoryScores(document.RootElement, options); + } + + internal static CreateModerationResponseResultCategoryScores DeserializeCreateModerationResponseResultCategoryScores(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + double hate = default; + double hateThreatening = default; + double harassment = default; + double harassmentThreatening = default; + double selfHarm = default; + double selfHarmIntent = default; + double selfHarmInstructions = default; + double sexual = default; + double sexualMinors = default; + double violence = default; + double violenceGraphic = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("hate"u8)) + { + hate = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("hate/threatening"u8)) + { + hateThreatening = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("harassment"u8)) + { + harassment = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("harassment/threatening"u8)) + { + harassmentThreatening = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("self-harm"u8)) + { + selfHarm = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("self-harm/intent"u8)) + { + selfHarmIntent = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("self-harm/instructions"u8)) + { + selfHarmInstructions = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("sexual"u8)) + { + sexual = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("sexual/minors"u8)) + { + sexualMinors = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("violence"u8)) + { + violence = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("violence/graphic"u8)) + { + violenceGraphic = property.Value.GetDouble(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateModerationResponseResultCategoryScores(hate, hateThreatening, harassment, harassmentThreatening, selfHarm, selfHarmIntent, selfHarmInstructions, sexual, sexualMinors, violence, violenceGraphic, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateModerationResponseResultCategoryScores)} does not support '{options.Format}' format."); + } + } + + CreateModerationResponseResultCategoryScores IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateModerationResponseResultCategoryScores(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateModerationResponseResultCategoryScores)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateModerationResponseResultCategoryScores FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateModerationResponseResultCategoryScores(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.cs b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.cs new file mode 100644 index 000000000..2e5247ddb --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.cs @@ -0,0 +1,129 @@ +// + +#nullable disable + +using System; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateModerationResponseResultCategoryScores. + public partial class CreateModerationResponseResultCategoryScores + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The score for the category 'hate'. + /// The score for the category 'hate/threatening'. + /// The score for the category 'harassment'. + /// The score for the category 'harassment/threatening'. + /// The score for the category 'self-harm'. + /// The score for the category 'self-harm/intent'. + /// The score for the category 'self-harm/instructive'. + /// The score for the category 'sexual'. + /// The score for the category 'sexual/minors'. + /// The score for the category 'violence'. + /// The score for the category 'violence/graphic'. + internal CreateModerationResponseResultCategoryScores(double hate, double hateThreatening, double harassment, double harassmentThreatening, double selfHarm, double selfHarmIntent, double selfHarmInstructions, double sexual, double sexualMinors, double violence, double violenceGraphic) + { + Hate = hate; + HateThreatening = hateThreatening; + Harassment = harassment; + HarassmentThreatening = harassmentThreatening; + SelfHarm = selfHarm; + SelfHarmIntent = selfHarmIntent; + SelfHarmInstructions = selfHarmInstructions; + Sexual = sexual; + SexualMinors = sexualMinors; + Violence = violence; + ViolenceGraphic = violenceGraphic; + } + + /// Initializes a new instance of . + /// The score for the category 'hate'. + /// The score for the category 'hate/threatening'. + /// The score for the category 'harassment'. + /// The score for the category 'harassment/threatening'. + /// The score for the category 'self-harm'. + /// The score for the category 'self-harm/intent'. + /// The score for the category 'self-harm/instructive'. + /// The score for the category 'sexual'. + /// The score for the category 'sexual/minors'. + /// The score for the category 'violence'. + /// The score for the category 'violence/graphic'. + /// Keeps track of any properties unknown to the library. + internal CreateModerationResponseResultCategoryScores(double hate, double hateThreatening, double harassment, double harassmentThreatening, double selfHarm, double selfHarmIntent, double selfHarmInstructions, double sexual, double sexualMinors, double violence, double violenceGraphic, IDictionary serializedAdditionalRawData) + { + Hate = hate; + HateThreatening = hateThreatening; + Harassment = harassment; + HarassmentThreatening = harassmentThreatening; + SelfHarm = selfHarm; + SelfHarmIntent = selfHarmIntent; + SelfHarmInstructions = selfHarmInstructions; + Sexual = sexual; + SexualMinors = sexualMinors; + Violence = violence; + ViolenceGraphic = violenceGraphic; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateModerationResponseResultCategoryScores() + { + } + + /// The score for the category 'hate'. + public double Hate { get; } + /// The score for the category 'hate/threatening'. + public double HateThreatening { get; } + /// The score for the category 'harassment'. + public double Harassment { get; } + /// The score for the category 'harassment/threatening'. + public double HarassmentThreatening { get; } + /// The score for the category 'self-harm'. + public double SelfHarm { get; } + /// The score for the category 'self-harm/intent'. + public double SelfHarmIntent { get; } + /// The score for the category 'self-harm/instructive'. + public double SelfHarmInstructions { get; } + /// The score for the category 'sexual'. + public double Sexual { get; } + /// The score for the category 'sexual/minors'. + public double SexualMinors { get; } + /// The score for the category 'violence'. + public double Violence { get; } + /// The score for the category 'violence/graphic'. + public double ViolenceGraphic { get; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateRunRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateRunRequest.Serialization.cs new file mode 100644 index 000000000..33e243bc6 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateRunRequest.Serialization.cs @@ -0,0 +1,285 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateRunRequest : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateRunRequest)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("assistant_id"u8); + writer.WriteStringValue(AssistantId); + if (OptionalProperty.IsDefined(Model)) + { + if (Model != null) + { + writer.WritePropertyName("model"u8); + writer.WriteStringValue(Model); + } + else + { + writer.WriteNull("model"); + } + } + if (OptionalProperty.IsDefined(Instructions)) + { + if (Instructions != null) + { + writer.WritePropertyName("instructions"u8); + writer.WriteStringValue(Instructions); + } + else + { + writer.WriteNull("instructions"); + } + } + if (OptionalProperty.IsDefined(AdditionalInstructions)) + { + if (AdditionalInstructions != null) + { + writer.WritePropertyName("additional_instructions"u8); + writer.WriteStringValue(AdditionalInstructions); + } + else + { + writer.WriteNull("additional_instructions"); + } + } + if (OptionalProperty.IsCollectionDefined(Tools)) + { + if (Tools != null) + { + writer.WritePropertyName("tools"u8); + writer.WriteStartArray(); + foreach (var item in Tools) + { + if (item == null) + { + writer.WriteNullValue(); + continue; + } +#if NET6_0_OR_GREATER + writer.WriteRawValue(item); +#else + using (JsonDocument document = JsonDocument.Parse(item)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + writer.WriteEndArray(); + } + else + { + writer.WriteNull("tools"); + } + } + if (OptionalProperty.IsCollectionDefined(Metadata)) + { + if (Metadata != null) + { + writer.WritePropertyName("metadata"u8); + writer.WriteStartObject(); + foreach (var item in Metadata) + { + writer.WritePropertyName(item.Key); + writer.WriteStringValue(item.Value); + } + writer.WriteEndObject(); + } + else + { + writer.WriteNull("metadata"); + } + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateRunRequest IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateRunRequest)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateRunRequest(document.RootElement, options); + } + + internal static CreateRunRequest DeserializeCreateRunRequest(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string assistantId = default; + OptionalProperty model = default; + OptionalProperty instructions = default; + OptionalProperty additionalInstructions = default; + OptionalProperty> tools = default; + OptionalProperty> metadata = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("assistant_id"u8)) + { + assistantId = property.Value.GetString(); + continue; + } + if (property.NameEquals("model"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + model = null; + continue; + } + model = property.Value.GetString(); + continue; + } + if (property.NameEquals("instructions"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + instructions = null; + continue; + } + instructions = property.Value.GetString(); + continue; + } + if (property.NameEquals("additional_instructions"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + additionalInstructions = null; + continue; + } + additionalInstructions = property.Value.GetString(); + continue; + } + if (property.NameEquals("tools"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + if (item.ValueKind == JsonValueKind.Null) + { + array.Add(null); + } + else + { + array.Add(BinaryData.FromString(item.GetRawText())); + } + } + tools = array; + continue; + } + if (property.NameEquals("metadata"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + Dictionary dictionary = new Dictionary(); + foreach (var property0 in property.Value.EnumerateObject()) + { + dictionary.Add(property0.Name, property0.Value.GetString()); + } + metadata = dictionary; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateRunRequest(assistantId, model.Value, instructions.Value, additionalInstructions.Value, OptionalProperty.ToList(tools), OptionalProperty.ToDictionary(metadata), serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateRunRequest)} does not support '{options.Format}' format."); + } + } + + CreateRunRequest IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateRunRequest(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateRunRequest)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateRunRequest FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateRunRequest(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateRunRequest.cs b/.dotnet/src/Generated/Models/CreateRunRequest.cs new file mode 100644 index 000000000..25e22310d --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateRunRequest.cs @@ -0,0 +1,156 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateRunRequest. + public partial class CreateRunRequest + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The ID of the [assistant](/docs/api-reference/assistants) to use to execute this run. + /// is null. + public CreateRunRequest(string assistantId) + { + ClientUtilities.AssertNotNull(assistantId, nameof(assistantId)); + + AssistantId = assistantId; + Tools = new OptionalList(); + Metadata = new OptionalDictionary(); + } + + /// Initializes a new instance of . + /// The ID of the [assistant](/docs/api-reference/assistants) to use to execute this run. + /// + /// The ID of the [Model](/docs/api-reference/models) to be used to execute this run. If a value + /// is provided here, it will override the model associated with the assistant. If not, the model + /// associated with the assistant will be used. + /// + /// + /// Overrides the [instructions](/docs/api-reference/assistants/createAssistant) of the assistant. + /// This is useful for modifying the behavior on a per-run basis. + /// + /// + /// Appends additional instructions at the end of the instructions for the run. This is useful for + /// modifying the behavior on a per-run basis without overriding other instructions. + /// + /// + /// Override the tools the assistant can use for this run. This is useful for modifying the + /// behavior on a per-run basis. + /// + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// Keeps track of any properties unknown to the library. + internal CreateRunRequest(string assistantId, string model, string instructions, string additionalInstructions, IList tools, IDictionary metadata, IDictionary serializedAdditionalRawData) + { + AssistantId = assistantId; + Model = model; + Instructions = instructions; + AdditionalInstructions = additionalInstructions; + Tools = tools; + Metadata = metadata; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateRunRequest() + { + } + + /// The ID of the [assistant](/docs/api-reference/assistants) to use to execute this run. + public string AssistantId { get; } + /// + /// The ID of the [Model](/docs/api-reference/models) to be used to execute this run. If a value + /// is provided here, it will override the model associated with the assistant. If not, the model + /// associated with the assistant will be used. + /// + public string Model { get; set; } + /// + /// Overrides the [instructions](/docs/api-reference/assistants/createAssistant) of the assistant. + /// This is useful for modifying the behavior on a per-run basis. + /// + public string Instructions { get; set; } + /// + /// Appends additional instructions at the end of the instructions for the run. This is useful for + /// modifying the behavior on a per-run basis without overriding other instructions. + /// + public string AdditionalInstructions { get; set; } + /// + /// Override the tools the assistant can use for this run. This is useful for modifying the + /// behavior on a per-run basis. + /// + /// To assign an object to the element of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + public IList Tools { get; set; } + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + public IDictionary Metadata { get; set; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateSpeechRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateSpeechRequest.Serialization.cs new file mode 100644 index 000000000..299ac0668 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateSpeechRequest.Serialization.cs @@ -0,0 +1,178 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateSpeechRequest : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateSpeechRequest)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("model"u8); + writer.WriteStringValue(Model.ToString()); + writer.WritePropertyName("input"u8); + writer.WriteStringValue(Input); + writer.WritePropertyName("voice"u8); + writer.WriteStringValue(Voice.ToString()); + if (OptionalProperty.IsDefined(ResponseFormat)) + { + writer.WritePropertyName("response_format"u8); + writer.WriteStringValue(ResponseFormat.Value.ToString()); + } + if (OptionalProperty.IsDefined(Speed)) + { + writer.WritePropertyName("speed"u8); + writer.WriteNumberValue(Speed.Value); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateSpeechRequest IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateSpeechRequest)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateSpeechRequest(document.RootElement, options); + } + + internal static CreateSpeechRequest DeserializeCreateSpeechRequest(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + CreateSpeechRequestModel model = default; + string input = default; + CreateSpeechRequestVoice voice = default; + OptionalProperty responseFormat = default; + OptionalProperty speed = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("model"u8)) + { + model = new CreateSpeechRequestModel(property.Value.GetString()); + continue; + } + if (property.NameEquals("input"u8)) + { + input = property.Value.GetString(); + continue; + } + if (property.NameEquals("voice"u8)) + { + voice = new CreateSpeechRequestVoice(property.Value.GetString()); + continue; + } + if (property.NameEquals("response_format"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + responseFormat = new CreateSpeechRequestResponseFormat(property.Value.GetString()); + continue; + } + if (property.NameEquals("speed"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + speed = property.Value.GetDouble(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateSpeechRequest(model, input, voice, OptionalProperty.ToNullable(responseFormat), OptionalProperty.ToNullable(speed), serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateSpeechRequest)} does not support '{options.Format}' format."); + } + } + + CreateSpeechRequest IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateSpeechRequest(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateSpeechRequest)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateSpeechRequest FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateSpeechRequest(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateSpeechRequest.cs b/.dotnet/src/Generated/Models/CreateSpeechRequest.cs new file mode 100644 index 000000000..ac765143c --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateSpeechRequest.cs @@ -0,0 +1,105 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateSpeechRequest. + public partial class CreateSpeechRequest + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// One of the available [TTS models](/docs/models/tts): `tts-1` or `tts-1-hd`. + /// The text to generate audio for. The maximum length is 4096 characters. + /// + /// The voice to use when generating the audio. Supported voices are `alloy`, `echo`, `fable`, + /// `onyx`, `nova`, and `shimmer`. Previews of the voices are available in the + /// [Text to speech guide](/docs/guides/text-to-speech/voice-options). + /// + /// is null. + public CreateSpeechRequest(CreateSpeechRequestModel model, string input, CreateSpeechRequestVoice voice) + { + ClientUtilities.AssertNotNull(input, nameof(input)); + + Model = model; + Input = input; + Voice = voice; + } + + /// Initializes a new instance of . + /// One of the available [TTS models](/docs/models/tts): `tts-1` or `tts-1-hd`. + /// The text to generate audio for. The maximum length is 4096 characters. + /// + /// The voice to use when generating the audio. Supported voices are `alloy`, `echo`, `fable`, + /// `onyx`, `nova`, and `shimmer`. Previews of the voices are available in the + /// [Text to speech guide](/docs/guides/text-to-speech/voice-options). + /// + /// The format to audio in. Supported formats are `mp3`, `opus`, `aac`, and `flac`. + /// The speed of the generated audio. Select a value from `0.25` to `4.0`. `1.0` is the default. + /// Keeps track of any properties unknown to the library. + internal CreateSpeechRequest(CreateSpeechRequestModel model, string input, CreateSpeechRequestVoice voice, CreateSpeechRequestResponseFormat? responseFormat, double? speed, IDictionary serializedAdditionalRawData) + { + Model = model; + Input = input; + Voice = voice; + ResponseFormat = responseFormat; + Speed = speed; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateSpeechRequest() + { + } + + /// One of the available [TTS models](/docs/models/tts): `tts-1` or `tts-1-hd`. + public CreateSpeechRequestModel Model { get; } + /// The text to generate audio for. The maximum length is 4096 characters. + public string Input { get; } + /// + /// The voice to use when generating the audio. Supported voices are `alloy`, `echo`, `fable`, + /// `onyx`, `nova`, and `shimmer`. Previews of the voices are available in the + /// [Text to speech guide](/docs/guides/text-to-speech/voice-options). + /// + public CreateSpeechRequestVoice Voice { get; } + /// The format to audio in. Supported formats are `mp3`, `opus`, `aac`, and `flac`. + public CreateSpeechRequestResponseFormat? ResponseFormat { get; set; } + /// The speed of the generated audio. Select a value from `0.25` to `4.0`. `1.0` is the default. + public double? Speed { get; set; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateSpeechRequestModel.cs b/.dotnet/src/Generated/Models/CreateSpeechRequestModel.cs new file mode 100644 index 000000000..0db564d08 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateSpeechRequestModel.cs @@ -0,0 +1,48 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for model in CreateSpeechRequest. + public readonly partial struct CreateSpeechRequestModel : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateSpeechRequestModel(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string Tts1Value = "tts-1"; + private const string Tts1HdValue = "tts-1-hd"; + + /// tts-1. + public static CreateSpeechRequestModel Tts1 { get; } = new CreateSpeechRequestModel(Tts1Value); + /// tts-1-hd. + public static CreateSpeechRequestModel Tts1Hd { get; } = new CreateSpeechRequestModel(Tts1HdValue); + /// Determines if two values are the same. + public static bool operator ==(CreateSpeechRequestModel left, CreateSpeechRequestModel right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateSpeechRequestModel left, CreateSpeechRequestModel right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateSpeechRequestModel(string value) => new CreateSpeechRequestModel(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateSpeechRequestModel other && Equals(other); + /// + public bool Equals(CreateSpeechRequestModel other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateSpeechRequestResponseFormat.cs b/.dotnet/src/Generated/Models/CreateSpeechRequestResponseFormat.cs new file mode 100644 index 000000000..ca5b8462f --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateSpeechRequestResponseFormat.cs @@ -0,0 +1,54 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for response_format in CreateSpeechRequest. + public readonly partial struct CreateSpeechRequestResponseFormat : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateSpeechRequestResponseFormat(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string Mp3Value = "mp3"; + private const string OpusValue = "opus"; + private const string AacValue = "aac"; + private const string FlacValue = "flac"; + + /// mp3. + public static CreateSpeechRequestResponseFormat Mp3 { get; } = new CreateSpeechRequestResponseFormat(Mp3Value); + /// opus. + public static CreateSpeechRequestResponseFormat Opus { get; } = new CreateSpeechRequestResponseFormat(OpusValue); + /// aac. + public static CreateSpeechRequestResponseFormat Aac { get; } = new CreateSpeechRequestResponseFormat(AacValue); + /// flac. + public static CreateSpeechRequestResponseFormat Flac { get; } = new CreateSpeechRequestResponseFormat(FlacValue); + /// Determines if two values are the same. + public static bool operator ==(CreateSpeechRequestResponseFormat left, CreateSpeechRequestResponseFormat right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateSpeechRequestResponseFormat left, CreateSpeechRequestResponseFormat right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateSpeechRequestResponseFormat(string value) => new CreateSpeechRequestResponseFormat(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateSpeechRequestResponseFormat other && Equals(other); + /// + public bool Equals(CreateSpeechRequestResponseFormat other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateSpeechRequestVoice.cs b/.dotnet/src/Generated/Models/CreateSpeechRequestVoice.cs new file mode 100644 index 000000000..db9af9d9d --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateSpeechRequestVoice.cs @@ -0,0 +1,60 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for voice in CreateSpeechRequest. + public readonly partial struct CreateSpeechRequestVoice : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateSpeechRequestVoice(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string AlloyValue = "alloy"; + private const string EchoValue = "echo"; + private const string FableValue = "fable"; + private const string OnyxValue = "onyx"; + private const string NovaValue = "nova"; + private const string ShimmerValue = "shimmer"; + + /// alloy. + public static CreateSpeechRequestVoice Alloy { get; } = new CreateSpeechRequestVoice(AlloyValue); + /// echo. + public static CreateSpeechRequestVoice Echo { get; } = new CreateSpeechRequestVoice(EchoValue); + /// fable. + public static CreateSpeechRequestVoice Fable { get; } = new CreateSpeechRequestVoice(FableValue); + /// onyx. + public static CreateSpeechRequestVoice Onyx { get; } = new CreateSpeechRequestVoice(OnyxValue); + /// nova. + public static CreateSpeechRequestVoice Nova { get; } = new CreateSpeechRequestVoice(NovaValue); + /// shimmer. + public static CreateSpeechRequestVoice Shimmer { get; } = new CreateSpeechRequestVoice(ShimmerValue); + /// Determines if two values are the same. + public static bool operator ==(CreateSpeechRequestVoice left, CreateSpeechRequestVoice right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateSpeechRequestVoice left, CreateSpeechRequestVoice right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateSpeechRequestVoice(string value) => new CreateSpeechRequestVoice(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateSpeechRequestVoice other && Equals(other); + /// + public bool Equals(CreateSpeechRequestVoice other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.Serialization.cs new file mode 100644 index 000000000..8710e7c9a --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.Serialization.cs @@ -0,0 +1,277 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateThreadAndRunRequest : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateThreadAndRunRequest)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("assistant_id"u8); + writer.WriteStringValue(AssistantId); + if (OptionalProperty.IsDefined(Thread)) + { + writer.WritePropertyName("thread"u8); + writer.WriteObjectValue(Thread); + } + if (OptionalProperty.IsDefined(Model)) + { + if (Model != null) + { + writer.WritePropertyName("model"u8); + writer.WriteStringValue(Model); + } + else + { + writer.WriteNull("model"); + } + } + if (OptionalProperty.IsDefined(Instructions)) + { + if (Instructions != null) + { + writer.WritePropertyName("instructions"u8); + writer.WriteStringValue(Instructions); + } + else + { + writer.WriteNull("instructions"); + } + } + if (OptionalProperty.IsCollectionDefined(Tools)) + { + if (Tools != null) + { + writer.WritePropertyName("tools"u8); + writer.WriteStartArray(); + foreach (var item in Tools) + { + if (item == null) + { + writer.WriteNullValue(); + continue; + } +#if NET6_0_OR_GREATER + writer.WriteRawValue(item); +#else + using (JsonDocument document = JsonDocument.Parse(item)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + writer.WriteEndArray(); + } + else + { + writer.WriteNull("tools"); + } + } + if (OptionalProperty.IsCollectionDefined(Metadata)) + { + if (Metadata != null) + { + writer.WritePropertyName("metadata"u8); + writer.WriteStartObject(); + foreach (var item in Metadata) + { + writer.WritePropertyName(item.Key); + writer.WriteStringValue(item.Value); + } + writer.WriteEndObject(); + } + else + { + writer.WriteNull("metadata"); + } + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateThreadAndRunRequest IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateThreadAndRunRequest)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateThreadAndRunRequest(document.RootElement, options); + } + + internal static CreateThreadAndRunRequest DeserializeCreateThreadAndRunRequest(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string assistantId = default; + OptionalProperty thread = default; + OptionalProperty model = default; + OptionalProperty instructions = default; + OptionalProperty> tools = default; + OptionalProperty> metadata = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("assistant_id"u8)) + { + assistantId = property.Value.GetString(); + continue; + } + if (property.NameEquals("thread"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + thread = CreateThreadRequest.DeserializeCreateThreadRequest(property.Value); + continue; + } + if (property.NameEquals("model"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + model = null; + continue; + } + model = property.Value.GetString(); + continue; + } + if (property.NameEquals("instructions"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + instructions = null; + continue; + } + instructions = property.Value.GetString(); + continue; + } + if (property.NameEquals("tools"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + if (item.ValueKind == JsonValueKind.Null) + { + array.Add(null); + } + else + { + array.Add(BinaryData.FromString(item.GetRawText())); + } + } + tools = array; + continue; + } + if (property.NameEquals("metadata"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + Dictionary dictionary = new Dictionary(); + foreach (var property0 in property.Value.EnumerateObject()) + { + dictionary.Add(property0.Name, property0.Value.GetString()); + } + metadata = dictionary; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateThreadAndRunRequest(assistantId, thread.Value, model.Value, instructions.Value, OptionalProperty.ToList(tools), OptionalProperty.ToDictionary(metadata), serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateThreadAndRunRequest)} does not support '{options.Format}' format."); + } + } + + CreateThreadAndRunRequest IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateThreadAndRunRequest(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateThreadAndRunRequest)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateThreadAndRunRequest FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateThreadAndRunRequest(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.cs b/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.cs new file mode 100644 index 000000000..cffca99a7 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.cs @@ -0,0 +1,150 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateThreadAndRunRequest. + public partial class CreateThreadAndRunRequest + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The ID of the [assistant](/docs/api-reference/assistants) to use to execute this run. + /// is null. + public CreateThreadAndRunRequest(string assistantId) + { + ClientUtilities.AssertNotNull(assistantId, nameof(assistantId)); + + AssistantId = assistantId; + Tools = new OptionalList(); + Metadata = new OptionalDictionary(); + } + + /// Initializes a new instance of . + /// The ID of the [assistant](/docs/api-reference/assistants) to use to execute this run. + /// If no thread is provided, an empty thread will be created. + /// + /// The ID of the [Model](/docs/api-reference/models) to be used to execute this run. If a value is + /// provided here, it will override the model associated with the assistant. If not, the model + /// associated with the assistant will be used. + /// + /// + /// Override the default system message of the assistant. This is useful for modifying the behavior + /// on a per-run basis. + /// + /// + /// Override the tools the assistant can use for this run. This is useful for modifying the + /// behavior on a per-run basis. + /// + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// Keeps track of any properties unknown to the library. + internal CreateThreadAndRunRequest(string assistantId, CreateThreadRequest thread, string model, string instructions, IList tools, IDictionary metadata, IDictionary serializedAdditionalRawData) + { + AssistantId = assistantId; + Thread = thread; + Model = model; + Instructions = instructions; + Tools = tools; + Metadata = metadata; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateThreadAndRunRequest() + { + } + + /// The ID of the [assistant](/docs/api-reference/assistants) to use to execute this run. + public string AssistantId { get; } + /// If no thread is provided, an empty thread will be created. + public CreateThreadRequest Thread { get; set; } + /// + /// The ID of the [Model](/docs/api-reference/models) to be used to execute this run. If a value is + /// provided here, it will override the model associated with the assistant. If not, the model + /// associated with the assistant will be used. + /// + public string Model { get; set; } + /// + /// Override the default system message of the assistant. This is useful for modifying the behavior + /// on a per-run basis. + /// + public string Instructions { get; set; } + /// + /// Override the tools the assistant can use for this run. This is useful for modifying the + /// behavior on a per-run basis. + /// + /// To assign an object to the element of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + public IList Tools { get; set; } + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + public IDictionary Metadata { get; set; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateThreadRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateThreadRequest.Serialization.cs new file mode 100644 index 000000000..e321794d2 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateThreadRequest.Serialization.cs @@ -0,0 +1,182 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateThreadRequest : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateThreadRequest)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + if (OptionalProperty.IsCollectionDefined(Messages)) + { + writer.WritePropertyName("messages"u8); + writer.WriteStartArray(); + foreach (var item in Messages) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + } + if (OptionalProperty.IsCollectionDefined(Metadata)) + { + if (Metadata != null) + { + writer.WritePropertyName("metadata"u8); + writer.WriteStartObject(); + foreach (var item in Metadata) + { + writer.WritePropertyName(item.Key); + writer.WriteStringValue(item.Value); + } + writer.WriteEndObject(); + } + else + { + writer.WriteNull("metadata"); + } + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateThreadRequest IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateThreadRequest)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateThreadRequest(document.RootElement, options); + } + + internal static CreateThreadRequest DeserializeCreateThreadRequest(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + OptionalProperty> messages = default; + OptionalProperty> metadata = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("messages"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(CreateMessageRequest.DeserializeCreateMessageRequest(item)); + } + messages = array; + continue; + } + if (property.NameEquals("metadata"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + Dictionary dictionary = new Dictionary(); + foreach (var property0 in property.Value.EnumerateObject()) + { + dictionary.Add(property0.Name, property0.Value.GetString()); + } + metadata = dictionary; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateThreadRequest(OptionalProperty.ToList(messages), OptionalProperty.ToDictionary(metadata), serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateThreadRequest)} does not support '{options.Format}' format."); + } + } + + CreateThreadRequest IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateThreadRequest(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateThreadRequest)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateThreadRequest FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateThreadRequest(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateThreadRequest.cs b/.dotnet/src/Generated/Models/CreateThreadRequest.cs new file mode 100644 index 000000000..b59545b62 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateThreadRequest.cs @@ -0,0 +1,77 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateThreadRequest. + public partial class CreateThreadRequest + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + public CreateThreadRequest() + { + Messages = new OptionalList(); + Metadata = new OptionalDictionary(); + } + + /// Initializes a new instance of . + /// A list of [messages](/docs/api-reference/messages) to start the thread with. + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// Keeps track of any properties unknown to the library. + internal CreateThreadRequest(IList messages, IDictionary metadata, IDictionary serializedAdditionalRawData) + { + Messages = messages; + Metadata = metadata; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// A list of [messages](/docs/api-reference/messages) to start the thread with. + public IList Messages { get; } + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + public IDictionary Metadata { get; set; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateTranscriptionRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateTranscriptionRequest.Serialization.cs new file mode 100644 index 000000000..8b89df137 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateTranscriptionRequest.Serialization.cs @@ -0,0 +1,192 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateTranscriptionRequest : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateTranscriptionRequest)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("file"u8); + writer.WriteBase64StringValue(File.ToArray(), "D"); + writer.WritePropertyName("model"u8); + writer.WriteStringValue(Model.ToString()); + if (OptionalProperty.IsDefined(Language)) + { + writer.WritePropertyName("language"u8); + writer.WriteStringValue(Language); + } + if (OptionalProperty.IsDefined(Prompt)) + { + writer.WritePropertyName("prompt"u8); + writer.WriteStringValue(Prompt); + } + if (OptionalProperty.IsDefined(ResponseFormat)) + { + writer.WritePropertyName("response_format"u8); + writer.WriteStringValue(ResponseFormat.Value.ToString()); + } + if (OptionalProperty.IsDefined(Temperature)) + { + writer.WritePropertyName("temperature"u8); + writer.WriteNumberValue(Temperature.Value); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateTranscriptionRequest IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateTranscriptionRequest)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateTranscriptionRequest(document.RootElement, options); + } + + internal static CreateTranscriptionRequest DeserializeCreateTranscriptionRequest(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + BinaryData file = default; + CreateTranscriptionRequestModel model = default; + OptionalProperty language = default; + OptionalProperty prompt = default; + OptionalProperty responseFormat = default; + OptionalProperty temperature = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("file"u8)) + { + file = BinaryData.FromBytes(property.Value.GetBytesFromBase64("D")); + continue; + } + if (property.NameEquals("model"u8)) + { + model = new CreateTranscriptionRequestModel(property.Value.GetString()); + continue; + } + if (property.NameEquals("language"u8)) + { + language = property.Value.GetString(); + continue; + } + if (property.NameEquals("prompt"u8)) + { + prompt = property.Value.GetString(); + continue; + } + if (property.NameEquals("response_format"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + responseFormat = new CreateTranscriptionRequestResponseFormat(property.Value.GetString()); + continue; + } + if (property.NameEquals("temperature"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + temperature = property.Value.GetDouble(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateTranscriptionRequest(file, model, language.Value, prompt.Value, OptionalProperty.ToNullable(responseFormat), OptionalProperty.ToNullable(temperature), serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateTranscriptionRequest)} does not support '{options.Format}' format."); + } + } + + CreateTranscriptionRequest IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateTranscriptionRequest(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateTranscriptionRequest)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateTranscriptionRequest FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateTranscriptionRequest(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateTranscriptionRequest.cs b/.dotnet/src/Generated/Models/CreateTranscriptionRequest.cs new file mode 100644 index 000000000..74d9d5ebd --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateTranscriptionRequest.cs @@ -0,0 +1,147 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateTranscriptionRequest. + public partial class CreateTranscriptionRequest + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// The audio file object (not file name) to transcribe, in one of these formats: flac, mp3, mp4, + /// mpeg, mpga, m4a, ogg, wav, or webm. + /// + /// ID of the model to use. Only `whisper-1` is currently available. + /// is null. + public CreateTranscriptionRequest(BinaryData file, CreateTranscriptionRequestModel model) + { + ClientUtilities.AssertNotNull(file, nameof(file)); + + File = file; + Model = model; + } + + /// Initializes a new instance of . + /// + /// The audio file object (not file name) to transcribe, in one of these formats: flac, mp3, mp4, + /// mpeg, mpga, m4a, ogg, wav, or webm. + /// + /// ID of the model to use. Only `whisper-1` is currently available. + /// + /// The language of the input audio. Supplying the input language in + /// [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) format will improve accuracy + /// and latency. + /// + /// + /// An optional text to guide the model's style or continue a previous audio segment. The + /// [prompt](/docs/guides/speech-to-text/prompting) should match the audio language. + /// + /// + /// The format of the transcript output, in one of these options: json, text, srt, verbose_json, or + /// vtt. + /// + /// + /// The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more + /// random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, + /// the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to + /// automatically increase the temperature until certain thresholds are hit. + /// + /// Keeps track of any properties unknown to the library. + internal CreateTranscriptionRequest(BinaryData file, CreateTranscriptionRequestModel model, string language, string prompt, CreateTranscriptionRequestResponseFormat? responseFormat, double? temperature, IDictionary serializedAdditionalRawData) + { + File = file; + Model = model; + Language = language; + Prompt = prompt; + ResponseFormat = responseFormat; + Temperature = temperature; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateTranscriptionRequest() + { + } + + /// + /// The audio file object (not file name) to transcribe, in one of these formats: flac, mp3, mp4, + /// mpeg, mpga, m4a, ogg, wav, or webm. + /// + /// To assign a byte[] to this property use . + /// The byte[] will be serialized to a Base64 encoded string. + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromBytes(new byte[] { 1, 2, 3 }) + /// Creates a payload of "AQID". + /// + /// + /// + /// + public BinaryData File { get; } + /// ID of the model to use. Only `whisper-1` is currently available. + public CreateTranscriptionRequestModel Model { get; } + /// + /// The language of the input audio. Supplying the input language in + /// [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) format will improve accuracy + /// and latency. + /// + public string Language { get; set; } + /// + /// An optional text to guide the model's style or continue a previous audio segment. The + /// [prompt](/docs/guides/speech-to-text/prompting) should match the audio language. + /// + public string Prompt { get; set; } + /// + /// The format of the transcript output, in one of these options: json, text, srt, verbose_json, or + /// vtt. + /// + public CreateTranscriptionRequestResponseFormat? ResponseFormat { get; set; } + /// + /// The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more + /// random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, + /// the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to + /// automatically increase the temperature until certain thresholds are hit. + /// + public double? Temperature { get; set; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateTranscriptionRequestModel.cs b/.dotnet/src/Generated/Models/CreateTranscriptionRequestModel.cs new file mode 100644 index 000000000..d3c46e425 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateTranscriptionRequestModel.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for model in CreateTranscriptionRequest. + public readonly partial struct CreateTranscriptionRequestModel : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateTranscriptionRequestModel(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string Whisper1Value = "whisper-1"; + + /// whisper-1. + public static CreateTranscriptionRequestModel Whisper1 { get; } = new CreateTranscriptionRequestModel(Whisper1Value); + /// Determines if two values are the same. + public static bool operator ==(CreateTranscriptionRequestModel left, CreateTranscriptionRequestModel right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateTranscriptionRequestModel left, CreateTranscriptionRequestModel right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateTranscriptionRequestModel(string value) => new CreateTranscriptionRequestModel(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateTranscriptionRequestModel other && Equals(other); + /// + public bool Equals(CreateTranscriptionRequestModel other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateTranscriptionRequestResponseFormat.cs b/.dotnet/src/Generated/Models/CreateTranscriptionRequestResponseFormat.cs new file mode 100644 index 000000000..354321879 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateTranscriptionRequestResponseFormat.cs @@ -0,0 +1,57 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for response_format in CreateTranscriptionRequest. + public readonly partial struct CreateTranscriptionRequestResponseFormat : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateTranscriptionRequestResponseFormat(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string JsonValue = "json"; + private const string TextValue = "text"; + private const string SrtValue = "srt"; + private const string VerboseJsonValue = "verbose_json"; + private const string VttValue = "vtt"; + + /// json. + public static CreateTranscriptionRequestResponseFormat Json { get; } = new CreateTranscriptionRequestResponseFormat(JsonValue); + /// text. + public static CreateTranscriptionRequestResponseFormat Text { get; } = new CreateTranscriptionRequestResponseFormat(TextValue); + /// srt. + public static CreateTranscriptionRequestResponseFormat Srt { get; } = new CreateTranscriptionRequestResponseFormat(SrtValue); + /// verbose_json. + public static CreateTranscriptionRequestResponseFormat VerboseJson { get; } = new CreateTranscriptionRequestResponseFormat(VerboseJsonValue); + /// vtt. + public static CreateTranscriptionRequestResponseFormat Vtt { get; } = new CreateTranscriptionRequestResponseFormat(VttValue); + /// Determines if two values are the same. + public static bool operator ==(CreateTranscriptionRequestResponseFormat left, CreateTranscriptionRequestResponseFormat right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateTranscriptionRequestResponseFormat left, CreateTranscriptionRequestResponseFormat right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateTranscriptionRequestResponseFormat(string value) => new CreateTranscriptionRequestResponseFormat(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateTranscriptionRequestResponseFormat other && Equals(other); + /// + public bool Equals(CreateTranscriptionRequestResponseFormat other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateTranscriptionResponse.Serialization.cs b/.dotnet/src/Generated/Models/CreateTranscriptionResponse.Serialization.cs new file mode 100644 index 000000000..7ebe36e6c --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateTranscriptionResponse.Serialization.cs @@ -0,0 +1,198 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateTranscriptionResponse : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateTranscriptionResponse)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("text"u8); + writer.WriteStringValue(Text); + if (OptionalProperty.IsDefined(Task)) + { + writer.WritePropertyName("task"u8); + writer.WriteStringValue(Task.Value.ToString()); + } + if (OptionalProperty.IsDefined(Language)) + { + writer.WritePropertyName("language"u8); + writer.WriteStringValue(Language); + } + if (OptionalProperty.IsDefined(Duration)) + { + writer.WritePropertyName("duration"u8); + writer.WriteNumberValue(Convert.ToInt32(Duration.Value.ToString("%s"))); + } + if (OptionalProperty.IsCollectionDefined(Segments)) + { + writer.WritePropertyName("segments"u8); + writer.WriteStartArray(); + foreach (var item in Segments) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateTranscriptionResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateTranscriptionResponse)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateTranscriptionResponse(document.RootElement, options); + } + + internal static CreateTranscriptionResponse DeserializeCreateTranscriptionResponse(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string text = default; + OptionalProperty task = default; + OptionalProperty language = default; + OptionalProperty duration = default; + OptionalProperty> segments = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("text"u8)) + { + text = property.Value.GetString(); + continue; + } + if (property.NameEquals("task"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + task = new CreateTranscriptionResponseTask(property.Value.GetString()); + continue; + } + if (property.NameEquals("language"u8)) + { + language = property.Value.GetString(); + continue; + } + if (property.NameEquals("duration"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + duration = TimeSpan.FromSeconds(property.Value.GetInt32()); + continue; + } + if (property.NameEquals("segments"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(AudioSegment.DeserializeAudioSegment(item)); + } + segments = array; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateTranscriptionResponse(text, OptionalProperty.ToNullable(task), language.Value, OptionalProperty.ToNullable(duration), OptionalProperty.ToList(segments), serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateTranscriptionResponse)} does not support '{options.Format}' format."); + } + } + + CreateTranscriptionResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateTranscriptionResponse(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateTranscriptionResponse)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateTranscriptionResponse FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateTranscriptionResponse(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateTranscriptionResponse.cs b/.dotnet/src/Generated/Models/CreateTranscriptionResponse.cs new file mode 100644 index 000000000..c526f24a1 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateTranscriptionResponse.cs @@ -0,0 +1,96 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateTranscriptionResponse. + public partial class CreateTranscriptionResponse + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The transcribed text for the provided audio data. + /// is null. + internal CreateTranscriptionResponse(string text) + { + ClientUtilities.AssertNotNull(text, nameof(text)); + + Text = text; + Segments = new OptionalList(); + } + + /// Initializes a new instance of . + /// The transcribed text for the provided audio data. + /// The label that describes which operation type generated the accompanying response data. + /// The spoken language that was detected in the audio data. + /// The total duration of the audio processed to produce accompanying transcription information. + /// + /// A collection of information about the timing, probabilities, and other detail of each processed + /// audio segment. + /// + /// Keeps track of any properties unknown to the library. + internal CreateTranscriptionResponse(string text, CreateTranscriptionResponseTask? task, string language, TimeSpan? duration, IReadOnlyList segments, IDictionary serializedAdditionalRawData) + { + Text = text; + Task = task; + Language = language; + Duration = duration; + Segments = segments; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateTranscriptionResponse() + { + } + + /// The transcribed text for the provided audio data. + public string Text { get; } + /// The label that describes which operation type generated the accompanying response data. + public CreateTranscriptionResponseTask? Task { get; } + /// The spoken language that was detected in the audio data. + public string Language { get; } + /// The total duration of the audio processed to produce accompanying transcription information. + public TimeSpan? Duration { get; } + /// + /// A collection of information about the timing, probabilities, and other detail of each processed + /// audio segment. + /// + public IReadOnlyList Segments { get; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateTranscriptionResponseTask.cs b/.dotnet/src/Generated/Models/CreateTranscriptionResponseTask.cs new file mode 100644 index 000000000..2cf79c9ae --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateTranscriptionResponseTask.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The CreateTranscriptionResponse_task. + public readonly partial struct CreateTranscriptionResponseTask : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateTranscriptionResponseTask(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string TranscribeValue = "transcribe"; + + /// transcribe. + public static CreateTranscriptionResponseTask Transcribe { get; } = new CreateTranscriptionResponseTask(TranscribeValue); + /// Determines if two values are the same. + public static bool operator ==(CreateTranscriptionResponseTask left, CreateTranscriptionResponseTask right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateTranscriptionResponseTask left, CreateTranscriptionResponseTask right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateTranscriptionResponseTask(string value) => new CreateTranscriptionResponseTask(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateTranscriptionResponseTask other && Equals(other); + /// + public bool Equals(CreateTranscriptionResponseTask other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateTranslationRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateTranslationRequest.Serialization.cs new file mode 100644 index 000000000..2e29df2c7 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateTranslationRequest.Serialization.cs @@ -0,0 +1,181 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateTranslationRequest : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateTranslationRequest)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("file"u8); + writer.WriteBase64StringValue(File.ToArray(), "D"); + writer.WritePropertyName("model"u8); + writer.WriteStringValue(Model.ToString()); + if (OptionalProperty.IsDefined(Prompt)) + { + writer.WritePropertyName("prompt"u8); + writer.WriteStringValue(Prompt); + } + if (OptionalProperty.IsDefined(ResponseFormat)) + { + writer.WritePropertyName("response_format"u8); + writer.WriteStringValue(ResponseFormat.Value.ToString()); + } + if (OptionalProperty.IsDefined(Temperature)) + { + writer.WritePropertyName("temperature"u8); + writer.WriteNumberValue(Temperature.Value); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateTranslationRequest IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateTranslationRequest)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateTranslationRequest(document.RootElement, options); + } + + internal static CreateTranslationRequest DeserializeCreateTranslationRequest(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + BinaryData file = default; + CreateTranslationRequestModel model = default; + OptionalProperty prompt = default; + OptionalProperty responseFormat = default; + OptionalProperty temperature = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("file"u8)) + { + file = BinaryData.FromBytes(property.Value.GetBytesFromBase64("D")); + continue; + } + if (property.NameEquals("model"u8)) + { + model = new CreateTranslationRequestModel(property.Value.GetString()); + continue; + } + if (property.NameEquals("prompt"u8)) + { + prompt = property.Value.GetString(); + continue; + } + if (property.NameEquals("response_format"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + responseFormat = new CreateTranslationRequestResponseFormat(property.Value.GetString()); + continue; + } + if (property.NameEquals("temperature"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + temperature = property.Value.GetDouble(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateTranslationRequest(file, model, prompt.Value, OptionalProperty.ToNullable(responseFormat), OptionalProperty.ToNullable(temperature), serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateTranslationRequest)} does not support '{options.Format}' format."); + } + } + + CreateTranslationRequest IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateTranslationRequest(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateTranslationRequest)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateTranslationRequest FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateTranslationRequest(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateTranslationRequest.cs b/.dotnet/src/Generated/Models/CreateTranslationRequest.cs new file mode 100644 index 000000000..6ee7db49a --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateTranslationRequest.cs @@ -0,0 +1,135 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateTranslationRequest. + public partial class CreateTranslationRequest + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// The audio file object (not file name) to translate, in one of these formats: flac, mp3, mp4, + /// mpeg, mpga, m4a, ogg, wav, or webm. + /// + /// ID of the model to use. Only `whisper-1` is currently available. + /// is null. + public CreateTranslationRequest(BinaryData file, CreateTranslationRequestModel model) + { + ClientUtilities.AssertNotNull(file, nameof(file)); + + File = file; + Model = model; + } + + /// Initializes a new instance of . + /// + /// The audio file object (not file name) to translate, in one of these formats: flac, mp3, mp4, + /// mpeg, mpga, m4a, ogg, wav, or webm. + /// + /// ID of the model to use. Only `whisper-1` is currently available. + /// + /// An optional text to guide the model's style or continue a previous audio segment. The + /// [prompt](/docs/guides/speech-to-text/prompting) should match the audio language. + /// + /// + /// The format of the transcript output, in one of these options: json, text, srt, verbose_json, or + /// vtt. + /// + /// + /// The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more + /// random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, + /// the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to + /// automatically increase the temperature until certain thresholds are hit. + /// + /// Keeps track of any properties unknown to the library. + internal CreateTranslationRequest(BinaryData file, CreateTranslationRequestModel model, string prompt, CreateTranslationRequestResponseFormat? responseFormat, double? temperature, IDictionary serializedAdditionalRawData) + { + File = file; + Model = model; + Prompt = prompt; + ResponseFormat = responseFormat; + Temperature = temperature; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateTranslationRequest() + { + } + + /// + /// The audio file object (not file name) to translate, in one of these formats: flac, mp3, mp4, + /// mpeg, mpga, m4a, ogg, wav, or webm. + /// + /// To assign a byte[] to this property use . + /// The byte[] will be serialized to a Base64 encoded string. + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromBytes(new byte[] { 1, 2, 3 }) + /// Creates a payload of "AQID". + /// + /// + /// + /// + public BinaryData File { get; } + /// ID of the model to use. Only `whisper-1` is currently available. + public CreateTranslationRequestModel Model { get; } + /// + /// An optional text to guide the model's style or continue a previous audio segment. The + /// [prompt](/docs/guides/speech-to-text/prompting) should match the audio language. + /// + public string Prompt { get; set; } + /// + /// The format of the transcript output, in one of these options: json, text, srt, verbose_json, or + /// vtt. + /// + public CreateTranslationRequestResponseFormat? ResponseFormat { get; set; } + /// + /// The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more + /// random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, + /// the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to + /// automatically increase the temperature until certain thresholds are hit. + /// + public double? Temperature { get; set; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateTranslationRequestModel.cs b/.dotnet/src/Generated/Models/CreateTranslationRequestModel.cs new file mode 100644 index 000000000..b9d4c7076 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateTranslationRequestModel.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for model in CreateTranslationRequest. + public readonly partial struct CreateTranslationRequestModel : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateTranslationRequestModel(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string Whisper1Value = "whisper-1"; + + /// whisper-1. + public static CreateTranslationRequestModel Whisper1 { get; } = new CreateTranslationRequestModel(Whisper1Value); + /// Determines if two values are the same. + public static bool operator ==(CreateTranslationRequestModel left, CreateTranslationRequestModel right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateTranslationRequestModel left, CreateTranslationRequestModel right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateTranslationRequestModel(string value) => new CreateTranslationRequestModel(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateTranslationRequestModel other && Equals(other); + /// + public bool Equals(CreateTranslationRequestModel other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateTranslationRequestResponseFormat.cs b/.dotnet/src/Generated/Models/CreateTranslationRequestResponseFormat.cs new file mode 100644 index 000000000..b24279e3c --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateTranslationRequestResponseFormat.cs @@ -0,0 +1,57 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for response_format in CreateTranslationRequest. + public readonly partial struct CreateTranslationRequestResponseFormat : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateTranslationRequestResponseFormat(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string JsonValue = "json"; + private const string TextValue = "text"; + private const string SrtValue = "srt"; + private const string VerboseJsonValue = "verbose_json"; + private const string VttValue = "vtt"; + + /// json. + public static CreateTranslationRequestResponseFormat Json { get; } = new CreateTranslationRequestResponseFormat(JsonValue); + /// text. + public static CreateTranslationRequestResponseFormat Text { get; } = new CreateTranslationRequestResponseFormat(TextValue); + /// srt. + public static CreateTranslationRequestResponseFormat Srt { get; } = new CreateTranslationRequestResponseFormat(SrtValue); + /// verbose_json. + public static CreateTranslationRequestResponseFormat VerboseJson { get; } = new CreateTranslationRequestResponseFormat(VerboseJsonValue); + /// vtt. + public static CreateTranslationRequestResponseFormat Vtt { get; } = new CreateTranslationRequestResponseFormat(VttValue); + /// Determines if two values are the same. + public static bool operator ==(CreateTranslationRequestResponseFormat left, CreateTranslationRequestResponseFormat right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateTranslationRequestResponseFormat left, CreateTranslationRequestResponseFormat right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateTranslationRequestResponseFormat(string value) => new CreateTranslationRequestResponseFormat(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateTranslationRequestResponseFormat other && Equals(other); + /// + public bool Equals(CreateTranslationRequestResponseFormat other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/CreateTranslationResponse.Serialization.cs b/.dotnet/src/Generated/Models/CreateTranslationResponse.Serialization.cs new file mode 100644 index 000000000..917fbfd99 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateTranslationResponse.Serialization.cs @@ -0,0 +1,198 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class CreateTranslationResponse : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateTranslationResponse)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("text"u8); + writer.WriteStringValue(Text); + if (OptionalProperty.IsDefined(Task)) + { + writer.WritePropertyName("task"u8); + writer.WriteStringValue(Task.Value.ToString()); + } + if (OptionalProperty.IsDefined(Language)) + { + writer.WritePropertyName("language"u8); + writer.WriteStringValue(Language); + } + if (OptionalProperty.IsDefined(Duration)) + { + writer.WritePropertyName("duration"u8); + writer.WriteNumberValue(Convert.ToInt32(Duration.Value.ToString("%s"))); + } + if (OptionalProperty.IsCollectionDefined(Segments)) + { + writer.WritePropertyName("segments"u8); + writer.WriteStartArray(); + foreach (var item in Segments) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + CreateTranslationResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(CreateTranslationResponse)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeCreateTranslationResponse(document.RootElement, options); + } + + internal static CreateTranslationResponse DeserializeCreateTranslationResponse(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string text = default; + OptionalProperty task = default; + OptionalProperty language = default; + OptionalProperty duration = default; + OptionalProperty> segments = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("text"u8)) + { + text = property.Value.GetString(); + continue; + } + if (property.NameEquals("task"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + task = new CreateTranslationResponseTask(property.Value.GetString()); + continue; + } + if (property.NameEquals("language"u8)) + { + language = property.Value.GetString(); + continue; + } + if (property.NameEquals("duration"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + duration = TimeSpan.FromSeconds(property.Value.GetInt32()); + continue; + } + if (property.NameEquals("segments"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(AudioSegment.DeserializeAudioSegment(item)); + } + segments = array; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new CreateTranslationResponse(text, OptionalProperty.ToNullable(task), language.Value, OptionalProperty.ToNullable(duration), OptionalProperty.ToList(segments), serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(CreateTranslationResponse)} does not support '{options.Format}' format."); + } + } + + CreateTranslationResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeCreateTranslationResponse(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(CreateTranslationResponse)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static CreateTranslationResponse FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeCreateTranslationResponse(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/CreateTranslationResponse.cs b/.dotnet/src/Generated/Models/CreateTranslationResponse.cs new file mode 100644 index 000000000..c6c9ea458 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateTranslationResponse.cs @@ -0,0 +1,96 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The CreateTranslationResponse. + public partial class CreateTranslationResponse + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The translated text for the provided audio data. + /// is null. + internal CreateTranslationResponse(string text) + { + ClientUtilities.AssertNotNull(text, nameof(text)); + + Text = text; + Segments = new OptionalList(); + } + + /// Initializes a new instance of . + /// The translated text for the provided audio data. + /// The label that describes which operation type generated the accompanying response data. + /// The spoken language that was detected in the audio data. + /// The total duration of the audio processed to produce accompanying translation information. + /// + /// A collection of information about the timing, probabilities, and other detail of each processed + /// audio segment. + /// + /// Keeps track of any properties unknown to the library. + internal CreateTranslationResponse(string text, CreateTranslationResponseTask? task, string language, TimeSpan? duration, IReadOnlyList segments, IDictionary serializedAdditionalRawData) + { + Text = text; + Task = task; + Language = language; + Duration = duration; + Segments = segments; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal CreateTranslationResponse() + { + } + + /// The translated text for the provided audio data. + public string Text { get; } + /// The label that describes which operation type generated the accompanying response data. + public CreateTranslationResponseTask? Task { get; } + /// The spoken language that was detected in the audio data. + public string Language { get; } + /// The total duration of the audio processed to produce accompanying translation information. + public TimeSpan? Duration { get; } + /// + /// A collection of information about the timing, probabilities, and other detail of each processed + /// audio segment. + /// + public IReadOnlyList Segments { get; } + } +} diff --git a/.dotnet/src/Generated/Models/CreateTranslationResponseTask.cs b/.dotnet/src/Generated/Models/CreateTranslationResponseTask.cs new file mode 100644 index 000000000..4104c9b1c --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateTranslationResponseTask.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The CreateTranslationResponse_task. + public readonly partial struct CreateTranslationResponseTask : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateTranslationResponseTask(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string TranslateValue = "translate"; + + /// translate. + public static CreateTranslationResponseTask Translate { get; } = new CreateTranslationResponseTask(TranslateValue); + /// Determines if two values are the same. + public static bool operator ==(CreateTranslationResponseTask left, CreateTranslationResponseTask right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateTranslationResponseTask left, CreateTranslationResponseTask right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateTranslationResponseTask(string value) => new CreateTranslationResponseTask(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateTranslationResponseTask other && Equals(other); + /// + public bool Equals(CreateTranslationResponseTask other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.Serialization.cs b/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.Serialization.cs new file mode 100644 index 000000000..2f92de865 --- /dev/null +++ b/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.Serialization.cs @@ -0,0 +1,148 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class DeleteAssistantFileResponse : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(DeleteAssistantFileResponse)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("id"u8); + writer.WriteStringValue(Id); + writer.WritePropertyName("deleted"u8); + writer.WriteBooleanValue(Deleted); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + DeleteAssistantFileResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(DeleteAssistantFileResponse)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeDeleteAssistantFileResponse(document.RootElement, options); + } + + internal static DeleteAssistantFileResponse DeserializeDeleteAssistantFileResponse(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string id = default; + bool deleted = default; + DeleteAssistantFileResponseObject @object = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetString(); + continue; + } + if (property.NameEquals("deleted"u8)) + { + deleted = property.Value.GetBoolean(); + continue; + } + if (property.NameEquals("object"u8)) + { + @object = new DeleteAssistantFileResponseObject(property.Value.GetString()); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new DeleteAssistantFileResponse(id, deleted, @object, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(DeleteAssistantFileResponse)} does not support '{options.Format}' format."); + } + } + + DeleteAssistantFileResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeDeleteAssistantFileResponse(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(DeleteAssistantFileResponse)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static DeleteAssistantFileResponse FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeDeleteAssistantFileResponse(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.cs b/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.cs new file mode 100644 index 000000000..478d175d2 --- /dev/null +++ b/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.cs @@ -0,0 +1,86 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// + /// Deletes the association between the assistant and the file, but does not delete the + /// [File](/docs/api-reference/files) object itself. + /// + public partial class DeleteAssistantFileResponse + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// + /// is null. + internal DeleteAssistantFileResponse(string id, bool deleted) + { + ClientUtilities.AssertNotNull(id, nameof(id)); + + Id = id; + Deleted = deleted; + } + + /// Initializes a new instance of . + /// + /// + /// + /// Keeps track of any properties unknown to the library. + internal DeleteAssistantFileResponse(string id, bool deleted, DeleteAssistantFileResponseObject @object, IDictionary serializedAdditionalRawData) + { + Id = id; + Deleted = deleted; + Object = @object; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal DeleteAssistantFileResponse() + { + } + + /// Gets the id. + public string Id { get; } + /// Gets the deleted. + public bool Deleted { get; } + /// Gets the object. + public DeleteAssistantFileResponseObject Object { get; } = DeleteAssistantFileResponseObject.AssistantFileDeleted; + } +} diff --git a/.dotnet/src/Generated/Models/DeleteAssistantFileResponseObject.cs b/.dotnet/src/Generated/Models/DeleteAssistantFileResponseObject.cs new file mode 100644 index 000000000..8f9d146db --- /dev/null +++ b/.dotnet/src/Generated/Models/DeleteAssistantFileResponseObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The DeleteAssistantFileResponse_object. + public readonly partial struct DeleteAssistantFileResponseObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public DeleteAssistantFileResponseObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string AssistantFileDeletedValue = "assistant.file.deleted"; + + /// assistant.file.deleted. + public static DeleteAssistantFileResponseObject AssistantFileDeleted { get; } = new DeleteAssistantFileResponseObject(AssistantFileDeletedValue); + /// Determines if two values are the same. + public static bool operator ==(DeleteAssistantFileResponseObject left, DeleteAssistantFileResponseObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(DeleteAssistantFileResponseObject left, DeleteAssistantFileResponseObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator DeleteAssistantFileResponseObject(string value) => new DeleteAssistantFileResponseObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is DeleteAssistantFileResponseObject other && Equals(other); + /// + public bool Equals(DeleteAssistantFileResponseObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/DeleteAssistantResponse.Serialization.cs b/.dotnet/src/Generated/Models/DeleteAssistantResponse.Serialization.cs new file mode 100644 index 000000000..da95808b9 --- /dev/null +++ b/.dotnet/src/Generated/Models/DeleteAssistantResponse.Serialization.cs @@ -0,0 +1,148 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class DeleteAssistantResponse : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(DeleteAssistantResponse)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("id"u8); + writer.WriteStringValue(Id); + writer.WritePropertyName("deleted"u8); + writer.WriteBooleanValue(Deleted); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + DeleteAssistantResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(DeleteAssistantResponse)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeDeleteAssistantResponse(document.RootElement, options); + } + + internal static DeleteAssistantResponse DeserializeDeleteAssistantResponse(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string id = default; + bool deleted = default; + DeleteAssistantResponseObject @object = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetString(); + continue; + } + if (property.NameEquals("deleted"u8)) + { + deleted = property.Value.GetBoolean(); + continue; + } + if (property.NameEquals("object"u8)) + { + @object = new DeleteAssistantResponseObject(property.Value.GetString()); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new DeleteAssistantResponse(id, deleted, @object, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(DeleteAssistantResponse)} does not support '{options.Format}' format."); + } + } + + DeleteAssistantResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeDeleteAssistantResponse(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(DeleteAssistantResponse)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static DeleteAssistantResponse FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeDeleteAssistantResponse(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/DeleteAssistantResponse.cs b/.dotnet/src/Generated/Models/DeleteAssistantResponse.cs new file mode 100644 index 000000000..059769a28 --- /dev/null +++ b/.dotnet/src/Generated/Models/DeleteAssistantResponse.cs @@ -0,0 +1,83 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The DeleteAssistantResponse. + public partial class DeleteAssistantResponse + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// + /// is null. + internal DeleteAssistantResponse(string id, bool deleted) + { + ClientUtilities.AssertNotNull(id, nameof(id)); + + Id = id; + Deleted = deleted; + } + + /// Initializes a new instance of . + /// + /// + /// + /// Keeps track of any properties unknown to the library. + internal DeleteAssistantResponse(string id, bool deleted, DeleteAssistantResponseObject @object, IDictionary serializedAdditionalRawData) + { + Id = id; + Deleted = deleted; + Object = @object; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal DeleteAssistantResponse() + { + } + + /// Gets the id. + public string Id { get; } + /// Gets the deleted. + public bool Deleted { get; } + /// Gets the object. + public DeleteAssistantResponseObject Object { get; } = DeleteAssistantResponseObject.AssistantDeleted; + } +} diff --git a/.dotnet/src/Generated/Models/DeleteAssistantResponseObject.cs b/.dotnet/src/Generated/Models/DeleteAssistantResponseObject.cs new file mode 100644 index 000000000..7c80077ca --- /dev/null +++ b/.dotnet/src/Generated/Models/DeleteAssistantResponseObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The DeleteAssistantResponse_object. + public readonly partial struct DeleteAssistantResponseObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public DeleteAssistantResponseObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string AssistantDeletedValue = "assistant.deleted"; + + /// assistant.deleted. + public static DeleteAssistantResponseObject AssistantDeleted { get; } = new DeleteAssistantResponseObject(AssistantDeletedValue); + /// Determines if two values are the same. + public static bool operator ==(DeleteAssistantResponseObject left, DeleteAssistantResponseObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(DeleteAssistantResponseObject left, DeleteAssistantResponseObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator DeleteAssistantResponseObject(string value) => new DeleteAssistantResponseObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is DeleteAssistantResponseObject other && Equals(other); + /// + public bool Equals(DeleteAssistantResponseObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/DeleteFileResponse.Serialization.cs b/.dotnet/src/Generated/Models/DeleteFileResponse.Serialization.cs new file mode 100644 index 000000000..6ed78cf28 --- /dev/null +++ b/.dotnet/src/Generated/Models/DeleteFileResponse.Serialization.cs @@ -0,0 +1,148 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class DeleteFileResponse : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(DeleteFileResponse)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("id"u8); + writer.WriteStringValue(Id); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + writer.WritePropertyName("deleted"u8); + writer.WriteBooleanValue(Deleted); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + DeleteFileResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(DeleteFileResponse)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeDeleteFileResponse(document.RootElement, options); + } + + internal static DeleteFileResponse DeserializeDeleteFileResponse(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string id = default; + DeleteFileResponseObject @object = default; + bool deleted = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetString(); + continue; + } + if (property.NameEquals("object"u8)) + { + @object = new DeleteFileResponseObject(property.Value.GetString()); + continue; + } + if (property.NameEquals("deleted"u8)) + { + deleted = property.Value.GetBoolean(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new DeleteFileResponse(id, @object, deleted, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(DeleteFileResponse)} does not support '{options.Format}' format."); + } + } + + DeleteFileResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeDeleteFileResponse(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(DeleteFileResponse)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static DeleteFileResponse FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeDeleteFileResponse(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/DeleteFileResponse.cs b/.dotnet/src/Generated/Models/DeleteFileResponse.cs new file mode 100644 index 000000000..202cb2637 --- /dev/null +++ b/.dotnet/src/Generated/Models/DeleteFileResponse.cs @@ -0,0 +1,84 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The DeleteFileResponse. + public partial class DeleteFileResponse + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// + /// is null. + internal DeleteFileResponse(string id, bool deleted) + { + ClientUtilities.AssertNotNull(id, nameof(id)); + + Id = id; + Deleted = deleted; + } + + /// Initializes a new instance of . + /// + /// + /// + /// Keeps track of any properties unknown to the library. + internal DeleteFileResponse(string id, DeleteFileResponseObject @object, bool deleted, IDictionary serializedAdditionalRawData) + { + Id = id; + Object = @object; + Deleted = deleted; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal DeleteFileResponse() + { + } + + /// Gets the id. + public string Id { get; } + /// Gets the object. + public DeleteFileResponseObject Object { get; } = DeleteFileResponseObject.File; + + /// Gets the deleted. + public bool Deleted { get; } + } +} diff --git a/.dotnet/src/Generated/Models/DeleteFileResponseObject.cs b/.dotnet/src/Generated/Models/DeleteFileResponseObject.cs new file mode 100644 index 000000000..8b8080a6a --- /dev/null +++ b/.dotnet/src/Generated/Models/DeleteFileResponseObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The DeleteFileResponse_object. + public readonly partial struct DeleteFileResponseObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public DeleteFileResponseObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string FileValue = "file"; + + /// file. + public static DeleteFileResponseObject File { get; } = new DeleteFileResponseObject(FileValue); + /// Determines if two values are the same. + public static bool operator ==(DeleteFileResponseObject left, DeleteFileResponseObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(DeleteFileResponseObject left, DeleteFileResponseObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator DeleteFileResponseObject(string value) => new DeleteFileResponseObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is DeleteFileResponseObject other && Equals(other); + /// + public bool Equals(DeleteFileResponseObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/DeleteModelResponse.Serialization.cs b/.dotnet/src/Generated/Models/DeleteModelResponse.Serialization.cs new file mode 100644 index 000000000..a16d26d8b --- /dev/null +++ b/.dotnet/src/Generated/Models/DeleteModelResponse.Serialization.cs @@ -0,0 +1,148 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class DeleteModelResponse : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(DeleteModelResponse)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("id"u8); + writer.WriteStringValue(Id); + writer.WritePropertyName("deleted"u8); + writer.WriteBooleanValue(Deleted); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + DeleteModelResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(DeleteModelResponse)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeDeleteModelResponse(document.RootElement, options); + } + + internal static DeleteModelResponse DeserializeDeleteModelResponse(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string id = default; + bool deleted = default; + DeleteModelResponseObject @object = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetString(); + continue; + } + if (property.NameEquals("deleted"u8)) + { + deleted = property.Value.GetBoolean(); + continue; + } + if (property.NameEquals("object"u8)) + { + @object = new DeleteModelResponseObject(property.Value.GetString()); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new DeleteModelResponse(id, deleted, @object, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(DeleteModelResponse)} does not support '{options.Format}' format."); + } + } + + DeleteModelResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeDeleteModelResponse(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(DeleteModelResponse)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static DeleteModelResponse FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeDeleteModelResponse(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/DeleteModelResponse.cs b/.dotnet/src/Generated/Models/DeleteModelResponse.cs new file mode 100644 index 000000000..fc8a2790b --- /dev/null +++ b/.dotnet/src/Generated/Models/DeleteModelResponse.cs @@ -0,0 +1,83 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The DeleteModelResponse. + public partial class DeleteModelResponse + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// + /// is null. + internal DeleteModelResponse(string id, bool deleted) + { + ClientUtilities.AssertNotNull(id, nameof(id)); + + Id = id; + Deleted = deleted; + } + + /// Initializes a new instance of . + /// + /// + /// + /// Keeps track of any properties unknown to the library. + internal DeleteModelResponse(string id, bool deleted, DeleteModelResponseObject @object, IDictionary serializedAdditionalRawData) + { + Id = id; + Deleted = deleted; + Object = @object; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal DeleteModelResponse() + { + } + + /// Gets the id. + public string Id { get; } + /// Gets the deleted. + public bool Deleted { get; } + /// Gets the object. + public DeleteModelResponseObject Object { get; } = DeleteModelResponseObject.Model; + } +} diff --git a/.dotnet/src/Generated/Models/DeleteModelResponseObject.cs b/.dotnet/src/Generated/Models/DeleteModelResponseObject.cs new file mode 100644 index 000000000..ec25f197b --- /dev/null +++ b/.dotnet/src/Generated/Models/DeleteModelResponseObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The DeleteModelResponse_object. + public readonly partial struct DeleteModelResponseObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public DeleteModelResponseObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string ModelValue = "model"; + + /// model. + public static DeleteModelResponseObject Model { get; } = new DeleteModelResponseObject(ModelValue); + /// Determines if two values are the same. + public static bool operator ==(DeleteModelResponseObject left, DeleteModelResponseObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(DeleteModelResponseObject left, DeleteModelResponseObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator DeleteModelResponseObject(string value) => new DeleteModelResponseObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is DeleteModelResponseObject other && Equals(other); + /// + public bool Equals(DeleteModelResponseObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/DeleteThreadResponse.Serialization.cs b/.dotnet/src/Generated/Models/DeleteThreadResponse.Serialization.cs new file mode 100644 index 000000000..f287add9c --- /dev/null +++ b/.dotnet/src/Generated/Models/DeleteThreadResponse.Serialization.cs @@ -0,0 +1,148 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class DeleteThreadResponse : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(DeleteThreadResponse)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("id"u8); + writer.WriteStringValue(Id); + writer.WritePropertyName("deleted"u8); + writer.WriteBooleanValue(Deleted); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + DeleteThreadResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(DeleteThreadResponse)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeDeleteThreadResponse(document.RootElement, options); + } + + internal static DeleteThreadResponse DeserializeDeleteThreadResponse(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string id = default; + bool deleted = default; + DeleteThreadResponseObject @object = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetString(); + continue; + } + if (property.NameEquals("deleted"u8)) + { + deleted = property.Value.GetBoolean(); + continue; + } + if (property.NameEquals("object"u8)) + { + @object = new DeleteThreadResponseObject(property.Value.GetString()); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new DeleteThreadResponse(id, deleted, @object, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(DeleteThreadResponse)} does not support '{options.Format}' format."); + } + } + + DeleteThreadResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeDeleteThreadResponse(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(DeleteThreadResponse)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static DeleteThreadResponse FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeDeleteThreadResponse(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/DeleteThreadResponse.cs b/.dotnet/src/Generated/Models/DeleteThreadResponse.cs new file mode 100644 index 000000000..740de89a5 --- /dev/null +++ b/.dotnet/src/Generated/Models/DeleteThreadResponse.cs @@ -0,0 +1,83 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The DeleteThreadResponse. + public partial class DeleteThreadResponse + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// + /// is null. + internal DeleteThreadResponse(string id, bool deleted) + { + ClientUtilities.AssertNotNull(id, nameof(id)); + + Id = id; + Deleted = deleted; + } + + /// Initializes a new instance of . + /// + /// + /// + /// Keeps track of any properties unknown to the library. + internal DeleteThreadResponse(string id, bool deleted, DeleteThreadResponseObject @object, IDictionary serializedAdditionalRawData) + { + Id = id; + Deleted = deleted; + Object = @object; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal DeleteThreadResponse() + { + } + + /// Gets the id. + public string Id { get; } + /// Gets the deleted. + public bool Deleted { get; } + /// Gets the object. + public DeleteThreadResponseObject Object { get; } = DeleteThreadResponseObject.ThreadDeleted; + } +} diff --git a/.dotnet/src/Generated/Models/DeleteThreadResponseObject.cs b/.dotnet/src/Generated/Models/DeleteThreadResponseObject.cs new file mode 100644 index 000000000..87838dd02 --- /dev/null +++ b/.dotnet/src/Generated/Models/DeleteThreadResponseObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The DeleteThreadResponse_object. + public readonly partial struct DeleteThreadResponseObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public DeleteThreadResponseObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string ThreadDeletedValue = "thread.deleted"; + + /// thread.deleted. + public static DeleteThreadResponseObject ThreadDeleted { get; } = new DeleteThreadResponseObject(ThreadDeletedValue); + /// Determines if two values are the same. + public static bool operator ==(DeleteThreadResponseObject left, DeleteThreadResponseObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(DeleteThreadResponseObject left, DeleteThreadResponseObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator DeleteThreadResponseObject(string value) => new DeleteThreadResponseObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is DeleteThreadResponseObject other && Equals(other); + /// + public bool Equals(DeleteThreadResponseObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/Embedding.Serialization.cs b/.dotnet/src/Generated/Models/Embedding.Serialization.cs new file mode 100644 index 000000000..cdb14b425 --- /dev/null +++ b/.dotnet/src/Generated/Models/Embedding.Serialization.cs @@ -0,0 +1,155 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class Embedding : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(Embedding)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("index"u8); + writer.WriteNumberValue(Index); + writer.WritePropertyName("embedding"u8); +#if NET6_0_OR_GREATER + writer.WriteRawValue(EmbeddingProperty); +#else + using (JsonDocument document = JsonDocument.Parse(EmbeddingProperty)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + Embedding IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(Embedding)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeEmbedding(document.RootElement, options); + } + + internal static Embedding DeserializeEmbedding(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + long index = default; + BinaryData embedding = default; + EmbeddingObject @object = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("index"u8)) + { + index = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("embedding"u8)) + { + embedding = BinaryData.FromString(property.Value.GetRawText()); + continue; + } + if (property.NameEquals("object"u8)) + { + @object = new EmbeddingObject(property.Value.GetString()); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new Embedding(index, embedding, @object, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(Embedding)} does not support '{options.Format}' format."); + } + } + + Embedding IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeEmbedding(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(Embedding)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static Embedding FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeEmbedding(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/Embedding.cs b/.dotnet/src/Generated/Models/Embedding.cs new file mode 100644 index 000000000..40eba7486 --- /dev/null +++ b/.dotnet/src/Generated/Models/Embedding.cs @@ -0,0 +1,130 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// Represents an embedding vector returned by embedding endpoint. + public partial class Embedding + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The index of the embedding in the list of embeddings. + /// + /// The embedding vector, which is a list of floats. The length of vector depends on the model as + /// listed in the [embedding guide](/docs/guides/embeddings). + /// + /// is null. + internal Embedding(long index, BinaryData embeddingProperty) + { + ClientUtilities.AssertNotNull(embeddingProperty, nameof(embeddingProperty)); + + Index = index; + EmbeddingProperty = embeddingProperty; + } + + /// Initializes a new instance of . + /// The index of the embedding in the list of embeddings. + /// + /// The embedding vector, which is a list of floats. The length of vector depends on the model as + /// listed in the [embedding guide](/docs/guides/embeddings). + /// + /// The object type, which is always "embedding". + /// Keeps track of any properties unknown to the library. + internal Embedding(long index, BinaryData embeddingProperty, EmbeddingObject @object, IDictionary serializedAdditionalRawData) + { + Index = index; + EmbeddingProperty = embeddingProperty; + Object = @object; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal Embedding() + { + } + + /// The index of the embedding in the list of embeddings. + public long Index { get; } + /// + /// The embedding vector, which is a list of floats. The length of vector depends on the model as + /// listed in the [embedding guide](/docs/guides/embeddings). + /// + /// To assign an object to this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// + /// Supported types: + /// + /// + /// where T is of type + /// + /// + /// + /// + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + public BinaryData EmbeddingProperty { get; } + /// The object type, which is always "embedding". + public EmbeddingObject Object { get; } = EmbeddingObject.Embedding; + } +} diff --git a/.dotnet/src/Generated/Models/EmbeddingObject.cs b/.dotnet/src/Generated/Models/EmbeddingObject.cs new file mode 100644 index 000000000..1a6df67a6 --- /dev/null +++ b/.dotnet/src/Generated/Models/EmbeddingObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The Embedding_object. + public readonly partial struct EmbeddingObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public EmbeddingObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string EmbeddingValue = "embedding"; + + /// embedding. + public static EmbeddingObject Embedding { get; } = new EmbeddingObject(EmbeddingValue); + /// Determines if two values are the same. + public static bool operator ==(EmbeddingObject left, EmbeddingObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(EmbeddingObject left, EmbeddingObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator EmbeddingObject(string value) => new EmbeddingObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is EmbeddingObject other && Equals(other); + /// + public bool Equals(EmbeddingObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/FineTune.Serialization.cs b/.dotnet/src/Generated/Models/FineTune.Serialization.cs new file mode 100644 index 000000000..cdbb27bb0 --- /dev/null +++ b/.dotnet/src/Generated/Models/FineTune.Serialization.cs @@ -0,0 +1,287 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class FineTune : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(FineTune)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("id"u8); + writer.WriteStringValue(Id); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + writer.WritePropertyName("created_at"u8); + writer.WriteNumberValue(CreatedAt, "U"); + writer.WritePropertyName("updated_at"u8); + writer.WriteNumberValue(UpdatedAt, "U"); + writer.WritePropertyName("model"u8); + writer.WriteStringValue(Model); + if (FineTunedModel != null) + { + writer.WritePropertyName("fine_tuned_model"u8); + writer.WriteStringValue(FineTunedModel); + } + else + { + writer.WriteNull("fine_tuned_model"); + } + writer.WritePropertyName("organization_id"u8); + writer.WriteStringValue(OrganizationId); + writer.WritePropertyName("status"u8); + writer.WriteStringValue(Status.ToString()); + writer.WritePropertyName("hyperparams"u8); + writer.WriteObjectValue(Hyperparams); + writer.WritePropertyName("training_files"u8); + writer.WriteStartArray(); + foreach (var item in TrainingFiles) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + writer.WritePropertyName("validation_files"u8); + writer.WriteStartArray(); + foreach (var item in ValidationFiles) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + writer.WritePropertyName("result_files"u8); + writer.WriteStartArray(); + foreach (var item in ResultFiles) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + if (OptionalProperty.IsCollectionDefined(Events)) + { + writer.WritePropertyName("events"u8); + writer.WriteStartArray(); + foreach (var item in Events) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + FineTune IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(FineTune)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeFineTune(document.RootElement, options); + } + + internal static FineTune DeserializeFineTune(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string id = default; + FineTuneObject @object = default; + DateTimeOffset createdAt = default; + DateTimeOffset updatedAt = default; + string model = default; + string fineTunedModel = default; + string organizationId = default; + FineTuneStatus status = default; + FineTuneHyperparams hyperparams = default; + IReadOnlyList trainingFiles = default; + IReadOnlyList validationFiles = default; + IReadOnlyList resultFiles = default; + OptionalProperty> events = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetString(); + continue; + } + if (property.NameEquals("object"u8)) + { + @object = new FineTuneObject(property.Value.GetString()); + continue; + } + if (property.NameEquals("created_at"u8)) + { + createdAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); + continue; + } + if (property.NameEquals("updated_at"u8)) + { + updatedAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); + continue; + } + if (property.NameEquals("model"u8)) + { + model = property.Value.GetString(); + continue; + } + if (property.NameEquals("fine_tuned_model"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + fineTunedModel = null; + continue; + } + fineTunedModel = property.Value.GetString(); + continue; + } + if (property.NameEquals("organization_id"u8)) + { + organizationId = property.Value.GetString(); + continue; + } + if (property.NameEquals("status"u8)) + { + status = new FineTuneStatus(property.Value.GetString()); + continue; + } + if (property.NameEquals("hyperparams"u8)) + { + hyperparams = FineTuneHyperparams.DeserializeFineTuneHyperparams(property.Value); + continue; + } + if (property.NameEquals("training_files"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(OpenAIFile.DeserializeOpenAIFile(item)); + } + trainingFiles = array; + continue; + } + if (property.NameEquals("validation_files"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(OpenAIFile.DeserializeOpenAIFile(item)); + } + validationFiles = array; + continue; + } + if (property.NameEquals("result_files"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(OpenAIFile.DeserializeOpenAIFile(item)); + } + resultFiles = array; + continue; + } + if (property.NameEquals("events"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(FineTuneEvent.DeserializeFineTuneEvent(item)); + } + events = array; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new FineTune(id, @object, createdAt, updatedAt, model, fineTunedModel, organizationId, status, hyperparams, trainingFiles, validationFiles, resultFiles, OptionalProperty.ToList(events), serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(FineTune)} does not support '{options.Format}' format."); + } + } + + FineTune IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeFineTune(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(FineTune)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static FineTune FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeFineTune(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/FineTune.cs b/.dotnet/src/Generated/Models/FineTune.cs new file mode 100644 index 000000000..6300b6a99 --- /dev/null +++ b/.dotnet/src/Generated/Models/FineTune.cs @@ -0,0 +1,169 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// The `FineTune` object represents a legacy fine-tune job that has been created through the API. + [Obsolete("deprecated")] + public partial class FineTune + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The object identifier, which can be referenced in the API endpoints. + /// The Unix timestamp (in seconds) for when the fine-tuning job was created. + /// The Unix timestamp (in seconds) for when the fine-tuning job was last updated. + /// The base model that is being fine-tuned. + /// The name of the fine-tuned model that is being created. + /// The organization that owns the fine-tuning job. + /// + /// The current status of the fine-tuning job, which can be either `created`, `running`, + /// `succeeded`, `failed`, or `cancelled`. + /// + /// + /// The hyperparameters used for the fine-tuning job. See the + /// [fine-tuning guide](/docs/guides/legacy-fine-tuning/hyperparameters) for more details. + /// + /// The list of files used for training. + /// The list of files used for validation. + /// The compiled results files for the fine-tuning job. + /// , , , , , or is null. + internal FineTune(string id, DateTimeOffset createdAt, DateTimeOffset updatedAt, string model, string fineTunedModel, string organizationId, FineTuneStatus status, FineTuneHyperparams hyperparams, IEnumerable trainingFiles, IEnumerable validationFiles, IEnumerable resultFiles) + { + ClientUtilities.AssertNotNull(id, nameof(id)); + ClientUtilities.AssertNotNull(model, nameof(model)); + ClientUtilities.AssertNotNull(organizationId, nameof(organizationId)); + ClientUtilities.AssertNotNull(hyperparams, nameof(hyperparams)); + ClientUtilities.AssertNotNull(trainingFiles, nameof(trainingFiles)); + ClientUtilities.AssertNotNull(validationFiles, nameof(validationFiles)); + ClientUtilities.AssertNotNull(resultFiles, nameof(resultFiles)); + + Id = id; + CreatedAt = createdAt; + UpdatedAt = updatedAt; + Model = model; + FineTunedModel = fineTunedModel; + OrganizationId = organizationId; + Status = status; + Hyperparams = hyperparams; + TrainingFiles = trainingFiles.ToList(); + ValidationFiles = validationFiles.ToList(); + ResultFiles = resultFiles.ToList(); + Events = new OptionalList(); + } + + /// Initializes a new instance of . + /// The object identifier, which can be referenced in the API endpoints. + /// The object type, which is always "fine-tune". + /// The Unix timestamp (in seconds) for when the fine-tuning job was created. + /// The Unix timestamp (in seconds) for when the fine-tuning job was last updated. + /// The base model that is being fine-tuned. + /// The name of the fine-tuned model that is being created. + /// The organization that owns the fine-tuning job. + /// + /// The current status of the fine-tuning job, which can be either `created`, `running`, + /// `succeeded`, `failed`, or `cancelled`. + /// + /// + /// The hyperparameters used for the fine-tuning job. See the + /// [fine-tuning guide](/docs/guides/legacy-fine-tuning/hyperparameters) for more details. + /// + /// The list of files used for training. + /// The list of files used for validation. + /// The compiled results files for the fine-tuning job. + /// The list of events that have been observed in the lifecycle of the FineTune job. + /// Keeps track of any properties unknown to the library. + internal FineTune(string id, FineTuneObject @object, DateTimeOffset createdAt, DateTimeOffset updatedAt, string model, string fineTunedModel, string organizationId, FineTuneStatus status, FineTuneHyperparams hyperparams, IReadOnlyList trainingFiles, IReadOnlyList validationFiles, IReadOnlyList resultFiles, IReadOnlyList events, IDictionary serializedAdditionalRawData) + { + Id = id; + Object = @object; + CreatedAt = createdAt; + UpdatedAt = updatedAt; + Model = model; + FineTunedModel = fineTunedModel; + OrganizationId = organizationId; + Status = status; + Hyperparams = hyperparams; + TrainingFiles = trainingFiles; + ValidationFiles = validationFiles; + ResultFiles = resultFiles; + Events = events; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal FineTune() + { + } + + /// The object identifier, which can be referenced in the API endpoints. + public string Id { get; } + /// The object type, which is always "fine-tune". + public FineTuneObject Object { get; } = FineTuneObject.FineTune; + + /// The Unix timestamp (in seconds) for when the fine-tuning job was created. + public DateTimeOffset CreatedAt { get; } + /// The Unix timestamp (in seconds) for when the fine-tuning job was last updated. + public DateTimeOffset UpdatedAt { get; } + /// The base model that is being fine-tuned. + public string Model { get; } + /// The name of the fine-tuned model that is being created. + public string FineTunedModel { get; } + /// The organization that owns the fine-tuning job. + public string OrganizationId { get; } + /// + /// The current status of the fine-tuning job, which can be either `created`, `running`, + /// `succeeded`, `failed`, or `cancelled`. + /// + public FineTuneStatus Status { get; } + /// + /// The hyperparameters used for the fine-tuning job. See the + /// [fine-tuning guide](/docs/guides/legacy-fine-tuning/hyperparameters) for more details. + /// + public FineTuneHyperparams Hyperparams { get; } + /// The list of files used for training. + public IReadOnlyList TrainingFiles { get; } + /// The list of files used for validation. + public IReadOnlyList ValidationFiles { get; } + /// The compiled results files for the fine-tuning job. + public IReadOnlyList ResultFiles { get; } + /// The list of events that have been observed in the lifecycle of the FineTune job. + public IReadOnlyList Events { get; } + } +} diff --git a/.dotnet/src/Generated/Models/FineTuneEvent.Serialization.cs b/.dotnet/src/Generated/Models/FineTuneEvent.Serialization.cs new file mode 100644 index 000000000..185b9830f --- /dev/null +++ b/.dotnet/src/Generated/Models/FineTuneEvent.Serialization.cs @@ -0,0 +1,156 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class FineTuneEvent : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(FineTuneEvent)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object); + writer.WritePropertyName("created_at"u8); + writer.WriteNumberValue(CreatedAt, "U"); + writer.WritePropertyName("level"u8); + writer.WriteStringValue(Level); + writer.WritePropertyName("message"u8); + writer.WriteStringValue(Message); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + FineTuneEvent IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(FineTuneEvent)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeFineTuneEvent(document.RootElement, options); + } + + internal static FineTuneEvent DeserializeFineTuneEvent(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string @object = default; + DateTimeOffset createdAt = default; + string level = default; + string message = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("object"u8)) + { + @object = property.Value.GetString(); + continue; + } + if (property.NameEquals("created_at"u8)) + { + createdAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); + continue; + } + if (property.NameEquals("level"u8)) + { + level = property.Value.GetString(); + continue; + } + if (property.NameEquals("message"u8)) + { + message = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new FineTuneEvent(@object, createdAt, level, message, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(FineTuneEvent)} does not support '{options.Format}' format."); + } + } + + FineTuneEvent IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeFineTuneEvent(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(FineTuneEvent)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static FineTuneEvent FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeFineTuneEvent(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/FineTuneEvent.cs b/.dotnet/src/Generated/Models/FineTuneEvent.cs new file mode 100644 index 000000000..dcf13faa4 --- /dev/null +++ b/.dotnet/src/Generated/Models/FineTuneEvent.cs @@ -0,0 +1,93 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The FineTuneEvent. + public partial class FineTuneEvent + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// + /// + /// + /// , or is null. + internal FineTuneEvent(string @object, DateTimeOffset createdAt, string level, string message) + { + ClientUtilities.AssertNotNull(@object, nameof(@object)); + ClientUtilities.AssertNotNull(level, nameof(level)); + ClientUtilities.AssertNotNull(message, nameof(message)); + + Object = @object; + CreatedAt = createdAt; + Level = level; + Message = message; + } + + /// Initializes a new instance of . + /// + /// + /// + /// + /// Keeps track of any properties unknown to the library. + internal FineTuneEvent(string @object, DateTimeOffset createdAt, string level, string message, IDictionary serializedAdditionalRawData) + { + Object = @object; + CreatedAt = createdAt; + Level = level; + Message = message; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal FineTuneEvent() + { + } + + /// Gets the object. + public string Object { get; } + /// Gets the created at. + public DateTimeOffset CreatedAt { get; } + /// Gets the level. + public string Level { get; } + /// Gets the message. + public string Message { get; } + } +} diff --git a/.dotnet/src/Generated/Models/FineTuneHyperparams.Serialization.cs b/.dotnet/src/Generated/Models/FineTuneHyperparams.Serialization.cs new file mode 100644 index 000000000..8e6588b67 --- /dev/null +++ b/.dotnet/src/Generated/Models/FineTuneHyperparams.Serialization.cs @@ -0,0 +1,197 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class FineTuneHyperparams : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(FineTuneHyperparams)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("n_epochs"u8); + writer.WriteNumberValue(NEpochs); + writer.WritePropertyName("batch_size"u8); + writer.WriteNumberValue(BatchSize); + writer.WritePropertyName("prompt_loss_weight"u8); + writer.WriteNumberValue(PromptLossWeight); + writer.WritePropertyName("learning_rate_multiplier"u8); + writer.WriteNumberValue(LearningRateMultiplier); + if (OptionalProperty.IsDefined(ComputeClassificationMetrics)) + { + writer.WritePropertyName("compute_classification_metrics"u8); + writer.WriteBooleanValue(ComputeClassificationMetrics.Value); + } + if (OptionalProperty.IsDefined(ClassificationPositiveClass)) + { + writer.WritePropertyName("classification_positive_class"u8); + writer.WriteStringValue(ClassificationPositiveClass); + } + if (OptionalProperty.IsDefined(ClassificationNClasses)) + { + writer.WritePropertyName("classification_n_classes"u8); + writer.WriteNumberValue(ClassificationNClasses.Value); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + FineTuneHyperparams IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(FineTuneHyperparams)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeFineTuneHyperparams(document.RootElement, options); + } + + internal static FineTuneHyperparams DeserializeFineTuneHyperparams(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + long nEpochs = default; + long batchSize = default; + double promptLossWeight = default; + double learningRateMultiplier = default; + OptionalProperty computeClassificationMetrics = default; + OptionalProperty classificationPositiveClass = default; + OptionalProperty classificationNClasses = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("n_epochs"u8)) + { + nEpochs = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("batch_size"u8)) + { + batchSize = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("prompt_loss_weight"u8)) + { + promptLossWeight = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("learning_rate_multiplier"u8)) + { + learningRateMultiplier = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("compute_classification_metrics"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + computeClassificationMetrics = property.Value.GetBoolean(); + continue; + } + if (property.NameEquals("classification_positive_class"u8)) + { + classificationPositiveClass = property.Value.GetString(); + continue; + } + if (property.NameEquals("classification_n_classes"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + classificationNClasses = property.Value.GetInt64(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new FineTuneHyperparams(nEpochs, batchSize, promptLossWeight, learningRateMultiplier, OptionalProperty.ToNullable(computeClassificationMetrics), classificationPositiveClass.Value, OptionalProperty.ToNullable(classificationNClasses), serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(FineTuneHyperparams)} does not support '{options.Format}' format."); + } + } + + FineTuneHyperparams IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeFineTuneHyperparams(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(FineTuneHyperparams)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static FineTuneHyperparams FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeFineTuneHyperparams(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/FineTuneHyperparams.cs b/.dotnet/src/Generated/Models/FineTuneHyperparams.cs new file mode 100644 index 000000000..f45f7fe7a --- /dev/null +++ b/.dotnet/src/Generated/Models/FineTuneHyperparams.cs @@ -0,0 +1,117 @@ +// + +#nullable disable + +using System; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The FineTuneHyperparams. + public partial class FineTuneHyperparams + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// The number of epochs to train the model for. An epoch refers to one full cycle through the + /// training dataset. + /// + /// + /// The batch size to use for training. The batch size is the number of training examples used to + /// train a single forward and backward pass. + /// + /// The weight to use for loss on the prompt tokens. + /// The learning rate multiplier to use for training. + internal FineTuneHyperparams(long nEpochs, long batchSize, double promptLossWeight, double learningRateMultiplier) + { + NEpochs = nEpochs; + BatchSize = batchSize; + PromptLossWeight = promptLossWeight; + LearningRateMultiplier = learningRateMultiplier; + } + + /// Initializes a new instance of . + /// + /// The number of epochs to train the model for. An epoch refers to one full cycle through the + /// training dataset. + /// + /// + /// The batch size to use for training. The batch size is the number of training examples used to + /// train a single forward and backward pass. + /// + /// The weight to use for loss on the prompt tokens. + /// The learning rate multiplier to use for training. + /// The classification metrics to compute using the validation dataset at the end of every epoch. + /// The positive class to use for computing classification metrics. + /// The number of classes to use for computing classification metrics. + /// Keeps track of any properties unknown to the library. + internal FineTuneHyperparams(long nEpochs, long batchSize, double promptLossWeight, double learningRateMultiplier, bool? computeClassificationMetrics, string classificationPositiveClass, long? classificationNClasses, IDictionary serializedAdditionalRawData) + { + NEpochs = nEpochs; + BatchSize = batchSize; + PromptLossWeight = promptLossWeight; + LearningRateMultiplier = learningRateMultiplier; + ComputeClassificationMetrics = computeClassificationMetrics; + ClassificationPositiveClass = classificationPositiveClass; + ClassificationNClasses = classificationNClasses; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal FineTuneHyperparams() + { + } + + /// + /// The number of epochs to train the model for. An epoch refers to one full cycle through the + /// training dataset. + /// + public long NEpochs { get; } + /// + /// The batch size to use for training. The batch size is the number of training examples used to + /// train a single forward and backward pass. + /// + public long BatchSize { get; } + /// The weight to use for loss on the prompt tokens. + public double PromptLossWeight { get; } + /// The learning rate multiplier to use for training. + public double LearningRateMultiplier { get; } + /// The classification metrics to compute using the validation dataset at the end of every epoch. + public bool? ComputeClassificationMetrics { get; } + /// The positive class to use for computing classification metrics. + public string ClassificationPositiveClass { get; } + /// The number of classes to use for computing classification metrics. + public long? ClassificationNClasses { get; } + } +} diff --git a/.dotnet/src/Generated/Models/FineTuneObject.cs b/.dotnet/src/Generated/Models/FineTuneObject.cs new file mode 100644 index 000000000..7c848fe16 --- /dev/null +++ b/.dotnet/src/Generated/Models/FineTuneObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The FineTune_object. + public readonly partial struct FineTuneObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public FineTuneObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string FineTuneValue = "fine-tune"; + + /// fine-tune. + public static FineTuneObject FineTune { get; } = new FineTuneObject(FineTuneValue); + /// Determines if two values are the same. + public static bool operator ==(FineTuneObject left, FineTuneObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(FineTuneObject left, FineTuneObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator FineTuneObject(string value) => new FineTuneObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is FineTuneObject other && Equals(other); + /// + public bool Equals(FineTuneObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/FineTuneStatus.cs b/.dotnet/src/Generated/Models/FineTuneStatus.cs new file mode 100644 index 000000000..00121f091 --- /dev/null +++ b/.dotnet/src/Generated/Models/FineTuneStatus.cs @@ -0,0 +1,57 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for status in FineTune. + public readonly partial struct FineTuneStatus : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public FineTuneStatus(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string CreatedValue = "created"; + private const string RunningValue = "running"; + private const string SucceededValue = "succeeded"; + private const string FailedValue = "failed"; + private const string CancelledValue = "cancelled"; + + /// created. + public static FineTuneStatus Created { get; } = new FineTuneStatus(CreatedValue); + /// running. + public static FineTuneStatus Running { get; } = new FineTuneStatus(RunningValue); + /// succeeded. + public static FineTuneStatus Succeeded { get; } = new FineTuneStatus(SucceededValue); + /// failed. + public static FineTuneStatus Failed { get; } = new FineTuneStatus(FailedValue); + /// cancelled. + public static FineTuneStatus Cancelled { get; } = new FineTuneStatus(CancelledValue); + /// Determines if two values are the same. + public static bool operator ==(FineTuneStatus left, FineTuneStatus right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(FineTuneStatus left, FineTuneStatus right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator FineTuneStatus(string value) => new FineTuneStatus(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is FineTuneStatus other && Equals(other); + /// + public bool Equals(FineTuneStatus other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/FineTuningJob.Serialization.cs b/.dotnet/src/Generated/Models/FineTuningJob.Serialization.cs new file mode 100644 index 000000000..a7b9c02b7 --- /dev/null +++ b/.dotnet/src/Generated/Models/FineTuningJob.Serialization.cs @@ -0,0 +1,306 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class FineTuningJob : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(FineTuningJob)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("id"u8); + writer.WriteStringValue(Id); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + writer.WritePropertyName("created_at"u8); + writer.WriteNumberValue(CreatedAt, "U"); + if (FinishedAt != null) + { + writer.WritePropertyName("finished_at"u8); + writer.WriteStringValue(FinishedAt.Value, "O"); + } + else + { + writer.WriteNull("finished_at"); + } + writer.WritePropertyName("model"u8); + writer.WriteStringValue(Model); + if (FineTunedModel != null) + { + writer.WritePropertyName("fine_tuned_model"u8); + writer.WriteStringValue(FineTunedModel); + } + else + { + writer.WriteNull("fine_tuned_model"); + } + writer.WritePropertyName("organization_id"u8); + writer.WriteStringValue(OrganizationId); + writer.WritePropertyName("status"u8); + writer.WriteStringValue(Status.ToString()); + writer.WritePropertyName("hyperparameters"u8); + writer.WriteObjectValue(Hyperparameters); + writer.WritePropertyName("training_file"u8); + writer.WriteStringValue(TrainingFile); + if (ValidationFile != null) + { + writer.WritePropertyName("validation_file"u8); + writer.WriteStringValue(ValidationFile); + } + else + { + writer.WriteNull("validation_file"); + } + writer.WritePropertyName("result_files"u8); + writer.WriteStartArray(); + foreach (var item in ResultFiles) + { + writer.WriteStringValue(item); + } + writer.WriteEndArray(); + if (TrainedTokens != null) + { + writer.WritePropertyName("trained_tokens"u8); + writer.WriteNumberValue(TrainedTokens.Value); + } + else + { + writer.WriteNull("trained_tokens"); + } + if (Error != null) + { + writer.WritePropertyName("error"u8); + writer.WriteObjectValue(Error); + } + else + { + writer.WriteNull("error"); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + FineTuningJob IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(FineTuningJob)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeFineTuningJob(document.RootElement, options); + } + + internal static FineTuningJob DeserializeFineTuningJob(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string id = default; + FineTuningJobObject @object = default; + DateTimeOffset createdAt = default; + DateTimeOffset? finishedAt = default; + string model = default; + string fineTunedModel = default; + string organizationId = default; + FineTuningJobStatus status = default; + FineTuningJobHyperparameters hyperparameters = default; + string trainingFile = default; + string validationFile = default; + IReadOnlyList resultFiles = default; + long? trainedTokens = default; + FineTuningJobError error = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetString(); + continue; + } + if (property.NameEquals("object"u8)) + { + @object = new FineTuningJobObject(property.Value.GetString()); + continue; + } + if (property.NameEquals("created_at"u8)) + { + createdAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); + continue; + } + if (property.NameEquals("finished_at"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + finishedAt = null; + continue; + } + finishedAt = property.Value.GetDateTimeOffset("O"); + continue; + } + if (property.NameEquals("model"u8)) + { + model = property.Value.GetString(); + continue; + } + if (property.NameEquals("fine_tuned_model"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + fineTunedModel = null; + continue; + } + fineTunedModel = property.Value.GetString(); + continue; + } + if (property.NameEquals("organization_id"u8)) + { + organizationId = property.Value.GetString(); + continue; + } + if (property.NameEquals("status"u8)) + { + status = new FineTuningJobStatus(property.Value.GetString()); + continue; + } + if (property.NameEquals("hyperparameters"u8)) + { + hyperparameters = FineTuningJobHyperparameters.DeserializeFineTuningJobHyperparameters(property.Value); + continue; + } + if (property.NameEquals("training_file"u8)) + { + trainingFile = property.Value.GetString(); + continue; + } + if (property.NameEquals("validation_file"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + validationFile = null; + continue; + } + validationFile = property.Value.GetString(); + continue; + } + if (property.NameEquals("result_files"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(item.GetString()); + } + resultFiles = array; + continue; + } + if (property.NameEquals("trained_tokens"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + trainedTokens = null; + continue; + } + trainedTokens = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("error"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + error = null; + continue; + } + error = FineTuningJobError.DeserializeFineTuningJobError(property.Value); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new FineTuningJob(id, @object, createdAt, finishedAt, model, fineTunedModel, organizationId, status, hyperparameters, trainingFile, validationFile, resultFiles, trainedTokens, error, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(FineTuningJob)} does not support '{options.Format}' format."); + } + } + + FineTuningJob IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeFineTuningJob(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(FineTuningJob)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static FineTuningJob FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeFineTuningJob(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/FineTuningJob.cs b/.dotnet/src/Generated/Models/FineTuningJob.cs new file mode 100644 index 000000000..0203658aa --- /dev/null +++ b/.dotnet/src/Generated/Models/FineTuningJob.cs @@ -0,0 +1,237 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// The FineTuningJob. + public partial class FineTuningJob + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The object identifier, which can be referenced in the API endpoints. + /// The Unix timestamp (in seconds) for when the fine-tuning job was created. + /// + /// The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be + /// null if the fine-tuning job is still running. + /// + /// The base model that is being fine-tuned. + /// + /// The name of the fine-tuned model that is being created. The value will be null if the + /// fine-tuning job is still running. + /// + /// The organization that owns the fine-tuning job. + /// + /// The current status of the fine-tuning job, which can be either `created`, `pending`, `running`, + /// `succeeded`, `failed`, or `cancelled`. + /// + /// + /// The hyperparameters used for the fine-tuning job. See the + /// [fine-tuning guide](/docs/guides/fine-tuning) for more details. + /// + /// + /// The file ID used for training. You can retrieve the training data with the + /// [Files API](/docs/api-reference/files/retrieve-contents). + /// + /// + /// The file ID used for validation. You can retrieve the validation results with the + /// [Files API](/docs/api-reference/files/retrieve-contents). + /// + /// + /// The compiled results file ID(s) for the fine-tuning job. You can retrieve the results with the + /// [Files API](/docs/api-reference/files/retrieve-contents). + /// + /// + /// The total number of billable tokens processed by this fine tuning job. The value will be null + /// if the fine-tuning job is still running. + /// + /// + /// For fine-tuning jobs that have `failed`, this will contain more information on the cause of the + /// failure. + /// + /// , , , , or is null. + internal FineTuningJob(string id, DateTimeOffset createdAt, DateTimeOffset? finishedAt, string model, string fineTunedModel, string organizationId, FineTuningJobStatus status, FineTuningJobHyperparameters hyperparameters, string trainingFile, string validationFile, IEnumerable resultFiles, long? trainedTokens, FineTuningJobError error) + { + ClientUtilities.AssertNotNull(id, nameof(id)); + ClientUtilities.AssertNotNull(model, nameof(model)); + ClientUtilities.AssertNotNull(organizationId, nameof(organizationId)); + ClientUtilities.AssertNotNull(hyperparameters, nameof(hyperparameters)); + ClientUtilities.AssertNotNull(trainingFile, nameof(trainingFile)); + ClientUtilities.AssertNotNull(resultFiles, nameof(resultFiles)); + + Id = id; + CreatedAt = createdAt; + FinishedAt = finishedAt; + Model = model; + FineTunedModel = fineTunedModel; + OrganizationId = organizationId; + Status = status; + Hyperparameters = hyperparameters; + TrainingFile = trainingFile; + ValidationFile = validationFile; + ResultFiles = resultFiles.ToList(); + TrainedTokens = trainedTokens; + Error = error; + } + + /// Initializes a new instance of . + /// The object identifier, which can be referenced in the API endpoints. + /// The object type, which is always "fine_tuning.job". + /// The Unix timestamp (in seconds) for when the fine-tuning job was created. + /// + /// The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be + /// null if the fine-tuning job is still running. + /// + /// The base model that is being fine-tuned. + /// + /// The name of the fine-tuned model that is being created. The value will be null if the + /// fine-tuning job is still running. + /// + /// The organization that owns the fine-tuning job. + /// + /// The current status of the fine-tuning job, which can be either `created`, `pending`, `running`, + /// `succeeded`, `failed`, or `cancelled`. + /// + /// + /// The hyperparameters used for the fine-tuning job. See the + /// [fine-tuning guide](/docs/guides/fine-tuning) for more details. + /// + /// + /// The file ID used for training. You can retrieve the training data with the + /// [Files API](/docs/api-reference/files/retrieve-contents). + /// + /// + /// The file ID used for validation. You can retrieve the validation results with the + /// [Files API](/docs/api-reference/files/retrieve-contents). + /// + /// + /// The compiled results file ID(s) for the fine-tuning job. You can retrieve the results with the + /// [Files API](/docs/api-reference/files/retrieve-contents). + /// + /// + /// The total number of billable tokens processed by this fine tuning job. The value will be null + /// if the fine-tuning job is still running. + /// + /// + /// For fine-tuning jobs that have `failed`, this will contain more information on the cause of the + /// failure. + /// + /// Keeps track of any properties unknown to the library. + internal FineTuningJob(string id, FineTuningJobObject @object, DateTimeOffset createdAt, DateTimeOffset? finishedAt, string model, string fineTunedModel, string organizationId, FineTuningJobStatus status, FineTuningJobHyperparameters hyperparameters, string trainingFile, string validationFile, IReadOnlyList resultFiles, long? trainedTokens, FineTuningJobError error, IDictionary serializedAdditionalRawData) + { + Id = id; + Object = @object; + CreatedAt = createdAt; + FinishedAt = finishedAt; + Model = model; + FineTunedModel = fineTunedModel; + OrganizationId = organizationId; + Status = status; + Hyperparameters = hyperparameters; + TrainingFile = trainingFile; + ValidationFile = validationFile; + ResultFiles = resultFiles; + TrainedTokens = trainedTokens; + Error = error; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal FineTuningJob() + { + } + + /// The object identifier, which can be referenced in the API endpoints. + public string Id { get; } + /// The object type, which is always "fine_tuning.job". + public FineTuningJobObject Object { get; } = FineTuningJobObject.FineTuningJob; + + /// The Unix timestamp (in seconds) for when the fine-tuning job was created. + public DateTimeOffset CreatedAt { get; } + /// + /// The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be + /// null if the fine-tuning job is still running. + /// + public DateTimeOffset? FinishedAt { get; } + /// The base model that is being fine-tuned. + public string Model { get; } + /// + /// The name of the fine-tuned model that is being created. The value will be null if the + /// fine-tuning job is still running. + /// + public string FineTunedModel { get; } + /// The organization that owns the fine-tuning job. + public string OrganizationId { get; } + /// + /// The current status of the fine-tuning job, which can be either `created`, `pending`, `running`, + /// `succeeded`, `failed`, or `cancelled`. + /// + public FineTuningJobStatus Status { get; } + /// + /// The hyperparameters used for the fine-tuning job. See the + /// [fine-tuning guide](/docs/guides/fine-tuning) for more details. + /// + public FineTuningJobHyperparameters Hyperparameters { get; } + /// + /// The file ID used for training. You can retrieve the training data with the + /// [Files API](/docs/api-reference/files/retrieve-contents). + /// + public string TrainingFile { get; } + /// + /// The file ID used for validation. You can retrieve the validation results with the + /// [Files API](/docs/api-reference/files/retrieve-contents). + /// + public string ValidationFile { get; } + /// + /// The compiled results file ID(s) for the fine-tuning job. You can retrieve the results with the + /// [Files API](/docs/api-reference/files/retrieve-contents). + /// + public IReadOnlyList ResultFiles { get; } + /// + /// The total number of billable tokens processed by this fine tuning job. The value will be null + /// if the fine-tuning job is still running. + /// + public long? TrainedTokens { get; } + /// + /// For fine-tuning jobs that have `failed`, this will contain more information on the cause of the + /// failure. + /// + public FineTuningJobError Error { get; } + } +} diff --git a/.dotnet/src/Generated/Models/FineTuningJobError.Serialization.cs b/.dotnet/src/Generated/Models/FineTuningJobError.Serialization.cs new file mode 100644 index 000000000..e586868e7 --- /dev/null +++ b/.dotnet/src/Generated/Models/FineTuningJobError.Serialization.cs @@ -0,0 +1,169 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class FineTuningJobError : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(FineTuningJobError)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + if (OptionalProperty.IsDefined(Message)) + { + writer.WritePropertyName("message"u8); + writer.WriteStringValue(Message); + } + if (OptionalProperty.IsDefined(Code)) + { + writer.WritePropertyName("code"u8); + writer.WriteStringValue(Code); + } + if (OptionalProperty.IsDefined(Param)) + { + if (Param != null) + { + writer.WritePropertyName("param"u8); + writer.WriteStringValue(Param); + } + else + { + writer.WriteNull("param"); + } + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + FineTuningJobError IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(FineTuningJobError)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeFineTuningJobError(document.RootElement, options); + } + + internal static FineTuningJobError DeserializeFineTuningJobError(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + OptionalProperty message = default; + OptionalProperty code = default; + OptionalProperty param = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("message"u8)) + { + message = property.Value.GetString(); + continue; + } + if (property.NameEquals("code"u8)) + { + code = property.Value.GetString(); + continue; + } + if (property.NameEquals("param"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + param = null; + continue; + } + param = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new FineTuningJobError(message.Value, code.Value, param.Value, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(FineTuningJobError)} does not support '{options.Format}' format."); + } + } + + FineTuningJobError IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeFineTuningJobError(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(FineTuningJobError)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static FineTuningJobError FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeFineTuningJobError(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/FineTuningJobError.cs b/.dotnet/src/Generated/Models/FineTuningJobError.cs new file mode 100644 index 000000000..9b5b27e34 --- /dev/null +++ b/.dotnet/src/Generated/Models/FineTuningJobError.cs @@ -0,0 +1,76 @@ +// + +#nullable disable + +using System; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The FineTuningJobError. + public partial class FineTuningJobError + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + internal FineTuningJobError() + { + } + + /// Initializes a new instance of . + /// A human-readable error message. + /// A machine-readable error code. + /// + /// The parameter that was invalid, usually `training_file` or `validation_file`. This field + /// will be null if the failure was not parameter-specific. + /// + /// Keeps track of any properties unknown to the library. + internal FineTuningJobError(string message, string code, string param, IDictionary serializedAdditionalRawData) + { + Message = message; + Code = code; + Param = param; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// A human-readable error message. + public string Message { get; } + /// A machine-readable error code. + public string Code { get; } + /// + /// The parameter that was invalid, usually `training_file` or `validation_file`. This field + /// will be null if the failure was not parameter-specific. + /// + public string Param { get; } + } +} diff --git a/.dotnet/src/Generated/Models/FineTuningJobEvent.Serialization.cs b/.dotnet/src/Generated/Models/FineTuningJobEvent.Serialization.cs new file mode 100644 index 000000000..20bb7a0fa --- /dev/null +++ b/.dotnet/src/Generated/Models/FineTuningJobEvent.Serialization.cs @@ -0,0 +1,164 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class FineTuningJobEvent : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(FineTuningJobEvent)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("id"u8); + writer.WriteStringValue(Id); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object); + writer.WritePropertyName("created_at"u8); + writer.WriteNumberValue(CreatedAt, "U"); + writer.WritePropertyName("level"u8); + writer.WriteStringValue(Level.ToString()); + writer.WritePropertyName("message"u8); + writer.WriteStringValue(Message); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + FineTuningJobEvent IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(FineTuningJobEvent)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeFineTuningJobEvent(document.RootElement, options); + } + + internal static FineTuningJobEvent DeserializeFineTuningJobEvent(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string id = default; + string @object = default; + DateTimeOffset createdAt = default; + FineTuningJobEventLevel level = default; + string message = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetString(); + continue; + } + if (property.NameEquals("object"u8)) + { + @object = property.Value.GetString(); + continue; + } + if (property.NameEquals("created_at"u8)) + { + createdAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); + continue; + } + if (property.NameEquals("level"u8)) + { + level = new FineTuningJobEventLevel(property.Value.GetString()); + continue; + } + if (property.NameEquals("message"u8)) + { + message = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new FineTuningJobEvent(id, @object, createdAt, level, message, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(FineTuningJobEvent)} does not support '{options.Format}' format."); + } + } + + FineTuningJobEvent IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeFineTuningJobEvent(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(FineTuningJobEvent)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static FineTuningJobEvent FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeFineTuningJobEvent(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/FineTuningJobEvent.cs b/.dotnet/src/Generated/Models/FineTuningJobEvent.cs new file mode 100644 index 000000000..a65270a76 --- /dev/null +++ b/.dotnet/src/Generated/Models/FineTuningJobEvent.cs @@ -0,0 +1,99 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The FineTuningJobEvent. + public partial class FineTuningJobEvent + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// + /// + /// + /// + /// , or is null. + internal FineTuningJobEvent(string id, string @object, DateTimeOffset createdAt, FineTuningJobEventLevel level, string message) + { + ClientUtilities.AssertNotNull(id, nameof(id)); + ClientUtilities.AssertNotNull(@object, nameof(@object)); + ClientUtilities.AssertNotNull(message, nameof(message)); + + Id = id; + Object = @object; + CreatedAt = createdAt; + Level = level; + Message = message; + } + + /// Initializes a new instance of . + /// + /// + /// + /// + /// + /// Keeps track of any properties unknown to the library. + internal FineTuningJobEvent(string id, string @object, DateTimeOffset createdAt, FineTuningJobEventLevel level, string message, IDictionary serializedAdditionalRawData) + { + Id = id; + Object = @object; + CreatedAt = createdAt; + Level = level; + Message = message; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal FineTuningJobEvent() + { + } + + /// Gets the id. + public string Id { get; } + /// Gets the object. + public string Object { get; } + /// Gets the created at. + public DateTimeOffset CreatedAt { get; } + /// Gets the level. + public FineTuningJobEventLevel Level { get; } + /// Gets the message. + public string Message { get; } + } +} diff --git a/.dotnet/src/Generated/Models/FineTuningJobEventLevel.cs b/.dotnet/src/Generated/Models/FineTuningJobEventLevel.cs new file mode 100644 index 000000000..7ac7da4c5 --- /dev/null +++ b/.dotnet/src/Generated/Models/FineTuningJobEventLevel.cs @@ -0,0 +1,51 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for level in FineTuningJobEvent. + public readonly partial struct FineTuningJobEventLevel : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public FineTuningJobEventLevel(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string InfoValue = "info"; + private const string WarnValue = "warn"; + private const string ErrorValue = "error"; + + /// info. + public static FineTuningJobEventLevel Info { get; } = new FineTuningJobEventLevel(InfoValue); + /// warn. + public static FineTuningJobEventLevel Warn { get; } = new FineTuningJobEventLevel(WarnValue); + /// error. + public static FineTuningJobEventLevel Error { get; } = new FineTuningJobEventLevel(ErrorValue); + /// Determines if two values are the same. + public static bool operator ==(FineTuningJobEventLevel left, FineTuningJobEventLevel right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(FineTuningJobEventLevel left, FineTuningJobEventLevel right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator FineTuningJobEventLevel(string value) => new FineTuningJobEventLevel(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is FineTuningJobEventLevel other && Equals(other); + /// + public bool Equals(FineTuningJobEventLevel other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.Serialization.cs b/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.Serialization.cs new file mode 100644 index 000000000..8e4802d8a --- /dev/null +++ b/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.Serialization.cs @@ -0,0 +1,146 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class FineTuningJobHyperparameters : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(FineTuningJobHyperparameters)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + if (OptionalProperty.IsDefined(NEpochs)) + { + writer.WritePropertyName("n_epochs"u8); +#if NET6_0_OR_GREATER + writer.WriteRawValue(NEpochs); +#else + using (JsonDocument document = JsonDocument.Parse(NEpochs)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + FineTuningJobHyperparameters IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(FineTuningJobHyperparameters)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeFineTuningJobHyperparameters(document.RootElement, options); + } + + internal static FineTuningJobHyperparameters DeserializeFineTuningJobHyperparameters(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + OptionalProperty nEpochs = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("n_epochs"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + nEpochs = BinaryData.FromString(property.Value.GetRawText()); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new FineTuningJobHyperparameters(nEpochs.Value, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(FineTuningJobHyperparameters)} does not support '{options.Format}' format."); + } + } + + FineTuningJobHyperparameters IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeFineTuningJobHyperparameters(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(FineTuningJobHyperparameters)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static FineTuningJobHyperparameters FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeFineTuningJobHyperparameters(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.cs b/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.cs new file mode 100644 index 000000000..efcb91d25 --- /dev/null +++ b/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.cs @@ -0,0 +1,112 @@ +// + +#nullable disable + +using System; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The FineTuningJobHyperparameters. + public partial class FineTuningJobHyperparameters + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + internal FineTuningJobHyperparameters() + { + } + + /// Initializes a new instance of . + /// + /// The number of epochs to train the model for. An epoch refers to one full cycle through the + /// training dataset. + /// + /// "Auto" decides the optimal number of epochs based on the size of the dataset. If setting the + /// number manually, we support any number between 1 and 50 epochs. + /// + /// Keeps track of any properties unknown to the library. + internal FineTuningJobHyperparameters(BinaryData nEpochs, IDictionary serializedAdditionalRawData) + { + NEpochs = nEpochs; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// + /// The number of epochs to train the model for. An epoch refers to one full cycle through the + /// training dataset. + /// + /// "Auto" decides the optimal number of epochs based on the size of the dataset. If setting the + /// number manually, we support any number between 1 and 50 epochs. + /// + /// To assign an object to this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// + /// Supported types: + /// + /// + /// "auto" + /// + /// + /// + /// + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + public BinaryData NEpochs { get; } + } +} diff --git a/.dotnet/src/Generated/Models/FineTuningJobObject.cs b/.dotnet/src/Generated/Models/FineTuningJobObject.cs new file mode 100644 index 000000000..cae76bffa --- /dev/null +++ b/.dotnet/src/Generated/Models/FineTuningJobObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The FineTuningJob_object. + public readonly partial struct FineTuningJobObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public FineTuningJobObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string FineTuningJobValue = "fine_tuning.job"; + + /// fine_tuning.job. + public static FineTuningJobObject FineTuningJob { get; } = new FineTuningJobObject(FineTuningJobValue); + /// Determines if two values are the same. + public static bool operator ==(FineTuningJobObject left, FineTuningJobObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(FineTuningJobObject left, FineTuningJobObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator FineTuningJobObject(string value) => new FineTuningJobObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is FineTuningJobObject other && Equals(other); + /// + public bool Equals(FineTuningJobObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/FineTuningJobStatus.cs b/.dotnet/src/Generated/Models/FineTuningJobStatus.cs new file mode 100644 index 000000000..23924df4f --- /dev/null +++ b/.dotnet/src/Generated/Models/FineTuningJobStatus.cs @@ -0,0 +1,60 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for status in FineTuningJob. + public readonly partial struct FineTuningJobStatus : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public FineTuningJobStatus(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string CreatedValue = "created"; + private const string PendingValue = "pending"; + private const string RunningValue = "running"; + private const string SucceededValue = "succeeded"; + private const string FailedValue = "failed"; + private const string CancelledValue = "cancelled"; + + /// created. + public static FineTuningJobStatus Created { get; } = new FineTuningJobStatus(CreatedValue); + /// pending. + public static FineTuningJobStatus Pending { get; } = new FineTuningJobStatus(PendingValue); + /// running. + public static FineTuningJobStatus Running { get; } = new FineTuningJobStatus(RunningValue); + /// succeeded. + public static FineTuningJobStatus Succeeded { get; } = new FineTuningJobStatus(SucceededValue); + /// failed. + public static FineTuningJobStatus Failed { get; } = new FineTuningJobStatus(FailedValue); + /// cancelled. + public static FineTuningJobStatus Cancelled { get; } = new FineTuningJobStatus(CancelledValue); + /// Determines if two values are the same. + public static bool operator ==(FineTuningJobStatus left, FineTuningJobStatus right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(FineTuningJobStatus left, FineTuningJobStatus right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator FineTuningJobStatus(string value) => new FineTuningJobStatus(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is FineTuningJobStatus other && Equals(other); + /// + public bool Equals(FineTuningJobStatus other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/FunctionObject.Serialization.cs b/.dotnet/src/Generated/Models/FunctionObject.Serialization.cs new file mode 100644 index 000000000..99d391fea --- /dev/null +++ b/.dotnet/src/Generated/Models/FunctionObject.Serialization.cs @@ -0,0 +1,158 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class FunctionObject : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(FunctionObject)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + if (OptionalProperty.IsDefined(Description)) + { + writer.WritePropertyName("description"u8); + writer.WriteStringValue(Description); + } + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + if (OptionalProperty.IsDefined(Parameters)) + { + writer.WritePropertyName("parameters"u8); + writer.WriteObjectValue(Parameters); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + FunctionObject IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(FunctionObject)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeFunctionObject(document.RootElement, options); + } + + internal static FunctionObject DeserializeFunctionObject(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + OptionalProperty description = default; + string name = default; + OptionalProperty parameters = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("description"u8)) + { + description = property.Value.GetString(); + continue; + } + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("parameters"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + parameters = FunctionParameters.DeserializeFunctionParameters(property.Value); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new FunctionObject(description.Value, name, parameters.Value, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(FunctionObject)} does not support '{options.Format}' format."); + } + } + + FunctionObject IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeFunctionObject(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(FunctionObject)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static FunctionObject FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeFunctionObject(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/FunctionObject.cs b/.dotnet/src/Generated/Models/FunctionObject.cs new file mode 100644 index 000000000..00e9c8cdb --- /dev/null +++ b/.dotnet/src/Generated/Models/FunctionObject.cs @@ -0,0 +1,96 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The FunctionObject. + public partial class FunctionObject + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and + /// dashes, with a maximum length of 64. + /// + /// is null. + public FunctionObject(string name) + { + ClientUtilities.AssertNotNull(name, nameof(name)); + + Name = name; + } + + /// Initializes a new instance of . + /// + /// A description of what the function does, used by the model to choose when and how to call the + /// function. + /// + /// + /// The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and + /// dashes, with a maximum length of 64. + /// + /// + /// Keeps track of any properties unknown to the library. + internal FunctionObject(string description, string name, FunctionParameters parameters, IDictionary serializedAdditionalRawData) + { + Description = description; + Name = name; + Parameters = parameters; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal FunctionObject() + { + } + + /// + /// A description of what the function does, used by the model to choose when and how to call the + /// function. + /// + public string Description { get; set; } + /// + /// The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and + /// dashes, with a maximum length of 64. + /// + public string Name { get; set; } + /// Gets or sets the parameters. + public FunctionParameters Parameters { get; set; } + } +} diff --git a/.dotnet/src/Generated/Models/FunctionParameters.Serialization.cs b/.dotnet/src/Generated/Models/FunctionParameters.Serialization.cs new file mode 100644 index 000000000..e6f167ed4 --- /dev/null +++ b/.dotnet/src/Generated/Models/FunctionParameters.Serialization.cs @@ -0,0 +1,118 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class FunctionParameters : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(FunctionParameters)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + foreach (var item in AdditionalProperties) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + writer.WriteEndObject(); + } + + FunctionParameters IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(FunctionParameters)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeFunctionParameters(document.RootElement, options); + } + + internal static FunctionParameters DeserializeFunctionParameters(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + IDictionary additionalProperties = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + additionalProperties = additionalPropertiesDictionary; + return new FunctionParameters(additionalProperties); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(FunctionParameters)} does not support '{options.Format}' format."); + } + } + + FunctionParameters IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeFunctionParameters(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(FunctionParameters)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static FunctionParameters FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeFunctionParameters(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/FunctionParameters.cs b/.dotnet/src/Generated/Models/FunctionParameters.cs new file mode 100644 index 000000000..ae3100e0d --- /dev/null +++ b/.dotnet/src/Generated/Models/FunctionParameters.cs @@ -0,0 +1,65 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// + /// The parameters the functions accepts, described as a JSON Schema object. See the + /// [guide](/docs/guides/gpt/function-calling) for examples, and the + /// [JSON Schema reference](https://json-schema.org/understanding-json-schema/) for documentation + /// about the format.\n\nTo describe a function that accepts no parameters, provide the value + /// `{\"type\": \"object\", \"properties\": {}}`. + /// + public partial class FunctionParameters + { + /// Initializes a new instance of . + public FunctionParameters() + { + AdditionalProperties = new OptionalDictionary(); + } + + /// Initializes a new instance of . + /// Additional Properties. + internal FunctionParameters(IDictionary additionalProperties) + { + AdditionalProperties = additionalProperties; + } + + /// + /// Additional Properties + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + public IDictionary AdditionalProperties { get; } + } +} diff --git a/.dotnet/src/Generated/Models/Image.Serialization.cs b/.dotnet/src/Generated/Models/Image.Serialization.cs new file mode 100644 index 000000000..209416ec1 --- /dev/null +++ b/.dotnet/src/Generated/Models/Image.Serialization.cs @@ -0,0 +1,165 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class Image : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(Image)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + if (OptionalProperty.IsDefined(B64Json)) + { + writer.WritePropertyName("b64_json"u8); + writer.WriteBase64StringValue(B64Json.ToArray(), "D"); + } + if (OptionalProperty.IsDefined(Url)) + { + writer.WritePropertyName("url"u8); + writer.WriteStringValue(Url.AbsoluteUri); + } + if (OptionalProperty.IsDefined(RevisedPrompt)) + { + writer.WritePropertyName("revised_prompt"u8); + writer.WriteStringValue(RevisedPrompt); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + Image IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(Image)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeImage(document.RootElement, options); + } + + internal static Image DeserializeImage(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + OptionalProperty b64Json = default; + OptionalProperty url = default; + OptionalProperty revisedPrompt = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("b64_json"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + b64Json = BinaryData.FromBytes(property.Value.GetBytesFromBase64("D")); + continue; + } + if (property.NameEquals("url"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + url = new Uri(property.Value.GetString()); + continue; + } + if (property.NameEquals("revised_prompt"u8)) + { + revisedPrompt = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new Image(b64Json.Value, url.Value, revisedPrompt.Value, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(Image)} does not support '{options.Format}' format."); + } + } + + Image IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeImage(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(Image)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static Image FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeImage(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/Image.cs b/.dotnet/src/Generated/Models/Image.cs new file mode 100644 index 000000000..a813097a2 --- /dev/null +++ b/.dotnet/src/Generated/Models/Image.cs @@ -0,0 +1,85 @@ +// + +#nullable disable + +using System; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// Represents the url or the content of an image generated by the OpenAI API. + public partial class Image + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + internal Image() + { + } + + /// Initializes a new instance of . + /// The base64-encoded JSON of the generated image, if `response_format` is `b64_json`. + /// The URL of the generated image, if `response_format` is `url` (default). + /// The prompt that was used to generate the image, if there was any revision to the prompt. + /// Keeps track of any properties unknown to the library. + internal Image(BinaryData b64Json, Uri url, string revisedPrompt, IDictionary serializedAdditionalRawData) + { + B64Json = b64Json; + Url = url; + RevisedPrompt = revisedPrompt; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// + /// The base64-encoded JSON of the generated image, if `response_format` is `b64_json`. + /// + /// To assign a byte[] to this property use . + /// The byte[] will be serialized to a Base64 encoded string. + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromBytes(new byte[] { 1, 2, 3 }) + /// Creates a payload of "AQID". + /// + /// + /// + /// + public BinaryData B64Json { get; } + /// The URL of the generated image, if `response_format` is `url` (default). + public Uri Url { get; } + /// The prompt that was used to generate the image, if there was any revision to the prompt. + public string RevisedPrompt { get; } + } +} diff --git a/.dotnet/src/Generated/Models/ImagesResponse.Serialization.cs b/.dotnet/src/Generated/Models/ImagesResponse.Serialization.cs new file mode 100644 index 000000000..6d3955c84 --- /dev/null +++ b/.dotnet/src/Generated/Models/ImagesResponse.Serialization.cs @@ -0,0 +1,150 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class ImagesResponse : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ImagesResponse)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("created"u8); + writer.WriteNumberValue(Created, "U"); + writer.WritePropertyName("data"u8); + writer.WriteStartArray(); + foreach (var item in Data) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ImagesResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ImagesResponse)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeImagesResponse(document.RootElement, options); + } + + internal static ImagesResponse DeserializeImagesResponse(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + DateTimeOffset created = default; + IReadOnlyList data = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("created"u8)) + { + created = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); + continue; + } + if (property.NameEquals("data"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(Image.DeserializeImage(item)); + } + data = array; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ImagesResponse(created, data, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ImagesResponse)} does not support '{options.Format}' format."); + } + } + + ImagesResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeImagesResponse(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ImagesResponse)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ImagesResponse FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeImagesResponse(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ImagesResponse.cs b/.dotnet/src/Generated/Models/ImagesResponse.cs new file mode 100644 index 000000000..d3c377be9 --- /dev/null +++ b/.dotnet/src/Generated/Models/ImagesResponse.cs @@ -0,0 +1,80 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// The ImagesResponse. + public partial class ImagesResponse + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// + /// is null. + internal ImagesResponse(DateTimeOffset created, IEnumerable data) + { + ClientUtilities.AssertNotNull(data, nameof(data)); + + Created = created; + Data = data.ToList(); + } + + /// Initializes a new instance of . + /// + /// + /// Keeps track of any properties unknown to the library. + internal ImagesResponse(DateTimeOffset created, IReadOnlyList data, IDictionary serializedAdditionalRawData) + { + Created = created; + Data = data; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal ImagesResponse() + { + } + + /// Gets the created. + public DateTimeOffset Created { get; } + /// Gets the data. + public IReadOnlyList Data { get; } + } +} diff --git a/.dotnet/src/Generated/Models/ListAssistantFilesResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListAssistantFilesResponse.Serialization.cs new file mode 100644 index 000000000..d1bb15a51 --- /dev/null +++ b/.dotnet/src/Generated/Models/ListAssistantFilesResponse.Serialization.cs @@ -0,0 +1,174 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class ListAssistantFilesResponse : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ListAssistantFilesResponse)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + writer.WritePropertyName("data"u8); + writer.WriteStartArray(); + foreach (var item in Data) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + writer.WritePropertyName("first_id"u8); + writer.WriteStringValue(FirstId); + writer.WritePropertyName("last_id"u8); + writer.WriteStringValue(LastId); + writer.WritePropertyName("has_more"u8); + writer.WriteBooleanValue(HasMore); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ListAssistantFilesResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ListAssistantFilesResponse)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeListAssistantFilesResponse(document.RootElement, options); + } + + internal static ListAssistantFilesResponse DeserializeListAssistantFilesResponse(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + ListAssistantFilesResponseObject @object = default; + IReadOnlyList data = default; + string firstId = default; + string lastId = default; + bool hasMore = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("object"u8)) + { + @object = new ListAssistantFilesResponseObject(property.Value.GetString()); + continue; + } + if (property.NameEquals("data"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(AssistantFileObject.DeserializeAssistantFileObject(item)); + } + data = array; + continue; + } + if (property.NameEquals("first_id"u8)) + { + firstId = property.Value.GetString(); + continue; + } + if (property.NameEquals("last_id"u8)) + { + lastId = property.Value.GetString(); + continue; + } + if (property.NameEquals("has_more"u8)) + { + hasMore = property.Value.GetBoolean(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ListAssistantFilesResponse(@object, data, firstId, lastId, hasMore, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ListAssistantFilesResponse)} does not support '{options.Format}' format."); + } + } + + ListAssistantFilesResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeListAssistantFilesResponse(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ListAssistantFilesResponse)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ListAssistantFilesResponse FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeListAssistantFilesResponse(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ListAssistantFilesResponse.cs b/.dotnet/src/Generated/Models/ListAssistantFilesResponse.cs new file mode 100644 index 000000000..d155bf3e6 --- /dev/null +++ b/.dotnet/src/Generated/Models/ListAssistantFilesResponse.cs @@ -0,0 +1,99 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// The ListAssistantFilesResponse. + public partial class ListAssistantFilesResponse + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// + /// + /// + /// , or is null. + internal ListAssistantFilesResponse(IEnumerable data, string firstId, string lastId, bool hasMore) + { + ClientUtilities.AssertNotNull(data, nameof(data)); + ClientUtilities.AssertNotNull(firstId, nameof(firstId)); + ClientUtilities.AssertNotNull(lastId, nameof(lastId)); + + Data = data.ToList(); + FirstId = firstId; + LastId = lastId; + HasMore = hasMore; + } + + /// Initializes a new instance of . + /// + /// + /// + /// + /// + /// Keeps track of any properties unknown to the library. + internal ListAssistantFilesResponse(ListAssistantFilesResponseObject @object, IReadOnlyList data, string firstId, string lastId, bool hasMore, IDictionary serializedAdditionalRawData) + { + Object = @object; + Data = data; + FirstId = firstId; + LastId = lastId; + HasMore = hasMore; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal ListAssistantFilesResponse() + { + } + + /// Gets the object. + public ListAssistantFilesResponseObject Object { get; } = ListAssistantFilesResponseObject.List; + + /// Gets the data. + public IReadOnlyList Data { get; } + /// Gets the first id. + public string FirstId { get; } + /// Gets the last id. + public string LastId { get; } + /// Gets the has more. + public bool HasMore { get; } + } +} diff --git a/.dotnet/src/Generated/Models/ListAssistantFilesResponseObject.cs b/.dotnet/src/Generated/Models/ListAssistantFilesResponseObject.cs new file mode 100644 index 000000000..5038ede26 --- /dev/null +++ b/.dotnet/src/Generated/Models/ListAssistantFilesResponseObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The ListAssistantFilesResponse_object. + public readonly partial struct ListAssistantFilesResponseObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public ListAssistantFilesResponseObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string ListValue = "list"; + + /// list. + public static ListAssistantFilesResponseObject List { get; } = new ListAssistantFilesResponseObject(ListValue); + /// Determines if two values are the same. + public static bool operator ==(ListAssistantFilesResponseObject left, ListAssistantFilesResponseObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(ListAssistantFilesResponseObject left, ListAssistantFilesResponseObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator ListAssistantFilesResponseObject(string value) => new ListAssistantFilesResponseObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is ListAssistantFilesResponseObject other && Equals(other); + /// + public bool Equals(ListAssistantFilesResponseObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/ListAssistantsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListAssistantsResponse.Serialization.cs new file mode 100644 index 000000000..f9c0b12b6 --- /dev/null +++ b/.dotnet/src/Generated/Models/ListAssistantsResponse.Serialization.cs @@ -0,0 +1,174 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class ListAssistantsResponse : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ListAssistantsResponse)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + writer.WritePropertyName("data"u8); + writer.WriteStartArray(); + foreach (var item in Data) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + writer.WritePropertyName("first_id"u8); + writer.WriteStringValue(FirstId); + writer.WritePropertyName("last_id"u8); + writer.WriteStringValue(LastId); + writer.WritePropertyName("has_more"u8); + writer.WriteBooleanValue(HasMore); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ListAssistantsResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ListAssistantsResponse)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeListAssistantsResponse(document.RootElement, options); + } + + internal static ListAssistantsResponse DeserializeListAssistantsResponse(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + ListAssistantsResponseObject @object = default; + IReadOnlyList data = default; + string firstId = default; + string lastId = default; + bool hasMore = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("object"u8)) + { + @object = new ListAssistantsResponseObject(property.Value.GetString()); + continue; + } + if (property.NameEquals("data"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(AssistantObject.DeserializeAssistantObject(item)); + } + data = array; + continue; + } + if (property.NameEquals("first_id"u8)) + { + firstId = property.Value.GetString(); + continue; + } + if (property.NameEquals("last_id"u8)) + { + lastId = property.Value.GetString(); + continue; + } + if (property.NameEquals("has_more"u8)) + { + hasMore = property.Value.GetBoolean(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ListAssistantsResponse(@object, data, firstId, lastId, hasMore, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ListAssistantsResponse)} does not support '{options.Format}' format."); + } + } + + ListAssistantsResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeListAssistantsResponse(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ListAssistantsResponse)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ListAssistantsResponse FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeListAssistantsResponse(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ListAssistantsResponse.cs b/.dotnet/src/Generated/Models/ListAssistantsResponse.cs new file mode 100644 index 000000000..002b27f3f --- /dev/null +++ b/.dotnet/src/Generated/Models/ListAssistantsResponse.cs @@ -0,0 +1,99 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// The ListAssistantsResponse. + public partial class ListAssistantsResponse + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// + /// + /// + /// , or is null. + internal ListAssistantsResponse(IEnumerable data, string firstId, string lastId, bool hasMore) + { + ClientUtilities.AssertNotNull(data, nameof(data)); + ClientUtilities.AssertNotNull(firstId, nameof(firstId)); + ClientUtilities.AssertNotNull(lastId, nameof(lastId)); + + Data = data.ToList(); + FirstId = firstId; + LastId = lastId; + HasMore = hasMore; + } + + /// Initializes a new instance of . + /// + /// + /// + /// + /// + /// Keeps track of any properties unknown to the library. + internal ListAssistantsResponse(ListAssistantsResponseObject @object, IReadOnlyList data, string firstId, string lastId, bool hasMore, IDictionary serializedAdditionalRawData) + { + Object = @object; + Data = data; + FirstId = firstId; + LastId = lastId; + HasMore = hasMore; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal ListAssistantsResponse() + { + } + + /// Gets the object. + public ListAssistantsResponseObject Object { get; } = ListAssistantsResponseObject.List; + + /// Gets the data. + public IReadOnlyList Data { get; } + /// Gets the first id. + public string FirstId { get; } + /// Gets the last id. + public string LastId { get; } + /// Gets the has more. + public bool HasMore { get; } + } +} diff --git a/.dotnet/src/Generated/Models/ListAssistantsResponseObject.cs b/.dotnet/src/Generated/Models/ListAssistantsResponseObject.cs new file mode 100644 index 000000000..5bbc18a2b --- /dev/null +++ b/.dotnet/src/Generated/Models/ListAssistantsResponseObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The ListAssistantsResponse_object. + public readonly partial struct ListAssistantsResponseObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public ListAssistantsResponseObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string ListValue = "list"; + + /// list. + public static ListAssistantsResponseObject List { get; } = new ListAssistantsResponseObject(ListValue); + /// Determines if two values are the same. + public static bool operator ==(ListAssistantsResponseObject left, ListAssistantsResponseObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(ListAssistantsResponseObject left, ListAssistantsResponseObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator ListAssistantsResponseObject(string value) => new ListAssistantsResponseObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is ListAssistantsResponseObject other && Equals(other); + /// + public bool Equals(ListAssistantsResponseObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/ListFilesResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListFilesResponse.Serialization.cs new file mode 100644 index 000000000..a580904af --- /dev/null +++ b/.dotnet/src/Generated/Models/ListFilesResponse.Serialization.cs @@ -0,0 +1,150 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class ListFilesResponse : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ListFilesResponse)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("data"u8); + writer.WriteStartArray(); + foreach (var item in Data) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ListFilesResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ListFilesResponse)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeListFilesResponse(document.RootElement, options); + } + + internal static ListFilesResponse DeserializeListFilesResponse(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + IReadOnlyList data = default; + ListFilesResponseObject @object = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("data"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(OpenAIFile.DeserializeOpenAIFile(item)); + } + data = array; + continue; + } + if (property.NameEquals("object"u8)) + { + @object = new ListFilesResponseObject(property.Value.GetString()); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ListFilesResponse(data, @object, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ListFilesResponse)} does not support '{options.Format}' format."); + } + } + + ListFilesResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeListFilesResponse(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ListFilesResponse)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ListFilesResponse FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeListFilesResponse(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ListFilesResponse.cs b/.dotnet/src/Generated/Models/ListFilesResponse.cs new file mode 100644 index 000000000..0738efe8d --- /dev/null +++ b/.dotnet/src/Generated/Models/ListFilesResponse.cs @@ -0,0 +1,78 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// The ListFilesResponse. + public partial class ListFilesResponse + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// is null. + internal ListFilesResponse(IEnumerable data) + { + ClientUtilities.AssertNotNull(data, nameof(data)); + + Data = data.ToList(); + } + + /// Initializes a new instance of . + /// + /// + /// Keeps track of any properties unknown to the library. + internal ListFilesResponse(IReadOnlyList data, ListFilesResponseObject @object, IDictionary serializedAdditionalRawData) + { + Data = data; + Object = @object; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal ListFilesResponse() + { + } + + /// Gets the data. + public IReadOnlyList Data { get; } + /// Gets the object. + public ListFilesResponseObject Object { get; } = ListFilesResponseObject.List; + } +} diff --git a/.dotnet/src/Generated/Models/ListFilesResponseObject.cs b/.dotnet/src/Generated/Models/ListFilesResponseObject.cs new file mode 100644 index 000000000..ef68e3dda --- /dev/null +++ b/.dotnet/src/Generated/Models/ListFilesResponseObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The ListFilesResponse_object. + public readonly partial struct ListFilesResponseObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public ListFilesResponseObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string ListValue = "list"; + + /// list. + public static ListFilesResponseObject List { get; } = new ListFilesResponseObject(ListValue); + /// Determines if two values are the same. + public static bool operator ==(ListFilesResponseObject left, ListFilesResponseObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(ListFilesResponseObject left, ListFilesResponseObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator ListFilesResponseObject(string value) => new ListFilesResponseObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is ListFilesResponseObject other && Equals(other); + /// + public bool Equals(ListFilesResponseObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/ListFineTuneEventsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListFineTuneEventsResponse.Serialization.cs new file mode 100644 index 000000000..bd3431eed --- /dev/null +++ b/.dotnet/src/Generated/Models/ListFineTuneEventsResponse.Serialization.cs @@ -0,0 +1,150 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class ListFineTuneEventsResponse : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ListFineTuneEventsResponse)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object); + writer.WritePropertyName("data"u8); + writer.WriteStartArray(); + foreach (var item in Data) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ListFineTuneEventsResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ListFineTuneEventsResponse)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeListFineTuneEventsResponse(document.RootElement, options); + } + + internal static ListFineTuneEventsResponse DeserializeListFineTuneEventsResponse(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string @object = default; + IReadOnlyList data = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("object"u8)) + { + @object = property.Value.GetString(); + continue; + } + if (property.NameEquals("data"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(FineTuneEvent.DeserializeFineTuneEvent(item)); + } + data = array; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ListFineTuneEventsResponse(@object, data, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ListFineTuneEventsResponse)} does not support '{options.Format}' format."); + } + } + + ListFineTuneEventsResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeListFineTuneEventsResponse(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ListFineTuneEventsResponse)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ListFineTuneEventsResponse FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeListFineTuneEventsResponse(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ListFineTuneEventsResponse.cs b/.dotnet/src/Generated/Models/ListFineTuneEventsResponse.cs new file mode 100644 index 000000000..743f4ee68 --- /dev/null +++ b/.dotnet/src/Generated/Models/ListFineTuneEventsResponse.cs @@ -0,0 +1,81 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// The ListFineTuneEventsResponse. + public partial class ListFineTuneEventsResponse + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// + /// or is null. + internal ListFineTuneEventsResponse(string @object, IEnumerable data) + { + ClientUtilities.AssertNotNull(@object, nameof(@object)); + ClientUtilities.AssertNotNull(data, nameof(data)); + + Object = @object; + Data = data.ToList(); + } + + /// Initializes a new instance of . + /// + /// + /// Keeps track of any properties unknown to the library. + internal ListFineTuneEventsResponse(string @object, IReadOnlyList data, IDictionary serializedAdditionalRawData) + { + Object = @object; + Data = data; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal ListFineTuneEventsResponse() + { + } + + /// Gets the object. + public string Object { get; } + /// Gets the data. + public IReadOnlyList Data { get; } + } +} diff --git a/.dotnet/src/Generated/Models/ListFineTunesResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListFineTunesResponse.Serialization.cs new file mode 100644 index 000000000..bfd1f5cf9 --- /dev/null +++ b/.dotnet/src/Generated/Models/ListFineTunesResponse.Serialization.cs @@ -0,0 +1,150 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class ListFineTunesResponse : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ListFineTunesResponse)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object); + writer.WritePropertyName("data"u8); + writer.WriteStartArray(); + foreach (var item in Data) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ListFineTunesResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ListFineTunesResponse)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeListFineTunesResponse(document.RootElement, options); + } + + internal static ListFineTunesResponse DeserializeListFineTunesResponse(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string @object = default; + IReadOnlyList data = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("object"u8)) + { + @object = property.Value.GetString(); + continue; + } + if (property.NameEquals("data"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(FineTune.DeserializeFineTune(item)); + } + data = array; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ListFineTunesResponse(@object, data, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ListFineTunesResponse)} does not support '{options.Format}' format."); + } + } + + ListFineTunesResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeListFineTunesResponse(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ListFineTunesResponse)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ListFineTunesResponse FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeListFineTunesResponse(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ListFineTunesResponse.cs b/.dotnet/src/Generated/Models/ListFineTunesResponse.cs new file mode 100644 index 000000000..1355ef3be --- /dev/null +++ b/.dotnet/src/Generated/Models/ListFineTunesResponse.cs @@ -0,0 +1,81 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// The ListFineTunesResponse. + public partial class ListFineTunesResponse + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// + /// or is null. + internal ListFineTunesResponse(string @object, IEnumerable data) + { + ClientUtilities.AssertNotNull(@object, nameof(@object)); + ClientUtilities.AssertNotNull(data, nameof(data)); + + Object = @object; + Data = data.ToList(); + } + + /// Initializes a new instance of . + /// + /// + /// Keeps track of any properties unknown to the library. + internal ListFineTunesResponse(string @object, IReadOnlyList data, IDictionary serializedAdditionalRawData) + { + Object = @object; + Data = data; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal ListFineTunesResponse() + { + } + + /// Gets the object. + public string Object { get; } + /// Gets the data. + public IReadOnlyList Data { get; } + } +} diff --git a/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.Serialization.cs new file mode 100644 index 000000000..b141b423a --- /dev/null +++ b/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.Serialization.cs @@ -0,0 +1,150 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class ListFineTuningJobEventsResponse : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ListFineTuningJobEventsResponse)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object); + writer.WritePropertyName("data"u8); + writer.WriteStartArray(); + foreach (var item in Data) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ListFineTuningJobEventsResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ListFineTuningJobEventsResponse)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeListFineTuningJobEventsResponse(document.RootElement, options); + } + + internal static ListFineTuningJobEventsResponse DeserializeListFineTuningJobEventsResponse(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string @object = default; + IReadOnlyList data = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("object"u8)) + { + @object = property.Value.GetString(); + continue; + } + if (property.NameEquals("data"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(FineTuningJobEvent.DeserializeFineTuningJobEvent(item)); + } + data = array; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ListFineTuningJobEventsResponse(@object, data, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ListFineTuningJobEventsResponse)} does not support '{options.Format}' format."); + } + } + + ListFineTuningJobEventsResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeListFineTuningJobEventsResponse(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ListFineTuningJobEventsResponse)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ListFineTuningJobEventsResponse FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeListFineTuningJobEventsResponse(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.cs b/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.cs new file mode 100644 index 000000000..94573da09 --- /dev/null +++ b/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.cs @@ -0,0 +1,81 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// The ListFineTuningJobEventsResponse. + public partial class ListFineTuningJobEventsResponse + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// + /// or is null. + internal ListFineTuningJobEventsResponse(string @object, IEnumerable data) + { + ClientUtilities.AssertNotNull(@object, nameof(@object)); + ClientUtilities.AssertNotNull(data, nameof(data)); + + Object = @object; + Data = data.ToList(); + } + + /// Initializes a new instance of . + /// + /// + /// Keeps track of any properties unknown to the library. + internal ListFineTuningJobEventsResponse(string @object, IReadOnlyList data, IDictionary serializedAdditionalRawData) + { + Object = @object; + Data = data; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal ListFineTuningJobEventsResponse() + { + } + + /// Gets the object. + public string Object { get; } + /// Gets the data. + public IReadOnlyList Data { get; } + } +} diff --git a/.dotnet/src/Generated/Models/ListMessageFilesResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListMessageFilesResponse.Serialization.cs new file mode 100644 index 000000000..516a772d1 --- /dev/null +++ b/.dotnet/src/Generated/Models/ListMessageFilesResponse.Serialization.cs @@ -0,0 +1,174 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class ListMessageFilesResponse : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ListMessageFilesResponse)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + writer.WritePropertyName("data"u8); + writer.WriteStartArray(); + foreach (var item in Data) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + writer.WritePropertyName("first_id"u8); + writer.WriteStringValue(FirstId); + writer.WritePropertyName("last_id"u8); + writer.WriteStringValue(LastId); + writer.WritePropertyName("has_more"u8); + writer.WriteBooleanValue(HasMore); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ListMessageFilesResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ListMessageFilesResponse)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeListMessageFilesResponse(document.RootElement, options); + } + + internal static ListMessageFilesResponse DeserializeListMessageFilesResponse(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + ListMessageFilesResponseObject @object = default; + IReadOnlyList data = default; + string firstId = default; + string lastId = default; + bool hasMore = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("object"u8)) + { + @object = new ListMessageFilesResponseObject(property.Value.GetString()); + continue; + } + if (property.NameEquals("data"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(MessageFileObject.DeserializeMessageFileObject(item)); + } + data = array; + continue; + } + if (property.NameEquals("first_id"u8)) + { + firstId = property.Value.GetString(); + continue; + } + if (property.NameEquals("last_id"u8)) + { + lastId = property.Value.GetString(); + continue; + } + if (property.NameEquals("has_more"u8)) + { + hasMore = property.Value.GetBoolean(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ListMessageFilesResponse(@object, data, firstId, lastId, hasMore, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ListMessageFilesResponse)} does not support '{options.Format}' format."); + } + } + + ListMessageFilesResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeListMessageFilesResponse(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ListMessageFilesResponse)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ListMessageFilesResponse FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeListMessageFilesResponse(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ListMessageFilesResponse.cs b/.dotnet/src/Generated/Models/ListMessageFilesResponse.cs new file mode 100644 index 000000000..e4476c13a --- /dev/null +++ b/.dotnet/src/Generated/Models/ListMessageFilesResponse.cs @@ -0,0 +1,99 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// The ListMessageFilesResponse. + public partial class ListMessageFilesResponse + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// + /// + /// + /// , or is null. + internal ListMessageFilesResponse(IEnumerable data, string firstId, string lastId, bool hasMore) + { + ClientUtilities.AssertNotNull(data, nameof(data)); + ClientUtilities.AssertNotNull(firstId, nameof(firstId)); + ClientUtilities.AssertNotNull(lastId, nameof(lastId)); + + Data = data.ToList(); + FirstId = firstId; + LastId = lastId; + HasMore = hasMore; + } + + /// Initializes a new instance of . + /// + /// + /// + /// + /// + /// Keeps track of any properties unknown to the library. + internal ListMessageFilesResponse(ListMessageFilesResponseObject @object, IReadOnlyList data, string firstId, string lastId, bool hasMore, IDictionary serializedAdditionalRawData) + { + Object = @object; + Data = data; + FirstId = firstId; + LastId = lastId; + HasMore = hasMore; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal ListMessageFilesResponse() + { + } + + /// Gets the object. + public ListMessageFilesResponseObject Object { get; } = ListMessageFilesResponseObject.List; + + /// Gets the data. + public IReadOnlyList Data { get; } + /// Gets the first id. + public string FirstId { get; } + /// Gets the last id. + public string LastId { get; } + /// Gets the has more. + public bool HasMore { get; } + } +} diff --git a/.dotnet/src/Generated/Models/ListMessageFilesResponseObject.cs b/.dotnet/src/Generated/Models/ListMessageFilesResponseObject.cs new file mode 100644 index 000000000..da8016c77 --- /dev/null +++ b/.dotnet/src/Generated/Models/ListMessageFilesResponseObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The ListMessageFilesResponse_object. + public readonly partial struct ListMessageFilesResponseObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public ListMessageFilesResponseObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string ListValue = "list"; + + /// list. + public static ListMessageFilesResponseObject List { get; } = new ListMessageFilesResponseObject(ListValue); + /// Determines if two values are the same. + public static bool operator ==(ListMessageFilesResponseObject left, ListMessageFilesResponseObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(ListMessageFilesResponseObject left, ListMessageFilesResponseObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator ListMessageFilesResponseObject(string value) => new ListMessageFilesResponseObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is ListMessageFilesResponseObject other && Equals(other); + /// + public bool Equals(ListMessageFilesResponseObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/ListMessagesResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListMessagesResponse.Serialization.cs new file mode 100644 index 000000000..b68c46995 --- /dev/null +++ b/.dotnet/src/Generated/Models/ListMessagesResponse.Serialization.cs @@ -0,0 +1,174 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class ListMessagesResponse : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ListMessagesResponse)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + writer.WritePropertyName("data"u8); + writer.WriteStartArray(); + foreach (var item in Data) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + writer.WritePropertyName("first_id"u8); + writer.WriteStringValue(FirstId); + writer.WritePropertyName("last_id"u8); + writer.WriteStringValue(LastId); + writer.WritePropertyName("has_more"u8); + writer.WriteBooleanValue(HasMore); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ListMessagesResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ListMessagesResponse)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeListMessagesResponse(document.RootElement, options); + } + + internal static ListMessagesResponse DeserializeListMessagesResponse(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + ListMessagesResponseObject @object = default; + IReadOnlyList data = default; + string firstId = default; + string lastId = default; + bool hasMore = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("object"u8)) + { + @object = new ListMessagesResponseObject(property.Value.GetString()); + continue; + } + if (property.NameEquals("data"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(MessageObject.DeserializeMessageObject(item)); + } + data = array; + continue; + } + if (property.NameEquals("first_id"u8)) + { + firstId = property.Value.GetString(); + continue; + } + if (property.NameEquals("last_id"u8)) + { + lastId = property.Value.GetString(); + continue; + } + if (property.NameEquals("has_more"u8)) + { + hasMore = property.Value.GetBoolean(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ListMessagesResponse(@object, data, firstId, lastId, hasMore, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ListMessagesResponse)} does not support '{options.Format}' format."); + } + } + + ListMessagesResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeListMessagesResponse(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ListMessagesResponse)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ListMessagesResponse FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeListMessagesResponse(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ListMessagesResponse.cs b/.dotnet/src/Generated/Models/ListMessagesResponse.cs new file mode 100644 index 000000000..41193e112 --- /dev/null +++ b/.dotnet/src/Generated/Models/ListMessagesResponse.cs @@ -0,0 +1,99 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// The ListMessagesResponse. + public partial class ListMessagesResponse + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// + /// + /// + /// , or is null. + internal ListMessagesResponse(IEnumerable data, string firstId, string lastId, bool hasMore) + { + ClientUtilities.AssertNotNull(data, nameof(data)); + ClientUtilities.AssertNotNull(firstId, nameof(firstId)); + ClientUtilities.AssertNotNull(lastId, nameof(lastId)); + + Data = data.ToList(); + FirstId = firstId; + LastId = lastId; + HasMore = hasMore; + } + + /// Initializes a new instance of . + /// + /// + /// + /// + /// + /// Keeps track of any properties unknown to the library. + internal ListMessagesResponse(ListMessagesResponseObject @object, IReadOnlyList data, string firstId, string lastId, bool hasMore, IDictionary serializedAdditionalRawData) + { + Object = @object; + Data = data; + FirstId = firstId; + LastId = lastId; + HasMore = hasMore; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal ListMessagesResponse() + { + } + + /// Gets the object. + public ListMessagesResponseObject Object { get; } = ListMessagesResponseObject.List; + + /// Gets the data. + public IReadOnlyList Data { get; } + /// Gets the first id. + public string FirstId { get; } + /// Gets the last id. + public string LastId { get; } + /// Gets the has more. + public bool HasMore { get; } + } +} diff --git a/.dotnet/src/Generated/Models/ListMessagesResponseObject.cs b/.dotnet/src/Generated/Models/ListMessagesResponseObject.cs new file mode 100644 index 000000000..ff1303bf4 --- /dev/null +++ b/.dotnet/src/Generated/Models/ListMessagesResponseObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The ListMessagesResponse_object. + public readonly partial struct ListMessagesResponseObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public ListMessagesResponseObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string ListValue = "list"; + + /// list. + public static ListMessagesResponseObject List { get; } = new ListMessagesResponseObject(ListValue); + /// Determines if two values are the same. + public static bool operator ==(ListMessagesResponseObject left, ListMessagesResponseObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(ListMessagesResponseObject left, ListMessagesResponseObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator ListMessagesResponseObject(string value) => new ListMessagesResponseObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is ListMessagesResponseObject other && Equals(other); + /// + public bool Equals(ListMessagesResponseObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/ListModelsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListModelsResponse.Serialization.cs new file mode 100644 index 000000000..8a6dbd3a7 --- /dev/null +++ b/.dotnet/src/Generated/Models/ListModelsResponse.Serialization.cs @@ -0,0 +1,150 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class ListModelsResponse : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ListModelsResponse)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + writer.WritePropertyName("data"u8); + writer.WriteStartArray(); + foreach (var item in Data) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ListModelsResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ListModelsResponse)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeListModelsResponse(document.RootElement, options); + } + + internal static ListModelsResponse DeserializeListModelsResponse(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + ListModelsResponseObject @object = default; + IReadOnlyList data = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("object"u8)) + { + @object = new ListModelsResponseObject(property.Value.GetString()); + continue; + } + if (property.NameEquals("data"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(Model.DeserializeModel(item)); + } + data = array; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ListModelsResponse(@object, data, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ListModelsResponse)} does not support '{options.Format}' format."); + } + } + + ListModelsResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeListModelsResponse(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ListModelsResponse)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ListModelsResponse FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeListModelsResponse(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ListModelsResponse.cs b/.dotnet/src/Generated/Models/ListModelsResponse.cs new file mode 100644 index 000000000..bc2ddf1a7 --- /dev/null +++ b/.dotnet/src/Generated/Models/ListModelsResponse.cs @@ -0,0 +1,79 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// The ListModelsResponse. + public partial class ListModelsResponse + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// is null. + internal ListModelsResponse(IEnumerable data) + { + ClientUtilities.AssertNotNull(data, nameof(data)); + + Data = data.ToList(); + } + + /// Initializes a new instance of . + /// + /// + /// Keeps track of any properties unknown to the library. + internal ListModelsResponse(ListModelsResponseObject @object, IReadOnlyList data, IDictionary serializedAdditionalRawData) + { + Object = @object; + Data = data; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal ListModelsResponse() + { + } + + /// Gets the object. + public ListModelsResponseObject Object { get; } = ListModelsResponseObject.List; + + /// Gets the data. + public IReadOnlyList Data { get; } + } +} diff --git a/.dotnet/src/Generated/Models/ListModelsResponseObject.cs b/.dotnet/src/Generated/Models/ListModelsResponseObject.cs new file mode 100644 index 000000000..bb0127059 --- /dev/null +++ b/.dotnet/src/Generated/Models/ListModelsResponseObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The ListModelsResponse_object. + public readonly partial struct ListModelsResponseObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public ListModelsResponseObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string ListValue = "list"; + + /// list. + public static ListModelsResponseObject List { get; } = new ListModelsResponseObject(ListValue); + /// Determines if two values are the same. + public static bool operator ==(ListModelsResponseObject left, ListModelsResponseObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(ListModelsResponseObject left, ListModelsResponseObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator ListModelsResponseObject(string value) => new ListModelsResponseObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is ListModelsResponseObject other && Equals(other); + /// + public bool Equals(ListModelsResponseObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/ListOrder.cs b/.dotnet/src/Generated/Models/ListOrder.cs new file mode 100644 index 000000000..0343ac0f3 --- /dev/null +++ b/.dotnet/src/Generated/Models/ListOrder.cs @@ -0,0 +1,47 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + public readonly partial struct ListOrder : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public ListOrder(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string AscValue = "asc"; + private const string DescValue = "desc"; + + /// asc. + public static ListOrder Asc { get; } = new ListOrder(AscValue); + /// desc. + public static ListOrder Desc { get; } = new ListOrder(DescValue); + /// Determines if two values are the same. + public static bool operator ==(ListOrder left, ListOrder right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(ListOrder left, ListOrder right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator ListOrder(string value) => new ListOrder(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is ListOrder other && Equals(other); + /// + public bool Equals(ListOrder other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.Serialization.cs new file mode 100644 index 000000000..dd8425fb7 --- /dev/null +++ b/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.Serialization.cs @@ -0,0 +1,158 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class ListPaginatedFineTuningJobsResponse : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ListPaginatedFineTuningJobsResponse)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object); + writer.WritePropertyName("data"u8); + writer.WriteStartArray(); + foreach (var item in Data) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + writer.WritePropertyName("has_more"u8); + writer.WriteBooleanValue(HasMore); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ListPaginatedFineTuningJobsResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ListPaginatedFineTuningJobsResponse)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeListPaginatedFineTuningJobsResponse(document.RootElement, options); + } + + internal static ListPaginatedFineTuningJobsResponse DeserializeListPaginatedFineTuningJobsResponse(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string @object = default; + IReadOnlyList data = default; + bool hasMore = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("object"u8)) + { + @object = property.Value.GetString(); + continue; + } + if (property.NameEquals("data"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(FineTuningJob.DeserializeFineTuningJob(item)); + } + data = array; + continue; + } + if (property.NameEquals("has_more"u8)) + { + hasMore = property.Value.GetBoolean(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ListPaginatedFineTuningJobsResponse(@object, data, hasMore, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ListPaginatedFineTuningJobsResponse)} does not support '{options.Format}' format."); + } + } + + ListPaginatedFineTuningJobsResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeListPaginatedFineTuningJobsResponse(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ListPaginatedFineTuningJobsResponse)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ListPaginatedFineTuningJobsResponse FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeListPaginatedFineTuningJobsResponse(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.cs b/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.cs new file mode 100644 index 000000000..db1bf28f5 --- /dev/null +++ b/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.cs @@ -0,0 +1,87 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// The ListPaginatedFineTuningJobsResponse. + public partial class ListPaginatedFineTuningJobsResponse + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// + /// + /// or is null. + internal ListPaginatedFineTuningJobsResponse(string @object, IEnumerable data, bool hasMore) + { + ClientUtilities.AssertNotNull(@object, nameof(@object)); + ClientUtilities.AssertNotNull(data, nameof(data)); + + Object = @object; + Data = data.ToList(); + HasMore = hasMore; + } + + /// Initializes a new instance of . + /// + /// + /// + /// Keeps track of any properties unknown to the library. + internal ListPaginatedFineTuningJobsResponse(string @object, IReadOnlyList data, bool hasMore, IDictionary serializedAdditionalRawData) + { + Object = @object; + Data = data; + HasMore = hasMore; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal ListPaginatedFineTuningJobsResponse() + { + } + + /// Gets the object. + public string Object { get; } + /// Gets the data. + public IReadOnlyList Data { get; } + /// Gets the has more. + public bool HasMore { get; } + } +} diff --git a/.dotnet/src/Generated/Models/ListRunStepsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListRunStepsResponse.Serialization.cs new file mode 100644 index 000000000..3aa87a8a1 --- /dev/null +++ b/.dotnet/src/Generated/Models/ListRunStepsResponse.Serialization.cs @@ -0,0 +1,174 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class ListRunStepsResponse : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ListRunStepsResponse)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + writer.WritePropertyName("data"u8); + writer.WriteStartArray(); + foreach (var item in Data) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + writer.WritePropertyName("first_id"u8); + writer.WriteStringValue(FirstId); + writer.WritePropertyName("last_id"u8); + writer.WriteStringValue(LastId); + writer.WritePropertyName("has_more"u8); + writer.WriteBooleanValue(HasMore); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ListRunStepsResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ListRunStepsResponse)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeListRunStepsResponse(document.RootElement, options); + } + + internal static ListRunStepsResponse DeserializeListRunStepsResponse(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + ListRunStepsResponseObject @object = default; + IReadOnlyList data = default; + string firstId = default; + string lastId = default; + bool hasMore = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("object"u8)) + { + @object = new ListRunStepsResponseObject(property.Value.GetString()); + continue; + } + if (property.NameEquals("data"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(RunStepObject.DeserializeRunStepObject(item)); + } + data = array; + continue; + } + if (property.NameEquals("first_id"u8)) + { + firstId = property.Value.GetString(); + continue; + } + if (property.NameEquals("last_id"u8)) + { + lastId = property.Value.GetString(); + continue; + } + if (property.NameEquals("has_more"u8)) + { + hasMore = property.Value.GetBoolean(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ListRunStepsResponse(@object, data, firstId, lastId, hasMore, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ListRunStepsResponse)} does not support '{options.Format}' format."); + } + } + + ListRunStepsResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeListRunStepsResponse(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ListRunStepsResponse)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ListRunStepsResponse FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeListRunStepsResponse(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ListRunStepsResponse.cs b/.dotnet/src/Generated/Models/ListRunStepsResponse.cs new file mode 100644 index 000000000..1df4309d3 --- /dev/null +++ b/.dotnet/src/Generated/Models/ListRunStepsResponse.cs @@ -0,0 +1,99 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// The ListRunStepsResponse. + public partial class ListRunStepsResponse + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// + /// + /// + /// , or is null. + internal ListRunStepsResponse(IEnumerable data, string firstId, string lastId, bool hasMore) + { + ClientUtilities.AssertNotNull(data, nameof(data)); + ClientUtilities.AssertNotNull(firstId, nameof(firstId)); + ClientUtilities.AssertNotNull(lastId, nameof(lastId)); + + Data = data.ToList(); + FirstId = firstId; + LastId = lastId; + HasMore = hasMore; + } + + /// Initializes a new instance of . + /// + /// + /// + /// + /// + /// Keeps track of any properties unknown to the library. + internal ListRunStepsResponse(ListRunStepsResponseObject @object, IReadOnlyList data, string firstId, string lastId, bool hasMore, IDictionary serializedAdditionalRawData) + { + Object = @object; + Data = data; + FirstId = firstId; + LastId = lastId; + HasMore = hasMore; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal ListRunStepsResponse() + { + } + + /// Gets the object. + public ListRunStepsResponseObject Object { get; } = ListRunStepsResponseObject.List; + + /// Gets the data. + public IReadOnlyList Data { get; } + /// Gets the first id. + public string FirstId { get; } + /// Gets the last id. + public string LastId { get; } + /// Gets the has more. + public bool HasMore { get; } + } +} diff --git a/.dotnet/src/Generated/Models/ListRunStepsResponseObject.cs b/.dotnet/src/Generated/Models/ListRunStepsResponseObject.cs new file mode 100644 index 000000000..043709495 --- /dev/null +++ b/.dotnet/src/Generated/Models/ListRunStepsResponseObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The ListRunStepsResponse_object. + public readonly partial struct ListRunStepsResponseObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public ListRunStepsResponseObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string ListValue = "list"; + + /// list. + public static ListRunStepsResponseObject List { get; } = new ListRunStepsResponseObject(ListValue); + /// Determines if two values are the same. + public static bool operator ==(ListRunStepsResponseObject left, ListRunStepsResponseObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(ListRunStepsResponseObject left, ListRunStepsResponseObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator ListRunStepsResponseObject(string value) => new ListRunStepsResponseObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is ListRunStepsResponseObject other && Equals(other); + /// + public bool Equals(ListRunStepsResponseObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/ListRunsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListRunsResponse.Serialization.cs new file mode 100644 index 000000000..d0705cd68 --- /dev/null +++ b/.dotnet/src/Generated/Models/ListRunsResponse.Serialization.cs @@ -0,0 +1,174 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class ListRunsResponse : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ListRunsResponse)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + writer.WritePropertyName("data"u8); + writer.WriteStartArray(); + foreach (var item in Data) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + writer.WritePropertyName("first_id"u8); + writer.WriteStringValue(FirstId); + writer.WritePropertyName("last_id"u8); + writer.WriteStringValue(LastId); + writer.WritePropertyName("has_more"u8); + writer.WriteBooleanValue(HasMore); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ListRunsResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ListRunsResponse)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeListRunsResponse(document.RootElement, options); + } + + internal static ListRunsResponse DeserializeListRunsResponse(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + ListRunsResponseObject @object = default; + IReadOnlyList data = default; + string firstId = default; + string lastId = default; + bool hasMore = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("object"u8)) + { + @object = new ListRunsResponseObject(property.Value.GetString()); + continue; + } + if (property.NameEquals("data"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(RunObject.DeserializeRunObject(item)); + } + data = array; + continue; + } + if (property.NameEquals("first_id"u8)) + { + firstId = property.Value.GetString(); + continue; + } + if (property.NameEquals("last_id"u8)) + { + lastId = property.Value.GetString(); + continue; + } + if (property.NameEquals("has_more"u8)) + { + hasMore = property.Value.GetBoolean(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ListRunsResponse(@object, data, firstId, lastId, hasMore, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ListRunsResponse)} does not support '{options.Format}' format."); + } + } + + ListRunsResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeListRunsResponse(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ListRunsResponse)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ListRunsResponse FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeListRunsResponse(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ListRunsResponse.cs b/.dotnet/src/Generated/Models/ListRunsResponse.cs new file mode 100644 index 000000000..efd6de920 --- /dev/null +++ b/.dotnet/src/Generated/Models/ListRunsResponse.cs @@ -0,0 +1,99 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// The ListRunsResponse. + public partial class ListRunsResponse + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// + /// + /// + /// , or is null. + internal ListRunsResponse(IEnumerable data, string firstId, string lastId, bool hasMore) + { + ClientUtilities.AssertNotNull(data, nameof(data)); + ClientUtilities.AssertNotNull(firstId, nameof(firstId)); + ClientUtilities.AssertNotNull(lastId, nameof(lastId)); + + Data = data.ToList(); + FirstId = firstId; + LastId = lastId; + HasMore = hasMore; + } + + /// Initializes a new instance of . + /// + /// + /// + /// + /// + /// Keeps track of any properties unknown to the library. + internal ListRunsResponse(ListRunsResponseObject @object, IReadOnlyList data, string firstId, string lastId, bool hasMore, IDictionary serializedAdditionalRawData) + { + Object = @object; + Data = data; + FirstId = firstId; + LastId = lastId; + HasMore = hasMore; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal ListRunsResponse() + { + } + + /// Gets the object. + public ListRunsResponseObject Object { get; } = ListRunsResponseObject.List; + + /// Gets the data. + public IReadOnlyList Data { get; } + /// Gets the first id. + public string FirstId { get; } + /// Gets the last id. + public string LastId { get; } + /// Gets the has more. + public bool HasMore { get; } + } +} diff --git a/.dotnet/src/Generated/Models/ListRunsResponseObject.cs b/.dotnet/src/Generated/Models/ListRunsResponseObject.cs new file mode 100644 index 000000000..548feb288 --- /dev/null +++ b/.dotnet/src/Generated/Models/ListRunsResponseObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The ListRunsResponse_object. + public readonly partial struct ListRunsResponseObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public ListRunsResponseObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string ListValue = "list"; + + /// list. + public static ListRunsResponseObject List { get; } = new ListRunsResponseObject(ListValue); + /// Determines if two values are the same. + public static bool operator ==(ListRunsResponseObject left, ListRunsResponseObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(ListRunsResponseObject left, ListRunsResponseObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator ListRunsResponseObject(string value) => new ListRunsResponseObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is ListRunsResponseObject other && Equals(other); + /// + public bool Equals(ListRunsResponseObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/MessageFileObject.Serialization.cs b/.dotnet/src/Generated/Models/MessageFileObject.Serialization.cs new file mode 100644 index 000000000..01d813ec5 --- /dev/null +++ b/.dotnet/src/Generated/Models/MessageFileObject.Serialization.cs @@ -0,0 +1,156 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class MessageFileObject : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(MessageFileObject)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("id"u8); + writer.WriteStringValue(Id); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + writer.WritePropertyName("created_at"u8); + writer.WriteNumberValue(CreatedAt, "U"); + writer.WritePropertyName("message_id"u8); + writer.WriteStringValue(MessageId); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + MessageFileObject IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(MessageFileObject)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeMessageFileObject(document.RootElement, options); + } + + internal static MessageFileObject DeserializeMessageFileObject(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string id = default; + MessageFileObjectObject @object = default; + DateTimeOffset createdAt = default; + string messageId = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetString(); + continue; + } + if (property.NameEquals("object"u8)) + { + @object = new MessageFileObjectObject(property.Value.GetString()); + continue; + } + if (property.NameEquals("created_at"u8)) + { + createdAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); + continue; + } + if (property.NameEquals("message_id"u8)) + { + messageId = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new MessageFileObject(id, @object, createdAt, messageId, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(MessageFileObject)} does not support '{options.Format}' format."); + } + } + + MessageFileObject IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeMessageFileObject(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(MessageFileObject)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static MessageFileObject FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeMessageFileObject(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/MessageFileObject.cs b/.dotnet/src/Generated/Models/MessageFileObject.cs new file mode 100644 index 000000000..0afed8c95 --- /dev/null +++ b/.dotnet/src/Generated/Models/MessageFileObject.cs @@ -0,0 +1,91 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// A list of files attached to a `message`. + public partial class MessageFileObject + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// TThe identifier, which can be referenced in API endpoints. + /// The Unix timestamp (in seconds) for when the message file was created. + /// The ID of the [message](/docs/api-reference/messages) that the [File](/docs/api-reference/files) is attached to. + /// or is null. + internal MessageFileObject(string id, DateTimeOffset createdAt, string messageId) + { + ClientUtilities.AssertNotNull(id, nameof(id)); + ClientUtilities.AssertNotNull(messageId, nameof(messageId)); + + Id = id; + CreatedAt = createdAt; + MessageId = messageId; + } + + /// Initializes a new instance of . + /// TThe identifier, which can be referenced in API endpoints. + /// The object type, which is always `thread.message.file`. + /// The Unix timestamp (in seconds) for when the message file was created. + /// The ID of the [message](/docs/api-reference/messages) that the [File](/docs/api-reference/files) is attached to. + /// Keeps track of any properties unknown to the library. + internal MessageFileObject(string id, MessageFileObjectObject @object, DateTimeOffset createdAt, string messageId, IDictionary serializedAdditionalRawData) + { + Id = id; + Object = @object; + CreatedAt = createdAt; + MessageId = messageId; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal MessageFileObject() + { + } + + /// TThe identifier, which can be referenced in API endpoints. + public string Id { get; } + /// The object type, which is always `thread.message.file`. + public MessageFileObjectObject Object { get; } = MessageFileObjectObject.ThreadMessageFile; + + /// The Unix timestamp (in seconds) for when the message file was created. + public DateTimeOffset CreatedAt { get; } + /// The ID of the [message](/docs/api-reference/messages) that the [File](/docs/api-reference/files) is attached to. + public string MessageId { get; } + } +} diff --git a/.dotnet/src/Generated/Models/MessageFileObjectObject.cs b/.dotnet/src/Generated/Models/MessageFileObjectObject.cs new file mode 100644 index 000000000..55f4cc6f8 --- /dev/null +++ b/.dotnet/src/Generated/Models/MessageFileObjectObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The MessageFileObject_object. + public readonly partial struct MessageFileObjectObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public MessageFileObjectObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string ThreadMessageFileValue = "thread.message.file"; + + /// thread.message.file. + public static MessageFileObjectObject ThreadMessageFile { get; } = new MessageFileObjectObject(ThreadMessageFileValue); + /// Determines if two values are the same. + public static bool operator ==(MessageFileObjectObject left, MessageFileObjectObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(MessageFileObjectObject left, MessageFileObjectObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator MessageFileObjectObject(string value) => new MessageFileObjectObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is MessageFileObjectObject other && Equals(other); + /// + public bool Equals(MessageFileObjectObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/MessageObject.Serialization.cs b/.dotnet/src/Generated/Models/MessageObject.Serialization.cs new file mode 100644 index 000000000..5f9db4673 --- /dev/null +++ b/.dotnet/src/Generated/Models/MessageObject.Serialization.cs @@ -0,0 +1,290 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class MessageObject : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(MessageObject)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("id"u8); + writer.WriteStringValue(Id); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + writer.WritePropertyName("created_at"u8); + writer.WriteNumberValue(CreatedAt, "U"); + writer.WritePropertyName("thread_id"u8); + writer.WriteStringValue(ThreadId); + writer.WritePropertyName("role"u8); + writer.WriteStringValue(Role.ToString()); + writer.WritePropertyName("content"u8); + writer.WriteStartArray(); + foreach (var item in Content) + { + if (item == null) + { + writer.WriteNullValue(); + continue; + } +#if NET6_0_OR_GREATER + writer.WriteRawValue(item); +#else + using (JsonDocument document = JsonDocument.Parse(item)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + writer.WriteEndArray(); + if (AssistantId != null) + { + writer.WritePropertyName("assistant_id"u8); + writer.WriteStringValue(AssistantId); + } + else + { + writer.WriteNull("assistant_id"); + } + if (RunId != null) + { + writer.WritePropertyName("run_id"u8); + writer.WriteStringValue(RunId); + } + else + { + writer.WriteNull("run_id"); + } + writer.WritePropertyName("file_ids"u8); + writer.WriteStartArray(); + foreach (var item in FileIds) + { + writer.WriteStringValue(item); + } + writer.WriteEndArray(); + if (Metadata != null && OptionalProperty.IsCollectionDefined(Metadata)) + { + writer.WritePropertyName("metadata"u8); + writer.WriteStartObject(); + foreach (var item in Metadata) + { + writer.WritePropertyName(item.Key); + writer.WriteStringValue(item.Value); + } + writer.WriteEndObject(); + } + else + { + writer.WriteNull("metadata"); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + MessageObject IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(MessageObject)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeMessageObject(document.RootElement, options); + } + + internal static MessageObject DeserializeMessageObject(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string id = default; + MessageObjectObject @object = default; + DateTimeOffset createdAt = default; + string threadId = default; + MessageObjectRole role = default; + IReadOnlyList content = default; + string assistantId = default; + string runId = default; + IReadOnlyList fileIds = default; + IReadOnlyDictionary metadata = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetString(); + continue; + } + if (property.NameEquals("object"u8)) + { + @object = new MessageObjectObject(property.Value.GetString()); + continue; + } + if (property.NameEquals("created_at"u8)) + { + createdAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); + continue; + } + if (property.NameEquals("thread_id"u8)) + { + threadId = property.Value.GetString(); + continue; + } + if (property.NameEquals("role"u8)) + { + role = new MessageObjectRole(property.Value.GetString()); + continue; + } + if (property.NameEquals("content"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + if (item.ValueKind == JsonValueKind.Null) + { + array.Add(null); + } + else + { + array.Add(BinaryData.FromString(item.GetRawText())); + } + } + content = array; + continue; + } + if (property.NameEquals("assistant_id"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + assistantId = null; + continue; + } + assistantId = property.Value.GetString(); + continue; + } + if (property.NameEquals("run_id"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + runId = null; + continue; + } + runId = property.Value.GetString(); + continue; + } + if (property.NameEquals("file_ids"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(item.GetString()); + } + fileIds = array; + continue; + } + if (property.NameEquals("metadata"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + metadata = new OptionalDictionary(); + continue; + } + Dictionary dictionary = new Dictionary(); + foreach (var property0 in property.Value.EnumerateObject()) + { + dictionary.Add(property0.Name, property0.Value.GetString()); + } + metadata = dictionary; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new MessageObject(id, @object, createdAt, threadId, role, content, assistantId, runId, fileIds, metadata, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(MessageObject)} does not support '{options.Format}' format."); + } + } + + MessageObject IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeMessageObject(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(MessageObject)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static MessageObject FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeMessageObject(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/MessageObject.cs b/.dotnet/src/Generated/Models/MessageObject.cs new file mode 100644 index 000000000..54ea98399 --- /dev/null +++ b/.dotnet/src/Generated/Models/MessageObject.cs @@ -0,0 +1,201 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// The MessageObject. + public partial class MessageObject + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The identifier, which can be referenced in API endpoints. + /// The Unix timestamp (in seconds) for when the message was created. + /// The [thread](/docs/api-reference/threads) ID that this message belongs to. + /// The entity that produced the message. One of `user` or `assistant`. + /// The content of the message in array of text and/or images. + /// + /// If applicable, the ID of the [assistant](/docs/api-reference/assistants) that authored this + /// message. + /// + /// + /// If applicable, the ID of the [run](/docs/api-reference/runs) associated with the authoring of + /// this message. + /// + /// + /// A list of [file](/docs/api-reference/files) IDs that the assistant should use. Useful for + /// tools like retrieval and code_interpreter that can access files. A maximum of 10 files can be + /// attached to a message. + /// + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// , , or is null. + internal MessageObject(string id, DateTimeOffset createdAt, string threadId, MessageObjectRole role, IEnumerable content, string assistantId, string runId, IEnumerable fileIds, IReadOnlyDictionary metadata) + { + ClientUtilities.AssertNotNull(id, nameof(id)); + ClientUtilities.AssertNotNull(threadId, nameof(threadId)); + ClientUtilities.AssertNotNull(content, nameof(content)); + ClientUtilities.AssertNotNull(fileIds, nameof(fileIds)); + + Id = id; + CreatedAt = createdAt; + ThreadId = threadId; + Role = role; + Content = content.ToList(); + AssistantId = assistantId; + RunId = runId; + FileIds = fileIds.ToList(); + Metadata = metadata; + } + + /// Initializes a new instance of . + /// The identifier, which can be referenced in API endpoints. + /// The object type, which is always `thread.message`. + /// The Unix timestamp (in seconds) for when the message was created. + /// The [thread](/docs/api-reference/threads) ID that this message belongs to. + /// The entity that produced the message. One of `user` or `assistant`. + /// The content of the message in array of text and/or images. + /// + /// If applicable, the ID of the [assistant](/docs/api-reference/assistants) that authored this + /// message. + /// + /// + /// If applicable, the ID of the [run](/docs/api-reference/runs) associated with the authoring of + /// this message. + /// + /// + /// A list of [file](/docs/api-reference/files) IDs that the assistant should use. Useful for + /// tools like retrieval and code_interpreter that can access files. A maximum of 10 files can be + /// attached to a message. + /// + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// Keeps track of any properties unknown to the library. + internal MessageObject(string id, MessageObjectObject @object, DateTimeOffset createdAt, string threadId, MessageObjectRole role, IReadOnlyList content, string assistantId, string runId, IReadOnlyList fileIds, IReadOnlyDictionary metadata, IDictionary serializedAdditionalRawData) + { + Id = id; + Object = @object; + CreatedAt = createdAt; + ThreadId = threadId; + Role = role; + Content = content; + AssistantId = assistantId; + RunId = runId; + FileIds = fileIds; + Metadata = metadata; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal MessageObject() + { + } + + /// The identifier, which can be referenced in API endpoints. + public string Id { get; } + /// The object type, which is always `thread.message`. + public MessageObjectObject Object { get; } = MessageObjectObject.ThreadMessage; + + /// The Unix timestamp (in seconds) for when the message was created. + public DateTimeOffset CreatedAt { get; } + /// The [thread](/docs/api-reference/threads) ID that this message belongs to. + public string ThreadId { get; } + /// The entity that produced the message. One of `user` or `assistant`. + public MessageObjectRole Role { get; } + /// + /// The content of the message in array of text and/or images. + /// + /// To assign an object to the element of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + public IReadOnlyList Content { get; } + /// + /// If applicable, the ID of the [assistant](/docs/api-reference/assistants) that authored this + /// message. + /// + public string AssistantId { get; } + /// + /// If applicable, the ID of the [run](/docs/api-reference/runs) associated with the authoring of + /// this message. + /// + public string RunId { get; } + /// + /// A list of [file](/docs/api-reference/files) IDs that the assistant should use. Useful for + /// tools like retrieval and code_interpreter that can access files. A maximum of 10 files can be + /// attached to a message. + /// + public IReadOnlyList FileIds { get; } + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + public IReadOnlyDictionary Metadata { get; } + } +} diff --git a/.dotnet/src/Generated/Models/MessageObjectObject.cs b/.dotnet/src/Generated/Models/MessageObjectObject.cs new file mode 100644 index 000000000..5f835f436 --- /dev/null +++ b/.dotnet/src/Generated/Models/MessageObjectObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The MessageObject_object. + public readonly partial struct MessageObjectObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public MessageObjectObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string ThreadMessageValue = "thread.message"; + + /// thread.message. + public static MessageObjectObject ThreadMessage { get; } = new MessageObjectObject(ThreadMessageValue); + /// Determines if two values are the same. + public static bool operator ==(MessageObjectObject left, MessageObjectObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(MessageObjectObject left, MessageObjectObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator MessageObjectObject(string value) => new MessageObjectObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is MessageObjectObject other && Equals(other); + /// + public bool Equals(MessageObjectObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/MessageObjectRole.cs b/.dotnet/src/Generated/Models/MessageObjectRole.cs new file mode 100644 index 000000000..a62512cd2 --- /dev/null +++ b/.dotnet/src/Generated/Models/MessageObjectRole.cs @@ -0,0 +1,48 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for role in MessageObject. + public readonly partial struct MessageObjectRole : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public MessageObjectRole(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string UserValue = "user"; + private const string AssistantValue = "assistant"; + + /// user. + public static MessageObjectRole User { get; } = new MessageObjectRole(UserValue); + /// assistant. + public static MessageObjectRole Assistant { get; } = new MessageObjectRole(AssistantValue); + /// Determines if two values are the same. + public static bool operator ==(MessageObjectRole left, MessageObjectRole right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(MessageObjectRole left, MessageObjectRole right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator MessageObjectRole(string value) => new MessageObjectRole(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is MessageObjectRole other && Equals(other); + /// + public bool Equals(MessageObjectRole other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/Model.Serialization.cs b/.dotnet/src/Generated/Models/Model.Serialization.cs new file mode 100644 index 000000000..b3a797b7b --- /dev/null +++ b/.dotnet/src/Generated/Models/Model.Serialization.cs @@ -0,0 +1,156 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class Model : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(Model)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("id"u8); + writer.WriteStringValue(Id); + writer.WritePropertyName("created"u8); + writer.WriteNumberValue(Created, "U"); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + writer.WritePropertyName("owned_by"u8); + writer.WriteStringValue(OwnedBy); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + Model IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(Model)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeModel(document.RootElement, options); + } + + internal static Model DeserializeModel(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string id = default; + DateTimeOffset created = default; + ModelObject @object = default; + string ownedBy = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetString(); + continue; + } + if (property.NameEquals("created"u8)) + { + created = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); + continue; + } + if (property.NameEquals("object"u8)) + { + @object = new ModelObject(property.Value.GetString()); + continue; + } + if (property.NameEquals("owned_by"u8)) + { + ownedBy = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new Model(id, created, @object, ownedBy, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(Model)} does not support '{options.Format}' format."); + } + } + + Model IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeModel(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(Model)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static Model FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeModel(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/Model.cs b/.dotnet/src/Generated/Models/Model.cs new file mode 100644 index 000000000..70edf9a14 --- /dev/null +++ b/.dotnet/src/Generated/Models/Model.cs @@ -0,0 +1,91 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// Describes an OpenAI model offering that can be used with the API. + public partial class Model + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The model identifier, which can be referenced in the API endpoints. + /// The Unix timestamp (in seconds) when the model was created. + /// The organization that owns the model. + /// or is null. + internal Model(string id, DateTimeOffset created, string ownedBy) + { + ClientUtilities.AssertNotNull(id, nameof(id)); + ClientUtilities.AssertNotNull(ownedBy, nameof(ownedBy)); + + Id = id; + Created = created; + OwnedBy = ownedBy; + } + + /// Initializes a new instance of . + /// The model identifier, which can be referenced in the API endpoints. + /// The Unix timestamp (in seconds) when the model was created. + /// The object type, which is always "model". + /// The organization that owns the model. + /// Keeps track of any properties unknown to the library. + internal Model(string id, DateTimeOffset created, ModelObject @object, string ownedBy, IDictionary serializedAdditionalRawData) + { + Id = id; + Created = created; + Object = @object; + OwnedBy = ownedBy; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal Model() + { + } + + /// The model identifier, which can be referenced in the API endpoints. + public string Id { get; } + /// The Unix timestamp (in seconds) when the model was created. + public DateTimeOffset Created { get; } + /// The object type, which is always "model". + public ModelObject Object { get; } = ModelObject.Model; + + /// The organization that owns the model. + public string OwnedBy { get; } + } +} diff --git a/.dotnet/src/Generated/Models/ModelObject.cs b/.dotnet/src/Generated/Models/ModelObject.cs new file mode 100644 index 000000000..063012b5a --- /dev/null +++ b/.dotnet/src/Generated/Models/ModelObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The Model_object. + public readonly partial struct ModelObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public ModelObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string ModelValue = "model"; + + /// model. + public static ModelObject Model { get; } = new ModelObject(ModelValue); + /// Determines if two values are the same. + public static bool operator ==(ModelObject left, ModelObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(ModelObject left, ModelObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator ModelObject(string value) => new ModelObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is ModelObject other && Equals(other); + /// + public bool Equals(ModelObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/ModifyAssistantRequest.Serialization.cs b/.dotnet/src/Generated/Models/ModifyAssistantRequest.Serialization.cs new file mode 100644 index 000000000..7e9027ef1 --- /dev/null +++ b/.dotnet/src/Generated/Models/ModifyAssistantRequest.Serialization.cs @@ -0,0 +1,306 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class ModifyAssistantRequest : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ModifyAssistantRequest)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + if (OptionalProperty.IsDefined(Model)) + { + writer.WritePropertyName("model"u8); + writer.WriteStringValue(Model); + } + if (OptionalProperty.IsDefined(Name)) + { + if (Name != null) + { + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + } + else + { + writer.WriteNull("name"); + } + } + if (OptionalProperty.IsDefined(Description)) + { + if (Description != null) + { + writer.WritePropertyName("description"u8); + writer.WriteStringValue(Description); + } + else + { + writer.WriteNull("description"); + } + } + if (OptionalProperty.IsDefined(Instructions)) + { + if (Instructions != null) + { + writer.WritePropertyName("instructions"u8); + writer.WriteStringValue(Instructions); + } + else + { + writer.WriteNull("instructions"); + } + } + if (OptionalProperty.IsCollectionDefined(Tools)) + { + writer.WritePropertyName("tools"u8); + writer.WriteStartArray(); + foreach (var item in Tools) + { + if (item == null) + { + writer.WriteNullValue(); + continue; + } +#if NET6_0_OR_GREATER + writer.WriteRawValue(item); +#else + using (JsonDocument document = JsonDocument.Parse(item)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + writer.WriteEndArray(); + } + if (OptionalProperty.IsCollectionDefined(FileIds)) + { + writer.WritePropertyName("file_ids"u8); + writer.WriteStartArray(); + foreach (var item in FileIds) + { + writer.WriteStringValue(item); + } + writer.WriteEndArray(); + } + if (OptionalProperty.IsCollectionDefined(Metadata)) + { + if (Metadata != null) + { + writer.WritePropertyName("metadata"u8); + writer.WriteStartObject(); + foreach (var item in Metadata) + { + writer.WritePropertyName(item.Key); + writer.WriteStringValue(item.Value); + } + writer.WriteEndObject(); + } + else + { + writer.WriteNull("metadata"); + } + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ModifyAssistantRequest IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ModifyAssistantRequest)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeModifyAssistantRequest(document.RootElement, options); + } + + internal static ModifyAssistantRequest DeserializeModifyAssistantRequest(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + OptionalProperty model = default; + OptionalProperty name = default; + OptionalProperty description = default; + OptionalProperty instructions = default; + OptionalProperty> tools = default; + OptionalProperty> fileIds = default; + OptionalProperty> metadata = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("model"u8)) + { + model = property.Value.GetString(); + continue; + } + if (property.NameEquals("name"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + name = null; + continue; + } + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("description"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + description = null; + continue; + } + description = property.Value.GetString(); + continue; + } + if (property.NameEquals("instructions"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + instructions = null; + continue; + } + instructions = property.Value.GetString(); + continue; + } + if (property.NameEquals("tools"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + if (item.ValueKind == JsonValueKind.Null) + { + array.Add(null); + } + else + { + array.Add(BinaryData.FromString(item.GetRawText())); + } + } + tools = array; + continue; + } + if (property.NameEquals("file_ids"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(item.GetString()); + } + fileIds = array; + continue; + } + if (property.NameEquals("metadata"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + Dictionary dictionary = new Dictionary(); + foreach (var property0 in property.Value.EnumerateObject()) + { + dictionary.Add(property0.Name, property0.Value.GetString()); + } + metadata = dictionary; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ModifyAssistantRequest(model.Value, name.Value, description.Value, instructions.Value, OptionalProperty.ToList(tools), OptionalProperty.ToList(fileIds), OptionalProperty.ToDictionary(metadata), serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ModifyAssistantRequest)} does not support '{options.Format}' format."); + } + } + + ModifyAssistantRequest IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeModifyAssistantRequest(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ModifyAssistantRequest)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ModifyAssistantRequest FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeModifyAssistantRequest(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ModifyAssistantRequest.cs b/.dotnet/src/Generated/Models/ModifyAssistantRequest.cs new file mode 100644 index 000000000..abc79d17a --- /dev/null +++ b/.dotnet/src/Generated/Models/ModifyAssistantRequest.cs @@ -0,0 +1,147 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The ModifyAssistantRequest. + public partial class ModifyAssistantRequest + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + public ModifyAssistantRequest() + { + Tools = new OptionalList(); + FileIds = new OptionalList(); + Metadata = new OptionalDictionary(); + } + + /// Initializes a new instance of . + /// + /// ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + /// see all of your available models, or see our [Model overview](/docs/models/overview) for + /// descriptions of them. + /// + /// The name of the assistant. The maximum length is 256 characters. + /// The description of the assistant. The maximum length is 512 characters. + /// The system instructions that the assistant uses. The maximum length is 32768 characters. + /// + /// A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. + /// Tools can be of types `code_interpreter`, `retrieval`, or `function`. + /// + /// + /// A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a + /// maximum of 20 files attached to the assistant. Files are ordered by their creation date in + /// ascending order. + /// + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// Keeps track of any properties unknown to the library. + internal ModifyAssistantRequest(string model, string name, string description, string instructions, IList tools, IList fileIds, IDictionary metadata, IDictionary serializedAdditionalRawData) + { + Model = model; + Name = name; + Description = description; + Instructions = instructions; + Tools = tools; + FileIds = fileIds; + Metadata = metadata; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// + /// ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + /// see all of your available models, or see our [Model overview](/docs/models/overview) for + /// descriptions of them. + /// + public string Model { get; set; } + /// The name of the assistant. The maximum length is 256 characters. + public string Name { get; set; } + /// The description of the assistant. The maximum length is 512 characters. + public string Description { get; set; } + /// The system instructions that the assistant uses. The maximum length is 32768 characters. + public string Instructions { get; set; } + /// + /// A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. + /// Tools can be of types `code_interpreter`, `retrieval`, or `function`. + /// + /// To assign an object to the element of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + public IList Tools { get; } + /// + /// A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a + /// maximum of 20 files attached to the assistant. Files are ordered by their creation date in + /// ascending order. + /// + public IList FileIds { get; } + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + public IDictionary Metadata { get; set; } + } +} diff --git a/.dotnet/src/Generated/Models/ModifyMessageRequest.Serialization.cs b/.dotnet/src/Generated/Models/ModifyMessageRequest.Serialization.cs new file mode 100644 index 000000000..35ee9a46e --- /dev/null +++ b/.dotnet/src/Generated/Models/ModifyMessageRequest.Serialization.cs @@ -0,0 +1,157 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class ModifyMessageRequest : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ModifyMessageRequest)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + if (OptionalProperty.IsCollectionDefined(Metadata)) + { + if (Metadata != null) + { + writer.WritePropertyName("metadata"u8); + writer.WriteStartObject(); + foreach (var item in Metadata) + { + writer.WritePropertyName(item.Key); + writer.WriteStringValue(item.Value); + } + writer.WriteEndObject(); + } + else + { + writer.WriteNull("metadata"); + } + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ModifyMessageRequest IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ModifyMessageRequest)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeModifyMessageRequest(document.RootElement, options); + } + + internal static ModifyMessageRequest DeserializeModifyMessageRequest(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + OptionalProperty> metadata = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("metadata"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + Dictionary dictionary = new Dictionary(); + foreach (var property0 in property.Value.EnumerateObject()) + { + dictionary.Add(property0.Name, property0.Value.GetString()); + } + metadata = dictionary; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ModifyMessageRequest(OptionalProperty.ToDictionary(metadata), serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ModifyMessageRequest)} does not support '{options.Format}' format."); + } + } + + ModifyMessageRequest IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeModifyMessageRequest(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ModifyMessageRequest)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ModifyMessageRequest FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeModifyMessageRequest(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ModifyMessageRequest.cs b/.dotnet/src/Generated/Models/ModifyMessageRequest.cs new file mode 100644 index 000000000..3a200b238 --- /dev/null +++ b/.dotnet/src/Generated/Models/ModifyMessageRequest.cs @@ -0,0 +1,72 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The ModifyMessageRequest. + public partial class ModifyMessageRequest + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + public ModifyMessageRequest() + { + Metadata = new OptionalDictionary(); + } + + /// Initializes a new instance of . + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// Keeps track of any properties unknown to the library. + internal ModifyMessageRequest(IDictionary metadata, IDictionary serializedAdditionalRawData) + { + Metadata = metadata; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + public IDictionary Metadata { get; set; } + } +} diff --git a/.dotnet/src/Generated/Models/ModifyRunRequest.Serialization.cs b/.dotnet/src/Generated/Models/ModifyRunRequest.Serialization.cs new file mode 100644 index 000000000..75c891191 --- /dev/null +++ b/.dotnet/src/Generated/Models/ModifyRunRequest.Serialization.cs @@ -0,0 +1,157 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class ModifyRunRequest : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ModifyRunRequest)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + if (OptionalProperty.IsCollectionDefined(Metadata)) + { + if (Metadata != null) + { + writer.WritePropertyName("metadata"u8); + writer.WriteStartObject(); + foreach (var item in Metadata) + { + writer.WritePropertyName(item.Key); + writer.WriteStringValue(item.Value); + } + writer.WriteEndObject(); + } + else + { + writer.WriteNull("metadata"); + } + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ModifyRunRequest IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ModifyRunRequest)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeModifyRunRequest(document.RootElement, options); + } + + internal static ModifyRunRequest DeserializeModifyRunRequest(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + OptionalProperty> metadata = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("metadata"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + Dictionary dictionary = new Dictionary(); + foreach (var property0 in property.Value.EnumerateObject()) + { + dictionary.Add(property0.Name, property0.Value.GetString()); + } + metadata = dictionary; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ModifyRunRequest(OptionalProperty.ToDictionary(metadata), serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ModifyRunRequest)} does not support '{options.Format}' format."); + } + } + + ModifyRunRequest IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeModifyRunRequest(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ModifyRunRequest)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ModifyRunRequest FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeModifyRunRequest(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ModifyRunRequest.cs b/.dotnet/src/Generated/Models/ModifyRunRequest.cs new file mode 100644 index 000000000..8a8a14588 --- /dev/null +++ b/.dotnet/src/Generated/Models/ModifyRunRequest.cs @@ -0,0 +1,72 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The ModifyRunRequest. + public partial class ModifyRunRequest + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + public ModifyRunRequest() + { + Metadata = new OptionalDictionary(); + } + + /// Initializes a new instance of . + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// Keeps track of any properties unknown to the library. + internal ModifyRunRequest(IDictionary metadata, IDictionary serializedAdditionalRawData) + { + Metadata = metadata; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + public IDictionary Metadata { get; set; } + } +} diff --git a/.dotnet/src/Generated/Models/ModifyThreadRequest.Serialization.cs b/.dotnet/src/Generated/Models/ModifyThreadRequest.Serialization.cs new file mode 100644 index 000000000..2e8149f8e --- /dev/null +++ b/.dotnet/src/Generated/Models/ModifyThreadRequest.Serialization.cs @@ -0,0 +1,157 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class ModifyThreadRequest : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ModifyThreadRequest)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + if (OptionalProperty.IsCollectionDefined(Metadata)) + { + if (Metadata != null) + { + writer.WritePropertyName("metadata"u8); + writer.WriteStartObject(); + foreach (var item in Metadata) + { + writer.WritePropertyName(item.Key); + writer.WriteStringValue(item.Value); + } + writer.WriteEndObject(); + } + else + { + writer.WriteNull("metadata"); + } + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ModifyThreadRequest IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ModifyThreadRequest)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeModifyThreadRequest(document.RootElement, options); + } + + internal static ModifyThreadRequest DeserializeModifyThreadRequest(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + OptionalProperty> metadata = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("metadata"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + Dictionary dictionary = new Dictionary(); + foreach (var property0 in property.Value.EnumerateObject()) + { + dictionary.Add(property0.Name, property0.Value.GetString()); + } + metadata = dictionary; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ModifyThreadRequest(OptionalProperty.ToDictionary(metadata), serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ModifyThreadRequest)} does not support '{options.Format}' format."); + } + } + + ModifyThreadRequest IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeModifyThreadRequest(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ModifyThreadRequest)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ModifyThreadRequest FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeModifyThreadRequest(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ModifyThreadRequest.cs b/.dotnet/src/Generated/Models/ModifyThreadRequest.cs new file mode 100644 index 000000000..635172be4 --- /dev/null +++ b/.dotnet/src/Generated/Models/ModifyThreadRequest.cs @@ -0,0 +1,72 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The ModifyThreadRequest. + public partial class ModifyThreadRequest + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + public ModifyThreadRequest() + { + Metadata = new OptionalDictionary(); + } + + /// Initializes a new instance of . + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// Keeps track of any properties unknown to the library. + internal ModifyThreadRequest(IDictionary metadata, IDictionary serializedAdditionalRawData) + { + Metadata = metadata; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + public IDictionary Metadata { get; set; } + } +} diff --git a/.dotnet/src/Generated/Models/OpenAIFile.Serialization.cs b/.dotnet/src/Generated/Models/OpenAIFile.Serialization.cs new file mode 100644 index 000000000..53c7116dd --- /dev/null +++ b/.dotnet/src/Generated/Models/OpenAIFile.Serialization.cs @@ -0,0 +1,191 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class OpenAIFile : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(OpenAIFile)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("id"u8); + writer.WriteStringValue(Id); + writer.WritePropertyName("bytes"u8); + writer.WriteNumberValue(Bytes); + writer.WritePropertyName("created_at"u8); + writer.WriteNumberValue(CreatedAt, "U"); + writer.WritePropertyName("filename"u8); + writer.WriteStringValue(Filename); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + writer.WritePropertyName("purpose"u8); + writer.WriteStringValue(Purpose.ToString()); + writer.WritePropertyName("status"u8); + writer.WriteStringValue(Status.ToString()); + if (OptionalProperty.IsDefined(StatusDetails)) + { + writer.WritePropertyName("status_details"u8); + writer.WriteStringValue(StatusDetails); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + OpenAIFile IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(OpenAIFile)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeOpenAIFile(document.RootElement, options); + } + + internal static OpenAIFile DeserializeOpenAIFile(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string id = default; + long bytes = default; + DateTimeOffset createdAt = default; + string filename = default; + OpenAIFileObject @object = default; + OpenAIFilePurpose purpose = default; + OpenAIFileStatus status = default; + OptionalProperty statusDetails = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetString(); + continue; + } + if (property.NameEquals("bytes"u8)) + { + bytes = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("created_at"u8)) + { + createdAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); + continue; + } + if (property.NameEquals("filename"u8)) + { + filename = property.Value.GetString(); + continue; + } + if (property.NameEquals("object"u8)) + { + @object = new OpenAIFileObject(property.Value.GetString()); + continue; + } + if (property.NameEquals("purpose"u8)) + { + purpose = new OpenAIFilePurpose(property.Value.GetString()); + continue; + } + if (property.NameEquals("status"u8)) + { + status = new OpenAIFileStatus(property.Value.GetString()); + continue; + } + if (property.NameEquals("status_details"u8)) + { + statusDetails = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new OpenAIFile(id, bytes, createdAt, filename, @object, purpose, status, statusDetails.Value, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(OpenAIFile)} does not support '{options.Format}' format."); + } + } + + OpenAIFile IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeOpenAIFile(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(OpenAIFile)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static OpenAIFile FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeOpenAIFile(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/OpenAIFile.cs b/.dotnet/src/Generated/Models/OpenAIFile.cs new file mode 100644 index 000000000..7d3adf563 --- /dev/null +++ b/.dotnet/src/Generated/Models/OpenAIFile.cs @@ -0,0 +1,137 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The `File` object represents a document that has been uploaded to OpenAI. + public partial class OpenAIFile + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The file identifier, which can be referenced in the API endpoints. + /// The size of the file, in bytes. + /// The Unix timestamp (in seconds) for when the file was created. + /// The name of the file. + /// + /// The intended purpose of the file. Supported values are `fine-tune`, `fine-tune-results`, + /// `assistants`, and `assistants_output`. + /// + /// + /// Deprecated. The current status of the file, which can be either `uploaded`, `processed`, or + /// `error`. + /// + /// or is null. + internal OpenAIFile(string id, long bytes, DateTimeOffset createdAt, string filename, OpenAIFilePurpose purpose, OpenAIFileStatus status) + { + ClientUtilities.AssertNotNull(id, nameof(id)); + ClientUtilities.AssertNotNull(filename, nameof(filename)); + + Id = id; + Bytes = bytes; + CreatedAt = createdAt; + Filename = filename; + Purpose = purpose; + Status = status; + } + + /// Initializes a new instance of . + /// The file identifier, which can be referenced in the API endpoints. + /// The size of the file, in bytes. + /// The Unix timestamp (in seconds) for when the file was created. + /// The name of the file. + /// The object type, which is always "file". + /// + /// The intended purpose of the file. Supported values are `fine-tune`, `fine-tune-results`, + /// `assistants`, and `assistants_output`. + /// + /// + /// Deprecated. The current status of the file, which can be either `uploaded`, `processed`, or + /// `error`. + /// + /// + /// Deprecated. For details on why a fine-tuning training file failed validation, see the `error` + /// field on `fine_tuning.job`. + /// + /// Keeps track of any properties unknown to the library. + internal OpenAIFile(string id, long bytes, DateTimeOffset createdAt, string filename, OpenAIFileObject @object, OpenAIFilePurpose purpose, OpenAIFileStatus status, string statusDetails, IDictionary serializedAdditionalRawData) + { + Id = id; + Bytes = bytes; + CreatedAt = createdAt; + Filename = filename; + Object = @object; + Purpose = purpose; + Status = status; + StatusDetails = statusDetails; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal OpenAIFile() + { + } + + /// The file identifier, which can be referenced in the API endpoints. + public string Id { get; } + /// The size of the file, in bytes. + public long Bytes { get; } + /// The Unix timestamp (in seconds) for when the file was created. + public DateTimeOffset CreatedAt { get; } + /// The name of the file. + public string Filename { get; } + /// The object type, which is always "file". + public OpenAIFileObject Object { get; } = OpenAIFileObject.File; + + /// + /// The intended purpose of the file. Supported values are `fine-tune`, `fine-tune-results`, + /// `assistants`, and `assistants_output`. + /// + public OpenAIFilePurpose Purpose { get; } + /// + /// Deprecated. The current status of the file, which can be either `uploaded`, `processed`, or + /// `error`. + /// + public OpenAIFileStatus Status { get; } + /// + /// Deprecated. For details on why a fine-tuning training file failed validation, see the `error` + /// field on `fine_tuning.job`. + /// + public string StatusDetails { get; } + } +} diff --git a/.dotnet/src/Generated/Models/OpenAIFileObject.cs b/.dotnet/src/Generated/Models/OpenAIFileObject.cs new file mode 100644 index 000000000..79e03b84c --- /dev/null +++ b/.dotnet/src/Generated/Models/OpenAIFileObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The OpenAIFile_object. + public readonly partial struct OpenAIFileObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public OpenAIFileObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string FileValue = "file"; + + /// file. + public static OpenAIFileObject File { get; } = new OpenAIFileObject(FileValue); + /// Determines if two values are the same. + public static bool operator ==(OpenAIFileObject left, OpenAIFileObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(OpenAIFileObject left, OpenAIFileObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator OpenAIFileObject(string value) => new OpenAIFileObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is OpenAIFileObject other && Equals(other); + /// + public bool Equals(OpenAIFileObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/OpenAIFilePurpose.cs b/.dotnet/src/Generated/Models/OpenAIFilePurpose.cs new file mode 100644 index 000000000..0f3c83bc5 --- /dev/null +++ b/.dotnet/src/Generated/Models/OpenAIFilePurpose.cs @@ -0,0 +1,54 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for purpose in OpenAIFile. + public readonly partial struct OpenAIFilePurpose : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public OpenAIFilePurpose(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string FineTuneValue = "fine-tune"; + private const string FineTuneResultsValue = "fine-tune-results"; + private const string AssistantsValue = "assistants"; + private const string AssistantsOutputValue = "assistants_output"; + + /// fine-tune. + public static OpenAIFilePurpose FineTune { get; } = new OpenAIFilePurpose(FineTuneValue); + /// fine-tune-results. + public static OpenAIFilePurpose FineTuneResults { get; } = new OpenAIFilePurpose(FineTuneResultsValue); + /// assistants. + public static OpenAIFilePurpose Assistants { get; } = new OpenAIFilePurpose(AssistantsValue); + /// assistants_output. + public static OpenAIFilePurpose AssistantsOutput { get; } = new OpenAIFilePurpose(AssistantsOutputValue); + /// Determines if two values are the same. + public static bool operator ==(OpenAIFilePurpose left, OpenAIFilePurpose right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(OpenAIFilePurpose left, OpenAIFilePurpose right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator OpenAIFilePurpose(string value) => new OpenAIFilePurpose(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is OpenAIFilePurpose other && Equals(other); + /// + public bool Equals(OpenAIFilePurpose other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/OpenAIFileStatus.cs b/.dotnet/src/Generated/Models/OpenAIFileStatus.cs new file mode 100644 index 000000000..c35731688 --- /dev/null +++ b/.dotnet/src/Generated/Models/OpenAIFileStatus.cs @@ -0,0 +1,51 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for status in OpenAIFile. + public readonly partial struct OpenAIFileStatus : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public OpenAIFileStatus(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string UploadedValue = "uploaded"; + private const string ProcessedValue = "processed"; + private const string ErrorValue = "error"; + + /// uploaded. + public static OpenAIFileStatus Uploaded { get; } = new OpenAIFileStatus(UploadedValue); + /// processed. + public static OpenAIFileStatus Processed { get; } = new OpenAIFileStatus(ProcessedValue); + /// error. + public static OpenAIFileStatus Error { get; } = new OpenAIFileStatus(ErrorValue); + /// Determines if two values are the same. + public static bool operator ==(OpenAIFileStatus left, OpenAIFileStatus right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(OpenAIFileStatus left, OpenAIFileStatus right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator OpenAIFileStatus(string value) => new OpenAIFileStatus(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is OpenAIFileStatus other && Equals(other); + /// + public bool Equals(OpenAIFileStatus other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/RunCompletionUsage.Serialization.cs b/.dotnet/src/Generated/Models/RunCompletionUsage.Serialization.cs new file mode 100644 index 000000000..e857ef3b6 --- /dev/null +++ b/.dotnet/src/Generated/Models/RunCompletionUsage.Serialization.cs @@ -0,0 +1,148 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class RunCompletionUsage : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(RunCompletionUsage)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("completion_tokens"u8); + writer.WriteNumberValue(CompletionTokens); + writer.WritePropertyName("prompt_tokens"u8); + writer.WriteNumberValue(PromptTokens); + writer.WritePropertyName("total_tokens"u8); + writer.WriteNumberValue(TotalTokens); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + RunCompletionUsage IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(RunCompletionUsage)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeRunCompletionUsage(document.RootElement, options); + } + + internal static RunCompletionUsage DeserializeRunCompletionUsage(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + long completionTokens = default; + long promptTokens = default; + long totalTokens = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("completion_tokens"u8)) + { + completionTokens = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("prompt_tokens"u8)) + { + promptTokens = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("total_tokens"u8)) + { + totalTokens = property.Value.GetInt64(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new RunCompletionUsage(completionTokens, promptTokens, totalTokens, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(RunCompletionUsage)} does not support '{options.Format}' format."); + } + } + + RunCompletionUsage IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeRunCompletionUsage(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(RunCompletionUsage)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static RunCompletionUsage FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeRunCompletionUsage(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/RunCompletionUsage.cs b/.dotnet/src/Generated/Models/RunCompletionUsage.cs new file mode 100644 index 000000000..be9401604 --- /dev/null +++ b/.dotnet/src/Generated/Models/RunCompletionUsage.cs @@ -0,0 +1,84 @@ +// + +#nullable disable + +using System; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// + /// Usage statistics related to the run. This value will be `null` if the run is not in a terminal + /// state (i.e. `in_progress`, `queued`, etc.). + /// + public partial class RunCompletionUsage + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// Number of completion tokens used over the course of the run. + /// Number of prompt tokens used over the course of the run. + /// Total number of tokens used (prompt + completion). + internal RunCompletionUsage(long completionTokens, long promptTokens, long totalTokens) + { + CompletionTokens = completionTokens; + PromptTokens = promptTokens; + TotalTokens = totalTokens; + } + + /// Initializes a new instance of . + /// Number of completion tokens used over the course of the run. + /// Number of prompt tokens used over the course of the run. + /// Total number of tokens used (prompt + completion). + /// Keeps track of any properties unknown to the library. + internal RunCompletionUsage(long completionTokens, long promptTokens, long totalTokens, IDictionary serializedAdditionalRawData) + { + CompletionTokens = completionTokens; + PromptTokens = promptTokens; + TotalTokens = totalTokens; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal RunCompletionUsage() + { + } + + /// Number of completion tokens used over the course of the run. + public long CompletionTokens { get; } + /// Number of prompt tokens used over the course of the run. + public long PromptTokens { get; } + /// Total number of tokens used (prompt + completion). + public long TotalTokens { get; } + } +} diff --git a/.dotnet/src/Generated/Models/RunObject.Serialization.cs b/.dotnet/src/Generated/Models/RunObject.Serialization.cs new file mode 100644 index 000000000..7128918dc --- /dev/null +++ b/.dotnet/src/Generated/Models/RunObject.Serialization.cs @@ -0,0 +1,422 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class RunObject : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(RunObject)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("id"u8); + writer.WriteStringValue(Id); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + writer.WritePropertyName("created_at"u8); + writer.WriteNumberValue(CreatedAt, "U"); + writer.WritePropertyName("thread_id"u8); + writer.WriteStringValue(ThreadId); + writer.WritePropertyName("assistant_id"u8); + writer.WriteStringValue(AssistantId); + writer.WritePropertyName("status"u8); + writer.WriteStringValue(Status.ToString()); + if (RequiredAction != null) + { + writer.WritePropertyName("required_action"u8); + writer.WriteObjectValue(RequiredAction); + } + else + { + writer.WriteNull("required_action"); + } + if (LastError != null) + { + writer.WritePropertyName("last_error"u8); + writer.WriteObjectValue(LastError); + } + else + { + writer.WriteNull("last_error"); + } + writer.WritePropertyName("expires_at"u8); + writer.WriteNumberValue(ExpiresAt, "U"); + if (StartedAt != null) + { + writer.WritePropertyName("started_at"u8); + writer.WriteStringValue(StartedAt.Value, "O"); + } + else + { + writer.WriteNull("started_at"); + } + if (CancelledAt != null) + { + writer.WritePropertyName("cancelled_at"u8); + writer.WriteStringValue(CancelledAt.Value, "O"); + } + else + { + writer.WriteNull("cancelled_at"); + } + if (FailedAt != null) + { + writer.WritePropertyName("failed_at"u8); + writer.WriteStringValue(FailedAt.Value, "O"); + } + else + { + writer.WriteNull("failed_at"); + } + if (CompletedAt != null) + { + writer.WritePropertyName("completed_at"u8); + writer.WriteStringValue(CompletedAt.Value, "O"); + } + else + { + writer.WriteNull("completed_at"); + } + writer.WritePropertyName("model"u8); + writer.WriteStringValue(Model); + writer.WritePropertyName("instructions"u8); + writer.WriteStringValue(Instructions); + writer.WritePropertyName("tools"u8); + writer.WriteStartArray(); + foreach (var item in Tools) + { + if (item == null) + { + writer.WriteNullValue(); + continue; + } +#if NET6_0_OR_GREATER + writer.WriteRawValue(item); +#else + using (JsonDocument document = JsonDocument.Parse(item)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + writer.WriteEndArray(); + writer.WritePropertyName("file_ids"u8); + writer.WriteStartArray(); + foreach (var item in FileIds) + { + writer.WriteStringValue(item); + } + writer.WriteEndArray(); + if (Metadata != null && OptionalProperty.IsCollectionDefined(Metadata)) + { + writer.WritePropertyName("metadata"u8); + writer.WriteStartObject(); + foreach (var item in Metadata) + { + writer.WritePropertyName(item.Key); + writer.WriteStringValue(item.Value); + } + writer.WriteEndObject(); + } + else + { + writer.WriteNull("metadata"); + } + if (Usage != null) + { + writer.WritePropertyName("usage"u8); + writer.WriteObjectValue(Usage); + } + else + { + writer.WriteNull("usage"); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + RunObject IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(RunObject)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeRunObject(document.RootElement, options); + } + + internal static RunObject DeserializeRunObject(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string id = default; + RunObjectObject @object = default; + DateTimeOffset createdAt = default; + string threadId = default; + string assistantId = default; + RunObjectStatus status = default; + RunObjectRequiredAction requiredAction = default; + RunObjectLastError lastError = default; + DateTimeOffset expiresAt = default; + DateTimeOffset? startedAt = default; + DateTimeOffset? cancelledAt = default; + DateTimeOffset? failedAt = default; + DateTimeOffset? completedAt = default; + string model = default; + string instructions = default; + IReadOnlyList tools = default; + IReadOnlyList fileIds = default; + IReadOnlyDictionary metadata = default; + RunCompletionUsage usage = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetString(); + continue; + } + if (property.NameEquals("object"u8)) + { + @object = new RunObjectObject(property.Value.GetString()); + continue; + } + if (property.NameEquals("created_at"u8)) + { + createdAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); + continue; + } + if (property.NameEquals("thread_id"u8)) + { + threadId = property.Value.GetString(); + continue; + } + if (property.NameEquals("assistant_id"u8)) + { + assistantId = property.Value.GetString(); + continue; + } + if (property.NameEquals("status"u8)) + { + status = new RunObjectStatus(property.Value.GetString()); + continue; + } + if (property.NameEquals("required_action"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + requiredAction = null; + continue; + } + requiredAction = RunObjectRequiredAction.DeserializeRunObjectRequiredAction(property.Value); + continue; + } + if (property.NameEquals("last_error"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + lastError = null; + continue; + } + lastError = RunObjectLastError.DeserializeRunObjectLastError(property.Value); + continue; + } + if (property.NameEquals("expires_at"u8)) + { + expiresAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); + continue; + } + if (property.NameEquals("started_at"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + startedAt = null; + continue; + } + startedAt = property.Value.GetDateTimeOffset("O"); + continue; + } + if (property.NameEquals("cancelled_at"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + cancelledAt = null; + continue; + } + cancelledAt = property.Value.GetDateTimeOffset("O"); + continue; + } + if (property.NameEquals("failed_at"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + failedAt = null; + continue; + } + failedAt = property.Value.GetDateTimeOffset("O"); + continue; + } + if (property.NameEquals("completed_at"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + completedAt = null; + continue; + } + completedAt = property.Value.GetDateTimeOffset("O"); + continue; + } + if (property.NameEquals("model"u8)) + { + model = property.Value.GetString(); + continue; + } + if (property.NameEquals("instructions"u8)) + { + instructions = property.Value.GetString(); + continue; + } + if (property.NameEquals("tools"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + if (item.ValueKind == JsonValueKind.Null) + { + array.Add(null); + } + else + { + array.Add(BinaryData.FromString(item.GetRawText())); + } + } + tools = array; + continue; + } + if (property.NameEquals("file_ids"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(item.GetString()); + } + fileIds = array; + continue; + } + if (property.NameEquals("metadata"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + metadata = new OptionalDictionary(); + continue; + } + Dictionary dictionary = new Dictionary(); + foreach (var property0 in property.Value.EnumerateObject()) + { + dictionary.Add(property0.Name, property0.Value.GetString()); + } + metadata = dictionary; + continue; + } + if (property.NameEquals("usage"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + usage = null; + continue; + } + usage = RunCompletionUsage.DeserializeRunCompletionUsage(property.Value); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new RunObject(id, @object, createdAt, threadId, assistantId, status, requiredAction, lastError, expiresAt, startedAt, cancelledAt, failedAt, completedAt, model, instructions, tools, fileIds, metadata, usage, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(RunObject)} does not support '{options.Format}' format."); + } + } + + RunObject IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeRunObject(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(RunObject)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static RunObject FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeRunObject(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/RunObject.cs b/.dotnet/src/Generated/Models/RunObject.cs new file mode 100644 index 000000000..8222d1eec --- /dev/null +++ b/.dotnet/src/Generated/Models/RunObject.cs @@ -0,0 +1,264 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// Represents an execution run on a [thread](/docs/api-reference/threads). + public partial class RunObject + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The identifier, which can be referenced in API endpoints. + /// The Unix timestamp (in seconds) for when the run was created. + /// + /// The ID of the [thread](/docs/api-reference/threads) that was executed on as a part of this + /// run. + /// + /// The ID of the [assistant](/docs/api-reference/assistants) used for execution of this run. + /// + /// The status of the run, which can be either `queued`, `in_progress`, `requires_action`, + /// `cancelling`, `cancelled`, `failed`, `completed`, or `expired`. + /// + /// + /// Details on the action required to continue the run. Will be `null` if no action is + /// required. + /// + /// The last error associated with this run. Will be `null` if there are no errors. + /// The Unix timestamp (in seconds) for when the run will expire. + /// The Unix timestamp (in seconds) for when the run was started. + /// The Unix timestamp (in seconds) for when the run was cancelled. + /// The Unix timestamp (in seconds) for when the run failed. + /// The Unix timestamp (in seconds) for when the run was completed. + /// The model that the [assistant](/docs/api-reference/assistants) used for this run. + /// The instructions that the [assistant](/docs/api-reference/assistants) used for this run. + /// The list of tools that the [assistant](/docs/api-reference/assistants) used for this run. + /// + /// The list of [File](/docs/api-reference/files) IDs the + /// [assistant](/docs/api-reference/assistants) used for this run. + /// + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// + /// , , , , , or is null. + internal RunObject(string id, DateTimeOffset createdAt, string threadId, string assistantId, RunObjectStatus status, RunObjectRequiredAction requiredAction, RunObjectLastError lastError, DateTimeOffset expiresAt, DateTimeOffset? startedAt, DateTimeOffset? cancelledAt, DateTimeOffset? failedAt, DateTimeOffset? completedAt, string model, string instructions, IEnumerable tools, IEnumerable fileIds, IReadOnlyDictionary metadata, RunCompletionUsage usage) + { + ClientUtilities.AssertNotNull(id, nameof(id)); + ClientUtilities.AssertNotNull(threadId, nameof(threadId)); + ClientUtilities.AssertNotNull(assistantId, nameof(assistantId)); + ClientUtilities.AssertNotNull(model, nameof(model)); + ClientUtilities.AssertNotNull(instructions, nameof(instructions)); + ClientUtilities.AssertNotNull(tools, nameof(tools)); + ClientUtilities.AssertNotNull(fileIds, nameof(fileIds)); + + Id = id; + CreatedAt = createdAt; + ThreadId = threadId; + AssistantId = assistantId; + Status = status; + RequiredAction = requiredAction; + LastError = lastError; + ExpiresAt = expiresAt; + StartedAt = startedAt; + CancelledAt = cancelledAt; + FailedAt = failedAt; + CompletedAt = completedAt; + Model = model; + Instructions = instructions; + Tools = tools.ToList(); + FileIds = fileIds.ToList(); + Metadata = metadata; + Usage = usage; + } + + /// Initializes a new instance of . + /// The identifier, which can be referenced in API endpoints. + /// The object type, which is always `thread.run`. + /// The Unix timestamp (in seconds) for when the run was created. + /// + /// The ID of the [thread](/docs/api-reference/threads) that was executed on as a part of this + /// run. + /// + /// The ID of the [assistant](/docs/api-reference/assistants) used for execution of this run. + /// + /// The status of the run, which can be either `queued`, `in_progress`, `requires_action`, + /// `cancelling`, `cancelled`, `failed`, `completed`, or `expired`. + /// + /// + /// Details on the action required to continue the run. Will be `null` if no action is + /// required. + /// + /// The last error associated with this run. Will be `null` if there are no errors. + /// The Unix timestamp (in seconds) for when the run will expire. + /// The Unix timestamp (in seconds) for when the run was started. + /// The Unix timestamp (in seconds) for when the run was cancelled. + /// The Unix timestamp (in seconds) for when the run failed. + /// The Unix timestamp (in seconds) for when the run was completed. + /// The model that the [assistant](/docs/api-reference/assistants) used for this run. + /// The instructions that the [assistant](/docs/api-reference/assistants) used for this run. + /// The list of tools that the [assistant](/docs/api-reference/assistants) used for this run. + /// + /// The list of [File](/docs/api-reference/files) IDs the + /// [assistant](/docs/api-reference/assistants) used for this run. + /// + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// + /// Keeps track of any properties unknown to the library. + internal RunObject(string id, RunObjectObject @object, DateTimeOffset createdAt, string threadId, string assistantId, RunObjectStatus status, RunObjectRequiredAction requiredAction, RunObjectLastError lastError, DateTimeOffset expiresAt, DateTimeOffset? startedAt, DateTimeOffset? cancelledAt, DateTimeOffset? failedAt, DateTimeOffset? completedAt, string model, string instructions, IReadOnlyList tools, IReadOnlyList fileIds, IReadOnlyDictionary metadata, RunCompletionUsage usage, IDictionary serializedAdditionalRawData) + { + Id = id; + Object = @object; + CreatedAt = createdAt; + ThreadId = threadId; + AssistantId = assistantId; + Status = status; + RequiredAction = requiredAction; + LastError = lastError; + ExpiresAt = expiresAt; + StartedAt = startedAt; + CancelledAt = cancelledAt; + FailedAt = failedAt; + CompletedAt = completedAt; + Model = model; + Instructions = instructions; + Tools = tools; + FileIds = fileIds; + Metadata = metadata; + Usage = usage; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal RunObject() + { + } + + /// The identifier, which can be referenced in API endpoints. + public string Id { get; } + /// The object type, which is always `thread.run`. + public RunObjectObject Object { get; } = RunObjectObject.ThreadRun; + + /// The Unix timestamp (in seconds) for when the run was created. + public DateTimeOffset CreatedAt { get; } + /// + /// The ID of the [thread](/docs/api-reference/threads) that was executed on as a part of this + /// run. + /// + public string ThreadId { get; } + /// The ID of the [assistant](/docs/api-reference/assistants) used for execution of this run. + public string AssistantId { get; } + /// + /// The status of the run, which can be either `queued`, `in_progress`, `requires_action`, + /// `cancelling`, `cancelled`, `failed`, `completed`, or `expired`. + /// + public RunObjectStatus Status { get; } + /// + /// Details on the action required to continue the run. Will be `null` if no action is + /// required. + /// + public RunObjectRequiredAction RequiredAction { get; } + /// The last error associated with this run. Will be `null` if there are no errors. + public RunObjectLastError LastError { get; } + /// The Unix timestamp (in seconds) for when the run will expire. + public DateTimeOffset ExpiresAt { get; } + /// The Unix timestamp (in seconds) for when the run was started. + public DateTimeOffset? StartedAt { get; } + /// The Unix timestamp (in seconds) for when the run was cancelled. + public DateTimeOffset? CancelledAt { get; } + /// The Unix timestamp (in seconds) for when the run failed. + public DateTimeOffset? FailedAt { get; } + /// The Unix timestamp (in seconds) for when the run was completed. + public DateTimeOffset? CompletedAt { get; } + /// The model that the [assistant](/docs/api-reference/assistants) used for this run. + public string Model { get; } + /// The instructions that the [assistant](/docs/api-reference/assistants) used for this run. + public string Instructions { get; } + /// + /// The list of tools that the [assistant](/docs/api-reference/assistants) used for this run. + /// + /// To assign an object to the element of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + public IReadOnlyList Tools { get; } + /// + /// The list of [File](/docs/api-reference/files) IDs the + /// [assistant](/docs/api-reference/assistants) used for this run. + /// + public IReadOnlyList FileIds { get; } + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + public IReadOnlyDictionary Metadata { get; } + /// Gets the usage. + public RunCompletionUsage Usage { get; } + } +} diff --git a/.dotnet/src/Generated/Models/RunObjectLastError.Serialization.cs b/.dotnet/src/Generated/Models/RunObjectLastError.Serialization.cs new file mode 100644 index 000000000..f40c2aa0a --- /dev/null +++ b/.dotnet/src/Generated/Models/RunObjectLastError.Serialization.cs @@ -0,0 +1,140 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class RunObjectLastError : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(RunObjectLastError)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("code"u8); + writer.WriteStringValue(Code.ToString()); + writer.WritePropertyName("message"u8); + writer.WriteStringValue(Message); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + RunObjectLastError IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(RunObjectLastError)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeRunObjectLastError(document.RootElement, options); + } + + internal static RunObjectLastError DeserializeRunObjectLastError(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + RunObjectLastErrorCode code = default; + string message = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("code"u8)) + { + code = new RunObjectLastErrorCode(property.Value.GetString()); + continue; + } + if (property.NameEquals("message"u8)) + { + message = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new RunObjectLastError(code, message, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(RunObjectLastError)} does not support '{options.Format}' format."); + } + } + + RunObjectLastError IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeRunObjectLastError(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(RunObjectLastError)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static RunObjectLastError FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeRunObjectLastError(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/RunObjectLastError.cs b/.dotnet/src/Generated/Models/RunObjectLastError.cs new file mode 100644 index 000000000..f2e26a107 --- /dev/null +++ b/.dotnet/src/Generated/Models/RunObjectLastError.cs @@ -0,0 +1,79 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The RunObjectLastError. + public partial class RunObjectLastError + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// One of `server_error` or `rate_limit_exceeded`. + /// A human-readable description of the error. + /// is null. + internal RunObjectLastError(RunObjectLastErrorCode code, string message) + { + ClientUtilities.AssertNotNull(message, nameof(message)); + + Code = code; + Message = message; + } + + /// Initializes a new instance of . + /// One of `server_error` or `rate_limit_exceeded`. + /// A human-readable description of the error. + /// Keeps track of any properties unknown to the library. + internal RunObjectLastError(RunObjectLastErrorCode code, string message, IDictionary serializedAdditionalRawData) + { + Code = code; + Message = message; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal RunObjectLastError() + { + } + + /// One of `server_error` or `rate_limit_exceeded`. + public RunObjectLastErrorCode Code { get; } + /// A human-readable description of the error. + public string Message { get; } + } +} diff --git a/.dotnet/src/Generated/Models/RunObjectLastErrorCode.cs b/.dotnet/src/Generated/Models/RunObjectLastErrorCode.cs new file mode 100644 index 000000000..abcb19758 --- /dev/null +++ b/.dotnet/src/Generated/Models/RunObjectLastErrorCode.cs @@ -0,0 +1,48 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for code in RunObjectLastError. + public readonly partial struct RunObjectLastErrorCode : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public RunObjectLastErrorCode(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string ServerErrorValue = "server_error"; + private const string RateLimitExceededValue = "rate_limit_exceeded"; + + /// server_error. + public static RunObjectLastErrorCode ServerError { get; } = new RunObjectLastErrorCode(ServerErrorValue); + /// rate_limit_exceeded. + public static RunObjectLastErrorCode RateLimitExceeded { get; } = new RunObjectLastErrorCode(RateLimitExceededValue); + /// Determines if two values are the same. + public static bool operator ==(RunObjectLastErrorCode left, RunObjectLastErrorCode right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(RunObjectLastErrorCode left, RunObjectLastErrorCode right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator RunObjectLastErrorCode(string value) => new RunObjectLastErrorCode(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is RunObjectLastErrorCode other && Equals(other); + /// + public bool Equals(RunObjectLastErrorCode other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/RunObjectObject.cs b/.dotnet/src/Generated/Models/RunObjectObject.cs new file mode 100644 index 000000000..c9b970b98 --- /dev/null +++ b/.dotnet/src/Generated/Models/RunObjectObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The RunObject_object. + public readonly partial struct RunObjectObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public RunObjectObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string ThreadRunValue = "thread.run"; + + /// thread.run. + public static RunObjectObject ThreadRun { get; } = new RunObjectObject(ThreadRunValue); + /// Determines if two values are the same. + public static bool operator ==(RunObjectObject left, RunObjectObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(RunObjectObject left, RunObjectObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator RunObjectObject(string value) => new RunObjectObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is RunObjectObject other && Equals(other); + /// + public bool Equals(RunObjectObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/RunObjectRequiredAction.Serialization.cs b/.dotnet/src/Generated/Models/RunObjectRequiredAction.Serialization.cs new file mode 100644 index 000000000..8b354c03e --- /dev/null +++ b/.dotnet/src/Generated/Models/RunObjectRequiredAction.Serialization.cs @@ -0,0 +1,140 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class RunObjectRequiredAction : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(RunObjectRequiredAction)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("type"u8); + writer.WriteStringValue(Type.ToString()); + writer.WritePropertyName("submit_tool_outputs"u8); + writer.WriteObjectValue(SubmitToolOutputs); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + RunObjectRequiredAction IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(RunObjectRequiredAction)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeRunObjectRequiredAction(document.RootElement, options); + } + + internal static RunObjectRequiredAction DeserializeRunObjectRequiredAction(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + RunObjectRequiredActionType type = default; + RunObjectRequiredActionSubmitToolOutputs submitToolOutputs = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("type"u8)) + { + type = new RunObjectRequiredActionType(property.Value.GetString()); + continue; + } + if (property.NameEquals("submit_tool_outputs"u8)) + { + submitToolOutputs = RunObjectRequiredActionSubmitToolOutputs.DeserializeRunObjectRequiredActionSubmitToolOutputs(property.Value); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new RunObjectRequiredAction(type, submitToolOutputs, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(RunObjectRequiredAction)} does not support '{options.Format}' format."); + } + } + + RunObjectRequiredAction IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeRunObjectRequiredAction(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(RunObjectRequiredAction)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static RunObjectRequiredAction FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeRunObjectRequiredAction(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/RunObjectRequiredAction.cs b/.dotnet/src/Generated/Models/RunObjectRequiredAction.cs new file mode 100644 index 000000000..fa11171c8 --- /dev/null +++ b/.dotnet/src/Generated/Models/RunObjectRequiredAction.cs @@ -0,0 +1,78 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The RunObjectRequiredAction. + public partial class RunObjectRequiredAction + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// Details on the tool outputs needed for this run to continue. + /// is null. + internal RunObjectRequiredAction(RunObjectRequiredActionSubmitToolOutputs submitToolOutputs) + { + ClientUtilities.AssertNotNull(submitToolOutputs, nameof(submitToolOutputs)); + + SubmitToolOutputs = submitToolOutputs; + } + + /// Initializes a new instance of . + /// For now, this is always `submit_tool_outputs`. + /// Details on the tool outputs needed for this run to continue. + /// Keeps track of any properties unknown to the library. + internal RunObjectRequiredAction(RunObjectRequiredActionType type, RunObjectRequiredActionSubmitToolOutputs submitToolOutputs, IDictionary serializedAdditionalRawData) + { + Type = type; + SubmitToolOutputs = submitToolOutputs; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal RunObjectRequiredAction() + { + } + + /// For now, this is always `submit_tool_outputs`. + public RunObjectRequiredActionType Type { get; } = RunObjectRequiredActionType.SubmitToolOutputs; + + /// Details on the tool outputs needed for this run to continue. + public RunObjectRequiredActionSubmitToolOutputs SubmitToolOutputs { get; } + } +} diff --git a/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.Serialization.cs b/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.Serialization.cs new file mode 100644 index 000000000..6f7c1b4e5 --- /dev/null +++ b/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.Serialization.cs @@ -0,0 +1,142 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class RunObjectRequiredActionSubmitToolOutputs : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(RunObjectRequiredActionSubmitToolOutputs)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("tool_calls"u8); + writer.WriteStartArray(); + foreach (var item in ToolCalls) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + RunObjectRequiredActionSubmitToolOutputs IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(RunObjectRequiredActionSubmitToolOutputs)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeRunObjectRequiredActionSubmitToolOutputs(document.RootElement, options); + } + + internal static RunObjectRequiredActionSubmitToolOutputs DeserializeRunObjectRequiredActionSubmitToolOutputs(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + IReadOnlyList toolCalls = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("tool_calls"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(RunToolCallObject.DeserializeRunToolCallObject(item)); + } + toolCalls = array; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new RunObjectRequiredActionSubmitToolOutputs(toolCalls, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(RunObjectRequiredActionSubmitToolOutputs)} does not support '{options.Format}' format."); + } + } + + RunObjectRequiredActionSubmitToolOutputs IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeRunObjectRequiredActionSubmitToolOutputs(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(RunObjectRequiredActionSubmitToolOutputs)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static RunObjectRequiredActionSubmitToolOutputs FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeRunObjectRequiredActionSubmitToolOutputs(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.cs b/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.cs new file mode 100644 index 000000000..e9f7b6a58 --- /dev/null +++ b/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.cs @@ -0,0 +1,74 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// The RunObjectRequiredActionSubmitToolOutputs. + public partial class RunObjectRequiredActionSubmitToolOutputs + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// A list of the relevant tool calls. + /// is null. + internal RunObjectRequiredActionSubmitToolOutputs(IEnumerable toolCalls) + { + ClientUtilities.AssertNotNull(toolCalls, nameof(toolCalls)); + + ToolCalls = toolCalls.ToList(); + } + + /// Initializes a new instance of . + /// A list of the relevant tool calls. + /// Keeps track of any properties unknown to the library. + internal RunObjectRequiredActionSubmitToolOutputs(IReadOnlyList toolCalls, IDictionary serializedAdditionalRawData) + { + ToolCalls = toolCalls; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal RunObjectRequiredActionSubmitToolOutputs() + { + } + + /// A list of the relevant tool calls. + public IReadOnlyList ToolCalls { get; } + } +} diff --git a/.dotnet/src/Generated/Models/RunObjectRequiredActionType.cs b/.dotnet/src/Generated/Models/RunObjectRequiredActionType.cs new file mode 100644 index 000000000..eb11f17ac --- /dev/null +++ b/.dotnet/src/Generated/Models/RunObjectRequiredActionType.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The RunObjectRequiredAction_type. + public readonly partial struct RunObjectRequiredActionType : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public RunObjectRequiredActionType(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string SubmitToolOutputsValue = "submit_tool_outputs"; + + /// submit_tool_outputs. + public static RunObjectRequiredActionType SubmitToolOutputs { get; } = new RunObjectRequiredActionType(SubmitToolOutputsValue); + /// Determines if two values are the same. + public static bool operator ==(RunObjectRequiredActionType left, RunObjectRequiredActionType right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(RunObjectRequiredActionType left, RunObjectRequiredActionType right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator RunObjectRequiredActionType(string value) => new RunObjectRequiredActionType(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is RunObjectRequiredActionType other && Equals(other); + /// + public bool Equals(RunObjectRequiredActionType other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/RunObjectStatus.cs b/.dotnet/src/Generated/Models/RunObjectStatus.cs new file mode 100644 index 000000000..52f7c1603 --- /dev/null +++ b/.dotnet/src/Generated/Models/RunObjectStatus.cs @@ -0,0 +1,66 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for status in RunObject. + public readonly partial struct RunObjectStatus : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public RunObjectStatus(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string QueuedValue = "queued"; + private const string InProgressValue = "in_progress"; + private const string RequiresActionValue = "requires_action"; + private const string CancellingValue = "cancelling"; + private const string CancelledValue = "cancelled"; + private const string FailedValue = "failed"; + private const string CompletedValue = "completed"; + private const string ExpiredValue = "expired"; + + /// queued. + public static RunObjectStatus Queued { get; } = new RunObjectStatus(QueuedValue); + /// in_progress. + public static RunObjectStatus InProgress { get; } = new RunObjectStatus(InProgressValue); + /// requires_action. + public static RunObjectStatus RequiresAction { get; } = new RunObjectStatus(RequiresActionValue); + /// cancelling. + public static RunObjectStatus Cancelling { get; } = new RunObjectStatus(CancellingValue); + /// cancelled. + public static RunObjectStatus Cancelled { get; } = new RunObjectStatus(CancelledValue); + /// failed. + public static RunObjectStatus Failed { get; } = new RunObjectStatus(FailedValue); + /// completed. + public static RunObjectStatus Completed { get; } = new RunObjectStatus(CompletedValue); + /// expired. + public static RunObjectStatus Expired { get; } = new RunObjectStatus(ExpiredValue); + /// Determines if two values are the same. + public static bool operator ==(RunObjectStatus left, RunObjectStatus right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(RunObjectStatus left, RunObjectStatus right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator RunObjectStatus(string value) => new RunObjectStatus(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is RunObjectStatus other && Equals(other); + /// + public bool Equals(RunObjectStatus other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.Serialization.cs b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.Serialization.cs new file mode 100644 index 000000000..9bfd95a67 --- /dev/null +++ b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.Serialization.cs @@ -0,0 +1,140 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + internal partial class RunStepDetailsMessageCreationObject : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(RunStepDetailsMessageCreationObject)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("type"u8); + writer.WriteStringValue(Type.ToString()); + writer.WritePropertyName("message_creation"u8); + writer.WriteObjectValue(MessageCreation); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + RunStepDetailsMessageCreationObject IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(RunStepDetailsMessageCreationObject)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeRunStepDetailsMessageCreationObject(document.RootElement, options); + } + + internal static RunStepDetailsMessageCreationObject DeserializeRunStepDetailsMessageCreationObject(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + RunStepDetailsMessageCreationObjectType type = default; + RunStepDetailsMessageCreationObjectMessageCreation messageCreation = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("type"u8)) + { + type = new RunStepDetailsMessageCreationObjectType(property.Value.GetString()); + continue; + } + if (property.NameEquals("message_creation"u8)) + { + messageCreation = RunStepDetailsMessageCreationObjectMessageCreation.DeserializeRunStepDetailsMessageCreationObjectMessageCreation(property.Value); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new RunStepDetailsMessageCreationObject(type, messageCreation, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(RunStepDetailsMessageCreationObject)} does not support '{options.Format}' format."); + } + } + + RunStepDetailsMessageCreationObject IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeRunStepDetailsMessageCreationObject(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(RunStepDetailsMessageCreationObject)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static RunStepDetailsMessageCreationObject FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeRunStepDetailsMessageCreationObject(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.cs b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.cs new file mode 100644 index 000000000..d0db44dad --- /dev/null +++ b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.cs @@ -0,0 +1,78 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// Details of the message creation by the run step. + internal partial class RunStepDetailsMessageCreationObject + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// is null. + internal RunStepDetailsMessageCreationObject(RunStepDetailsMessageCreationObjectMessageCreation messageCreation) + { + ClientUtilities.AssertNotNull(messageCreation, nameof(messageCreation)); + + MessageCreation = messageCreation; + } + + /// Initializes a new instance of . + /// Details of the message creation by the run step. + /// + /// Keeps track of any properties unknown to the library. + internal RunStepDetailsMessageCreationObject(RunStepDetailsMessageCreationObjectType type, RunStepDetailsMessageCreationObjectMessageCreation messageCreation, IDictionary serializedAdditionalRawData) + { + Type = type; + MessageCreation = messageCreation; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal RunStepDetailsMessageCreationObject() + { + } + + /// Details of the message creation by the run step. + public RunStepDetailsMessageCreationObjectType Type { get; } = RunStepDetailsMessageCreationObjectType.MessageCreation; + + /// Gets the message creation. + public RunStepDetailsMessageCreationObjectMessageCreation MessageCreation { get; } + } +} diff --git a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.Serialization.cs b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.Serialization.cs new file mode 100644 index 000000000..aadaece5e --- /dev/null +++ b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.Serialization.cs @@ -0,0 +1,132 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + internal partial class RunStepDetailsMessageCreationObjectMessageCreation : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(RunStepDetailsMessageCreationObjectMessageCreation)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("message_id"u8); + writer.WriteStringValue(MessageId); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + RunStepDetailsMessageCreationObjectMessageCreation IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(RunStepDetailsMessageCreationObjectMessageCreation)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeRunStepDetailsMessageCreationObjectMessageCreation(document.RootElement, options); + } + + internal static RunStepDetailsMessageCreationObjectMessageCreation DeserializeRunStepDetailsMessageCreationObjectMessageCreation(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string messageId = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("message_id"u8)) + { + messageId = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new RunStepDetailsMessageCreationObjectMessageCreation(messageId, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(RunStepDetailsMessageCreationObjectMessageCreation)} does not support '{options.Format}' format."); + } + } + + RunStepDetailsMessageCreationObjectMessageCreation IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeRunStepDetailsMessageCreationObjectMessageCreation(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(RunStepDetailsMessageCreationObjectMessageCreation)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static RunStepDetailsMessageCreationObjectMessageCreation FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeRunStepDetailsMessageCreationObjectMessageCreation(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.cs b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.cs new file mode 100644 index 000000000..3163ffe5c --- /dev/null +++ b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.cs @@ -0,0 +1,73 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The RunStepDetailsMessageCreationObjectMessageCreation. + internal partial class RunStepDetailsMessageCreationObjectMessageCreation + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The ID of the message that was created by this run step. + /// is null. + internal RunStepDetailsMessageCreationObjectMessageCreation(string messageId) + { + ClientUtilities.AssertNotNull(messageId, nameof(messageId)); + + MessageId = messageId; + } + + /// Initializes a new instance of . + /// The ID of the message that was created by this run step. + /// Keeps track of any properties unknown to the library. + internal RunStepDetailsMessageCreationObjectMessageCreation(string messageId, IDictionary serializedAdditionalRawData) + { + MessageId = messageId; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal RunStepDetailsMessageCreationObjectMessageCreation() + { + } + + /// The ID of the message that was created by this run step. + public string MessageId { get; } + } +} diff --git a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectType.cs b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectType.cs new file mode 100644 index 000000000..007fd9eed --- /dev/null +++ b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectType.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The RunStepDetailsMessageCreationObject_type. + internal readonly partial struct RunStepDetailsMessageCreationObjectType : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public RunStepDetailsMessageCreationObjectType(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string MessageCreationValue = "message_creation"; + + /// message_creation. + public static RunStepDetailsMessageCreationObjectType MessageCreation { get; } = new RunStepDetailsMessageCreationObjectType(MessageCreationValue); + /// Determines if two values are the same. + public static bool operator ==(RunStepDetailsMessageCreationObjectType left, RunStepDetailsMessageCreationObjectType right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(RunStepDetailsMessageCreationObjectType left, RunStepDetailsMessageCreationObjectType right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator RunStepDetailsMessageCreationObjectType(string value) => new RunStepDetailsMessageCreationObjectType(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is RunStepDetailsMessageCreationObjectType other && Equals(other); + /// + public bool Equals(RunStepDetailsMessageCreationObjectType other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.Serialization.cs b/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.Serialization.cs new file mode 100644 index 000000000..5fa47d28b --- /dev/null +++ b/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.Serialization.cs @@ -0,0 +1,169 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + internal partial class RunStepDetailsToolCallsObject : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(RunStepDetailsToolCallsObject)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("type"u8); + writer.WriteStringValue(Type.ToString()); + writer.WritePropertyName("tool_calls"u8); + writer.WriteStartArray(); + foreach (var item in ToolCalls) + { + if (item == null) + { + writer.WriteNullValue(); + continue; + } +#if NET6_0_OR_GREATER + writer.WriteRawValue(item); +#else + using (JsonDocument document = JsonDocument.Parse(item)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + writer.WriteEndArray(); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + RunStepDetailsToolCallsObject IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(RunStepDetailsToolCallsObject)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeRunStepDetailsToolCallsObject(document.RootElement, options); + } + + internal static RunStepDetailsToolCallsObject DeserializeRunStepDetailsToolCallsObject(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + RunStepDetailsToolCallsObjectType type = default; + IReadOnlyList toolCalls = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("type"u8)) + { + type = new RunStepDetailsToolCallsObjectType(property.Value.GetString()); + continue; + } + if (property.NameEquals("tool_calls"u8)) + { + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + if (item.ValueKind == JsonValueKind.Null) + { + array.Add(null); + } + else + { + array.Add(BinaryData.FromString(item.GetRawText())); + } + } + toolCalls = array; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new RunStepDetailsToolCallsObject(type, toolCalls, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(RunStepDetailsToolCallsObject)} does not support '{options.Format}' format."); + } + } + + RunStepDetailsToolCallsObject IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeRunStepDetailsToolCallsObject(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(RunStepDetailsToolCallsObject)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static RunStepDetailsToolCallsObject FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeRunStepDetailsToolCallsObject(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.cs b/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.cs new file mode 100644 index 000000000..76cdc1d4c --- /dev/null +++ b/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.cs @@ -0,0 +1,115 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// Details of the tool call. + internal partial class RunStepDetailsToolCallsObject + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// An array of tool calls the run step was involved in. These can be associated with one of three + /// types of tools: `code_interpreter`, `retrieval`, or `function`. + /// + /// is null. + internal RunStepDetailsToolCallsObject(IEnumerable toolCalls) + { + ClientUtilities.AssertNotNull(toolCalls, nameof(toolCalls)); + + ToolCalls = toolCalls.ToList(); + } + + /// Initializes a new instance of . + /// Always `tool_calls`. + /// + /// An array of tool calls the run step was involved in. These can be associated with one of three + /// types of tools: `code_interpreter`, `retrieval`, or `function`. + /// + /// Keeps track of any properties unknown to the library. + internal RunStepDetailsToolCallsObject(RunStepDetailsToolCallsObjectType type, IReadOnlyList toolCalls, IDictionary serializedAdditionalRawData) + { + Type = type; + ToolCalls = toolCalls; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal RunStepDetailsToolCallsObject() + { + } + + /// Always `tool_calls`. + public RunStepDetailsToolCallsObjectType Type { get; } = RunStepDetailsToolCallsObjectType.ToolCalls; + + /// + /// An array of tool calls the run step was involved in. These can be associated with one of three + /// types of tools: `code_interpreter`, `retrieval`, or `function`. + /// + /// To assign an object to the element of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + public IReadOnlyList ToolCalls { get; } + } +} diff --git a/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObjectType.cs b/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObjectType.cs new file mode 100644 index 000000000..56b168ac3 --- /dev/null +++ b/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObjectType.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The RunStepDetailsToolCallsObject_type. + internal readonly partial struct RunStepDetailsToolCallsObjectType : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public RunStepDetailsToolCallsObjectType(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string ToolCallsValue = "tool_calls"; + + /// tool_calls. + public static RunStepDetailsToolCallsObjectType ToolCalls { get; } = new RunStepDetailsToolCallsObjectType(ToolCallsValue); + /// Determines if two values are the same. + public static bool operator ==(RunStepDetailsToolCallsObjectType left, RunStepDetailsToolCallsObjectType right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(RunStepDetailsToolCallsObjectType left, RunStepDetailsToolCallsObjectType right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator RunStepDetailsToolCallsObjectType(string value) => new RunStepDetailsToolCallsObjectType(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is RunStepDetailsToolCallsObjectType other && Equals(other); + /// + public bool Equals(RunStepDetailsToolCallsObjectType other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/RunStepObject.Serialization.cs b/.dotnet/src/Generated/Models/RunStepObject.Serialization.cs new file mode 100644 index 000000000..74f027391 --- /dev/null +++ b/.dotnet/src/Generated/Models/RunStepObject.Serialization.cs @@ -0,0 +1,354 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class RunStepObject : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(RunStepObject)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("id"u8); + writer.WriteStringValue(Id); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + writer.WritePropertyName("created_at"u8); + writer.WriteNumberValue(CreatedAt, "U"); + writer.WritePropertyName("assistant_id"u8); + writer.WriteStringValue(AssistantId); + writer.WritePropertyName("thread_id"u8); + writer.WriteStringValue(ThreadId); + writer.WritePropertyName("run_id"u8); + writer.WriteStringValue(RunId); + writer.WritePropertyName("type"u8); + writer.WriteStringValue(Type.ToString()); + writer.WritePropertyName("status"u8); + writer.WriteStringValue(Status.ToString()); + writer.WritePropertyName("step_details"u8); +#if NET6_0_OR_GREATER + writer.WriteRawValue(StepDetails); +#else + using (JsonDocument document = JsonDocument.Parse(StepDetails)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + if (LastError != null) + { + writer.WritePropertyName("last_error"u8); + writer.WriteObjectValue(LastError); + } + else + { + writer.WriteNull("last_error"); + } + if (ExpiresAt != null) + { + writer.WritePropertyName("expires_at"u8); + writer.WriteStringValue(ExpiresAt.Value, "O"); + } + else + { + writer.WriteNull("expires_at"); + } + if (CancelledAt != null) + { + writer.WritePropertyName("cancelled_at"u8); + writer.WriteStringValue(CancelledAt.Value, "O"); + } + else + { + writer.WriteNull("cancelled_at"); + } + if (FailedAt != null) + { + writer.WritePropertyName("failed_at"u8); + writer.WriteStringValue(FailedAt.Value, "O"); + } + else + { + writer.WriteNull("failed_at"); + } + if (CompletedAt != null) + { + writer.WritePropertyName("completed_at"u8); + writer.WriteStringValue(CompletedAt.Value, "O"); + } + else + { + writer.WriteNull("completed_at"); + } + if (Metadata != null && OptionalProperty.IsCollectionDefined(Metadata)) + { + writer.WritePropertyName("metadata"u8); + writer.WriteStartObject(); + foreach (var item in Metadata) + { + writer.WritePropertyName(item.Key); + writer.WriteStringValue(item.Value); + } + writer.WriteEndObject(); + } + else + { + writer.WriteNull("metadata"); + } + if (Usage != null) + { + writer.WritePropertyName("usage"u8); + writer.WriteObjectValue(Usage); + } + else + { + writer.WriteNull("usage"); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + RunStepObject IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(RunStepObject)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeRunStepObject(document.RootElement, options); + } + + internal static RunStepObject DeserializeRunStepObject(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string id = default; + RunStepObjectObject @object = default; + DateTimeOffset createdAt = default; + string assistantId = default; + string threadId = default; + string runId = default; + RunStepObjectType type = default; + RunStepObjectStatus status = default; + BinaryData stepDetails = default; + RunStepObjectLastError lastError = default; + DateTimeOffset? expiresAt = default; + DateTimeOffset? cancelledAt = default; + DateTimeOffset? failedAt = default; + DateTimeOffset? completedAt = default; + IReadOnlyDictionary metadata = default; + RunCompletionUsage usage = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetString(); + continue; + } + if (property.NameEquals("object"u8)) + { + @object = new RunStepObjectObject(property.Value.GetString()); + continue; + } + if (property.NameEquals("created_at"u8)) + { + createdAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); + continue; + } + if (property.NameEquals("assistant_id"u8)) + { + assistantId = property.Value.GetString(); + continue; + } + if (property.NameEquals("thread_id"u8)) + { + threadId = property.Value.GetString(); + continue; + } + if (property.NameEquals("run_id"u8)) + { + runId = property.Value.GetString(); + continue; + } + if (property.NameEquals("type"u8)) + { + type = new RunStepObjectType(property.Value.GetString()); + continue; + } + if (property.NameEquals("status"u8)) + { + status = new RunStepObjectStatus(property.Value.GetString()); + continue; + } + if (property.NameEquals("step_details"u8)) + { + stepDetails = BinaryData.FromString(property.Value.GetRawText()); + continue; + } + if (property.NameEquals("last_error"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + lastError = null; + continue; + } + lastError = RunStepObjectLastError.DeserializeRunStepObjectLastError(property.Value); + continue; + } + if (property.NameEquals("expires_at"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + expiresAt = null; + continue; + } + expiresAt = property.Value.GetDateTimeOffset("O"); + continue; + } + if (property.NameEquals("cancelled_at"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + cancelledAt = null; + continue; + } + cancelledAt = property.Value.GetDateTimeOffset("O"); + continue; + } + if (property.NameEquals("failed_at"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + failedAt = null; + continue; + } + failedAt = property.Value.GetDateTimeOffset("O"); + continue; + } + if (property.NameEquals("completed_at"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + completedAt = null; + continue; + } + completedAt = property.Value.GetDateTimeOffset("O"); + continue; + } + if (property.NameEquals("metadata"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + metadata = new OptionalDictionary(); + continue; + } + Dictionary dictionary = new Dictionary(); + foreach (var property0 in property.Value.EnumerateObject()) + { + dictionary.Add(property0.Name, property0.Value.GetString()); + } + metadata = dictionary; + continue; + } + if (property.NameEquals("usage"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + usage = null; + continue; + } + usage = RunCompletionUsage.DeserializeRunCompletionUsage(property.Value); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new RunStepObject(id, @object, createdAt, assistantId, threadId, runId, type, status, stepDetails, lastError, expiresAt, cancelledAt, failedAt, completedAt, metadata, usage, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(RunStepObject)} does not support '{options.Format}' format."); + } + } + + RunStepObject IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeRunStepObject(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(RunStepObject)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static RunStepObject FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeRunStepObject(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/RunStepObject.cs b/.dotnet/src/Generated/Models/RunStepObject.cs new file mode 100644 index 000000000..801dc2367 --- /dev/null +++ b/.dotnet/src/Generated/Models/RunStepObject.cs @@ -0,0 +1,236 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// Represents a step in execution of a run. + public partial class RunStepObject + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The identifier of the run step, which can be referenced in API endpoints. + /// The Unix timestamp (in seconds) for when the run step was created. + /// The ID of the [assistant](/docs/api-reference/assistants) associated with the run step. + /// The ID of the [thread](/docs/api-reference/threads) that was run. + /// The ID of the [run](/docs/api-reference/runs) that this run step is a part of. + /// The type of run step, which can be either `message_creation` or `tool_calls`. + /// + /// The status of the run step, which can be either `in_progress`, `cancelled`, `failed`, + /// `completed`, or `expired`. + /// + /// The details of the run step. + /// The last error associated with this run step. Will be `null` if there are no errors. + /// + /// The Unix timestamp (in seconds) for when the run step expired. A step is considered expired + /// if the parent run is expired. + /// + /// The Unix timestamp (in seconds) for when the run step was cancelled. + /// The Unix timestamp (in seconds) for when the run step failed. + /// T The Unix timestamp (in seconds) for when the run step completed.. + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// + /// , , , or is null. + internal RunStepObject(string id, DateTimeOffset createdAt, string assistantId, string threadId, string runId, RunStepObjectType type, RunStepObjectStatus status, BinaryData stepDetails, RunStepObjectLastError lastError, DateTimeOffset? expiresAt, DateTimeOffset? cancelledAt, DateTimeOffset? failedAt, DateTimeOffset? completedAt, IReadOnlyDictionary metadata, RunCompletionUsage usage) + { + ClientUtilities.AssertNotNull(id, nameof(id)); + ClientUtilities.AssertNotNull(assistantId, nameof(assistantId)); + ClientUtilities.AssertNotNull(threadId, nameof(threadId)); + ClientUtilities.AssertNotNull(runId, nameof(runId)); + ClientUtilities.AssertNotNull(stepDetails, nameof(stepDetails)); + + Id = id; + CreatedAt = createdAt; + AssistantId = assistantId; + ThreadId = threadId; + RunId = runId; + Type = type; + Status = status; + StepDetails = stepDetails; + LastError = lastError; + ExpiresAt = expiresAt; + CancelledAt = cancelledAt; + FailedAt = failedAt; + CompletedAt = completedAt; + Metadata = metadata; + Usage = usage; + } + + /// Initializes a new instance of . + /// The identifier of the run step, which can be referenced in API endpoints. + /// The object type, which is always `thread.run.step`. + /// The Unix timestamp (in seconds) for when the run step was created. + /// The ID of the [assistant](/docs/api-reference/assistants) associated with the run step. + /// The ID of the [thread](/docs/api-reference/threads) that was run. + /// The ID of the [run](/docs/api-reference/runs) that this run step is a part of. + /// The type of run step, which can be either `message_creation` or `tool_calls`. + /// + /// The status of the run step, which can be either `in_progress`, `cancelled`, `failed`, + /// `completed`, or `expired`. + /// + /// The details of the run step. + /// The last error associated with this run step. Will be `null` if there are no errors. + /// + /// The Unix timestamp (in seconds) for when the run step expired. A step is considered expired + /// if the parent run is expired. + /// + /// The Unix timestamp (in seconds) for when the run step was cancelled. + /// The Unix timestamp (in seconds) for when the run step failed. + /// T The Unix timestamp (in seconds) for when the run step completed.. + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// + /// Keeps track of any properties unknown to the library. + internal RunStepObject(string id, RunStepObjectObject @object, DateTimeOffset createdAt, string assistantId, string threadId, string runId, RunStepObjectType type, RunStepObjectStatus status, BinaryData stepDetails, RunStepObjectLastError lastError, DateTimeOffset? expiresAt, DateTimeOffset? cancelledAt, DateTimeOffset? failedAt, DateTimeOffset? completedAt, IReadOnlyDictionary metadata, RunCompletionUsage usage, IDictionary serializedAdditionalRawData) + { + Id = id; + Object = @object; + CreatedAt = createdAt; + AssistantId = assistantId; + ThreadId = threadId; + RunId = runId; + Type = type; + Status = status; + StepDetails = stepDetails; + LastError = lastError; + ExpiresAt = expiresAt; + CancelledAt = cancelledAt; + FailedAt = failedAt; + CompletedAt = completedAt; + Metadata = metadata; + Usage = usage; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal RunStepObject() + { + } + + /// The identifier of the run step, which can be referenced in API endpoints. + public string Id { get; } + /// The object type, which is always `thread.run.step`. + public RunStepObjectObject Object { get; } = RunStepObjectObject.ThreadRunStep; + + /// The Unix timestamp (in seconds) for when the run step was created. + public DateTimeOffset CreatedAt { get; } + /// The ID of the [assistant](/docs/api-reference/assistants) associated with the run step. + public string AssistantId { get; } + /// The ID of the [thread](/docs/api-reference/threads) that was run. + public string ThreadId { get; } + /// The ID of the [run](/docs/api-reference/runs) that this run step is a part of. + public string RunId { get; } + /// The type of run step, which can be either `message_creation` or `tool_calls`. + public RunStepObjectType Type { get; } + /// + /// The status of the run step, which can be either `in_progress`, `cancelled`, `failed`, + /// `completed`, or `expired`. + /// + public RunStepObjectStatus Status { get; } + /// + /// The details of the run step. + /// + /// To assign an object to this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// + /// Supported types: + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + public BinaryData StepDetails { get; } + /// The last error associated with this run step. Will be `null` if there are no errors. + public RunStepObjectLastError LastError { get; } + /// + /// The Unix timestamp (in seconds) for when the run step expired. A step is considered expired + /// if the parent run is expired. + /// + public DateTimeOffset? ExpiresAt { get; } + /// The Unix timestamp (in seconds) for when the run step was cancelled. + public DateTimeOffset? CancelledAt { get; } + /// The Unix timestamp (in seconds) for when the run step failed. + public DateTimeOffset? FailedAt { get; } + /// T The Unix timestamp (in seconds) for when the run step completed.. + public DateTimeOffset? CompletedAt { get; } + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + public IReadOnlyDictionary Metadata { get; } + /// Gets the usage. + public RunCompletionUsage Usage { get; } + } +} diff --git a/.dotnet/src/Generated/Models/RunStepObjectLastError.Serialization.cs b/.dotnet/src/Generated/Models/RunStepObjectLastError.Serialization.cs new file mode 100644 index 000000000..368f9006e --- /dev/null +++ b/.dotnet/src/Generated/Models/RunStepObjectLastError.Serialization.cs @@ -0,0 +1,140 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class RunStepObjectLastError : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(RunStepObjectLastError)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("code"u8); + writer.WriteStringValue(Code.ToString()); + writer.WritePropertyName("message"u8); + writer.WriteStringValue(Message); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + RunStepObjectLastError IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(RunStepObjectLastError)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeRunStepObjectLastError(document.RootElement, options); + } + + internal static RunStepObjectLastError DeserializeRunStepObjectLastError(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + RunStepObjectLastErrorCode code = default; + string message = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("code"u8)) + { + code = new RunStepObjectLastErrorCode(property.Value.GetString()); + continue; + } + if (property.NameEquals("message"u8)) + { + message = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new RunStepObjectLastError(code, message, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(RunStepObjectLastError)} does not support '{options.Format}' format."); + } + } + + RunStepObjectLastError IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeRunStepObjectLastError(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(RunStepObjectLastError)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static RunStepObjectLastError FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeRunStepObjectLastError(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/RunStepObjectLastError.cs b/.dotnet/src/Generated/Models/RunStepObjectLastError.cs new file mode 100644 index 000000000..8742db0c0 --- /dev/null +++ b/.dotnet/src/Generated/Models/RunStepObjectLastError.cs @@ -0,0 +1,79 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The RunStepObjectLastError. + public partial class RunStepObjectLastError + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// One of `server_error` or `rate_limit_exceeded`. + /// A human-readable description of the error. + /// is null. + internal RunStepObjectLastError(RunStepObjectLastErrorCode code, string message) + { + ClientUtilities.AssertNotNull(message, nameof(message)); + + Code = code; + Message = message; + } + + /// Initializes a new instance of . + /// One of `server_error` or `rate_limit_exceeded`. + /// A human-readable description of the error. + /// Keeps track of any properties unknown to the library. + internal RunStepObjectLastError(RunStepObjectLastErrorCode code, string message, IDictionary serializedAdditionalRawData) + { + Code = code; + Message = message; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal RunStepObjectLastError() + { + } + + /// One of `server_error` or `rate_limit_exceeded`. + public RunStepObjectLastErrorCode Code { get; } + /// A human-readable description of the error. + public string Message { get; } + } +} diff --git a/.dotnet/src/Generated/Models/RunStepObjectLastErrorCode.cs b/.dotnet/src/Generated/Models/RunStepObjectLastErrorCode.cs new file mode 100644 index 000000000..e3b156259 --- /dev/null +++ b/.dotnet/src/Generated/Models/RunStepObjectLastErrorCode.cs @@ -0,0 +1,48 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for code in RunStepObjectLastError. + public readonly partial struct RunStepObjectLastErrorCode : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public RunStepObjectLastErrorCode(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string ServerErrorValue = "server_error"; + private const string RateLimitExceededValue = "rate_limit_exceeded"; + + /// server_error. + public static RunStepObjectLastErrorCode ServerError { get; } = new RunStepObjectLastErrorCode(ServerErrorValue); + /// rate_limit_exceeded. + public static RunStepObjectLastErrorCode RateLimitExceeded { get; } = new RunStepObjectLastErrorCode(RateLimitExceededValue); + /// Determines if two values are the same. + public static bool operator ==(RunStepObjectLastErrorCode left, RunStepObjectLastErrorCode right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(RunStepObjectLastErrorCode left, RunStepObjectLastErrorCode right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator RunStepObjectLastErrorCode(string value) => new RunStepObjectLastErrorCode(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is RunStepObjectLastErrorCode other && Equals(other); + /// + public bool Equals(RunStepObjectLastErrorCode other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/RunStepObjectObject.cs b/.dotnet/src/Generated/Models/RunStepObjectObject.cs new file mode 100644 index 000000000..3c774719f --- /dev/null +++ b/.dotnet/src/Generated/Models/RunStepObjectObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The RunStepObject_object. + public readonly partial struct RunStepObjectObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public RunStepObjectObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string ThreadRunStepValue = "thread.run.step"; + + /// thread.run.step. + public static RunStepObjectObject ThreadRunStep { get; } = new RunStepObjectObject(ThreadRunStepValue); + /// Determines if two values are the same. + public static bool operator ==(RunStepObjectObject left, RunStepObjectObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(RunStepObjectObject left, RunStepObjectObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator RunStepObjectObject(string value) => new RunStepObjectObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is RunStepObjectObject other && Equals(other); + /// + public bool Equals(RunStepObjectObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/RunStepObjectStatus.cs b/.dotnet/src/Generated/Models/RunStepObjectStatus.cs new file mode 100644 index 000000000..4b11e62a4 --- /dev/null +++ b/.dotnet/src/Generated/Models/RunStepObjectStatus.cs @@ -0,0 +1,57 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for status in RunStepObject. + public readonly partial struct RunStepObjectStatus : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public RunStepObjectStatus(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string InProgressValue = "in_progress"; + private const string CancelledValue = "cancelled"; + private const string FailedValue = "failed"; + private const string CompletedValue = "completed"; + private const string ExpiredValue = "expired"; + + /// in_progress. + public static RunStepObjectStatus InProgress { get; } = new RunStepObjectStatus(InProgressValue); + /// cancelled. + public static RunStepObjectStatus Cancelled { get; } = new RunStepObjectStatus(CancelledValue); + /// failed. + public static RunStepObjectStatus Failed { get; } = new RunStepObjectStatus(FailedValue); + /// completed. + public static RunStepObjectStatus Completed { get; } = new RunStepObjectStatus(CompletedValue); + /// expired. + public static RunStepObjectStatus Expired { get; } = new RunStepObjectStatus(ExpiredValue); + /// Determines if two values are the same. + public static bool operator ==(RunStepObjectStatus left, RunStepObjectStatus right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(RunStepObjectStatus left, RunStepObjectStatus right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator RunStepObjectStatus(string value) => new RunStepObjectStatus(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is RunStepObjectStatus other && Equals(other); + /// + public bool Equals(RunStepObjectStatus other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/RunStepObjectType.cs b/.dotnet/src/Generated/Models/RunStepObjectType.cs new file mode 100644 index 000000000..49adee903 --- /dev/null +++ b/.dotnet/src/Generated/Models/RunStepObjectType.cs @@ -0,0 +1,48 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for type in RunStepObject. + public readonly partial struct RunStepObjectType : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public RunStepObjectType(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string MessageCreationValue = "message_creation"; + private const string ToolCallsValue = "tool_calls"; + + /// message_creation. + public static RunStepObjectType MessageCreation { get; } = new RunStepObjectType(MessageCreationValue); + /// tool_calls. + public static RunStepObjectType ToolCalls { get; } = new RunStepObjectType(ToolCallsValue); + /// Determines if two values are the same. + public static bool operator ==(RunStepObjectType left, RunStepObjectType right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(RunStepObjectType left, RunStepObjectType right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator RunStepObjectType(string value) => new RunStepObjectType(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is RunStepObjectType other && Equals(other); + /// + public bool Equals(RunStepObjectType other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/RunToolCallObject.Serialization.cs b/.dotnet/src/Generated/Models/RunToolCallObject.Serialization.cs new file mode 100644 index 000000000..421bb3a02 --- /dev/null +++ b/.dotnet/src/Generated/Models/RunToolCallObject.Serialization.cs @@ -0,0 +1,148 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class RunToolCallObject : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(RunToolCallObject)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("id"u8); + writer.WriteStringValue(Id); + writer.WritePropertyName("type"u8); + writer.WriteStringValue(Type.ToString()); + writer.WritePropertyName("function"u8); + writer.WriteObjectValue(Function); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + RunToolCallObject IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(RunToolCallObject)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeRunToolCallObject(document.RootElement, options); + } + + internal static RunToolCallObject DeserializeRunToolCallObject(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string id = default; + RunToolCallObjectType type = default; + RunToolCallObjectFunction function = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetString(); + continue; + } + if (property.NameEquals("type"u8)) + { + type = new RunToolCallObjectType(property.Value.GetString()); + continue; + } + if (property.NameEquals("function"u8)) + { + function = RunToolCallObjectFunction.DeserializeRunToolCallObjectFunction(property.Value); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new RunToolCallObject(id, type, function, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(RunToolCallObject)} does not support '{options.Format}' format."); + } + } + + RunToolCallObject IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeRunToolCallObject(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(RunToolCallObject)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static RunToolCallObject FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeRunToolCallObject(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/RunToolCallObject.cs b/.dotnet/src/Generated/Models/RunToolCallObject.cs new file mode 100644 index 000000000..b6f3694a3 --- /dev/null +++ b/.dotnet/src/Generated/Models/RunToolCallObject.cs @@ -0,0 +1,94 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// Tool call objects. + public partial class RunToolCallObject + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// + /// The ID of the tool call. This ID must be referenced when you submit the tool outputs in using + /// the [Submit tool outputs to run](/docs/api-reference/runs/submitToolOutputs) endpoint. + /// + /// The function definition. + /// or is null. + internal RunToolCallObject(string id, RunToolCallObjectFunction function) + { + ClientUtilities.AssertNotNull(id, nameof(id)); + ClientUtilities.AssertNotNull(function, nameof(function)); + + Id = id; + Function = function; + } + + /// Initializes a new instance of . + /// + /// The ID of the tool call. This ID must be referenced when you submit the tool outputs in using + /// the [Submit tool outputs to run](/docs/api-reference/runs/submitToolOutputs) endpoint. + /// + /// The type of tool call the output is required for. For now, this is always `function`. + /// The function definition. + /// Keeps track of any properties unknown to the library. + internal RunToolCallObject(string id, RunToolCallObjectType type, RunToolCallObjectFunction function, IDictionary serializedAdditionalRawData) + { + Id = id; + Type = type; + Function = function; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal RunToolCallObject() + { + } + + /// + /// The ID of the tool call. This ID must be referenced when you submit the tool outputs in using + /// the [Submit tool outputs to run](/docs/api-reference/runs/submitToolOutputs) endpoint. + /// + public string Id { get; } + /// The type of tool call the output is required for. For now, this is always `function`. + public RunToolCallObjectType Type { get; } = RunToolCallObjectType.Function; + + /// The function definition. + public RunToolCallObjectFunction Function { get; } + } +} diff --git a/.dotnet/src/Generated/Models/RunToolCallObjectFunction.Serialization.cs b/.dotnet/src/Generated/Models/RunToolCallObjectFunction.Serialization.cs new file mode 100644 index 000000000..ecef680d8 --- /dev/null +++ b/.dotnet/src/Generated/Models/RunToolCallObjectFunction.Serialization.cs @@ -0,0 +1,140 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class RunToolCallObjectFunction : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(RunToolCallObjectFunction)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + writer.WritePropertyName("arguments"u8); + writer.WriteStringValue(Arguments); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + RunToolCallObjectFunction IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(RunToolCallObjectFunction)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeRunToolCallObjectFunction(document.RootElement, options); + } + + internal static RunToolCallObjectFunction DeserializeRunToolCallObjectFunction(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string name = default; + string arguments = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("arguments"u8)) + { + arguments = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new RunToolCallObjectFunction(name, arguments, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(RunToolCallObjectFunction)} does not support '{options.Format}' format."); + } + } + + RunToolCallObjectFunction IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeRunToolCallObjectFunction(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(RunToolCallObjectFunction)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static RunToolCallObjectFunction FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeRunToolCallObjectFunction(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/RunToolCallObjectFunction.cs b/.dotnet/src/Generated/Models/RunToolCallObjectFunction.cs new file mode 100644 index 000000000..c94197dac --- /dev/null +++ b/.dotnet/src/Generated/Models/RunToolCallObjectFunction.cs @@ -0,0 +1,80 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The RunToolCallObjectFunction. + public partial class RunToolCallObjectFunction + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The name of the function. + /// The arguments that the model expects you to pass to the function. + /// or is null. + internal RunToolCallObjectFunction(string name, string arguments) + { + ClientUtilities.AssertNotNull(name, nameof(name)); + ClientUtilities.AssertNotNull(arguments, nameof(arguments)); + + Name = name; + Arguments = arguments; + } + + /// Initializes a new instance of . + /// The name of the function. + /// The arguments that the model expects you to pass to the function. + /// Keeps track of any properties unknown to the library. + internal RunToolCallObjectFunction(string name, string arguments, IDictionary serializedAdditionalRawData) + { + Name = name; + Arguments = arguments; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal RunToolCallObjectFunction() + { + } + + /// The name of the function. + public string Name { get; } + /// The arguments that the model expects you to pass to the function. + public string Arguments { get; } + } +} diff --git a/.dotnet/src/Generated/Models/RunToolCallObjectType.cs b/.dotnet/src/Generated/Models/RunToolCallObjectType.cs new file mode 100644 index 000000000..fb277c525 --- /dev/null +++ b/.dotnet/src/Generated/Models/RunToolCallObjectType.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The RunToolCallObject_type. + public readonly partial struct RunToolCallObjectType : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public RunToolCallObjectType(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string FunctionValue = "function"; + + /// function. + public static RunToolCallObjectType Function { get; } = new RunToolCallObjectType(FunctionValue); + /// Determines if two values are the same. + public static bool operator ==(RunToolCallObjectType left, RunToolCallObjectType right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(RunToolCallObjectType left, RunToolCallObjectType right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator RunToolCallObjectType(string value) => new RunToolCallObjectType(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is RunToolCallObjectType other && Equals(other); + /// + public bool Equals(RunToolCallObjectType other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.Serialization.cs b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.Serialization.cs new file mode 100644 index 000000000..b1c71aec2 --- /dev/null +++ b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.Serialization.cs @@ -0,0 +1,132 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class SubmitToolOutputsRunRequest : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(SubmitToolOutputsRunRequest)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("tool_outputs"u8); + writer.WriteObjectValue(ToolOutputs); + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + SubmitToolOutputsRunRequest IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(SubmitToolOutputsRunRequest)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeSubmitToolOutputsRunRequest(document.RootElement, options); + } + + internal static SubmitToolOutputsRunRequest DeserializeSubmitToolOutputsRunRequest(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + SubmitToolOutputsRunRequestToolOutputs toolOutputs = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("tool_outputs"u8)) + { + toolOutputs = SubmitToolOutputsRunRequestToolOutputs.DeserializeSubmitToolOutputsRunRequestToolOutputs(property.Value); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new SubmitToolOutputsRunRequest(toolOutputs, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(SubmitToolOutputsRunRequest)} does not support '{options.Format}' format."); + } + } + + SubmitToolOutputsRunRequest IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeSubmitToolOutputsRunRequest(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(SubmitToolOutputsRunRequest)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static SubmitToolOutputsRunRequest FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeSubmitToolOutputsRunRequest(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.cs b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.cs new file mode 100644 index 000000000..47d39c5d4 --- /dev/null +++ b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.cs @@ -0,0 +1,73 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The SubmitToolOutputsRunRequest. + public partial class SubmitToolOutputsRunRequest + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// A list of tools for which the outputs are being submitted. + /// is null. + public SubmitToolOutputsRunRequest(SubmitToolOutputsRunRequestToolOutputs toolOutputs) + { + ClientUtilities.AssertNotNull(toolOutputs, nameof(toolOutputs)); + + ToolOutputs = toolOutputs; + } + + /// Initializes a new instance of . + /// A list of tools for which the outputs are being submitted. + /// Keeps track of any properties unknown to the library. + internal SubmitToolOutputsRunRequest(SubmitToolOutputsRunRequestToolOutputs toolOutputs, IDictionary serializedAdditionalRawData) + { + ToolOutputs = toolOutputs; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal SubmitToolOutputsRunRequest() + { + } + + /// A list of tools for which the outputs are being submitted. + public SubmitToolOutputsRunRequestToolOutputs ToolOutputs { get; } + } +} diff --git a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutputs.Serialization.cs b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutputs.Serialization.cs new file mode 100644 index 000000000..dc7e3a12d --- /dev/null +++ b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutputs.Serialization.cs @@ -0,0 +1,146 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class SubmitToolOutputsRunRequestToolOutputs : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(SubmitToolOutputsRunRequestToolOutputs)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + if (OptionalProperty.IsDefined(ToolCallId)) + { + writer.WritePropertyName("tool_call_id"u8); + writer.WriteStringValue(ToolCallId); + } + if (OptionalProperty.IsDefined(Output)) + { + writer.WritePropertyName("output"u8); + writer.WriteStringValue(Output); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + SubmitToolOutputsRunRequestToolOutputs IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(SubmitToolOutputsRunRequestToolOutputs)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeSubmitToolOutputsRunRequestToolOutputs(document.RootElement, options); + } + + internal static SubmitToolOutputsRunRequestToolOutputs DeserializeSubmitToolOutputsRunRequestToolOutputs(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + OptionalProperty toolCallId = default; + OptionalProperty output = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("tool_call_id"u8)) + { + toolCallId = property.Value.GetString(); + continue; + } + if (property.NameEquals("output"u8)) + { + output = property.Value.GetString(); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new SubmitToolOutputsRunRequestToolOutputs(toolCallId.Value, output.Value, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(SubmitToolOutputsRunRequestToolOutputs)} does not support '{options.Format}' format."); + } + } + + SubmitToolOutputsRunRequestToolOutputs IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeSubmitToolOutputsRunRequestToolOutputs(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(SubmitToolOutputsRunRequestToolOutputs)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static SubmitToolOutputsRunRequestToolOutputs FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeSubmitToolOutputsRunRequestToolOutputs(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutputs.cs b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutputs.cs new file mode 100644 index 000000000..45de2cc25 --- /dev/null +++ b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutputs.cs @@ -0,0 +1,72 @@ +// + +#nullable disable + +using System; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// The SubmitToolOutputsRunRequestToolOutputs. + public partial class SubmitToolOutputsRunRequestToolOutputs + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + public SubmitToolOutputsRunRequestToolOutputs() + { + } + + /// Initializes a new instance of . + /// + /// The ID of the tool call in the `required_action` object within the run object the output is + /// being submitted for. + /// + /// The output of the tool call to be submitted to continue the run. + /// Keeps track of any properties unknown to the library. + internal SubmitToolOutputsRunRequestToolOutputs(string toolCallId, string output, IDictionary serializedAdditionalRawData) + { + ToolCallId = toolCallId; + Output = output; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// + /// The ID of the tool call in the `required_action` object within the run object the output is + /// being submitted for. + /// + public string ToolCallId { get; set; } + /// The output of the tool call to be submitted to continue the run. + public string Output { get; set; } + } +} diff --git a/.dotnet/src/Generated/Models/ThreadObject.Serialization.cs b/.dotnet/src/Generated/Models/ThreadObject.Serialization.cs new file mode 100644 index 000000000..1d3b80be1 --- /dev/null +++ b/.dotnet/src/Generated/Models/ThreadObject.Serialization.cs @@ -0,0 +1,179 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class ThreadObject : IUtf8JsonWriteable, IJsonModel + { + void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ThreadObject)} does not support '{format}' format."); + } + + writer.WriteStartObject(); + writer.WritePropertyName("id"u8); + writer.WriteStringValue(Id); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + writer.WritePropertyName("created_at"u8); + writer.WriteNumberValue(CreatedAt, "U"); + if (Metadata != null && OptionalProperty.IsCollectionDefined(Metadata)) + { + writer.WritePropertyName("metadata"u8); + writer.WriteStartObject(); + foreach (var item in Metadata) + { + writer.WritePropertyName(item.Key); + writer.WriteStringValue(item.Value); + } + writer.WriteEndObject(); + } + else + { + writer.WriteNull("metadata"); + } + if (options.Format != "W" && _serializedAdditionalRawData != null) + { + foreach (var item in _serializedAdditionalRawData) + { + writer.WritePropertyName(item.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(item.Value); +#else + using (JsonDocument document = JsonDocument.Parse(item.Value)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + } + writer.WriteEndObject(); + } + + ThreadObject IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ThreadObject)} does not support '{format}' format."); + } + + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeThreadObject(document.RootElement, options); + } + + internal static ThreadObject DeserializeThreadObject(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string id = default; + ThreadObjectObject @object = default; + DateTimeOffset createdAt = default; + IReadOnlyDictionary metadata = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetString(); + continue; + } + if (property.NameEquals("object"u8)) + { + @object = new ThreadObjectObject(property.Value.GetString()); + continue; + } + if (property.NameEquals("created_at"u8)) + { + createdAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); + continue; + } + if (property.NameEquals("metadata"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + metadata = new OptionalDictionary(); + continue; + } + Dictionary dictionary = new Dictionary(); + foreach (var property0 in property.Value.EnumerateObject()) + { + dictionary.Add(property0.Name, property0.Value.GetString()); + } + metadata = dictionary; + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new ThreadObject(id, @object, createdAt, metadata, serializedAdditionalRawData); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ThreadObject)} does not support '{options.Format}' format."); + } + } + + ThreadObject IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeThreadObject(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ThreadObject)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + /// Deserializes the model from a raw response. + /// The result to deserialize the model from. + internal static ThreadObject FromResponse(PipelineResponse response) + { + using var document = JsonDocument.Parse(response.Content); + return DeserializeThreadObject(document.RootElement); + } + + /// Convert into a Utf8JsonRequestBody. + internal virtual RequestBody ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } + } +} diff --git a/.dotnet/src/Generated/Models/ThreadObject.cs b/.dotnet/src/Generated/Models/ThreadObject.cs new file mode 100644 index 000000000..600c5b250 --- /dev/null +++ b/.dotnet/src/Generated/Models/ThreadObject.cs @@ -0,0 +1,102 @@ +// + +#nullable disable + +using System; +using System.ClientModel.Internal; +using System.Collections.Generic; + +namespace OpenAI.Models +{ + /// Represents a thread that contains [messages](/docs/api-reference/messages). + public partial class ThreadObject + { + /// + /// Keeps track of any properties unknown to the library. + /// + /// To assign an object to the value of this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + private IDictionary _serializedAdditionalRawData; + + /// Initializes a new instance of . + /// The identifier, which can be referenced in API endpoints. + /// The Unix timestamp (in seconds) for when the thread was created. + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// is null. + internal ThreadObject(string id, DateTimeOffset createdAt, IReadOnlyDictionary metadata) + { + ClientUtilities.AssertNotNull(id, nameof(id)); + + Id = id; + CreatedAt = createdAt; + Metadata = metadata; + } + + /// Initializes a new instance of . + /// The identifier, which can be referenced in API endpoints. + /// The object type, which is always `thread`. + /// The Unix timestamp (in seconds) for when the thread was created. + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// Keeps track of any properties unknown to the library. + internal ThreadObject(string id, ThreadObjectObject @object, DateTimeOffset createdAt, IReadOnlyDictionary metadata, IDictionary serializedAdditionalRawData) + { + Id = id; + Object = @object; + CreatedAt = createdAt; + Metadata = metadata; + _serializedAdditionalRawData = serializedAdditionalRawData; + } + + /// Initializes a new instance of for deserialization. + internal ThreadObject() + { + } + + /// The identifier, which can be referenced in API endpoints. + public string Id { get; } + /// The object type, which is always `thread`. + public ThreadObjectObject Object { get; } = ThreadObjectObject.Thread; + + /// The Unix timestamp (in seconds) for when the thread was created. + public DateTimeOffset CreatedAt { get; } + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + public IReadOnlyDictionary Metadata { get; } + } +} diff --git a/.dotnet/src/Generated/Models/ThreadObjectObject.cs b/.dotnet/src/Generated/Models/ThreadObjectObject.cs new file mode 100644 index 000000000..4fd5f5e05 --- /dev/null +++ b/.dotnet/src/Generated/Models/ThreadObjectObject.cs @@ -0,0 +1,45 @@ +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The ThreadObject_object. + public readonly partial struct ThreadObjectObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public ThreadObjectObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string ThreadValue = "thread"; + + /// thread. + public static ThreadObjectObject Thread { get; } = new ThreadObjectObject(ThreadValue); + /// Determines if two values are the same. + public static bool operator ==(ThreadObjectObject left, ThreadObjectObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(ThreadObjectObject left, ThreadObjectObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator ThreadObjectObject(string value) => new ThreadObjectObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is ThreadObjectObject other && Equals(other); + /// + public bool Equals(ThreadObjectObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/ModelsOps.cs b/.dotnet/src/Generated/ModelsOps.cs new file mode 100644 index 000000000..5b9442920 --- /dev/null +++ b/.dotnet/src/Generated/ModelsOps.cs @@ -0,0 +1,419 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.ClientModel.Primitives.Pipeline; +using System.Threading; +using System.Threading.Tasks; +using OpenAI.Models; + +namespace OpenAI +{ + // Data plane generated sub-client. + /// The ModelsOps sub-client. + public partial class ModelsOps + { + private const string AuthorizationHeader = "Authorization"; + private readonly KeyCredential _keyCredential; + private const string AuthorizationApiKeyPrefix = "Bearer"; + private readonly MessagePipeline _pipeline; + private readonly Uri _endpoint; + + /// The ClientDiagnostics is used to provide tracing support for the client library. + internal TelemetrySource ClientDiagnostics { get; } + + /// The HTTP pipeline for sending and receiving REST requests and responses. + public virtual MessagePipeline Pipeline => _pipeline; + + /// Initializes a new instance of ModelsOps for mocking. + protected ModelsOps() + { + } + + /// Initializes a new instance of ModelsOps. + /// The handler for diagnostic messaging in the client. + /// The HTTP pipeline for sending and receiving REST requests and responses. + /// The key credential to copy. + /// OpenAI Endpoint. + internal ModelsOps(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + { + ClientDiagnostics = clientDiagnostics; + _pipeline = pipeline; + _keyCredential = keyCredential; + _endpoint = endpoint; + } + + /// + /// Lists the currently available models, and provides basic information about each one such as the + /// owner and availability. + /// + /// The cancellation token to use. + public virtual async Task> GetModelsAsync(CancellationToken cancellationToken = default) + { + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await GetModelsAsync(context).ConfigureAwait(false); + return Result.FromValue(ListModelsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// Lists the currently available models, and provides basic information about each one such as the + /// owner and availability. + /// + /// The cancellation token to use. + public virtual Result GetModels(CancellationToken cancellationToken = default) + { + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = GetModels(context); + return Result.FromValue(ListModelsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Lists the currently available models, and provides basic information about each one such as the + /// owner and availability. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task GetModelsAsync(RequestOptions context) + { + using var scope = ClientDiagnostics.CreateSpan("ModelsOps.GetModels"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetModelsRequest(context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Lists the currently available models, and provides basic information about each one such as the + /// owner and availability. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result GetModels(RequestOptions context) + { + using var scope = ClientDiagnostics.CreateSpan("ModelsOps.GetModels"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetModelsRequest(context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// Retrieves a model instance, providing basic information about the model such as the owner and + /// permissioning. + /// + /// The ID of the model to use for this request. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual async Task> RetrieveAsync(string model, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(model, nameof(model)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await RetrieveAsync(model, context).ConfigureAwait(false); + return Result.FromValue(Model.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// Retrieves a model instance, providing basic information about the model such as the owner and + /// permissioning. + /// + /// The ID of the model to use for this request. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual Result Retrieve(string model, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(model, nameof(model)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = Retrieve(model, context); + return Result.FromValue(Model.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Retrieves a model instance, providing basic information about the model such as the owner and + /// permissioning. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the model to use for this request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task RetrieveAsync(string model, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(model, nameof(model)); + + using var scope = ClientDiagnostics.CreateSpan("ModelsOps.Retrieve"); + scope.Start(); + try + { + using PipelineMessage message = CreateRetrieveRequest(model, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Retrieves a model instance, providing basic information about the model such as the owner and + /// permissioning. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the model to use for this request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result Retrieve(string model, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(model, nameof(model)); + + using var scope = ClientDiagnostics.CreateSpan("ModelsOps.Retrieve"); + scope.Start(); + try + { + using PipelineMessage message = CreateRetrieveRequest(model, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Delete a fine-tuned model. You must have the Owner role in your organization to delete a model. + /// The model to delete. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual async Task> DeleteAsync(string model, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(model, nameof(model)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await DeleteAsync(model, context).ConfigureAwait(false); + return Result.FromValue(DeleteModelResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Delete a fine-tuned model. You must have the Owner role in your organization to delete a model. + /// The model to delete. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual Result Delete(string model, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(model, nameof(model)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = Delete(model, context); + return Result.FromValue(DeleteModelResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Delete a fine-tuned model. You must have the Owner role in your organization to delete a model. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The model to delete. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task DeleteAsync(string model, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(model, nameof(model)); + + using var scope = ClientDiagnostics.CreateSpan("ModelsOps.Delete"); + scope.Start(); + try + { + using PipelineMessage message = CreateDeleteRequest(model, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Delete a fine-tuned model. You must have the Owner role in your organization to delete a model. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The model to delete. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result Delete(string model, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(model, nameof(model)); + + using var scope = ClientDiagnostics.CreateSpan("ModelsOps.Delete"); + scope.Start(); + try + { + using PipelineMessage message = CreateDeleteRequest(model, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + internal PipelineMessage CreateGetModelsRequest(RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("GET"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/models", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + internal PipelineMessage CreateRetrieveRequest(string model, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("GET"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/models/", false); + uri.AppendPath(model, true); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + internal PipelineMessage CreateDeleteRequest(string model, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("DELETE"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/models/", false); + uri.AppendPath(model, true); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + private static RequestOptions DefaultRequestContext = new RequestOptions(); + internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) + { + if (!cancellationToken.CanBeCanceled) + { + return DefaultRequestContext; + } + + return new RequestOptions() { CancellationToken = cancellationToken }; + } + + private static ResponseErrorClassifier _responseErrorClassifier200; + private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); + } +} diff --git a/.dotnet/src/Generated/Moderations.cs b/.dotnet/src/Generated/Moderations.cs new file mode 100644 index 000000000..7c4520943 --- /dev/null +++ b/.dotnet/src/Generated/Moderations.cs @@ -0,0 +1,183 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.ClientModel.Primitives.Pipeline; +using System.Threading; +using System.Threading.Tasks; +using OpenAI.Models; + +namespace OpenAI +{ + // Data plane generated sub-client. + /// The Moderations sub-client. + public partial class Moderations + { + private const string AuthorizationHeader = "Authorization"; + private readonly KeyCredential _keyCredential; + private const string AuthorizationApiKeyPrefix = "Bearer"; + private readonly MessagePipeline _pipeline; + private readonly Uri _endpoint; + + /// The ClientDiagnostics is used to provide tracing support for the client library. + internal TelemetrySource ClientDiagnostics { get; } + + /// The HTTP pipeline for sending and receiving REST requests and responses. + public virtual MessagePipeline Pipeline => _pipeline; + + /// Initializes a new instance of Moderations for mocking. + protected Moderations() + { + } + + /// Initializes a new instance of Moderations. + /// The handler for diagnostic messaging in the client. + /// The HTTP pipeline for sending and receiving REST requests and responses. + /// The key credential to copy. + /// OpenAI Endpoint. + internal Moderations(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + { + ClientDiagnostics = clientDiagnostics; + _pipeline = pipeline; + _keyCredential = keyCredential; + _endpoint = endpoint; + } + + /// Classifies if text violates OpenAI's Content Policy. + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual async Task> CreateModerationAsync(CreateModerationRequest content, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content0 = content.ToRequestBody(); + Result result = await CreateModerationAsync(content0, context).ConfigureAwait(false); + return Result.FromValue(CreateModerationResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Classifies if text violates OpenAI's Content Policy. + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual Result CreateModeration(CreateModerationRequest content, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content0 = content.ToRequestBody(); + Result result = CreateModeration(content0, context); + return Result.FromValue(CreateModerationResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Classifies if text violates OpenAI's Content Policy + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task CreateModerationAsync(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Moderations.CreateModeration"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateModerationRequest(content, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Classifies if text violates OpenAI's Content Policy + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result CreateModeration(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Moderations.CreateModeration"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateModerationRequest(content, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + internal PipelineMessage CreateCreateModerationRequest(RequestBody content, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/moderations", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + request.SetHeaderValue("Content-Type", "application/json"); + request.Content = content; + return message; + } + + private static RequestOptions DefaultRequestContext = new RequestOptions(); + internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) + { + if (!cancellationToken.CanBeCanceled) + { + return DefaultRequestContext; + } + + return new RequestOptions() { CancellationToken = cancellationToken }; + } + + private static ResponseErrorClassifier _responseErrorClassifier200; + private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); + } +} diff --git a/.dotnet/src/Generated/OpenAIClient.cs b/.dotnet/src/Generated/OpenAIClient.cs new file mode 100644 index 000000000..ba4da1bc6 --- /dev/null +++ b/.dotnet/src/Generated/OpenAIClient.cs @@ -0,0 +1,158 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.ClientModel.Primitives.Pipeline; +using System.Threading; + +namespace OpenAI +{ + // Data plane generated client. + /// The OpenAI service client. + public partial class OpenAIClient + { + private const string AuthorizationHeader = "Authorization"; + private readonly KeyCredential _keyCredential; + private const string AuthorizationApiKeyPrefix = "Bearer"; + private readonly MessagePipeline _pipeline; + private readonly Uri _endpoint; + + /// The ClientDiagnostics is used to provide tracing support for the client library. + internal TelemetrySource ClientDiagnostics { get; } + + /// The HTTP pipeline for sending and receiving REST requests and responses. + public virtual MessagePipeline Pipeline => _pipeline; + + /// Initializes a new instance of OpenAIClient for mocking. + protected OpenAIClient() + { + } + + /// Initializes a new instance of OpenAIClient. + /// A credential used to authenticate to an Azure Service. + /// is null. + public OpenAIClient(KeyCredential credential) : this(new Uri("https://api.openai.com/v1"), credential, new OpenAIClientOptions()) + { + } + + /// Initializes a new instance of OpenAIClient. + /// OpenAI Endpoint. + /// A credential used to authenticate to an Azure Service. + /// The options for configuring the client. + /// or is null. + public OpenAIClient(Uri endpoint, KeyCredential credential, OpenAIClientOptions options) + { + ClientUtilities.AssertNotNull(endpoint, nameof(endpoint)); + ClientUtilities.AssertNotNull(credential, nameof(credential)); + options ??= new OpenAIClientOptions(); + + ClientDiagnostics = new TelemetrySource(options, true); + _keyCredential = credential; + _pipeline = MessagePipeline.Create(options, new IPipelinePolicy[] { new KeyCredentialPolicy(_keyCredential, AuthorizationHeader, AuthorizationApiKeyPrefix) }, Array.Empty>()); + _endpoint = endpoint; + } + + private FineTuning _cachedFineTuning; + private Audio _cachedAudio; + private Assistants _cachedAssistants; + private Chat _cachedChat; + private Completions _cachedCompletions; + private Embeddings _cachedEmbeddings; + private Files _cachedFiles; + private FineTunes _cachedFineTunes; + private Images _cachedImages; + private Messages _cachedMessages; + private ModelsOps _cachedModelsOps; + private Moderations _cachedModerations; + private Runs _cachedRuns; + private Threads _cachedThreads; + + /// Initializes a new instance of FineTuning. + public virtual FineTuning GetFineTuningClient() + { + return Volatile.Read(ref _cachedFineTuning) ?? Interlocked.CompareExchange(ref _cachedFineTuning, new FineTuning(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedFineTuning; + } + + /// Initializes a new instance of Audio. + public virtual Audio GetAudioClient() + { + return Volatile.Read(ref _cachedAudio) ?? Interlocked.CompareExchange(ref _cachedAudio, new Audio(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedAudio; + } + + /// Initializes a new instance of Assistants. + public virtual Assistants GetAssistantsClient() + { + return Volatile.Read(ref _cachedAssistants) ?? Interlocked.CompareExchange(ref _cachedAssistants, new Assistants(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedAssistants; + } + + /// Initializes a new instance of Chat. + public virtual Chat GetChatClient() + { + return Volatile.Read(ref _cachedChat) ?? Interlocked.CompareExchange(ref _cachedChat, new Chat(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedChat; + } + + /// Initializes a new instance of Completions. + public virtual Completions GetCompletionsClient() + { + return Volatile.Read(ref _cachedCompletions) ?? Interlocked.CompareExchange(ref _cachedCompletions, new Completions(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedCompletions; + } + + /// Initializes a new instance of Embeddings. + public virtual Embeddings GetEmbeddingsClient() + { + return Volatile.Read(ref _cachedEmbeddings) ?? Interlocked.CompareExchange(ref _cachedEmbeddings, new Embeddings(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedEmbeddings; + } + + /// Initializes a new instance of Files. + public virtual Files GetFilesClient() + { + return Volatile.Read(ref _cachedFiles) ?? Interlocked.CompareExchange(ref _cachedFiles, new Files(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedFiles; + } + + /// Initializes a new instance of FineTunes. + public virtual FineTunes GetFineTunesClient() + { + return Volatile.Read(ref _cachedFineTunes) ?? Interlocked.CompareExchange(ref _cachedFineTunes, new FineTunes(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedFineTunes; + } + + /// Initializes a new instance of Images. + public virtual Images GetImagesClient() + { + return Volatile.Read(ref _cachedImages) ?? Interlocked.CompareExchange(ref _cachedImages, new Images(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedImages; + } + + /// Initializes a new instance of Messages. + public virtual Messages GetMessagesClient() + { + return Volatile.Read(ref _cachedMessages) ?? Interlocked.CompareExchange(ref _cachedMessages, new Messages(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedMessages; + } + + /// Initializes a new instance of ModelsOps. + public virtual ModelsOps GetModelsOpsClient() + { + return Volatile.Read(ref _cachedModelsOps) ?? Interlocked.CompareExchange(ref _cachedModelsOps, new ModelsOps(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedModelsOps; + } + + /// Initializes a new instance of Moderations. + public virtual Moderations GetModerationsClient() + { + return Volatile.Read(ref _cachedModerations) ?? Interlocked.CompareExchange(ref _cachedModerations, new Moderations(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedModerations; + } + + /// Initializes a new instance of Runs. + public virtual Runs GetRunsClient() + { + return Volatile.Read(ref _cachedRuns) ?? Interlocked.CompareExchange(ref _cachedRuns, new Runs(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedRuns; + } + + /// Initializes a new instance of Threads. + public virtual Threads GetThreadsClient() + { + return Volatile.Read(ref _cachedThreads) ?? Interlocked.CompareExchange(ref _cachedThreads, new Threads(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedThreads; + } + } +} diff --git a/.dotnet/src/Generated/OpenAIClientOptions.cs b/.dotnet/src/Generated/OpenAIClientOptions.cs new file mode 100644 index 000000000..5b661878a --- /dev/null +++ b/.dotnet/src/Generated/OpenAIClientOptions.cs @@ -0,0 +1,13 @@ +// + +#nullable disable + +using System.ClientModel; + +namespace OpenAI +{ + /// Client options for OpenAIClient. + public partial class OpenAIClientOptions : RequestOptions + { + } +} diff --git a/.dotnet/src/Generated/OpenAIModelFactory.cs b/.dotnet/src/Generated/OpenAIModelFactory.cs new file mode 100644 index 000000000..ae070eb8a --- /dev/null +++ b/.dotnet/src/Generated/OpenAIModelFactory.cs @@ -0,0 +1,1769 @@ +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Models +{ + /// Model factory for models. + public static partial class OpenAIModelFactory + { + /// Initializes a new instance of . + /// + /// The ID of an uploaded file that contains training data. + /// + /// See [upload file](/docs/api-reference/files/upload) for how to upload a file. + /// + /// Your dataset must be formatted as a JSONL file. Additionally, you must upload your file with + /// the purpose `fine-tune`. + /// + /// See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. + /// + /// + /// The ID of an uploaded file that contains validation data. + /// + /// If you provide this file, the data is used to generate validation metrics periodically during + /// fine-tuning. These metrics can be viewed in the fine-tuning results file. The same data should + /// not be present in both train and validation files. + /// + /// Your dataset must be formatted as a JSONL file. You must upload your file with the purpose + /// `fine-tune`. + /// + /// See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. + /// + /// + /// The name of the model to fine-tune. You can select one of the + /// [supported models](/docs/guides/fine-tuning/what-models-can-be-fine-tuned). + /// + /// The hyperparameters used for the fine-tuning job. + /// + /// 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`. + /// + /// A new instance for mocking. + public static CreateFineTuningJobRequest CreateFineTuningJobRequest(string trainingFile = null, string validationFile = null, CreateFineTuningJobRequestModel model = default, CreateFineTuningJobRequestHyperparameters hyperparameters = null, string suffix = null) + { + return new CreateFineTuningJobRequest(trainingFile, validationFile, model, hyperparameters, suffix, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The object identifier, which can be referenced in the API endpoints. + /// The object type, which is always "fine_tuning.job". + /// The Unix timestamp (in seconds) for when the fine-tuning job was created. + /// + /// The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be + /// null if the fine-tuning job is still running. + /// + /// The base model that is being fine-tuned. + /// + /// The name of the fine-tuned model that is being created. The value will be null if the + /// fine-tuning job is still running. + /// + /// The organization that owns the fine-tuning job. + /// + /// The current status of the fine-tuning job, which can be either `created`, `pending`, `running`, + /// `succeeded`, `failed`, or `cancelled`. + /// + /// + /// The hyperparameters used for the fine-tuning job. See the + /// [fine-tuning guide](/docs/guides/fine-tuning) for more details. + /// + /// + /// The file ID used for training. You can retrieve the training data with the + /// [Files API](/docs/api-reference/files/retrieve-contents). + /// + /// + /// The file ID used for validation. You can retrieve the validation results with the + /// [Files API](/docs/api-reference/files/retrieve-contents). + /// + /// + /// The compiled results file ID(s) for the fine-tuning job. You can retrieve the results with the + /// [Files API](/docs/api-reference/files/retrieve-contents). + /// + /// + /// The total number of billable tokens processed by this fine tuning job. The value will be null + /// if the fine-tuning job is still running. + /// + /// + /// For fine-tuning jobs that have `failed`, this will contain more information on the cause of the + /// failure. + /// + /// A new instance for mocking. + public static FineTuningJob FineTuningJob(string id = null, FineTuningJobObject @object = default, DateTimeOffset createdAt = default, DateTimeOffset? finishedAt = null, string model = null, string fineTunedModel = null, string organizationId = null, FineTuningJobStatus status = default, FineTuningJobHyperparameters hyperparameters = null, string trainingFile = null, string validationFile = null, IEnumerable resultFiles = null, long? trainedTokens = null, FineTuningJobError error = null) + { + resultFiles ??= new List(); + + return new FineTuningJob(id, @object, createdAt, finishedAt, model, fineTunedModel, organizationId, status, hyperparameters, trainingFile, validationFile, resultFiles?.ToList(), trainedTokens, error, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// The number of epochs to train the model for. An epoch refers to one full cycle through the + /// training dataset. + /// + /// "Auto" decides the optimal number of epochs based on the size of the dataset. If setting the + /// number manually, we support any number between 1 and 50 epochs. + /// + /// A new instance for mocking. + public static FineTuningJobHyperparameters FineTuningJobHyperparameters(BinaryData nEpochs = null) + { + return new FineTuningJobHyperparameters(nEpochs, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// A human-readable error message. + /// A machine-readable error code. + /// + /// The parameter that was invalid, usually `training_file` or `validation_file`. This field + /// will be null if the failure was not parameter-specific. + /// + /// A new instance for mocking. + public static FineTuningJobError FineTuningJobError(string message = null, string code = null, string param = null) + { + return new FineTuningJobError(message, code, param, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// + /// + /// A new instance for mocking. + public static ListPaginatedFineTuningJobsResponse ListPaginatedFineTuningJobsResponse(string @object = null, IEnumerable data = null, bool hasMore = default) + { + data ??= new List(); + + return new ListPaginatedFineTuningJobsResponse(@object, data?.ToList(), hasMore, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// + /// A new instance for mocking. + public static ListFineTuningJobEventsResponse ListFineTuningJobEventsResponse(string @object = null, IEnumerable data = null) + { + data ??= new List(); + + return new ListFineTuningJobEventsResponse(@object, data?.ToList(), serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// + /// + /// + /// + /// A new instance for mocking. + public static FineTuningJobEvent FineTuningJobEvent(string id = null, string @object = null, DateTimeOffset createdAt = default, FineTuningJobEventLevel level = default, string message = null) + { + return new FineTuningJobEvent(id, @object, createdAt, level, message, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// One of the available [TTS models](/docs/models/tts): `tts-1` or `tts-1-hd`. + /// The text to generate audio for. The maximum length is 4096 characters. + /// + /// The voice to use when generating the audio. Supported voices are `alloy`, `echo`, `fable`, + /// `onyx`, `nova`, and `shimmer`. Previews of the voices are available in the + /// [Text to speech guide](/docs/guides/text-to-speech/voice-options). + /// + /// The format to audio in. Supported formats are `mp3`, `opus`, `aac`, and `flac`. + /// The speed of the generated audio. Select a value from `0.25` to `4.0`. `1.0` is the default. + /// A new instance for mocking. + public static CreateSpeechRequest CreateSpeechRequest(CreateSpeechRequestModel model = default, string input = null, CreateSpeechRequestVoice voice = default, CreateSpeechRequestResponseFormat? responseFormat = null, double? speed = null) + { + return new CreateSpeechRequest(model, input, voice, responseFormat, speed, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// The audio file object (not file name) to transcribe, in one of these formats: flac, mp3, mp4, + /// mpeg, mpga, m4a, ogg, wav, or webm. + /// + /// ID of the model to use. Only `whisper-1` is currently available. + /// + /// The language of the input audio. Supplying the input language in + /// [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) format will improve accuracy + /// and latency. + /// + /// + /// An optional text to guide the model's style or continue a previous audio segment. The + /// [prompt](/docs/guides/speech-to-text/prompting) should match the audio language. + /// + /// + /// The format of the transcript output, in one of these options: json, text, srt, verbose_json, or + /// vtt. + /// + /// + /// The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more + /// random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, + /// the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to + /// automatically increase the temperature until certain thresholds are hit. + /// + /// A new instance for mocking. + public static CreateTranscriptionRequest CreateTranscriptionRequest(BinaryData file = null, CreateTranscriptionRequestModel model = default, string language = null, string prompt = null, CreateTranscriptionRequestResponseFormat? responseFormat = null, double? temperature = null) + { + return new CreateTranscriptionRequest(file, model, language, prompt, responseFormat, temperature, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The transcribed text for the provided audio data. + /// The label that describes which operation type generated the accompanying response data. + /// The spoken language that was detected in the audio data. + /// The total duration of the audio processed to produce accompanying transcription information. + /// + /// A collection of information about the timing, probabilities, and other detail of each processed + /// audio segment. + /// + /// A new instance for mocking. + public static CreateTranscriptionResponse CreateTranscriptionResponse(string text = null, CreateTranscriptionResponseTask? task = null, string language = null, TimeSpan? duration = null, IEnumerable segments = null) + { + segments ??= new List(); + + return new CreateTranscriptionResponse(text, task, language, duration, segments?.ToList(), serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The zero-based index of this segment. + /// + /// The seek position associated with the processing of this audio segment. Seek positions are + /// expressed as hundredths of seconds. The model may process several segments from a single seek + /// position, so while the seek position will never represent a later time than the segment's + /// start, the segment's start may represent a significantly later time than the segment's + /// associated seek position. + /// + /// The time at which this segment started relative to the beginning of the audio. + /// The time at which this segment ended relative to the beginning of the audio. + /// The text that was part of this audio segment. + /// The token IDs matching the text in this audio segment. + /// The temperature score associated with this audio segment. + /// The average log probability associated with this audio segment. + /// The compression ratio of this audio segment. + /// The probability of no speech detection within this audio segment. + /// A new instance for mocking. + public static AudioSegment AudioSegment(long id = default, long seek = default, TimeSpan start = default, TimeSpan end = default, string text = null, IEnumerable tokens = null, double temperature = default, double avgLogprob = default, double compressionRatio = default, double noSpeechProb = default) + { + tokens ??= new List(); + + return new AudioSegment(id, seek, start, end, text, tokens?.ToList(), temperature, avgLogprob, compressionRatio, noSpeechProb, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// The audio file object (not file name) to translate, in one of these formats: flac, mp3, mp4, + /// mpeg, mpga, m4a, ogg, wav, or webm. + /// + /// ID of the model to use. Only `whisper-1` is currently available. + /// + /// An optional text to guide the model's style or continue a previous audio segment. The + /// [prompt](/docs/guides/speech-to-text/prompting) should match the audio language. + /// + /// + /// The format of the transcript output, in one of these options: json, text, srt, verbose_json, or + /// vtt. + /// + /// + /// The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more + /// random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, + /// the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to + /// automatically increase the temperature until certain thresholds are hit. + /// + /// A new instance for mocking. + public static CreateTranslationRequest CreateTranslationRequest(BinaryData file = null, CreateTranslationRequestModel model = default, string prompt = null, CreateTranslationRequestResponseFormat? responseFormat = null, double? temperature = null) + { + return new CreateTranslationRequest(file, model, prompt, responseFormat, temperature, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The translated text for the provided audio data. + /// The label that describes which operation type generated the accompanying response data. + /// The spoken language that was detected in the audio data. + /// The total duration of the audio processed to produce accompanying translation information. + /// + /// A collection of information about the timing, probabilities, and other detail of each processed + /// audio segment. + /// + /// A new instance for mocking. + public static CreateTranslationResponse CreateTranslationResponse(string text = null, CreateTranslationResponseTask? task = null, string language = null, TimeSpan? duration = null, IEnumerable segments = null) + { + segments ??= new List(); + + return new CreateTranslationResponse(text, task, language, duration, segments?.ToList(), serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + /// see all of your available models, or see our [Model overview](/docs/models/overview) for + /// descriptions of them. + /// + /// The name of the assistant. The maximum length is 256 characters. + /// The description of the assistant. The maximum length is 512 characters. + /// The system instructions that the assistant uses. The maximum length is 32768 characters. + /// + /// A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. + /// Tools can be of types `code_interpreter`, `retrieval`, or `function`. + /// + /// + /// A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a + /// maximum of 20 files attached to the assistant. Files are ordered by their creation date in + /// ascending order. + /// + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// A new instance for mocking. + public static CreateAssistantRequest CreateAssistantRequest(string model = null, string name = null, string description = null, string instructions = null, IEnumerable tools = null, IEnumerable fileIds = null, IDictionary metadata = null) + { + tools ??= new List(); + fileIds ??= new List(); + metadata ??= new Dictionary(); + + return new CreateAssistantRequest(model, name, description, instructions, tools?.ToList(), fileIds?.ToList(), metadata, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The identifier, which can be referenced in API endpoints. + /// The object type, which is always `assistant`. + /// The Unix timestamp (in seconds) for when the assistant was created. + /// The name of the assistant. The maximum length is 256 characters. + /// The description of the assistant. The maximum length is 512 characters. + /// + /// ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + /// see all of your available models, or see our [Model overview](/docs/models/overview) for + /// descriptions of them. + /// + /// The system instructions that the assistant uses. The maximum length is 32768 characters. + /// + /// A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. + /// Tools can be of types `code_interpreter`, `retrieval`, or `function`. + /// + /// + /// A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a + /// maximum of 20 files attached to the assistant. Files are ordered by their creation date in + /// ascending order. + /// + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// A new instance for mocking. + public static AssistantObject AssistantObject(string id = null, AssistantObjectObject @object = default, DateTimeOffset createdAt = default, string name = null, string description = null, string model = null, string instructions = null, IEnumerable tools = null, IEnumerable fileIds = null, IReadOnlyDictionary metadata = null) + { + tools ??= new List(); + fileIds ??= new List(); + metadata ??= new Dictionary(); + + return new AssistantObject(id, @object, createdAt, name, description, model, instructions, tools?.ToList(), fileIds?.ToList(), metadata, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// + /// + /// + /// + /// A new instance for mocking. + public static ListAssistantsResponse ListAssistantsResponse(ListAssistantsResponseObject @object = default, IEnumerable data = null, string firstId = null, string lastId = null, bool hasMore = default) + { + data ??= new List(); + + return new ListAssistantsResponse(@object, data?.ToList(), firstId, lastId, hasMore, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// + /// + /// A new instance for mocking. + public static DeleteAssistantResponse DeleteAssistantResponse(string id = null, bool deleted = default, DeleteAssistantResponseObject @object = default) + { + return new DeleteAssistantResponse(id, deleted, @object, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The identifier, which can be referenced in API endpoints. + /// The object type, which is always `assistant.file`. + /// The Unix timestamp (in seconds) for when the assistant file was created. + /// The assistant ID that the file is attached to. + /// A new instance for mocking. + public static AssistantFileObject AssistantFileObject(string id = null, AssistantFileObjectObject @object = default, DateTimeOffset createdAt = default, string assistantId = null) + { + return new AssistantFileObject(id, @object, createdAt, assistantId, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// + /// + /// + /// + /// A new instance for mocking. + public static ListAssistantFilesResponse ListAssistantFilesResponse(ListAssistantFilesResponseObject @object = default, IEnumerable data = null, string firstId = null, string lastId = null, bool hasMore = default) + { + data ??= new List(); + + return new ListAssistantFilesResponse(@object, data?.ToList(), firstId, lastId, hasMore, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// + /// + /// A new instance for mocking. + public static DeleteAssistantFileResponse DeleteAssistantFileResponse(string id = null, bool deleted = default, DeleteAssistantFileResponseObject @object = default) + { + return new DeleteAssistantFileResponse(id, deleted, @object, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// A list of messages comprising the conversation so far. + /// [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb). + /// + /// + /// ID of the model to use. See the [model endpoint compatibility](/docs/models/model-endpoint-compatibility) + /// table for details on which models work with the Chat API. + /// + /// + /// Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing + /// frequency in the text so far, decreasing the model's likelihood to repeat the same line + /// verbatim. + /// + /// [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) + /// + /// + /// Modify the likelihood of specified tokens appearing in the completion. + /// + /// Accepts a JSON object that maps tokens (specified by their token ID in the tokenizer) to an + /// associated bias value from -100 to 100. Mathematically, the bias is added to the logits + /// generated by the model prior to sampling. The exact effect will vary per model, but values + /// between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 + /// should result in a ban or exclusive selection of the relevant token. + /// + /// + /// Whether to return log probabilities of the output tokens or not. If true, returns the log + /// probabilities of each output token returned in the `content` of `message`. This option is + /// currently not available on the `gpt-4-vision-preview` model. + /// + /// + /// An integer between 0 and 5 specifying the number of most likely tokens to return at each token + /// position, each with an associated log probability. `logprobs` must be set to `true` if this + /// parameter is used. + /// + /// + /// The maximum number of [tokens](/tokenizer) that can be generated in the chat completion. + /// + /// The total length of input tokens and generated tokens is limited by the model's context length. + /// [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) + /// for counting tokens. + /// + /// + /// How many chat completion choices to generate for each input message. Note that you will be + /// charged based on the number of generated tokens across all of the choices. Keep `n` as `1` to + /// minimize costs. + /// + /// + /// Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear + /// in the text so far, increasing the model's likelihood to talk about new topics. + /// + /// [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) + /// + /// + /// An object specifying the format that the model must output. Compatible with + /// [GPT-4 Turbo](/docs/models/gpt-4-and-gpt-4-turbo) and `gpt-3.5-turbo-1106`. + /// + /// 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. + /// + /// + /// This feature is in Beta. + /// + /// If specified, our system will make a best effort to sample deterministically, such that + /// repeated requests with the same `seed` and parameters should return the same result. + /// + /// Determinism is not guaranteed, and you should refer to the `system_fingerprint` response + /// parameter to monitor changes in the backend. + /// + /// Up to 4 sequences where the API will stop generating further tokens. + /// + /// If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only + /// [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) + /// as they become available, with the stream terminated by a `data: [DONE]` message. + /// [Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions). + /// + /// + /// What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output + /// more random, while lower values like 0.2 will make it more focused and deterministic. + /// + /// We generally recommend altering this or `top_p` but not both. + /// + /// + /// An alternative to sampling with temperature, called nucleus sampling, where the model considers + /// the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising + /// the top 10% probability mass are considered. + /// + /// We generally recommend altering this or `temperature` but not both. + /// + /// + /// A list of tools the model may call. Currently, only functions are supported as a tool. Use this + /// to provide a list of functions the model may generate JSON inputs for. + /// + /// + /// + /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect + /// abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + /// + /// + /// Deprecated in favor of `tool_choice`. + /// + /// Controls which (if any) function is called by the model. `none` means the model will not call a + /// function and instead generates a message. `auto` means the model can pick between generating a + /// message or calling a function. Specifying a particular function via `{"name": "my_function"}` + /// forces the model to call that function. + /// + /// `none` is the default when no functions are present. `auto` is the default if functions are + /// present. + /// + /// + /// Deprecated in favor of `tools`. + /// + /// A list of functions the model may generate JSON inputs for. + /// + /// A new instance for mocking. + public static CreateChatCompletionRequest CreateChatCompletionRequest(IEnumerable messages = null, CreateChatCompletionRequestModel model = default, double? frequencyPenalty = null, IDictionary logitBias = null, bool? logprobs = null, long? topLogprobs = null, long? maxTokens = null, long? n = null, double? presencePenalty = null, CreateChatCompletionRequestResponseFormat responseFormat = null, long? seed = null, BinaryData stop = null, bool? stream = null, double? temperature = null, double? topP = null, IEnumerable tools = null, BinaryData toolChoice = null, string user = null, BinaryData functionCall = null, IEnumerable functions = null) + { + messages ??= new List(); + logitBias ??= new Dictionary(); + tools ??= new List(); + functions ??= new List(); + + return new CreateChatCompletionRequest(messages?.ToList(), model, frequencyPenalty, logitBias, logprobs, topLogprobs, maxTokens, n, presencePenalty, responseFormat, seed, stop, stream, temperature, topP, tools?.ToList(), toolChoice, user, functionCall, functions?.ToList(), serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The ID of the tool call. + /// The type of the tool. Currently, only `function` is supported. + /// The function that the model called. + /// A new instance for mocking. + public static ChatCompletionMessageToolCall ChatCompletionMessageToolCall(string id = null, ChatCompletionMessageToolCallType type = default, ChatCompletionMessageToolCallFunction function = null) + { + return new ChatCompletionMessageToolCall(id, type, function, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The type of the tool. Currently, only `function` is supported. + /// + /// A new instance for mocking. + public static ChatCompletionTool ChatCompletionTool(ChatCompletionToolType type = default, FunctionObject function = null) + { + return new ChatCompletionTool(type, function, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// A description of what the function does, used by the model to choose when and how to call the + /// function. + /// + /// + /// The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and + /// dashes, with a maximum length of 64. + /// + /// + /// A new instance for mocking. + public static ChatCompletionFunctions ChatCompletionFunctions(string description = null, string name = null, FunctionParameters parameters = null) + { + return new ChatCompletionFunctions(description, name, parameters, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// A unique identifier for the chat completion. + /// A list of chat completion choices. Can be more than one if `n` is greater than 1. + /// The Unix timestamp (in seconds) of when the chat completion was created. + /// The model used for the chat completion. + /// + /// 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. + /// + /// The object type, which is always `chat.completion`. + /// + /// A new instance for mocking. + public static CreateChatCompletionResponse CreateChatCompletionResponse(string id = null, IEnumerable choices = null, DateTimeOffset created = default, string model = null, string systemFingerprint = null, CreateChatCompletionResponseObject @object = default, CompletionUsage usage = null) + { + choices ??= new List(); + + return new CreateChatCompletionResponse(id, choices?.ToList(), created, model, systemFingerprint, @object, usage, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// The reason the model stopped generating tokens. This will be `stop` if the model hit a + /// natural stop point or a provided stop sequence, `length` if the maximum number of tokens + /// specified in the request was reached, `content_filter` if content was omitted due to a flag + /// from our content filters, `tool_calls` if the model called a tool, or `function_call` + /// (deprecated) if the model called a function. + /// + /// The index of the choice in the list of choices. + /// + /// Log probability information for the choice. + /// A new instance for mocking. + public static CreateChatCompletionResponseChoice CreateChatCompletionResponseChoice(CreateChatCompletionResponseChoiceFinishReason finishReason = default, long index = default, ChatCompletionResponseMessage message = null, CreateChatCompletionResponseChoiceLogprobs logprobs = null) + { + return new CreateChatCompletionResponseChoice(finishReason, index, message, logprobs, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The contents of the message. + /// + /// The role of the author of this message. + /// Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model. + /// A new instance for mocking. + public static ChatCompletionResponseMessage ChatCompletionResponseMessage(string content = null, IEnumerable toolCalls = null, ChatCompletionResponseMessageRole role = default, ChatCompletionResponseMessageFunctionCall functionCall = null) + { + toolCalls ??= new List(); + + return new ChatCompletionResponseMessage(content, toolCalls?.ToList(), role, functionCall, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// The arguments to call the function with, as generated by the model in JSON format. Note that + /// the model does not always generate valid JSON, and may hallucinate parameters not defined by + /// your function schema. Validate the arguments in your code before calling your function. + /// + /// The name of the function to call. + /// A new instance for mocking. + public static ChatCompletionResponseMessageFunctionCall ChatCompletionResponseMessageFunctionCall(string arguments = null, string name = null) + { + return new ChatCompletionResponseMessageFunctionCall(arguments, name, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// A new instance for mocking. + public static CreateChatCompletionResponseChoiceLogprobs CreateChatCompletionResponseChoiceLogprobs(IEnumerable content = null) + { + content ??= new List(); + + return new CreateChatCompletionResponseChoiceLogprobs(content?.ToList(), serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The token. + /// The log probability of this token. + /// + /// A list of integers representing the UTF-8 bytes representation of the token. Useful in + /// instances where characters are represented by multiple tokens and their byte representations + /// must be combined to generate the correct text representation. Can be `null` if there is no + /// bytes representation for the token. + /// + /// + /// List of the most likely tokens and their log probability, at this token position. In rare + /// cases, there may be fewer than the number of requested `top_logprobs` returned. + /// + /// A new instance for mocking. + public static ChatCompletionTokenLogprob ChatCompletionTokenLogprob(string token = null, double logprob = default, IEnumerable bytes = null, IEnumerable topLogprobs = null) + { + bytes ??= new List(); + topLogprobs ??= new List(); + + return new ChatCompletionTokenLogprob(token, logprob, bytes?.ToList(), topLogprobs?.ToList(), serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The token. + /// The log probability of this token. + /// + /// A list of integers representing the UTF-8 bytes representation of the token. Useful in + /// instances where characters are represented by multiple tokens and their byte representations + /// must be combined to generate the correct text representation. Can be `null` if there is no + /// bytes representation for the token. + /// + /// A new instance for mocking. + public static ChatCompletionTokenLogprobTopLogprob ChatCompletionTokenLogprobTopLogprob(string token = null, double logprob = default, IEnumerable bytes = null) + { + bytes ??= new List(); + + return new ChatCompletionTokenLogprobTopLogprob(token, logprob, bytes?.ToList(), serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// Number of tokens in the prompt. + /// Number of tokens in the generated completion. + /// Total number of tokens used in the request (prompt + completion). + /// A new instance for mocking. + public static CompletionUsage CompletionUsage(long promptTokens = default, long completionTokens = default, long totalTokens = default) + { + return new CompletionUsage(promptTokens, completionTokens, totalTokens, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + /// see all of your available models, or see our [Model overview](/docs/models/overview) for + /// descriptions of them. + /// + /// + /// The prompt(s) to generate completions for, encoded as a string, array of strings, array of + /// tokens, or array of token arrays. + /// + /// Note that <|endoftext|> is the document separator that the model sees during training, so if a + /// prompt is not specified the model will generate as if from the beginning of a new document. + /// + /// + /// Generates `best_of` completions server-side and returns the "best" (the one with the highest + /// log probability per token). Results cannot be streamed. + /// + /// When used with `n`, `best_of` controls the number of candidate completions and `n` specifies + /// how many to return – `best_of` must be greater than `n`. + /// + /// **Note:** Because this parameter generates many completions, it can quickly consume your token + /// quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. + /// + /// Echo back the prompt in addition to the completion. + /// + /// Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing + /// frequency in the text so far, decreasing the model's likelihood to repeat the same line + /// verbatim. + /// + /// [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) + /// + /// + /// Modify the likelihood of specified tokens appearing in the completion. + /// + /// Accepts a JSON object that maps tokens (specified by their token ID in the GPT tokenizer) to an + /// associated bias value from -100 to 100. You can use this [tokenizer tool](/tokenizer?view=bpe) + /// to convert text to token IDs. Mathematically, the bias is added to the logits generated by the + /// model prior to sampling. The exact effect will vary per model, but values between -1 and 1 + /// should decrease or increase likelihood of selection; values like -100 or 100 should result in a + /// ban or exclusive selection of the relevant token. + /// + /// As an example, you can pass `{"50256": -100}` to prevent the <|endoftext|> token from being + /// generated. + /// + /// + /// Include the log probabilities on the `logprobs` most likely tokens, as well the chosen tokens. + /// For example, if `logprobs` is 5, the API will return a list of the 5 most likely tokens. The + /// API will always return the `logprob` of the sampled token, so there may be up to `logprobs+1` + /// elements in the response. + /// + /// The maximum value for `logprobs` is 5. + /// + /// + /// The maximum number of [tokens](/tokenizer) to generate in the completion. + /// + /// The token count of your prompt plus `max_tokens` cannot exceed the model's context length. + /// [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) + /// for counting tokens. + /// + /// + /// How many completions to generate for each prompt. + /// + /// **Note:** Because this parameter generates many completions, it can quickly consume your token + /// quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. + /// + /// + /// Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear + /// in the text so far, increasing the model's likelihood to talk about new topics. + /// + /// [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) + /// + /// + /// If specified, our system will make a best effort to sample deterministically, such that + /// repeated requests with the same `seed` and parameters should return the same result. + /// + /// Determinism is not guaranteed, and you should refer to the `system_fingerprint` response + /// parameter to monitor changes in the backend. + /// + /// Up to 4 sequences where the API will stop generating further tokens. + /// + /// If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only + /// [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) + /// as they become available, with the stream terminated by a `data: [DONE]` message. + /// [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_stream_completions.ipynb). + /// + /// The suffix that comes after a completion of inserted text. + /// + /// What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output + /// more random, while lower values like 0.2 will make it more focused and deterministic. + /// + /// We generally recommend altering this or `top_p` but not both. + /// + /// + /// An alternative to sampling with temperature, called nucleus sampling, where the model considers + /// the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising + /// the top 10% probability mass are considered. + /// + /// We generally recommend altering this or `temperature` but not both. + /// + /// + /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect + /// abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + /// + /// A new instance for mocking. + public static CreateCompletionRequest CreateCompletionRequest(CreateCompletionRequestModel model = default, BinaryData prompt = null, long? bestOf = null, bool? echo = null, double? frequencyPenalty = null, IDictionary logitBias = null, long? logprobs = null, long? maxTokens = null, long? n = null, double? presencePenalty = null, long? seed = null, BinaryData stop = null, bool? stream = null, string suffix = null, double? temperature = null, double? topP = null, string user = null) + { + logitBias ??= new Dictionary(); + + return new CreateCompletionRequest(model, prompt, bestOf, echo, frequencyPenalty, logitBias, logprobs, maxTokens, n, presencePenalty, seed, stop, stream, suffix, temperature, topP, user, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// A unique identifier for the completion. + /// The list of completion choices the model generated for the input. + /// The Unix timestamp (in seconds) of when the completion was created. + /// The model used for the completion. + /// + /// 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. + /// + /// The object type, which is always `text_completion`. + /// Usage statistics for the completion request. + /// A new instance for mocking. + public static CreateCompletionResponse CreateCompletionResponse(string id = null, IEnumerable choices = null, DateTimeOffset created = default, string model = null, string systemFingerprint = null, CreateCompletionResponseObject @object = default, CompletionUsage usage = null) + { + choices ??= new List(); + + return new CreateCompletionResponse(id, choices?.ToList(), created, model, systemFingerprint, @object, usage, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// + /// + /// + /// The reason the model stopped generating tokens. This will be `stop` if the model hit a + /// natural stop point or a provided stop sequence, or `content_filter` if content was omitted + /// due to a flag from our content filters, `length` if the maximum number of tokens specified + /// in the request was reached, or `content_filter` if content was omitted due to a flag from our + /// content filters. + /// + /// A new instance for mocking. + public static CreateCompletionResponseChoice CreateCompletionResponseChoice(long index = default, string text = null, CreateCompletionResponseChoiceLogprobs logprobs = null, CreateCompletionResponseChoiceFinishReason finishReason = default) + { + return new CreateCompletionResponseChoice(index, text, logprobs, finishReason, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// + /// + /// + /// A new instance for mocking. + public static CreateCompletionResponseChoiceLogprobs CreateCompletionResponseChoiceLogprobs(IEnumerable tokens = null, IEnumerable tokenLogprobs = null, IEnumerable> topLogprobs = null, IEnumerable textOffset = null) + { + tokens ??= new List(); + tokenLogprobs ??= new List(); + topLogprobs ??= new List>(); + textOffset ??= new List(); + + return new CreateCompletionResponseChoiceLogprobs(tokens?.ToList(), tokenLogprobs?.ToList(), topLogprobs?.ToList(), textOffset?.ToList(), serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a + /// single request, pass an array of strings or array of token arrays. Each input must not exceed + /// the max input tokens for the model (8191 tokens for `text-embedding-ada-002`) and cannot be an + /// empty string. + /// [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) + /// for counting tokens. + /// + /// + /// ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + /// see all of your available models, or see our [Model overview](/docs/models/overview) for + /// descriptions of them. + /// + /// + /// The format to return the embeddings in. Can be either `float` or + /// [`base64`](https://pypi.org/project/pybase64/). + /// + /// + /// The number of dimensions the resulting output embeddings should have. Only supported in + /// `text-embedding-3` and later models. + /// + /// + /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect + /// abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + /// + /// A new instance for mocking. + public static CreateEmbeddingRequest CreateEmbeddingRequest(BinaryData input = null, CreateEmbeddingRequestModel model = default, CreateEmbeddingRequestEncodingFormat? encodingFormat = null, long? dimensions = null, string user = null) + { + return new CreateEmbeddingRequest(input, model, encodingFormat, dimensions, user, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The list of embeddings generated by the model. + /// The name of the model used to generate the embedding. + /// The object type, which is always "list". + /// The usage information for the request. + /// A new instance for mocking. + public static CreateEmbeddingResponse CreateEmbeddingResponse(IEnumerable data = null, string model = null, CreateEmbeddingResponseObject @object = default, CreateEmbeddingResponseUsage usage = null) + { + data ??= new List(); + + return new CreateEmbeddingResponse(data?.ToList(), model, @object, usage, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The index of the embedding in the list of embeddings. + /// + /// The embedding vector, which is a list of floats. The length of vector depends on the model as + /// listed in the [embedding guide](/docs/guides/embeddings). + /// + /// The object type, which is always "embedding". + /// A new instance for mocking. + public static Embedding Embedding(long index = default, BinaryData embeddingProperty = null, EmbeddingObject @object = default) + { + return new Embedding(index, embeddingProperty, @object, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The number of tokens used by the prompt. + /// The total number of tokens used by the request. + /// A new instance for mocking. + public static CreateEmbeddingResponseUsage CreateEmbeddingResponseUsage(long promptTokens = default, long totalTokens = default) + { + return new CreateEmbeddingResponseUsage(promptTokens, totalTokens, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The file identifier, which can be referenced in the API endpoints. + /// The size of the file, in bytes. + /// The Unix timestamp (in seconds) for when the file was created. + /// The name of the file. + /// The object type, which is always "file". + /// + /// The intended purpose of the file. Supported values are `fine-tune`, `fine-tune-results`, + /// `assistants`, and `assistants_output`. + /// + /// + /// Deprecated. The current status of the file, which can be either `uploaded`, `processed`, or + /// `error`. + /// + /// + /// Deprecated. For details on why a fine-tuning training file failed validation, see the `error` + /// field on `fine_tuning.job`. + /// + /// A new instance for mocking. + public static OpenAIFile OpenAIFile(string id = null, long bytes = default, DateTimeOffset createdAt = default, string filename = null, OpenAIFileObject @object = default, OpenAIFilePurpose purpose = default, OpenAIFileStatus status = default, string statusDetails = null) + { + return new OpenAIFile(id, bytes, createdAt, filename, @object, purpose, status, statusDetails, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// + /// A new instance for mocking. + public static ListFilesResponse ListFilesResponse(IEnumerable data = null, ListFilesResponseObject @object = default) + { + data ??= new List(); + + return new ListFilesResponse(data?.ToList(), @object, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// + /// + /// A new instance for mocking. + public static DeleteFileResponse DeleteFileResponse(string id = null, DeleteFileResponseObject @object = default, bool deleted = default) + { + return new DeleteFileResponse(id, @object, deleted, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// The ID of an uploaded file that contains training data. + /// + /// See [upload file](/docs/api-reference/files/upload) for how to upload a file. + /// + /// Your dataset must be formatted as a JSONL file, where each training example is a JSON object + /// with the keys "prompt" and "completion". Additionally, you must upload your file with the + /// purpose `fine-tune`. + /// + /// See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more + /// details. + /// + /// + /// The ID of an uploaded file that contains validation data. + /// + /// If you provide this file, the data is used to generate validation metrics periodically during + /// fine-tuning. These metrics can be viewed in the + /// [fine-tuning results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model). + /// Your train and validation data should be mutually exclusive. + /// + /// Your dataset must be formatted as a JSONL file, where each validation example is a JSON object + /// with the keys "prompt" and "completion". Additionally, you must upload your file with the + /// purpose `fine-tune`. + /// + /// See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more + /// details. + /// + /// + /// The name of the base model to fine-tune. You can select one of "ada", "babbage", "curie", + /// "davinci", or a fine-tuned model created after 2022-04-21 and before 2023-08-22. To learn more + /// about these models, see the [Models](/docs/models) documentation. + /// + /// + /// The number of epochs to train the model for. An epoch refers to one full cycle through the + /// training dataset. + /// + /// + /// The batch size to use for training. The batch size is the number of training examples used to + /// train a single forward and backward pass. + /// + /// By default, the batch size will be dynamically configured to be ~0.2% of the number of examples + /// in the training set, capped at 256 - in general, we've found that larger batch sizes tend to + /// work better for larger datasets. + /// + /// + /// The learning rate multiplier to use for training. The fine-tuning learning rate is the original + /// learning rate used for pretraining multiplied by this value. + /// + /// By default, the learning rate multiplier is the 0.05, 0.1, or 0.2 depending on final + /// `batch_size` (larger learning rates tend to perform better with larger batch sizes). We + /// recommend experimenting with values in the range 0.02 to 0.2 to see what produces the best + /// results. + /// + /// + /// The weight to use for loss on the prompt tokens. This controls how much the model tries to + /// learn to generate the prompt (as compared to the completion which always has a weight of 1.0), + /// and can add a stabilizing effect to training when completions are short. + /// + /// If prompts are extremely long (relative to completions), it may make sense to reduce this + /// weight so as to avoid over-prioritizing learning the prompt. + /// + /// + /// If set, we calculate classification-specific metrics such as accuracy and F-1 score using the + /// validation set at the end of every epoch. These metrics can be viewed in the + /// [results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model). + /// + /// In order to compute classification metrics, you must provide a `validation_file`. Additionally, + /// you must specify `classification_n_classes` for multiclass classification or + /// `classification_positive_class` for binary classification. + /// + /// + /// The number of classes in a classification task. + /// + /// This parameter is required for multiclass classification. + /// + /// + /// The positive class in binary classification. + /// + /// This parameter is needed to generate precision, recall, and F1 metrics when doing binary + /// classification. + /// + /// + /// If this is provided, we calculate F-beta scores at the specified beta values. The F-beta score + /// is a generalization of F-1 score. This is only used for binary classification. + /// + /// With a beta of 1 (i.e. the F-1 score), precision and recall are given the same weight. A larger + /// beta score puts more weight on recall and less on precision. A smaller beta score puts more + /// weight on precision and less on recall. + /// + /// + /// 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 + /// `ada:ft-your-org:custom-model-name-2022-02-15-04-21-04`. + /// + /// A new instance for mocking. + public static CreateFineTuneRequest CreateFineTuneRequest(string trainingFile = null, string validationFile = null, CreateFineTuneRequestModel? model = null, long? nEpochs = null, long? batchSize = null, double? learningRateMultiplier = null, double? promptLossRate = null, bool? computeClassificationMetrics = null, long? classificationNClasses = null, string classificationPositiveClass = null, IEnumerable classificationBetas = null, string suffix = null) + { + classificationBetas ??= new List(); + + return new CreateFineTuneRequest(trainingFile, validationFile, model, nEpochs, batchSize, learningRateMultiplier, promptLossRate, computeClassificationMetrics, classificationNClasses, classificationPositiveClass, classificationBetas?.ToList(), suffix, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The object identifier, which can be referenced in the API endpoints. + /// The object type, which is always "fine-tune". + /// The Unix timestamp (in seconds) for when the fine-tuning job was created. + /// The Unix timestamp (in seconds) for when the fine-tuning job was last updated. + /// The base model that is being fine-tuned. + /// The name of the fine-tuned model that is being created. + /// The organization that owns the fine-tuning job. + /// + /// The current status of the fine-tuning job, which can be either `created`, `running`, + /// `succeeded`, `failed`, or `cancelled`. + /// + /// + /// The hyperparameters used for the fine-tuning job. See the + /// [fine-tuning guide](/docs/guides/legacy-fine-tuning/hyperparameters) for more details. + /// + /// The list of files used for training. + /// The list of files used for validation. + /// The compiled results files for the fine-tuning job. + /// The list of events that have been observed in the lifecycle of the FineTune job. + /// A new instance for mocking. + public static FineTune FineTune(string id = null, FineTuneObject @object = default, DateTimeOffset createdAt = default, DateTimeOffset updatedAt = default, string model = null, string fineTunedModel = null, string organizationId = null, FineTuneStatus status = default, FineTuneHyperparams hyperparams = null, IEnumerable trainingFiles = null, IEnumerable validationFiles = null, IEnumerable resultFiles = null, IEnumerable events = null) + { + trainingFiles ??= new List(); + validationFiles ??= new List(); + resultFiles ??= new List(); + events ??= new List(); + + return new FineTune(id, @object, createdAt, updatedAt, model, fineTunedModel, organizationId, status, hyperparams, trainingFiles?.ToList(), validationFiles?.ToList(), resultFiles?.ToList(), events?.ToList(), serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// The number of epochs to train the model for. An epoch refers to one full cycle through the + /// training dataset. + /// + /// + /// The batch size to use for training. The batch size is the number of training examples used to + /// train a single forward and backward pass. + /// + /// The weight to use for loss on the prompt tokens. + /// The learning rate multiplier to use for training. + /// The classification metrics to compute using the validation dataset at the end of every epoch. + /// The positive class to use for computing classification metrics. + /// The number of classes to use for computing classification metrics. + /// A new instance for mocking. + public static FineTuneHyperparams FineTuneHyperparams(long nEpochs = default, long batchSize = default, double promptLossWeight = default, double learningRateMultiplier = default, bool? computeClassificationMetrics = null, string classificationPositiveClass = null, long? classificationNClasses = null) + { + return new FineTuneHyperparams(nEpochs, batchSize, promptLossWeight, learningRateMultiplier, computeClassificationMetrics, classificationPositiveClass, classificationNClasses, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// + /// + /// + /// A new instance for mocking. + public static FineTuneEvent FineTuneEvent(string @object = null, DateTimeOffset createdAt = default, string level = null, string message = null) + { + return new FineTuneEvent(@object, createdAt, level, message, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// + /// A new instance for mocking. + public static ListFineTunesResponse ListFineTunesResponse(string @object = null, IEnumerable data = null) + { + data ??= new List(); + + return new ListFineTunesResponse(@object, data?.ToList(), serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// + /// A new instance for mocking. + public static ListFineTuneEventsResponse ListFineTuneEventsResponse(string @object = null, IEnumerable data = null) + { + data ??= new List(); + + return new ListFineTuneEventsResponse(@object, data?.ToList(), serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// A text description of the desired image(s). The maximum length is 1000 characters for + /// `dall-e-2` and 4000 characters for `dall-e-3`. + /// + /// The model to use for image generation. + /// + /// The number of images to generate. Must be between 1 and 10. For `dall-e-3`, only `n=1` is + /// supported. + /// + /// + /// The quality of the image that will be generated. `hd` creates images with finer details and + /// greater consistency across the image. This param is only supported for `dall-e-3`. + /// + /// The format in which the generated images are returned. Must be one of `url` or `b64_json`. + /// + /// 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. + /// + /// + /// The style of the generated images. Must be one of `vivid` or `natural`. Vivid causes the model + /// to lean towards generating hyper-real and dramatic images. Natural causes the model to produce + /// more natural, less hyper-real looking images. This param is only supported for `dall-e-3`. + /// + /// + /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect + /// abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + /// + /// A new instance for mocking. + public static CreateImageRequest CreateImageRequest(string prompt = null, CreateImageRequestModel? model = null, long? n = null, CreateImageRequestQuality? quality = null, CreateImageRequestResponseFormat? responseFormat = null, CreateImageRequestSize? size = null, CreateImageRequestStyle? style = null, string user = null) + { + return new CreateImageRequest(prompt, model, n, quality, responseFormat, size, style, user, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// + /// A new instance for mocking. + public static ImagesResponse ImagesResponse(DateTimeOffset created = default, IEnumerable data = null) + { + data ??= new List(); + + return new ImagesResponse(created, data?.ToList(), serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The base64-encoded JSON of the generated image, if `response_format` is `b64_json`. + /// The URL of the generated image, if `response_format` is `url` (default). + /// The prompt that was used to generate the image, if there was any revision to the prompt. + /// A new instance for mocking. + public static Image Image(BinaryData b64Json = null, Uri url = null, string revisedPrompt = null) + { + return new Image(b64Json, url, revisedPrompt, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// The image to edit. Must be a valid PNG file, less than 4MB, and square. If mask is not + /// provided, image must have transparency, which will be used as the mask. + /// + /// A text description of the desired image(s). The maximum length is 1000 characters. + /// + /// An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where + /// `image` should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions + /// as `image`. + /// + /// The model to use for image generation. Only `dall-e-2` is supported at this time. + /// The number of images to generate. Must be between 1 and 10. + /// The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`. + /// The format in which the generated images are returned. Must be one of `url` or `b64_json`. + /// + /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect + /// abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + /// + /// A new instance for mocking. + public static CreateImageEditRequest CreateImageEditRequest(BinaryData image = null, string prompt = null, BinaryData mask = null, CreateImageEditRequestModel? model = null, long? n = null, CreateImageEditRequestSize? size = null, CreateImageEditRequestResponseFormat? responseFormat = null, string user = null) + { + return new CreateImageEditRequest(image, prompt, mask, model, n, size, responseFormat, user, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// The image to use as the basis for the variation(s). Must be a valid PNG file, less than 4MB, + /// and square. + /// + /// The model to use for image generation. Only `dall-e-2` is supported at this time. + /// The number of images to generate. Must be between 1 and 10. + /// The format in which the generated images are returned. Must be one of `url` or `b64_json`. + /// The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`. + /// + /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect + /// abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + /// + /// A new instance for mocking. + public static CreateImageVariationRequest CreateImageVariationRequest(BinaryData image = null, CreateImageVariationRequestModel? model = null, long? n = null, CreateImageVariationRequestResponseFormat? responseFormat = null, CreateImageVariationRequestSize? size = null, string user = null) + { + return new CreateImageVariationRequest(image, model, n, responseFormat, size, user, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The role of the entity that is creating the message. Currently only `user` is supported. + /// The content of the message. + /// + /// A list of [File](/docs/api-reference/files) IDs that the message should use. There can be a + /// maximum of 10 files attached to a message. Useful for tools like `retrieval` and + /// `code_interpreter` that can access and use files. + /// + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// A new instance for mocking. + public static CreateMessageRequest CreateMessageRequest(CreateMessageRequestRole role = default, string content = null, IEnumerable fileIds = null, IDictionary metadata = null) + { + fileIds ??= new List(); + metadata ??= new Dictionary(); + + return new CreateMessageRequest(role, content, fileIds?.ToList(), metadata, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The identifier, which can be referenced in API endpoints. + /// The object type, which is always `thread.message`. + /// The Unix timestamp (in seconds) for when the message was created. + /// The [thread](/docs/api-reference/threads) ID that this message belongs to. + /// The entity that produced the message. One of `user` or `assistant`. + /// The content of the message in array of text and/or images. + /// + /// If applicable, the ID of the [assistant](/docs/api-reference/assistants) that authored this + /// message. + /// + /// + /// If applicable, the ID of the [run](/docs/api-reference/runs) associated with the authoring of + /// this message. + /// + /// + /// A list of [file](/docs/api-reference/files) IDs that the assistant should use. Useful for + /// tools like retrieval and code_interpreter that can access files. A maximum of 10 files can be + /// attached to a message. + /// + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// A new instance for mocking. + public static MessageObject MessageObject(string id = null, MessageObjectObject @object = default, DateTimeOffset createdAt = default, string threadId = null, MessageObjectRole role = default, IEnumerable content = null, string assistantId = null, string runId = null, IEnumerable fileIds = null, IReadOnlyDictionary metadata = null) + { + content ??= new List(); + fileIds ??= new List(); + metadata ??= new Dictionary(); + + return new MessageObject(id, @object, createdAt, threadId, role, content?.ToList(), assistantId, runId, fileIds?.ToList(), metadata, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// + /// + /// + /// + /// A new instance for mocking. + public static ListMessagesResponse ListMessagesResponse(ListMessagesResponseObject @object = default, IEnumerable data = null, string firstId = null, string lastId = null, bool hasMore = default) + { + data ??= new List(); + + return new ListMessagesResponse(@object, data?.ToList(), firstId, lastId, hasMore, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// + /// + /// + /// + /// A new instance for mocking. + public static ListMessageFilesResponse ListMessageFilesResponse(ListMessageFilesResponseObject @object = default, IEnumerable data = null, string firstId = null, string lastId = null, bool hasMore = default) + { + data ??= new List(); + + return new ListMessageFilesResponse(@object, data?.ToList(), firstId, lastId, hasMore, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// TThe identifier, which can be referenced in API endpoints. + /// The object type, which is always `thread.message.file`. + /// The Unix timestamp (in seconds) for when the message file was created. + /// The ID of the [message](/docs/api-reference/messages) that the [File](/docs/api-reference/files) is attached to. + /// A new instance for mocking. + public static MessageFileObject MessageFileObject(string id = null, MessageFileObjectObject @object = default, DateTimeOffset createdAt = default, string messageId = null) + { + return new MessageFileObject(id, @object, createdAt, messageId, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// + /// A new instance for mocking. + public static ListModelsResponse ListModelsResponse(ListModelsResponseObject @object = default, IEnumerable data = null) + { + data ??= new List(); + + return new ListModelsResponse(@object, data?.ToList(), serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The model identifier, which can be referenced in the API endpoints. + /// The Unix timestamp (in seconds) when the model was created. + /// The object type, which is always "model". + /// The organization that owns the model. + /// A new instance for mocking. + public static Model Model(string id = null, DateTimeOffset created = default, ModelObject @object = default, string ownedBy = null) + { + return new Model(id, created, @object, ownedBy, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// + /// + /// A new instance for mocking. + public static DeleteModelResponse DeleteModelResponse(string id = null, bool deleted = default, DeleteModelResponseObject @object = default) + { + return new DeleteModelResponse(id, deleted, @object, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The input text to classify. + /// + /// Two content moderations models are available: `text-moderation-stable` and + /// `text-moderation-latest`. The default is `text-moderation-latest` which will be automatically + /// upgraded over time. This ensures you are always using our most accurate model. If you use + /// `text-moderation-stable`, we will provide advanced notice before updating the model. Accuracy + /// of `text-moderation-stable` may be slightly lower than for `text-moderation-latest`. + /// + /// A new instance for mocking. + public static CreateModerationRequest CreateModerationRequest(BinaryData input = null, CreateModerationRequestModel? model = null) + { + return new CreateModerationRequest(input, model, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The unique identifier for the moderation request. + /// The model used to generate the moderation results. + /// A list of moderation objects. + /// A new instance for mocking. + public static CreateModerationResponse CreateModerationResponse(string id = null, string model = null, IEnumerable results = null) + { + results ??= new List(); + + return new CreateModerationResponse(id, model, results?.ToList(), serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// Whether the content violates [OpenAI's usage policies](/policies/usage-policies). + /// A list of the categories, and whether they are flagged or not. + /// A list of the categories along with their scores as predicted by model. + /// A new instance for mocking. + public static CreateModerationResponseResult CreateModerationResponseResult(bool flagged = default, CreateModerationResponseResultCategories categories = null, CreateModerationResponseResultCategoryScores categoryScores = null) + { + return new CreateModerationResponseResult(flagged, categories, categoryScores, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// Content that expresses, incites, or promotes hate based on race, gender, ethnicity, + /// religion, nationality, sexual orientation, disability status, or caste. Hateful content + /// aimed at non-protected groups (e.g., chess players) is harrassment. + /// + /// + /// Hateful content that also includes violence or serious harm towards the targeted group + /// based on race, gender, ethnicity, religion, nationality, sexual orientation, disability + /// status, or caste. + /// + /// Content that expresses, incites, or promotes harassing language towards any target. + /// Harassment content that also includes violence or serious harm towards any target. + /// + /// Content that promotes, encourages, or depicts acts of self-harm, such as suicide, cutting, + /// and eating disorders. + /// + /// + /// Content where the speaker expresses that they are engaging or intend to engage in acts of + /// self-harm, such as suicide, cutting, and eating disorders. + /// + /// + /// Content that encourages performing acts of self-harm, such as suicide, cutting, and eating + /// disorders, or that gives instructions or advice on how to commit such acts. + /// + /// + /// Content meant to arouse sexual excitement, such as the description of sexual activity, or + /// that promotes sexual services (excluding sex education and wellness). + /// + /// Sexual content that includes an individual who is under 18 years old. + /// Content that depicts death, violence, or physical injury. + /// Content that depicts death, violence, or physical injury in graphic detail. + /// A new instance for mocking. + public static CreateModerationResponseResultCategories CreateModerationResponseResultCategories(bool hate = default, bool hateThreatening = default, bool harassment = default, bool harassmentThreatening = default, bool selfHarm = default, bool selfHarmIntent = default, bool selfHarmInstructions = default, bool sexual = default, bool sexualMinors = default, bool violence = default, bool violenceGraphic = default) + { + return new CreateModerationResponseResultCategories(hate, hateThreatening, harassment, harassmentThreatening, selfHarm, selfHarmIntent, selfHarmInstructions, sexual, sexualMinors, violence, violenceGraphic, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The score for the category 'hate'. + /// The score for the category 'hate/threatening'. + /// The score for the category 'harassment'. + /// The score for the category 'harassment/threatening'. + /// The score for the category 'self-harm'. + /// The score for the category 'self-harm/intent'. + /// The score for the category 'self-harm/instructive'. + /// The score for the category 'sexual'. + /// The score for the category 'sexual/minors'. + /// The score for the category 'violence'. + /// The score for the category 'violence/graphic'. + /// A new instance for mocking. + public static CreateModerationResponseResultCategoryScores CreateModerationResponseResultCategoryScores(double hate = default, double hateThreatening = default, double harassment = default, double harassmentThreatening = default, double selfHarm = default, double selfHarmIntent = default, double selfHarmInstructions = default, double sexual = default, double sexualMinors = default, double violence = default, double violenceGraphic = default) + { + return new CreateModerationResponseResultCategoryScores(hate, hateThreatening, harassment, harassmentThreatening, selfHarm, selfHarmIntent, selfHarmInstructions, sexual, sexualMinors, violence, violenceGraphic, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The ID of the [assistant](/docs/api-reference/assistants) to use to execute this run. + /// If no thread is provided, an empty thread will be created. + /// + /// The ID of the [Model](/docs/api-reference/models) to be used to execute this run. If a value is + /// provided here, it will override the model associated with the assistant. If not, the model + /// associated with the assistant will be used. + /// + /// + /// Override the default system message of the assistant. This is useful for modifying the behavior + /// on a per-run basis. + /// + /// + /// Override the tools the assistant can use for this run. This is useful for modifying the + /// behavior on a per-run basis. + /// + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// A new instance for mocking. + public static CreateThreadAndRunRequest CreateThreadAndRunRequest(string assistantId = null, CreateThreadRequest thread = null, string model = null, string instructions = null, IEnumerable tools = null, IDictionary metadata = null) + { + tools ??= new List(); + metadata ??= new Dictionary(); + + return new CreateThreadAndRunRequest(assistantId, thread, model, instructions, tools?.ToList(), metadata, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The identifier, which can be referenced in API endpoints. + /// The object type, which is always `thread.run`. + /// The Unix timestamp (in seconds) for when the run was created. + /// + /// The ID of the [thread](/docs/api-reference/threads) that was executed on as a part of this + /// run. + /// + /// The ID of the [assistant](/docs/api-reference/assistants) used for execution of this run. + /// + /// The status of the run, which can be either `queued`, `in_progress`, `requires_action`, + /// `cancelling`, `cancelled`, `failed`, `completed`, or `expired`. + /// + /// + /// Details on the action required to continue the run. Will be `null` if no action is + /// required. + /// + /// The last error associated with this run. Will be `null` if there are no errors. + /// The Unix timestamp (in seconds) for when the run will expire. + /// The Unix timestamp (in seconds) for when the run was started. + /// The Unix timestamp (in seconds) for when the run was cancelled. + /// The Unix timestamp (in seconds) for when the run failed. + /// The Unix timestamp (in seconds) for when the run was completed. + /// The model that the [assistant](/docs/api-reference/assistants) used for this run. + /// The instructions that the [assistant](/docs/api-reference/assistants) used for this run. + /// The list of tools that the [assistant](/docs/api-reference/assistants) used for this run. + /// + /// The list of [File](/docs/api-reference/files) IDs the + /// [assistant](/docs/api-reference/assistants) used for this run. + /// + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// + /// A new instance for mocking. + public static RunObject RunObject(string id = null, RunObjectObject @object = default, DateTimeOffset createdAt = default, string threadId = null, string assistantId = null, RunObjectStatus status = default, RunObjectRequiredAction requiredAction = null, RunObjectLastError lastError = null, DateTimeOffset expiresAt = default, DateTimeOffset? startedAt = null, DateTimeOffset? cancelledAt = null, DateTimeOffset? failedAt = null, DateTimeOffset? completedAt = null, string model = null, string instructions = null, IEnumerable tools = null, IEnumerable fileIds = null, IReadOnlyDictionary metadata = null, RunCompletionUsage usage = null) + { + tools ??= new List(); + fileIds ??= new List(); + metadata ??= new Dictionary(); + + return new RunObject(id, @object, createdAt, threadId, assistantId, status, requiredAction, lastError, expiresAt, startedAt, cancelledAt, failedAt, completedAt, model, instructions, tools?.ToList(), fileIds?.ToList(), metadata, usage, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// For now, this is always `submit_tool_outputs`. + /// Details on the tool outputs needed for this run to continue. + /// A new instance for mocking. + public static RunObjectRequiredAction RunObjectRequiredAction(RunObjectRequiredActionType type = default, RunObjectRequiredActionSubmitToolOutputs submitToolOutputs = null) + { + return new RunObjectRequiredAction(type, submitToolOutputs, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// A list of the relevant tool calls. + /// A new instance for mocking. + public static RunObjectRequiredActionSubmitToolOutputs RunObjectRequiredActionSubmitToolOutputs(IEnumerable toolCalls = null) + { + toolCalls ??= new List(); + + return new RunObjectRequiredActionSubmitToolOutputs(toolCalls?.ToList(), serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// The ID of the tool call. This ID must be referenced when you submit the tool outputs in using + /// the [Submit tool outputs to run](/docs/api-reference/runs/submitToolOutputs) endpoint. + /// + /// The type of tool call the output is required for. For now, this is always `function`. + /// The function definition. + /// A new instance for mocking. + public static RunToolCallObject RunToolCallObject(string id = null, RunToolCallObjectType type = default, RunToolCallObjectFunction function = null) + { + return new RunToolCallObject(id, type, function, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The name of the function. + /// The arguments that the model expects you to pass to the function. + /// A new instance for mocking. + public static RunToolCallObjectFunction RunToolCallObjectFunction(string name = null, string arguments = null) + { + return new RunToolCallObjectFunction(name, arguments, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// One of `server_error` or `rate_limit_exceeded`. + /// A human-readable description of the error. + /// A new instance for mocking. + public static RunObjectLastError RunObjectLastError(RunObjectLastErrorCode code = default, string message = null) + { + return new RunObjectLastError(code, message, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// Number of completion tokens used over the course of the run. + /// Number of prompt tokens used over the course of the run. + /// Total number of tokens used (prompt + completion). + /// A new instance for mocking. + public static RunCompletionUsage RunCompletionUsage(long completionTokens = default, long promptTokens = default, long totalTokens = default) + { + return new RunCompletionUsage(completionTokens, promptTokens, totalTokens, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The ID of the [assistant](/docs/api-reference/assistants) to use to execute this run. + /// + /// The ID of the [Model](/docs/api-reference/models) to be used to execute this run. If a value + /// is provided here, it will override the model associated with the assistant. If not, the model + /// associated with the assistant will be used. + /// + /// + /// Overrides the [instructions](/docs/api-reference/assistants/createAssistant) of the assistant. + /// This is useful for modifying the behavior on a per-run basis. + /// + /// + /// Appends additional instructions at the end of the instructions for the run. This is useful for + /// modifying the behavior on a per-run basis without overriding other instructions. + /// + /// + /// Override the tools the assistant can use for this run. This is useful for modifying the + /// behavior on a per-run basis. + /// + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// A new instance for mocking. + public static CreateRunRequest CreateRunRequest(string assistantId = null, string model = null, string instructions = null, string additionalInstructions = null, IEnumerable tools = null, IDictionary metadata = null) + { + tools ??= new List(); + metadata ??= new Dictionary(); + + return new CreateRunRequest(assistantId, model, instructions, additionalInstructions, tools?.ToList(), metadata, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// + /// + /// + /// + /// A new instance for mocking. + public static ListRunsResponse ListRunsResponse(ListRunsResponseObject @object = default, IEnumerable data = null, string firstId = null, string lastId = null, bool hasMore = default) + { + data ??= new List(); + + return new ListRunsResponse(@object, data?.ToList(), firstId, lastId, hasMore, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// + /// + /// + /// + /// A new instance for mocking. + public static ListRunStepsResponse ListRunStepsResponse(ListRunStepsResponseObject @object = default, IEnumerable data = null, string firstId = null, string lastId = null, bool hasMore = default) + { + data ??= new List(); + + return new ListRunStepsResponse(@object, data?.ToList(), firstId, lastId, hasMore, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The identifier of the run step, which can be referenced in API endpoints. + /// The object type, which is always `thread.run.step`. + /// The Unix timestamp (in seconds) for when the run step was created. + /// The ID of the [assistant](/docs/api-reference/assistants) associated with the run step. + /// The ID of the [thread](/docs/api-reference/threads) that was run. + /// The ID of the [run](/docs/api-reference/runs) that this run step is a part of. + /// The type of run step, which can be either `message_creation` or `tool_calls`. + /// + /// The status of the run step, which can be either `in_progress`, `cancelled`, `failed`, + /// `completed`, or `expired`. + /// + /// The details of the run step. + /// The last error associated with this run step. Will be `null` if there are no errors. + /// + /// The Unix timestamp (in seconds) for when the run step expired. A step is considered expired + /// if the parent run is expired. + /// + /// The Unix timestamp (in seconds) for when the run step was cancelled. + /// The Unix timestamp (in seconds) for when the run step failed. + /// T The Unix timestamp (in seconds) for when the run step completed.. + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// + /// A new instance for mocking. + public static RunStepObject RunStepObject(string id = null, RunStepObjectObject @object = default, DateTimeOffset createdAt = default, string assistantId = null, string threadId = null, string runId = null, RunStepObjectType type = default, RunStepObjectStatus status = default, BinaryData stepDetails = null, RunStepObjectLastError lastError = null, DateTimeOffset? expiresAt = null, DateTimeOffset? cancelledAt = null, DateTimeOffset? failedAt = null, DateTimeOffset? completedAt = null, IReadOnlyDictionary metadata = null, RunCompletionUsage usage = null) + { + metadata ??= new Dictionary(); + + return new RunStepObject(id, @object, createdAt, assistantId, threadId, runId, type, status, stepDetails, lastError, expiresAt, cancelledAt, failedAt, completedAt, metadata, usage, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// One of `server_error` or `rate_limit_exceeded`. + /// A human-readable description of the error. + /// A new instance for mocking. + public static RunStepObjectLastError RunStepObjectLastError(RunStepObjectLastErrorCode code = default, string message = null) + { + return new RunStepObjectLastError(code, message, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The identifier, which can be referenced in API endpoints. + /// The object type, which is always `thread`. + /// The Unix timestamp (in seconds) for when the thread was created. + /// + /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + /// additional information about the object in a structured format. Keys can be a maximum of 64 + /// characters long and values can be a maxium of 512 characters long. + /// + /// A new instance for mocking. + public static ThreadObject ThreadObject(string id = null, ThreadObjectObject @object = default, DateTimeOffset createdAt = default, IReadOnlyDictionary metadata = null) + { + metadata ??= new Dictionary(); + + return new ThreadObject(id, @object, createdAt, metadata, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// + /// + /// + /// A new instance for mocking. + public static DeleteThreadResponse DeleteThreadResponse(string id = null, bool deleted = default, DeleteThreadResponseObject @object = default) + { + return new DeleteThreadResponse(id, deleted, @object, serializedAdditionalRawData: null); + } + } +} diff --git a/.dotnet/src/Generated/Runs.cs b/.dotnet/src/Generated/Runs.cs new file mode 100644 index 000000000..fbe954204 --- /dev/null +++ b/.dotnet/src/Generated/Runs.cs @@ -0,0 +1,1442 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.ClientModel.Primitives.Pipeline; +using System.Threading; +using System.Threading.Tasks; +using OpenAI.Models; + +namespace OpenAI +{ + // Data plane generated sub-client. + /// The Runs sub-client. + public partial class Runs + { + private const string AuthorizationHeader = "Authorization"; + private readonly KeyCredential _keyCredential; + private const string AuthorizationApiKeyPrefix = "Bearer"; + private readonly MessagePipeline _pipeline; + private readonly Uri _endpoint; + + /// The ClientDiagnostics is used to provide tracing support for the client library. + internal TelemetrySource ClientDiagnostics { get; } + + /// The HTTP pipeline for sending and receiving REST requests and responses. + public virtual MessagePipeline Pipeline => _pipeline; + + /// Initializes a new instance of Runs for mocking. + protected Runs() + { + } + + /// Initializes a new instance of Runs. + /// The handler for diagnostic messaging in the client. + /// The HTTP pipeline for sending and receiving REST requests and responses. + /// The key credential to copy. + /// OpenAI Endpoint. + internal Runs(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + { + ClientDiagnostics = clientDiagnostics; + _pipeline = pipeline; + _keyCredential = keyCredential; + _endpoint = endpoint; + } + + /// Create a thread and run it in one request. + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual async Task> CreateThreadAndRunAsync(CreateThreadAndRunRequest threadAndRun, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(threadAndRun, nameof(threadAndRun)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = threadAndRun.ToRequestBody(); + Result result = await CreateThreadAndRunAsync(content, context).ConfigureAwait(false); + return Result.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Create a thread and run it in one request. + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual Result CreateThreadAndRun(CreateThreadAndRunRequest threadAndRun, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(threadAndRun, nameof(threadAndRun)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = threadAndRun.ToRequestBody(); + Result result = CreateThreadAndRun(content, context); + return Result.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Create a thread and run it in one request. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task CreateThreadAndRunAsync(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Runs.CreateThreadAndRun"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateThreadAndRunRequest(content, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Create a thread and run it in one request. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result CreateThreadAndRun(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Runs.CreateThreadAndRun"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateThreadAndRunRequest(content, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Create a run. + /// The ID of the thread to run. + /// The to use. + /// The cancellation token to use. + /// or is null. + /// is an empty string, and was expected to be non-empty. + public virtual async Task> CreateRunAsync(string threadId, CreateRunRequest run, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNull(run, nameof(run)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = run.ToRequestBody(); + Result result = await CreateRunAsync(threadId, content, context).ConfigureAwait(false); + return Result.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Create a run. + /// The ID of the thread to run. + /// The to use. + /// The cancellation token to use. + /// or is null. + /// is an empty string, and was expected to be non-empty. + public virtual Result CreateRun(string threadId, CreateRunRequest run, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNull(run, nameof(run)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = run.ToRequestBody(); + Result result = CreateRun(threadId, content, context); + return Result.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Create a run. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the thread to run. + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task CreateRunAsync(string threadId, RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Runs.CreateRun"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateRunRequest(threadId, content, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Create a run. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the thread to run. + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result CreateRun(string threadId, RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Runs.CreateRun"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateRunRequest(threadId, content, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Returns a list of runs belonging to a thread. + /// The ID of the thread the run belongs to. + /// + /// A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + /// default is 20. + /// + /// + /// Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + /// for descending order. + /// + /// + /// A cursor for use in pagination. `after` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include after=obj_foo in order to fetch the next page of the list. + /// + /// + /// A cursor for use in pagination. `before` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. + /// + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual async Task> GetRunsAsync(string threadId, int? limit = null, ListOrder? order = null, string after = null, string before = null, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await GetRunsAsync(threadId, limit, order?.ToString(), after, before, context).ConfigureAwait(false); + return Result.FromValue(ListRunsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Returns a list of runs belonging to a thread. + /// The ID of the thread the run belongs to. + /// + /// A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + /// default is 20. + /// + /// + /// Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + /// for descending order. + /// + /// + /// A cursor for use in pagination. `after` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include after=obj_foo in order to fetch the next page of the list. + /// + /// + /// A cursor for use in pagination. `before` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. + /// + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual Result GetRuns(string threadId, int? limit = null, ListOrder? order = null, string after = null, string before = null, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = GetRuns(threadId, limit, order?.ToString(), after, before, context); + return Result.FromValue(ListRunsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Returns a list of runs belonging to a thread. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the thread the run belongs to. + /// + /// A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + /// default is 20. + /// + /// + /// Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + /// for descending order. Allowed values: "asc" | "desc" + /// + /// + /// A cursor for use in pagination. `after` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include after=obj_foo in order to fetch the next page of the list. + /// + /// + /// A cursor for use in pagination. `before` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. + /// + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task GetRunsAsync(string threadId, int? limit, string order, string after, string before, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + + using var scope = ClientDiagnostics.CreateSpan("Runs.GetRuns"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetRunsRequest(threadId, limit, order, after, before, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Returns a list of runs belonging to a thread. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the thread the run belongs to. + /// + /// A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + /// default is 20. + /// + /// + /// Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + /// for descending order. Allowed values: "asc" | "desc" + /// + /// + /// A cursor for use in pagination. `after` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include after=obj_foo in order to fetch the next page of the list. + /// + /// + /// A cursor for use in pagination. `before` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. + /// + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result GetRuns(string threadId, int? limit, string order, string after, string before, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + + using var scope = ClientDiagnostics.CreateSpan("Runs.GetRuns"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetRunsRequest(threadId, limit, order, after, before, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Retrieves a run. + /// The ID of the [thread](/docs/api-reference/threads) that was run. + /// The ID of the run to retrieve. + /// The cancellation token to use. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + public virtual async Task> GetRunAsync(string threadId, string runId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await GetRunAsync(threadId, runId, context).ConfigureAwait(false); + return Result.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Retrieves a run. + /// The ID of the [thread](/docs/api-reference/threads) that was run. + /// The ID of the run to retrieve. + /// The cancellation token to use. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + public virtual Result GetRun(string threadId, string runId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = GetRun(threadId, runId, context); + return Result.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Retrieves a run. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the [thread](/docs/api-reference/threads) that was run. + /// The ID of the run to retrieve. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task GetRunAsync(string threadId, string runId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + + using var scope = ClientDiagnostics.CreateSpan("Runs.GetRun"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetRunRequest(threadId, runId, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Retrieves a run. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the [thread](/docs/api-reference/threads) that was run. + /// The ID of the run to retrieve. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result GetRun(string threadId, string runId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + + using var scope = ClientDiagnostics.CreateSpan("Runs.GetRun"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetRunRequest(threadId, runId, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Modifies a run. + /// The ID of the [thread](/docs/api-reference/threads) that was run. + /// The ID of the run to modify. + /// The to use. + /// The cancellation token to use. + /// , or is null. + /// or is an empty string, and was expected to be non-empty. + public virtual async Task> ModifyRunAsync(string threadId, string runId, ModifyRunRequest run, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + ClientUtilities.AssertNotNull(run, nameof(run)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = run.ToRequestBody(); + Result result = await ModifyRunAsync(threadId, runId, content, context).ConfigureAwait(false); + return Result.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Modifies a run. + /// The ID of the [thread](/docs/api-reference/threads) that was run. + /// The ID of the run to modify. + /// The to use. + /// The cancellation token to use. + /// , or is null. + /// or is an empty string, and was expected to be non-empty. + public virtual Result ModifyRun(string threadId, string runId, ModifyRunRequest run, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + ClientUtilities.AssertNotNull(run, nameof(run)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = run.ToRequestBody(); + Result result = ModifyRun(threadId, runId, content, context); + return Result.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Modifies a run. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the [thread](/docs/api-reference/threads) that was run. + /// The ID of the run to modify. + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// , or is null. + /// or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task ModifyRunAsync(string threadId, string runId, RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Runs.ModifyRun"); + scope.Start(); + try + { + using PipelineMessage message = CreateModifyRunRequest(threadId, runId, content, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Modifies a run. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the [thread](/docs/api-reference/threads) that was run. + /// The ID of the run to modify. + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// , or is null. + /// or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result ModifyRun(string threadId, string runId, RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Runs.ModifyRun"); + scope.Start(); + try + { + using PipelineMessage message = CreateModifyRunRequest(threadId, runId, content, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Cancels a run that is `in_progress`. + /// The ID of the thread to which this run belongs. + /// The ID of the run to cancel. + /// The cancellation token to use. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + public virtual async Task> CancelRunAsync(string threadId, string runId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await CancelRunAsync(threadId, runId, context).ConfigureAwait(false); + return Result.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Cancels a run that is `in_progress`. + /// The ID of the thread to which this run belongs. + /// The ID of the run to cancel. + /// The cancellation token to use. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + public virtual Result CancelRun(string threadId, string runId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = CancelRun(threadId, runId, context); + return Result.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Cancels a run that is `in_progress`. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the thread to which this run belongs. + /// The ID of the run to cancel. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task CancelRunAsync(string threadId, string runId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + + using var scope = ClientDiagnostics.CreateSpan("Runs.CancelRun"); + scope.Start(); + try + { + using PipelineMessage message = CreateCancelRunRequest(threadId, runId, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Cancels a run that is `in_progress`. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the thread to which this run belongs. + /// The ID of the run to cancel. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result CancelRun(string threadId, string runId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + + using var scope = ClientDiagnostics.CreateSpan("Runs.CancelRun"); + scope.Start(); + try + { + using PipelineMessage message = CreateCancelRunRequest(threadId, runId, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// When a run has the `status: "requires_action"` and `required_action.type` is + /// `submit_tool_outputs`, this endpoint can be used to submit the outputs from the tool calls once + /// they're all completed. All outputs must be submitted in a single request. + /// + /// The ID of the [thread](/docs/api-reference/threads) to which this run belongs. + /// The ID of the run that requires the tool output submission. + /// The to use. + /// The cancellation token to use. + /// , or is null. + /// or is an empty string, and was expected to be non-empty. + public virtual async Task> SubmitToolOuputsToRunAsync(string threadId, string runId, SubmitToolOutputsRunRequest submitToolOutputsRun, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + ClientUtilities.AssertNotNull(submitToolOutputsRun, nameof(submitToolOutputsRun)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = submitToolOutputsRun.ToRequestBody(); + Result result = await SubmitToolOuputsToRunAsync(threadId, runId, content, context).ConfigureAwait(false); + return Result.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// When a run has the `status: "requires_action"` and `required_action.type` is + /// `submit_tool_outputs`, this endpoint can be used to submit the outputs from the tool calls once + /// they're all completed. All outputs must be submitted in a single request. + /// + /// The ID of the [thread](/docs/api-reference/threads) to which this run belongs. + /// The ID of the run that requires the tool output submission. + /// The to use. + /// The cancellation token to use. + /// , or is null. + /// or is an empty string, and was expected to be non-empty. + public virtual Result SubmitToolOuputsToRun(string threadId, string runId, SubmitToolOutputsRunRequest submitToolOutputsRun, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + ClientUtilities.AssertNotNull(submitToolOutputsRun, nameof(submitToolOutputsRun)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = submitToolOutputsRun.ToRequestBody(); + Result result = SubmitToolOuputsToRun(threadId, runId, content, context); + return Result.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] When a run has the `status: "requires_action"` and `required_action.type` is + /// `submit_tool_outputs`, this endpoint can be used to submit the outputs from the tool calls once + /// they're all completed. All outputs must be submitted in a single request. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the [thread](/docs/api-reference/threads) to which this run belongs. + /// The ID of the run that requires the tool output submission. + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// , or is null. + /// or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task SubmitToolOuputsToRunAsync(string threadId, string runId, RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Runs.SubmitToolOuputsToRun"); + scope.Start(); + try + { + using PipelineMessage message = CreateSubmitToolOuputsToRunRequest(threadId, runId, content, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] When a run has the `status: "requires_action"` and `required_action.type` is + /// `submit_tool_outputs`, this endpoint can be used to submit the outputs from the tool calls once + /// they're all completed. All outputs must be submitted in a single request. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the [thread](/docs/api-reference/threads) to which this run belongs. + /// The ID of the run that requires the tool output submission. + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// , or is null. + /// or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result SubmitToolOuputsToRun(string threadId, string runId, RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Runs.SubmitToolOuputsToRun"); + scope.Start(); + try + { + using PipelineMessage message = CreateSubmitToolOuputsToRunRequest(threadId, runId, content, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Returns a list of run steps belonging to a run. + /// The ID of the thread the run and run steps belong to. + /// The ID of the run the run steps belong to. + /// + /// A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + /// default is 20. + /// + /// + /// Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + /// for descending order. + /// + /// + /// A cursor for use in pagination. `after` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include after=obj_foo in order to fetch the next page of the list. + /// + /// + /// A cursor for use in pagination. `before` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. + /// + /// The cancellation token to use. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + public virtual async Task> GetRunStepsAsync(string threadId, string runId, int? limit = null, ListOrder? order = null, string after = null, string before = null, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await GetRunStepsAsync(threadId, runId, limit, order?.ToString(), after, before, context).ConfigureAwait(false); + return Result.FromValue(ListRunStepsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Returns a list of run steps belonging to a run. + /// The ID of the thread the run and run steps belong to. + /// The ID of the run the run steps belong to. + /// + /// A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + /// default is 20. + /// + /// + /// Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + /// for descending order. + /// + /// + /// A cursor for use in pagination. `after` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include after=obj_foo in order to fetch the next page of the list. + /// + /// + /// A cursor for use in pagination. `before` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. + /// + /// The cancellation token to use. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + public virtual Result GetRunSteps(string threadId, string runId, int? limit = null, ListOrder? order = null, string after = null, string before = null, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = GetRunSteps(threadId, runId, limit, order?.ToString(), after, before, context); + return Result.FromValue(ListRunStepsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Returns a list of run steps belonging to a run. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the thread the run and run steps belong to. + /// The ID of the run the run steps belong to. + /// + /// A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + /// default is 20. + /// + /// + /// Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + /// for descending order. Allowed values: "asc" | "desc" + /// + /// + /// A cursor for use in pagination. `after` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include after=obj_foo in order to fetch the next page of the list. + /// + /// + /// A cursor for use in pagination. `before` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. + /// + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task GetRunStepsAsync(string threadId, string runId, int? limit, string order, string after, string before, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + + using var scope = ClientDiagnostics.CreateSpan("Runs.GetRunSteps"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetRunStepsRequest(threadId, runId, limit, order, after, before, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Returns a list of run steps belonging to a run. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the thread the run and run steps belong to. + /// The ID of the run the run steps belong to. + /// + /// A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + /// default is 20. + /// + /// + /// Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + /// for descending order. Allowed values: "asc" | "desc" + /// + /// + /// A cursor for use in pagination. `after` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include after=obj_foo in order to fetch the next page of the list. + /// + /// + /// A cursor for use in pagination. `before` is an object ID that defines your place in the list. + /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. + /// + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result GetRunSteps(string threadId, string runId, int? limit, string order, string after, string before, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + + using var scope = ClientDiagnostics.CreateSpan("Runs.GetRunSteps"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetRunStepsRequest(threadId, runId, limit, order, after, before, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Retrieves a run step. + /// The ID of the thread to which the run and run step belongs. + /// The ID of the run to which the run step belongs. + /// The ID of the run step to retrieve. + /// The cancellation token to use. + /// , or is null. + /// , or is an empty string, and was expected to be non-empty. + public virtual async Task> GetRunStepAsync(string threadId, string runId, string stepId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + ClientUtilities.AssertNotNullOrEmpty(stepId, nameof(stepId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await GetRunStepAsync(threadId, runId, stepId, context).ConfigureAwait(false); + return Result.FromValue(RunStepObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Retrieves a run step. + /// The ID of the thread to which the run and run step belongs. + /// The ID of the run to which the run step belongs. + /// The ID of the run step to retrieve. + /// The cancellation token to use. + /// , or is null. + /// , or is an empty string, and was expected to be non-empty. + public virtual Result GetRunStep(string threadId, string runId, string stepId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + ClientUtilities.AssertNotNullOrEmpty(stepId, nameof(stepId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = GetRunStep(threadId, runId, stepId, context); + return Result.FromValue(RunStepObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Retrieves a run step. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the thread to which the run and run step belongs. + /// The ID of the run to which the run step belongs. + /// The ID of the run step to retrieve. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// , or is null. + /// , or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task GetRunStepAsync(string threadId, string runId, string stepId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + ClientUtilities.AssertNotNullOrEmpty(stepId, nameof(stepId)); + + using var scope = ClientDiagnostics.CreateSpan("Runs.GetRunStep"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetRunStepRequest(threadId, runId, stepId, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Retrieves a run step. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the thread to which the run and run step belongs. + /// The ID of the run to which the run step belongs. + /// The ID of the run step to retrieve. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// , or is null. + /// , or is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result GetRunStep(string threadId, string runId, string stepId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + ClientUtilities.AssertNotNullOrEmpty(stepId, nameof(stepId)); + + using var scope = ClientDiagnostics.CreateSpan("Runs.GetRunStep"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetRunStepRequest(threadId, runId, stepId, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + internal PipelineMessage CreateCreateThreadAndRunRequest(RequestBody content, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/threads/runs", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + request.SetHeaderValue("Content-Type", "application/json"); + request.Content = content; + return message; + } + + internal PipelineMessage CreateCreateRunRequest(string threadId, RequestBody content, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/threads/", false); + uri.AppendPath(threadId, true); + uri.AppendPath("/runs", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + request.SetHeaderValue("Content-Type", "application/json"); + request.Content = content; + return message; + } + + internal PipelineMessage CreateGetRunsRequest(string threadId, int? limit, string order, string after, string before, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("GET"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/threads/", false); + uri.AppendPath(threadId, true); + uri.AppendPath("/runs", false); + if (limit != null) + { + uri.AppendQuery("limit", limit.Value, true); + } + if (order != null) + { + uri.AppendQuery("order", order, true); + } + if (after != null) + { + uri.AppendQuery("after", after, true); + } + if (before != null) + { + uri.AppendQuery("before", before, true); + } + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + internal PipelineMessage CreateGetRunRequest(string threadId, string runId, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("GET"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/threads/", false); + uri.AppendPath(threadId, true); + uri.AppendPath("/runs/", false); + uri.AppendPath(runId, true); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + internal PipelineMessage CreateModifyRunRequest(string threadId, string runId, RequestBody content, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/threads/", false); + uri.AppendPath(threadId, true); + uri.AppendPath("/runs/", false); + uri.AppendPath(runId, true); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + request.SetHeaderValue("Content-Type", "application/json"); + request.Content = content; + return message; + } + + internal PipelineMessage CreateCancelRunRequest(string threadId, string runId, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/threads/", false); + uri.AppendPath(threadId, true); + uri.AppendPath("/runs/", false); + uri.AppendPath(runId, true); + uri.AppendPath("/cancel", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + internal PipelineMessage CreateSubmitToolOuputsToRunRequest(string threadId, string runId, RequestBody content, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/threads/", false); + uri.AppendPath(threadId, true); + uri.AppendPath("/runs/", false); + uri.AppendPath(runId, true); + uri.AppendPath("/submit_tool_outputs", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + request.SetHeaderValue("Content-Type", "application/json"); + request.Content = content; + return message; + } + + internal PipelineMessage CreateGetRunStepsRequest(string threadId, string runId, int? limit, string order, string after, string before, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("GET"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/threads/", false); + uri.AppendPath(threadId, true); + uri.AppendPath("/runs/", false); + uri.AppendPath(runId, true); + uri.AppendPath("/steps", false); + if (limit != null) + { + uri.AppendQuery("limit", limit.Value, true); + } + if (order != null) + { + uri.AppendQuery("order", order, true); + } + if (after != null) + { + uri.AppendQuery("after", after, true); + } + if (before != null) + { + uri.AppendQuery("before", before, true); + } + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + internal PipelineMessage CreateGetRunStepRequest(string threadId, string runId, string stepId, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("GET"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/threads/", false); + uri.AppendPath(threadId, true); + uri.AppendPath("/runs/", false); + uri.AppendPath(runId, true); + uri.AppendPath("/steps/", false); + uri.AppendPath(stepId, true); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + private static RequestOptions DefaultRequestContext = new RequestOptions(); + internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) + { + if (!cancellationToken.CanBeCanceled) + { + return DefaultRequestContext; + } + + return new RequestOptions() { CancellationToken = cancellationToken }; + } + + private static ResponseErrorClassifier _responseErrorClassifier200; + private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); + } +} diff --git a/.dotnet/src/Generated/Threads.cs b/.dotnet/src/Generated/Threads.cs new file mode 100644 index 000000000..b7ef0388d --- /dev/null +++ b/.dotnet/src/Generated/Threads.cs @@ -0,0 +1,555 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using System.ClientModel.Internal; +using System.ClientModel.Primitives; +using System.ClientModel.Primitives.Pipeline; +using System.Threading; +using System.Threading.Tasks; +using OpenAI.Models; + +namespace OpenAI +{ + // Data plane generated sub-client. + /// The Threads sub-client. + public partial class Threads + { + private const string AuthorizationHeader = "Authorization"; + private readonly KeyCredential _keyCredential; + private const string AuthorizationApiKeyPrefix = "Bearer"; + private readonly MessagePipeline _pipeline; + private readonly Uri _endpoint; + + /// The ClientDiagnostics is used to provide tracing support for the client library. + internal TelemetrySource ClientDiagnostics { get; } + + /// The HTTP pipeline for sending and receiving REST requests and responses. + public virtual MessagePipeline Pipeline => _pipeline; + + /// Initializes a new instance of Threads for mocking. + protected Threads() + { + } + + /// Initializes a new instance of Threads. + /// The handler for diagnostic messaging in the client. + /// The HTTP pipeline for sending and receiving REST requests and responses. + /// The key credential to copy. + /// OpenAI Endpoint. + internal Threads(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + { + ClientDiagnostics = clientDiagnostics; + _pipeline = pipeline; + _keyCredential = keyCredential; + _endpoint = endpoint; + } + + /// Create a thread. + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual async Task> CreateThreadAsync(CreateThreadRequest thread, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(thread, nameof(thread)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = thread.ToRequestBody(); + Result result = await CreateThreadAsync(content, context).ConfigureAwait(false); + return Result.FromValue(ThreadObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Create a thread. + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual Result CreateThread(CreateThreadRequest thread, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(thread, nameof(thread)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = thread.ToRequestBody(); + Result result = CreateThread(content, context); + return Result.FromValue(ThreadObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Create a thread. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task CreateThreadAsync(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Threads.CreateThread"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateThreadRequest(content, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Create a thread. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result CreateThread(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Threads.CreateThread"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateThreadRequest(content, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Retrieves a thread. + /// The ID of the thread to retrieve. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual async Task> GetThreadAsync(string threadId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await GetThreadAsync(threadId, context).ConfigureAwait(false); + return Result.FromValue(ThreadObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Retrieves a thread. + /// The ID of the thread to retrieve. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual Result GetThread(string threadId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = GetThread(threadId, context); + return Result.FromValue(ThreadObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Retrieves a thread. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the thread to retrieve. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task GetThreadAsync(string threadId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + + using var scope = ClientDiagnostics.CreateSpan("Threads.GetThread"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetThreadRequest(threadId, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Retrieves a thread. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the thread to retrieve. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result GetThread(string threadId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + + using var scope = ClientDiagnostics.CreateSpan("Threads.GetThread"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetThreadRequest(threadId, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Modifies a thread. + /// The ID of the thread to modify. Only the `metadata` can be modified. + /// The to use. + /// The cancellation token to use. + /// or is null. + /// is an empty string, and was expected to be non-empty. + public virtual async Task> ModifyThreadAsync(string threadId, ModifyThreadRequest thread, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNull(thread, nameof(thread)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = thread.ToRequestBody(); + Result result = await ModifyThreadAsync(threadId, content, context).ConfigureAwait(false); + return Result.FromValue(ThreadObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Modifies a thread. + /// The ID of the thread to modify. Only the `metadata` can be modified. + /// The to use. + /// The cancellation token to use. + /// or is null. + /// is an empty string, and was expected to be non-empty. + public virtual Result ModifyThread(string threadId, ModifyThreadRequest thread, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNull(thread, nameof(thread)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = thread.ToRequestBody(); + Result result = ModifyThread(threadId, content, context); + return Result.FromValue(ThreadObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Modifies a thread. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the thread to modify. Only the `metadata` can be modified. + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task ModifyThreadAsync(string threadId, RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Threads.ModifyThread"); + scope.Start(); + try + { + using PipelineMessage message = CreateModifyThreadRequest(threadId, content, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Modifies a thread. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the thread to modify. Only the `metadata` can be modified. + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result ModifyThread(string threadId, RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("Threads.ModifyThread"); + scope.Start(); + try + { + using PipelineMessage message = CreateModifyThreadRequest(threadId, content, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Delete a thread. + /// The ID of the thread to delete. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual async Task> DeleteThreadAsync(string threadId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await DeleteThreadAsync(threadId, context).ConfigureAwait(false); + return Result.FromValue(DeleteThreadResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Delete a thread. + /// The ID of the thread to delete. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual Result DeleteThread(string threadId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = DeleteThread(threadId, context); + return Result.FromValue(DeleteThreadResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Delete a thread. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the thread to delete. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task DeleteThreadAsync(string threadId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + + using var scope = ClientDiagnostics.CreateSpan("Threads.DeleteThread"); + scope.Start(); + try + { + using PipelineMessage message = CreateDeleteThreadRequest(threadId, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Delete a thread. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the thread to delete. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result DeleteThread(string threadId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + + using var scope = ClientDiagnostics.CreateSpan("Threads.DeleteThread"); + scope.Start(); + try + { + using PipelineMessage message = CreateDeleteThreadRequest(threadId, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + internal PipelineMessage CreateCreateThreadRequest(RequestBody content, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/threads", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + request.SetHeaderValue("Content-Type", "application/json"); + request.Content = content; + return message; + } + + internal PipelineMessage CreateGetThreadRequest(string threadId, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("GET"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/threads/", false); + uri.AppendPath(threadId, true); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + internal PipelineMessage CreateModifyThreadRequest(string threadId, RequestBody content, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/threads/", false); + uri.AppendPath(threadId, true); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + request.SetHeaderValue("Content-Type", "application/json"); + request.Content = content; + return message; + } + + internal PipelineMessage CreateDeleteThreadRequest(string threadId, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("DELETE"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/threads/", false); + uri.AppendPath(threadId, true); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + private static RequestOptions DefaultRequestContext = new RequestOptions(); + internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) + { + if (!cancellationToken.CanBeCanceled) + { + return DefaultRequestContext; + } + + return new RequestOptions() { CancellationToken = cancellationToken }; + } + + private static ResponseErrorClassifier _responseErrorClassifier200; + private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); + } +} diff --git a/.dotnet/src/OpenAI.csproj b/.dotnet/src/OpenAI.csproj new file mode 100644 index 000000000..c07146eaf --- /dev/null +++ b/.dotnet/src/OpenAI.csproj @@ -0,0 +1,16 @@ + + + This is the OpenAI client library for developing .NET applications with rich experience. + SDK Code Generation OpenAI + 1.0.0-beta.1 + OpenAI + netstandard2.0 + latest + true + + + + + + + diff --git a/.dotnet/tests/Generated/Tests/AssistantsTests.cs b/.dotnet/tests/Generated/Tests/AssistantsTests.cs new file mode 100644 index 000000000..ea014b7fb --- /dev/null +++ b/.dotnet/tests/Generated/Tests/AssistantsTests.cs @@ -0,0 +1,22 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using NUnit.Framework; +using OpenAI; + +namespace OpenAI.Tests +{ + public partial class AssistantsTests + { + [Test] + public void SmokeTest() + { + KeyCredential credential = new KeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + Assistants client = new OpenAIClient(credential).GetAssistantsClient(); + Assert.IsNotNull(client); + } + } +} diff --git a/.dotnet/tests/Generated/Tests/AudioTests.cs b/.dotnet/tests/Generated/Tests/AudioTests.cs new file mode 100644 index 000000000..8fe314b48 --- /dev/null +++ b/.dotnet/tests/Generated/Tests/AudioTests.cs @@ -0,0 +1,22 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using NUnit.Framework; +using OpenAI; + +namespace OpenAI.Tests +{ + public partial class AudioTests + { + [Test] + public void SmokeTest() + { + KeyCredential credential = new KeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + Audio client = new OpenAIClient(credential).GetAudioClient(); + Assert.IsNotNull(client); + } + } +} diff --git a/.dotnet/tests/Generated/Tests/ChatTests.cs b/.dotnet/tests/Generated/Tests/ChatTests.cs new file mode 100644 index 000000000..eb5b40763 --- /dev/null +++ b/.dotnet/tests/Generated/Tests/ChatTests.cs @@ -0,0 +1,22 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using NUnit.Framework; +using OpenAI; + +namespace OpenAI.Tests +{ + public partial class ChatTests + { + [Test] + public void SmokeTest() + { + KeyCredential credential = new KeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + Chat client = new OpenAIClient(credential).GetChatClient(); + Assert.IsNotNull(client); + } + } +} diff --git a/.dotnet/tests/Generated/Tests/CompletionsTests.cs b/.dotnet/tests/Generated/Tests/CompletionsTests.cs new file mode 100644 index 000000000..3a0695403 --- /dev/null +++ b/.dotnet/tests/Generated/Tests/CompletionsTests.cs @@ -0,0 +1,22 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using NUnit.Framework; +using OpenAI; + +namespace OpenAI.Tests +{ + public partial class CompletionsTests + { + [Test] + public void SmokeTest() + { + KeyCredential credential = new KeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + Completions client = new OpenAIClient(credential).GetCompletionsClient(); + Assert.IsNotNull(client); + } + } +} diff --git a/.dotnet/tests/Generated/Tests/EmbeddingsTests.cs b/.dotnet/tests/Generated/Tests/EmbeddingsTests.cs new file mode 100644 index 000000000..8a6052960 --- /dev/null +++ b/.dotnet/tests/Generated/Tests/EmbeddingsTests.cs @@ -0,0 +1,22 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using NUnit.Framework; +using OpenAI; + +namespace OpenAI.Tests +{ + public partial class EmbeddingsTests + { + [Test] + public void SmokeTest() + { + KeyCredential credential = new KeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + Embeddings client = new OpenAIClient(credential).GetEmbeddingsClient(); + Assert.IsNotNull(client); + } + } +} diff --git a/.dotnet/tests/Generated/Tests/FilesTests.cs b/.dotnet/tests/Generated/Tests/FilesTests.cs new file mode 100644 index 000000000..9372d75f4 --- /dev/null +++ b/.dotnet/tests/Generated/Tests/FilesTests.cs @@ -0,0 +1,22 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using NUnit.Framework; +using OpenAI; + +namespace OpenAI.Tests +{ + public partial class FilesTests + { + [Test] + public void SmokeTest() + { + KeyCredential credential = new KeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + Files client = new OpenAIClient(credential).GetFilesClient(); + Assert.IsNotNull(client); + } + } +} diff --git a/.dotnet/tests/Generated/Tests/FineTuningJobsTests.cs b/.dotnet/tests/Generated/Tests/FineTuningJobsTests.cs new file mode 100644 index 000000000..ea1fc2ad2 --- /dev/null +++ b/.dotnet/tests/Generated/Tests/FineTuningJobsTests.cs @@ -0,0 +1,22 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using NUnit.Framework; +using OpenAI; + +namespace OpenAI.Tests +{ + public partial class FineTuningJobsTests + { + [Test] + public void SmokeTest() + { + KeyCredential credential = new KeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + FineTuningJobs client = new OpenAIClient(credential).GetFineTuningClient().GetFineTuningJobsClient(); + Assert.IsNotNull(client); + } + } +} diff --git a/.dotnet/tests/Generated/Tests/ImagesTests.cs b/.dotnet/tests/Generated/Tests/ImagesTests.cs new file mode 100644 index 000000000..a48795229 --- /dev/null +++ b/.dotnet/tests/Generated/Tests/ImagesTests.cs @@ -0,0 +1,22 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using NUnit.Framework; +using OpenAI; + +namespace OpenAI.Tests +{ + public partial class ImagesTests + { + [Test] + public void SmokeTest() + { + KeyCredential credential = new KeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + Images client = new OpenAIClient(credential).GetImagesClient(); + Assert.IsNotNull(client); + } + } +} diff --git a/.dotnet/tests/Generated/Tests/MessagesTests.cs b/.dotnet/tests/Generated/Tests/MessagesTests.cs new file mode 100644 index 000000000..4b62bbf50 --- /dev/null +++ b/.dotnet/tests/Generated/Tests/MessagesTests.cs @@ -0,0 +1,22 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using NUnit.Framework; +using OpenAI; + +namespace OpenAI.Tests +{ + public partial class MessagesTests + { + [Test] + public void SmokeTest() + { + KeyCredential credential = new KeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + Messages client = new OpenAIClient(credential).GetMessagesClient(); + Assert.IsNotNull(client); + } + } +} diff --git a/.dotnet/tests/Generated/Tests/ModelsOpsTests.cs b/.dotnet/tests/Generated/Tests/ModelsOpsTests.cs new file mode 100644 index 000000000..24c9896c0 --- /dev/null +++ b/.dotnet/tests/Generated/Tests/ModelsOpsTests.cs @@ -0,0 +1,22 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using NUnit.Framework; +using OpenAI; + +namespace OpenAI.Tests +{ + public partial class ModelsOpsTests + { + [Test] + public void SmokeTest() + { + KeyCredential credential = new KeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + ModelsOps client = new OpenAIClient(credential).GetModelsOpsClient(); + Assert.IsNotNull(client); + } + } +} diff --git a/.dotnet/tests/Generated/Tests/ModerationsTests.cs b/.dotnet/tests/Generated/Tests/ModerationsTests.cs new file mode 100644 index 000000000..138b487d3 --- /dev/null +++ b/.dotnet/tests/Generated/Tests/ModerationsTests.cs @@ -0,0 +1,22 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using NUnit.Framework; +using OpenAI; + +namespace OpenAI.Tests +{ + public partial class ModerationsTests + { + [Test] + public void SmokeTest() + { + KeyCredential credential = new KeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + Moderations client = new OpenAIClient(credential).GetModerationsClient(); + Assert.IsNotNull(client); + } + } +} diff --git a/.dotnet/tests/Generated/Tests/RunsTests.cs b/.dotnet/tests/Generated/Tests/RunsTests.cs new file mode 100644 index 000000000..e3b8ee12b --- /dev/null +++ b/.dotnet/tests/Generated/Tests/RunsTests.cs @@ -0,0 +1,22 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using NUnit.Framework; +using OpenAI; + +namespace OpenAI.Tests +{ + public partial class RunsTests + { + [Test] + public void SmokeTest() + { + KeyCredential credential = new KeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + Runs client = new OpenAIClient(credential).GetRunsClient(); + Assert.IsNotNull(client); + } + } +} diff --git a/.dotnet/tests/Generated/Tests/ThreadsTests.cs b/.dotnet/tests/Generated/Tests/ThreadsTests.cs new file mode 100644 index 000000000..9b7ef6f78 --- /dev/null +++ b/.dotnet/tests/Generated/Tests/ThreadsTests.cs @@ -0,0 +1,22 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using NUnit.Framework; +using OpenAI; + +namespace OpenAI.Tests +{ + public partial class ThreadsTests + { + [Test] + public void SmokeTest() + { + KeyCredential credential = new KeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + Threads client = new OpenAIClient(credential).GetThreadsClient(); + Assert.IsNotNull(client); + } + } +} diff --git a/.dotnet/tests/OpenAI.Tests.csproj b/.dotnet/tests/OpenAI.Tests.csproj new file mode 100644 index 000000000..a279ac212 --- /dev/null +++ b/.dotnet/tests/OpenAI.Tests.csproj @@ -0,0 +1,18 @@ + + + net7.0 + + $(NoWarn);CS1591 + + + + + + + + + + + + + diff --git a/.dotnet/tsp-output/@typespec/openapi3/openapi.yaml b/.dotnet/tsp-output/@typespec/openapi3/openapi.yaml new file mode 100644 index 000000000..cc299da11 --- /dev/null +++ b/.dotnet/tsp-output/@typespec/openapi3/openapi.yaml @@ -0,0 +1,6019 @@ +openapi: 3.0.0 +info: + title: OpenAI API + version: 2.0.0 + description: The OpenAI REST API. Please see https://platform.openai.com/docs/api-reference for more details. +tags: + - name: Fine-tuning + - name: Audio + - name: Assistants + - name: Chat + - name: Completions + - name: Embeddings + - name: Files + - name: Images + - name: Models + - name: Moderations +paths: + /assistants: + post: + tags: + - Assistants + operationId: createAssistant + summary: Create an assistant with a model and instructions. + parameters: [] + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/AssistantObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateAssistantRequest' + get: + tags: + - Assistants + operationId: listAssistants + summary: Returns a list of assistants. + parameters: + - name: limit + in: query + required: false + description: |- + A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + default is 20. + schema: + type: integer + format: int32 + default: 20 + - name: order + in: query + required: false + description: |- + Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + for descending order. + schema: + $ref: '#/components/schemas/ListOrder' + default: desc + - name: after + in: query + required: false + description: |- + A cursor for use in pagination. `after` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include after=obj_foo in order to fetch the next page of the list. + schema: + type: string + - name: before + in: query + required: false + description: |- + A cursor for use in pagination. `before` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include before=obj_foo in order to fetch the previous page of the list. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ListAssistantsResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /assistants/{assistant_id}: + get: + tags: + - Assistants + operationId: getAssistant + summary: Retrieves an assistant. + parameters: + - name: assistant_id + in: path + required: true + description: The ID of the assistant to retrieve. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/AssistantObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + post: + tags: + - Assistants + operationId: modifyAssistant + summary: Modifies an assistant. + parameters: + - name: assistant_id + in: path + required: true + description: The ID of the assistant to modify. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/AssistantObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ModifyAssistantRequest' + delete: + tags: + - Assistants + operationId: deleteAssistant + summary: Delete an assistant. + parameters: + - name: assistant_id + in: path + required: true + description: The ID of the assistant to delete. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/DeleteAssistantResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /assistants/{assistant_id}/files: + post: + tags: + - Assistants + operationId: createAssistantFile + summary: |- + Create an assistant file by attaching a [File](/docs/api-reference/files) to a + [assistant](/docs/api-reference/assistants). + parameters: + - name: assistant_id + in: path + required: true + description: The ID of the assistant for which to create a file. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/AssistantFileObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateAssistantFileRequest' + get: + tags: + - Assistants + operationId: listAssistantFiles + summary: Returns a list of assistant files. + parameters: + - name: assistant_id + in: path + required: true + description: The ID of the assistant the file belongs to. + schema: + type: string + - name: limit + in: query + required: false + description: |- + A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + default is 20. + schema: + type: integer + format: int32 + default: 20 + - name: order + in: query + required: false + description: |- + Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + for descending order. + schema: + $ref: '#/components/schemas/ListOrder' + default: desc + - name: after + in: query + required: false + description: |- + A cursor for use in pagination. `after` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include after=obj_foo in order to fetch the next page of the list. + schema: + type: string + - name: before + in: query + required: false + description: |- + A cursor for use in pagination. `before` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include before=obj_foo in order to fetch the previous page of the list. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ListAssistantFilesResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /assistants/{assistant_id}/files/{file_id}: + get: + tags: + - Assistants + operationId: getAssistantFile + summary: Retrieves an assistant file. + parameters: + - name: assistant_id + in: path + required: true + description: The ID of the assistant the file belongs to. + schema: + type: string + - name: file_id + in: path + required: true + description: The ID of the file we're getting. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/AssistantFileObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + delete: + tags: + - Assistants + operationId: deleteAssistantFile + summary: Delete an assistant file. + parameters: + - name: assistant_id + in: path + required: true + description: The ID of the assistant the file belongs to. + schema: + type: string + - name: file_id + in: path + required: true + description: The ID of the file to delete. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/DeleteAssistantFileResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /audio/speech: + post: + tags: + - Audio + operationId: createSpeech + summary: Generates audio from the input text. + parameters: [] + responses: + '200': + description: The request has succeeded. + headers: + Transfer-Encoding: + required: false + description: chunked + schema: + type: string + content: + application/octet-stream: + schema: + type: string + format: binary + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateSpeechRequest' + /audio/transcriptions: + post: + tags: + - Audio + operationId: createTranscription + summary: Transcribes audio into the input language. + parameters: [] + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/CreateTranscriptionResponse' + text/plain: + schema: + type: string + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/CreateTranscriptionRequestMultiPart' + /audio/translations: + post: + tags: + - Audio + operationId: createTranslation + summary: Translates audio into English.. + parameters: [] + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/CreateTranslationResponse' + text/plain: + schema: + type: string + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/CreateTranslationRequestMultiPart' + /chat/completions: + post: + tags: + - Chat + operationId: createChatCompletion + summary: Creates a model response for the given chat conversation. + parameters: [] + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/CreateChatCompletionResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateChatCompletionRequest' + /completions: + post: + tags: + - Completions + operationId: createCompletion + summary: Creates a completion for the provided prompt and parameters. + parameters: [] + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/CreateCompletionResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateCompletionRequest' + /embeddings: + post: + tags: + - Embeddings + operationId: createEmbedding + summary: Creates an embedding vector representing the input text. + parameters: [] + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/CreateEmbeddingResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateEmbeddingRequest' + /files: + post: + tags: + - Files + operationId: createFile + summary: |- + Upload a file that can be used across various endpoints. The size of all the files uploaded by + one organization can be up to 100 GB. + + The size of individual files can be a maximum of 512 MB or 2 million tokens for Assistants. See + the [Assistants Tools guide](/docs/assistants/tools) to learn more about the types of files + supported. The Fine-tuning API only supports `.jsonl` files. + + Please [contact us](https://help.openai.com/) if you need to increase these storage limits. + parameters: [] + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/OpenAIFile' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/CreateFileRequestMultiPart' + get: + tags: + - Files + operationId: listFiles + summary: Returns a list of files that belong to the user's organization. + parameters: + - name: purpose + in: query + required: false + description: Only return files with the given purpose. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ListFilesResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /files/{file_id}: + get: + tags: + - Files + operationId: retrieveFile + summary: Returns information about a specific file. + parameters: + - name: file_id + in: path + required: true + description: The ID of the file to use for this request. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/OpenAIFile' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + delete: + tags: + - Files + operationId: deleteFile + summary: Delete a file + parameters: + - name: file_id + in: path + required: true + description: The ID of the file to use for this request. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/DeleteFileResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /files/{file_id}/content: + get: + tags: + - Files + operationId: downloadFile + summary: Returns the contents of the specified file. + parameters: + - name: file_id + in: path + required: true + description: The ID of the file to use for this request. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + type: string + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /fine-tunes: + post: + tags: + - Fine-tuning + operationId: createFineTune + summary: |- + Creates a job that fine-tunes a specified model from a given dataset. + + Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete. + + [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) + parameters: [] + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/FineTune' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateFineTuneRequest' + deprecated: true + get: + tags: + - Fine-tuning + operationId: listFineTunes + summary: List your organization's fine-tuning jobs + parameters: [] + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ListFineTunesResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + deprecated: true + /fine-tunes/{fine_tune_id}: + get: + tags: + - Fine-tuning + operationId: retrieveFineTune + summary: |- + Gets info about the fine-tune job. + + [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) + parameters: + - name: fine_tune_id + in: path + required: true + description: The ID of the fine-tune job + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/FineTune' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + deprecated: true + /fine-tunes/{fine_tune_id}/cancel: + post: + tags: + - Fine-tuning + operationId: cancelFineTune + summary: Immediately cancel a fine-tune job. + parameters: + - name: fine_tune_id + in: path + required: true + description: The ID of the fine-tune job to cancel + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/FineTune' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + deprecated: true + /fine-tunes/{fine_tune_id}/events: + get: + tags: + - Fine-tuning + operationId: listFineTuneEvents + summary: Get fine-grained status updates for a fine-tune job. + parameters: + - name: fine_tune_id + in: path + required: true + description: The ID of the fine-tune job to get events for. + schema: + type: string + - name: stream + in: query + required: false + description: |- + Whether to stream events for the fine-tune job. If set to true, events will be sent as + data-only + [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) + as they become available. The stream will terminate with a `data: [DONE]` message when the + job is finished (succeeded, cancelled, or failed). + + If set to false, only events generated so far will be returned. + schema: + type: boolean + default: false + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ListFineTuneEventsResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + deprecated: true + /fine_tuning/jobs: + post: + tags: + - Fine-tuning + operationId: createFineTuningJob + description: |- + Creates a job that fine-tunes a specified model from a given dataset. + + Response includes details of the enqueued job including job status and the name of the + fine-tuned models once complete. + + [Learn more about fine-tuning](/docs/guides/fine-tuning) + parameters: [] + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/FineTuningJob' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateFineTuningJobRequest' + get: + tags: + - Fine-tuning + operationId: listPaginatedFineTuningJobs + parameters: + - name: after + in: query + required: false + description: Identifier for the last job from the previous pagination request. + schema: + type: string + - name: limit + in: query + required: false + description: Number of fine-tuning jobs to retrieve. + schema: + type: integer + format: int64 + default: 20 + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ListPaginatedFineTuningJobsResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /fine_tuning/jobs/{fine_tuning_job_id}: + get: + tags: + - Fine-tuning + operationId: retrieveFineTuningJob + summary: |- + Get info about a fine-tuning job. + + [Learn more about fine-tuning](/docs/guides/fine-tuning) + parameters: + - name: fine_tuning_job_id + in: path + required: true + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/FineTuningJob' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /fine_tuning/jobs/{fine_tuning_job_id}/cancel: + post: + tags: + - Fine-tuning + operationId: cancelFineTuningJob + summary: Immediately cancel a fine-tune job. + parameters: + - name: fine_tuning_job_id + in: path + required: true + description: The ID of the fine-tuning job to cancel. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/FineTuningJob' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /fine_tuning/jobs/{fine_tuning_job_id}/events: + get: + tags: + - Fine-tuning + operationId: listFineTuningEvents + summary: Get status updates for a fine-tuning job. + parameters: + - name: fine_tuning_job_id + in: path + required: true + description: The ID of the fine-tuning job to get events for. + schema: + type: string + - name: after + in: query + required: false + description: Identifier for the last event from the previous pagination request. + schema: + type: string + - name: limit + in: query + required: false + description: Number of events to retrieve. + schema: + type: integer + default: 20 + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ListFineTuningJobEventsResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /images/edits: + post: + tags: + - Images + operationId: createImageEdit + summary: Creates an edited or extended image given an original image and a prompt. + parameters: [] + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ImagesResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/CreateImageEditRequestMultiPart' + /images/generations: + post: + tags: + - Images + operationId: createImage + summary: Creates an image given a prompt + parameters: [] + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ImagesResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateImageRequest' + /images/variations: + post: + tags: + - Images + operationId: createImageVariation + summary: Creates an edited or extended image given an original image and a prompt. + parameters: [] + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ImagesResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/CreateImageVariationRequestMultiPart' + /models: + get: + tags: + - Models + operationId: listModels + summary: |- + Lists the currently available models, and provides basic information about each one such as the + owner and availability. + parameters: [] + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ListModelsResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /models/{model}: + get: + tags: + - Models + operationId: retrieveModel + summary: |- + Retrieves a model instance, providing basic information about the model such as the owner and + permissioning. + parameters: + - name: model + in: path + required: true + description: The ID of the model to use for this request. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/Model' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + delete: + tags: + - Models + operationId: deleteModel + summary: Delete a fine-tuned model. You must have the Owner role in your organization to delete a model. + parameters: + - name: model + in: path + required: true + description: The model to delete + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/DeleteModelResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /moderations: + post: + tags: + - Moderations + operationId: createModeration + summary: Classifies if text violates OpenAI's Content Policy + parameters: [] + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/CreateModerationResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateModerationRequest' + /threads: + post: + tags: + - Assistants + operationId: createThread + summary: Create a thread. + parameters: [] + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ThreadObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateThreadRequest' + /threads/runs: + post: + tags: + - Assistants + operationId: createThreadAndRun + summary: Create a thread and run it in one request. + parameters: [] + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/RunObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateThreadAndRunRequest' + /threads/{thread_id}: + get: + tags: + - Assistants + operationId: getThread + summary: Retrieves a thread. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the thread to retrieve. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ThreadObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + post: + tags: + - Assistants + operationId: modifyThread + summary: Modifies a thread. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the thread to modify. Only the `metadata` can be modified. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ThreadObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ModifyThreadRequest' + delete: + tags: + - Assistants + operationId: deleteThread + summary: Delete a thread. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the thread to delete. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/DeleteThreadResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /threads/{thread_id}/messages: + post: + tags: + - Assistants + operationId: createMessage + summary: Create a message. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the [thread](/docs/api-reference/threads) to create a message for. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/MessageObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateMessageRequest' + get: + tags: + - Assistants + operationId: listMessages + summary: Returns a list of messages for a given thread. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the [thread](/docs/api-reference/threads) the messages belong to. + schema: + type: string + - name: limit + in: query + required: false + description: |- + A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + default is 20. + schema: + type: integer + format: int32 + default: 20 + - name: order + in: query + required: false + description: |- + Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + for descending order. + schema: + $ref: '#/components/schemas/ListOrder' + default: desc + - name: after + in: query + required: false + description: |- + A cursor for use in pagination. `after` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include after=obj_foo in order to fetch the next page of the list. + schema: + type: string + - name: before + in: query + required: false + description: |- + A cursor for use in pagination. `before` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include before=obj_foo in order to fetch the previous page of the list. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ListMessagesResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /threads/{thread_id}/messages/{message_id}: + get: + tags: + - Assistants + operationId: getMessage + summary: Retrieve a message. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the [thread](/docs/api-reference/threads) to which this message belongs. + schema: + type: string + - name: message_id + in: path + required: true + description: The ID of the message to retrieve. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/MessageObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + post: + tags: + - Assistants + operationId: modifyMessage + summary: Modifies a message. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the thread to which this message belongs. + schema: + type: string + - name: message_id + in: path + required: true + description: The ID of the message to modify. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/MessageObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ModifyMessageRequest' + /threads/{thread_id}/messages/{message_id}/files: + get: + tags: + - Assistants + operationId: listMessageFiles + summary: Returns a list of message files. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the thread that the message and files belong to. + schema: + type: string + - name: message_id + in: path + required: true + description: The ID of the message that the files belongs to. + schema: + type: string + - name: limit + in: query + required: false + description: |- + A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + default is 20. + schema: + type: integer + format: int32 + default: 20 + - name: order + in: query + required: false + description: |- + Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + for descending order. + schema: + $ref: '#/components/schemas/ListOrder' + default: desc + - name: after + in: query + required: false + description: |- + A cursor for use in pagination. `after` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include after=obj_foo in order to fetch the next page of the list. + schema: + type: string + - name: before + in: query + required: false + description: |- + A cursor for use in pagination. `before` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include before=obj_foo in order to fetch the previous page of the list. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ListMessageFilesResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /threads/{thread_id}/messages/{message_id}/files/{file_id}: + get: + tags: + - Assistants + operationId: getMessageFile + summary: Retrieves a message file. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the thread to which the message and File belong. + schema: + type: string + - name: message_id + in: path + required: true + description: The ID of the message the file belongs to. + schema: + type: string + - name: file_id + in: path + required: true + description: The ID of the file being retrieved. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/MessageFileObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /threads/{thread_id}/runs: + post: + tags: + - Assistants + operationId: createRun + summary: Create a run. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the thread to run. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/RunObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/CreateRunRequest' + get: + tags: + - Assistants + operationId: listRuns + summary: Returns a list of runs belonging to a thread. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the thread the run belongs to. + schema: + type: string + - name: limit + in: query + required: false + description: |- + A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + default is 20. + schema: + type: integer + format: int32 + default: 20 + - name: order + in: query + required: false + description: |- + Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + for descending order. + schema: + $ref: '#/components/schemas/ListOrder' + default: desc + - name: after + in: query + required: false + description: |- + A cursor for use in pagination. `after` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include after=obj_foo in order to fetch the next page of the list. + schema: + type: string + - name: before + in: query + required: false + description: |- + A cursor for use in pagination. `before` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include before=obj_foo in order to fetch the previous page of the list. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ListRunsResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /threads/{thread_id}/runs/{run_id}: + get: + tags: + - Assistants + operationId: getRun + summary: Retrieves a run. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the [thread](/docs/api-reference/threads) that was run. + schema: + type: string + - name: run_id + in: path + required: true + description: The ID of the run to retrieve. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/RunObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + post: + tags: + - Assistants + operationId: modifyRun + summary: Modifies a run. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the [thread](/docs/api-reference/threads) that was run. + schema: + type: string + - name: run_id + in: path + required: true + description: The ID of the run to modify. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/RunObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/ModifyRunRequest' + /threads/{thread_id}/runs/{run_id}/cancel: + post: + tags: + - Assistants + operationId: cancelRun + summary: Cancels a run that is `in_progress`. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the thread to which this run belongs. + schema: + type: string + - name: run_id + in: path + required: true + description: The ID of the run to cancel. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/RunObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /threads/{thread_id}/runs/{run_id}/steps: + get: + tags: + - Assistants + operationId: listRunSteps + summary: Returns a list of run steps belonging to a run. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the thread the run and run steps belong to. + schema: + type: string + - name: run_id + in: path + required: true + description: The ID of the run the run steps belong to. + schema: + type: string + - name: limit + in: query + required: false + description: |- + A limit on the number of objects to be returned. Limit can range between 1 and 100, and the + default is 20. + schema: + type: integer + format: int32 + default: 20 + - name: order + in: query + required: false + description: |- + Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` + for descending order. + schema: + $ref: '#/components/schemas/ListOrder' + default: desc + - name: after + in: query + required: false + description: |- + A cursor for use in pagination. `after` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include after=obj_foo in order to fetch the next page of the list. + schema: + type: string + - name: before + in: query + required: false + description: |- + A cursor for use in pagination. `before` is an object ID that defines your place in the list. + For instance, if you make a list request and receive 100 objects, ending with obj_foo, your + subsequent call can include before=obj_foo in order to fetch the previous page of the list. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/ListRunStepsResponse' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /threads/{thread_id}/runs/{run_id}/steps/{step_id}: + get: + tags: + - Assistants + operationId: getRunStep + summary: Retrieves a run step. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the thread to which the run and run step belongs. + schema: + type: string + - name: run_id + in: path + required: true + description: The ID of the run to which the run step belongs. + schema: + type: string + - name: step_id + in: path + required: true + description: The ID of the run step to retrieve. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/RunStepObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + /threads/{thread_id}/runs/{run_id}/submit_tool_outputs: + post: + tags: + - Assistants + operationId: submitToolOuputsToRun + summary: |- + When a run has the `status: "requires_action"` and `required_action.type` is + `submit_tool_outputs`, this endpoint can be used to submit the outputs from the tool calls once + they're all completed. All outputs must be submitted in a single request. + parameters: + - name: thread_id + in: path + required: true + description: The ID of the [thread](/docs/api-reference/threads) to which this run belongs. + schema: + type: string + - name: run_id + in: path + required: true + description: The ID of the run that requires the tool output submission. + schema: + type: string + responses: + '200': + description: The request has succeeded. + content: + application/json: + schema: + $ref: '#/components/schemas/RunObject' + default: + description: An unexpected error response. + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + requestBody: + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/SubmitToolOutputsRunRequest' +security: + - BearerAuth: [] +components: + schemas: + AssistantFileObject: + type: object + required: + - id + - object + - created_at + - assistant_id + properties: + id: + type: string + description: The identifier, which can be referenced in API endpoints. + object: + type: string + enum: + - assistant.file + description: The object type, which is always `assistant.file`. + created_at: + type: integer + format: unixtime + description: The Unix timestamp (in seconds) for when the assistant file was created. + assistant_id: + type: string + description: The assistant ID that the file is attached to. + description: A list of [Files](/docs/api-reference/files) attached to an `assistant`. + AssistantObject: + type: object + required: + - id + - object + - created_at + - name + - description + - model + - instructions + - tools + - file_ids + - metadata + properties: + id: + type: string + description: The identifier, which can be referenced in API endpoints. + object: + type: string + enum: + - assistant + description: The object type, which is always `assistant`. + created_at: + type: integer + format: unixtime + description: The Unix timestamp (in seconds) for when the assistant was created. + name: + type: string + nullable: true + maxLength: 256 + description: The name of the assistant. The maximum length is 256 characters. + description: + type: string + nullable: true + maxLength: 512 + description: The description of the assistant. The maximum length is 512 characters. + model: + type: string + description: |- + ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + see all of your available models, or see our [Model overview](/docs/models/overview) for + descriptions of them. + instructions: + type: string + nullable: true + maxLength: 32768 + description: The system instructions that the assistant uses. The maximum length is 32768 characters. + tools: + allOf: + - $ref: '#/components/schemas/CreateAssistantRequestToolsItem' + description: |- + A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. + Tools can be of types `code_interpreter`, `retrieval`, or `function`. + default: [] + file_ids: + type: array + items: + type: string + maxItems: 20 + description: |- + A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a + maximum of 20 files attached to the assistant. Files are ordered by their creation date in + ascending order. + default: [] + metadata: + type: object + additionalProperties: + type: string + nullable: true + description: |- + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + x-oaiTypeLabel: map + description: Represents an `assistant` that can call the model and use tools. + AssistantToolsCode: + type: object + required: + - type + properties: + type: + type: string + enum: + - code_interpreter + description: 'The type of tool being defined: `code_interpreter`' + AssistantToolsFunction: + type: object + required: + - type + - function + properties: + type: + type: string + enum: + - function + description: 'The type of tool being defined: `function`' + function: + $ref: '#/components/schemas/FunctionObject' + AssistantToolsRetrieval: + type: object + required: + - type + properties: + type: + type: string + enum: + - retrieval + description: 'The type of tool being defined: `retrieval`' + AudioSegment: + type: object + required: + - id + - seek + - start + - end + - text + - tokens + - temperature + - avg_logprob + - compression_ratio + - no_speech_prob + properties: + id: + type: integer + format: int64 + description: The zero-based index of this segment. + seek: + type: integer + format: int64 + description: |- + The seek position associated with the processing of this audio segment. Seek positions are + expressed as hundredths of seconds. The model may process several segments from a single seek + position, so while the seek position will never represent a later time than the segment's + start, the segment's start may represent a significantly later time than the segment's + associated seek position. + start: + type: number + format: double + description: The time at which this segment started relative to the beginning of the audio. + end: + type: number + format: double + description: The time at which this segment ended relative to the beginning of the audio. + text: + type: string + description: The text that was part of this audio segment. + tokens: + allOf: + - $ref: '#/components/schemas/TokenArrayItem' + description: The token IDs matching the text in this audio segment. + temperature: + type: number + format: double + minimum: 0 + maximum: 1 + description: The temperature score associated with this audio segment. + avg_logprob: + type: number + format: double + description: The average log probability associated with this audio segment. + compression_ratio: + type: number + format: double + description: The compression ratio of this audio segment. + no_speech_prob: + type: number + format: double + description: The probability of no speech detection within this audio segment. + ChatCompletionFunctionCallOption: + type: object + required: + - name + properties: + name: + type: string + description: The name of the function to call. + description: |- + Specifying a particular function via `{"name": "my_function"}` forces the model to call that + function. + ChatCompletionFunctions: + type: object + required: + - name + properties: + description: + type: string + description: |- + A description of what the function does, used by the model to choose when and how to call the + function. + name: + type: string + description: |- + The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and + dashes, with a maximum length of 64. + parameters: + $ref: '#/components/schemas/FunctionParameters' + deprecated: true + ChatCompletionMessageToolCall: + type: object + required: + - id + - type + - function + properties: + id: + type: string + description: The ID of the tool call. + type: + type: string + enum: + - function + description: The type of the tool. Currently, only `function` is supported. + function: + type: object + properties: + name: + type: string + description: The name of the function to call. + arguments: + type: string + description: |- + The arguments to call the function with, as generated by the model in JSON format. Note that + the model does not always generate valid JSON, and may hallucinate parameters not defined by + your function schema. Validate the arguments in your code before calling your function. + required: + - name + - arguments + description: The function that the model called. + ChatCompletionMessageToolCallsItem: + type: array + items: + $ref: '#/components/schemas/ChatCompletionMessageToolCall' + description: The tool calls generated by the model, such as function calls. + ChatCompletionNamedToolChoice: + type: object + required: + - type + - function + properties: + type: + type: string + enum: + - function + description: The type of the tool. Currently, only `function` is supported. + function: + type: object + properties: + name: + type: string + description: The name of the function to call. + required: + - name + description: Specifies a tool the model should use. Use to force the model to call a specific function. + ChatCompletionRequestAssistantMessage: + type: object + required: + - role + properties: + content: + type: string + nullable: true + description: |- + The contents of the assistant message. Required unless `tool_calls` or `function_call` is' + specified. + role: + type: string + enum: + - assistant + description: The role of the messages author, in this case `assistant`. + name: + type: string + description: |- + An optional name for the participant. Provides the model information to differentiate between + participants of the same role. + tool_calls: + $ref: '#/components/schemas/ChatCompletionMessageToolCallsItem' + function_call: + type: object + properties: + arguments: + type: string + description: |- + The arguments to call the function with, as generated by the model in JSON format. Note that + the model does not always generate valid JSON, and may hallucinate parameters not defined by + your function schema. Validate the arguments in your code before calling your function. + name: + type: string + description: The name of the function to call. + required: + - arguments + - name + description: |- + Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be + called, as generated by the model. + deprecated: true + ChatCompletionRequestFunctionMessage: + type: object + required: + - role + - content + - name + properties: + role: + type: string + enum: + - function + description: The role of the messages author, in this case `function`. + content: + type: string + nullable: true + description: The contents of the function message. + name: + type: string + description: The name of the function to call. + ChatCompletionRequestMessage: + oneOf: + - $ref: '#/components/schemas/ChatCompletionRequestSystemMessage' + - $ref: '#/components/schemas/ChatCompletionRequestUserMessage' + - $ref: '#/components/schemas/ChatCompletionRequestAssistantMessage' + - $ref: '#/components/schemas/ChatCompletionRequestToolMessage' + - $ref: '#/components/schemas/ChatCompletionRequestFunctionMessage' + x-oaiExpandable: true + ChatCompletionRequestMessageContentPart: + oneOf: + - $ref: '#/components/schemas/ChatCompletionRequestMessageContentPartText' + - $ref: '#/components/schemas/ChatCompletionRequestMessageContentPartImage' + x-oaiExpandable: true + ChatCompletionRequestMessageContentPartImage: + type: object + required: + - type + - image_url + properties: + type: + type: string + enum: + - image_url + description: The type of the content part. + image_url: + type: object + properties: + url: + anyOf: + - type: string + format: uri + - type: string + description: Either a URL of the image or the base64 encoded image data. + detail: + type: string + enum: + - auto + - low + - high + description: |- + Specifies the detail level of the image. Learn more in the + [Vision guide](/docs/guides/vision/low-or-high-fidelity-image-understanding). + default: auto + required: + - url + ChatCompletionRequestMessageContentPartText: + type: object + required: + - type + - text + properties: + type: + type: string + enum: + - text + - json_object + description: The type of the content part. + text: + type: string + description: The text content. + ChatCompletionRequestMessageContentParts: + type: array + items: + $ref: '#/components/schemas/ChatCompletionRequestMessageContentPart' + minItems: 1 + ChatCompletionRequestSystemMessage: + type: object + required: + - content + - role + properties: + content: + type: string + description: The contents of the system message. + x-oaiExpandable: true + role: + type: string + enum: + - system + description: The role of the messages author, in this case `system`. + name: + type: string + description: |- + An optional name for the participant. Provides the model information to differentiate between + participants of the same role. + ChatCompletionRequestToolMessage: + type: object + required: + - role + - content + - tool_call_id + properties: + role: + type: string + enum: + - tool + description: The role of the messages author, in this case `tool`. + content: + type: string + description: The contents of the tool message. + tool_call_id: + type: string + description: Tool call that this message is responding to. + ChatCompletionRequestUserMessage: + type: object + required: + - content + - role + properties: + content: + allOf: + - $ref: '#/components/schemas/ChatCompletionRequestUserMessageContent' + description: The contents of the system message. + x-oaiExpandable: true + role: + type: string + enum: + - user + - assistant + description: The role of the messages author, in this case `user`. + name: + type: string + description: |- + An optional name for the participant. Provides the model information to differentiate between + participants of the same role. + ChatCompletionRequestUserMessageContent: + oneOf: + - type: string + - $ref: '#/components/schemas/ChatCompletionRequestMessageContentParts' + ChatCompletionResponseMessage: + type: object + required: + - content + - role + properties: + content: + type: string + nullable: true + description: The contents of the message. + tool_calls: + $ref: '#/components/schemas/ChatCompletionMessageToolCallsItem' + role: + type: string + enum: + - assistant + description: The role of the author of this message. + function_call: + type: object + properties: + arguments: + type: string + description: |- + The arguments to call the function with, as generated by the model in JSON format. Note that + the model does not always generate valid JSON, and may hallucinate parameters not defined by + your function schema. Validate the arguments in your code before calling your function. + name: + type: string + description: The name of the function to call. + required: + - arguments + - name + description: Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model. + deprecated: true + ChatCompletionTokenLogprob: + type: object + required: + - token + - logprob + - bytes + - top_logprobs + properties: + token: + type: string + description: The token. + logprob: + type: number + format: double + description: The log probability of this token. + bytes: + type: array + items: + type: integer + format: int64 + nullable: true + description: |- + A list of integers representing the UTF-8 bytes representation of the token. Useful in + instances where characters are represented by multiple tokens and their byte representations + must be combined to generate the correct text representation. Can be `null` if there is no + bytes representation for the token. + top_logprobs: + type: array + items: + type: object + properties: + token: + type: string + description: The token. + logprob: + type: number + format: double + description: The log probability of this token. + bytes: + type: array + items: + type: integer + format: int64 + nullable: true + description: |- + A list of integers representing the UTF-8 bytes representation of the token. Useful in + instances where characters are represented by multiple tokens and their byte representations + must be combined to generate the correct text representation. Can be `null` if there is no + bytes representation for the token. + required: + - token + - logprob + - bytes + description: |- + List of the most likely tokens and their log probability, at this token position. In rare + cases, there may be fewer than the number of requested `top_logprobs` returned. + ChatCompletionTool: + type: object + required: + - type + - function + properties: + type: + type: string + enum: + - function + description: The type of the tool. Currently, only `function` is supported. + function: + $ref: '#/components/schemas/FunctionObject' + ChatCompletionToolChoiceOption: + oneOf: + - type: string + enum: + - none + - auto + - auto + - $ref: '#/components/schemas/ChatCompletionNamedToolChoice' + description: |- + Controls which (if any) function is called by the model. `none` means the model will not call a + function and instead generates a message. `auto` means the model can pick between generating a + message or calling a function. Specifying a particular function via + `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that + function. + + `none` is the default when no functions are present. `auto` is the default if functions are + present. + x-oaiExpandable: true + CompletionUsage: + type: object + required: + - prompt_tokens + - completion_tokens + - total_tokens + properties: + prompt_tokens: + type: integer + format: int64 + description: Number of tokens in the prompt. + completion_tokens: + type: integer + format: int64 + description: Number of tokens in the generated completion + total_tokens: + type: integer + format: int64 + description: Total number of tokens used in the request (prompt + completion). + description: Usage statistics for the completion request. + CreateAssistantFileRequest: + type: object + required: + - file_id + properties: + file_id: + type: string + description: |- + A [File](/docs/api-reference/files) ID (with `purpose="assistants"`) that the assistant should + use. Useful for tools like `retrieval` and `code_interpreter` that can access files. + CreateAssistantRequest: + type: object + required: + - model + properties: + model: + type: string + description: |- + ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + see all of your available models, or see our [Model overview](/docs/models/overview) for + descriptions of them. + name: + type: string + nullable: true + maxLength: 256 + description: The name of the assistant. The maximum length is 256 characters. + description: + type: string + nullable: true + maxLength: 512 + description: The description of the assistant. The maximum length is 512 characters. + instructions: + type: string + nullable: true + maxLength: 32768 + description: The system instructions that the assistant uses. The maximum length is 32768 characters. + tools: + allOf: + - $ref: '#/components/schemas/CreateAssistantRequestToolsItem' + description: |- + A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. + Tools can be of types `code_interpreter`, `retrieval`, or `function`. + default: [] + file_ids: + type: array + items: + type: string + maxItems: 20 + description: |- + A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a + maximum of 20 files attached to the assistant. Files are ordered by their creation date in + ascending order. + default: [] + metadata: + type: object + additionalProperties: + type: string + nullable: true + description: |- + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + x-oaiTypeLabel: map + CreateAssistantRequestTool: + oneOf: + - $ref: '#/components/schemas/AssistantToolsCode' + - $ref: '#/components/schemas/AssistantToolsRetrieval' + - $ref: '#/components/schemas/AssistantToolsFunction' + x-oaiExpandable: true + CreateAssistantRequestToolsItem: + type: array + items: + $ref: '#/components/schemas/CreateAssistantRequestTool' + maxItems: 128 + CreateChatCompletionRequest: + type: object + required: + - messages + - model + properties: + messages: + type: array + items: + $ref: '#/components/schemas/ChatCompletionRequestMessage' + minItems: 1 + description: |- + A list of messages comprising the conversation so far. + [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb). + model: + anyOf: + - type: string + - type: string + enum: + - gpt-4-0125-preview + - gpt-4-turbo-preview + - gpt-4-1106-preview + - gpt-4-vision-preview + - gpt-4 + - gpt-4-0314 + - gpt-4-0613 + - gpt-4-32k + - gpt-4-32k-0314 + - gpt-4-32k-0613 + - gpt-3.5-turbo + - gpt-3.5-turbo-16k + - gpt-3.5-turbo-0301 + - gpt-3.5-turbo-0613 + - gpt-3.5-turbo-1106 + - gpt-3.5-turbo-16k-0613 + description: |- + ID of the model to use. See the [model endpoint compatibility](/docs/models/model-endpoint-compatibility) + table for details on which models work with the Chat API. + x-oaiTypeLabel: string + frequency_penalty: + type: number + format: double + nullable: true + minimum: -2 + maximum: 2 + description: |- + Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing + frequency in the text so far, decreasing the model's likelihood to repeat the same line + verbatim. + + [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) + default: 0 + logit_bias: + type: object + additionalProperties: + type: integer + format: int64 + nullable: true + description: |- + Modify the likelihood of specified tokens appearing in the completion. + + Accepts a JSON object that maps tokens (specified by their token ID in the tokenizer) to an + associated bias value from -100 to 100. Mathematically, the bias is added to the logits + generated by the model prior to sampling. The exact effect will vary per model, but values + between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 + should result in a ban or exclusive selection of the relevant token. + x-oaiTypeLabel: map + default: null + logprobs: + type: boolean + nullable: true + description: |- + Whether to return log probabilities of the output tokens or not. If true, returns the log + probabilities of each output token returned in the `content` of `message`. This option is + currently not available on the `gpt-4-vision-preview` model. + default: false + top_logprobs: + type: integer + format: int64 + nullable: true + minimum: 0 + maximum: 5 + description: |- + An integer between 0 and 5 specifying the number of most likely tokens to return at each token + position, each with an associated log probability. `logprobs` must be set to `true` if this + parameter is used. + max_tokens: + type: integer + format: int64 + nullable: true + minimum: 0 + description: |- + The maximum number of [tokens](/tokenizer) that can be generated in the chat completion. + + The total length of input tokens and generated tokens is limited by the model's context length. + [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) + for counting tokens. + default: 16 + n: + type: integer + format: int64 + nullable: true + minimum: 1 + maximum: 128 + description: |- + How many chat completion choices to generate for each input message. Note that you will be + charged based on the number of generated tokens across all of the choices. Keep `n` as `1` to + minimize costs. + default: 1 + presence_penalty: + type: number + format: double + nullable: true + minimum: -2 + maximum: 2 + description: |- + Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear + in the text so far, increasing the model's likelihood to talk about new topics. + + [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) + default: 0 + response_format: + type: object + properties: + type: + type: string + enum: + - text + - json_object + description: Must be one of `text` or `json_object`. + default: text + description: |- + An object specifying the format that the model must output. Compatible with + [GPT-4 Turbo](/docs/models/gpt-4-and-gpt-4-turbo) and `gpt-3.5-turbo-1106`. + + 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. + seed: + type: integer + format: int64 + nullable: true + minimum: -9223372036854776000 + maximum: 9223372036854776000 + description: |- + This feature is in Beta. + + If specified, our system will make a best effort to sample deterministically, such that + repeated requests with the same `seed` and parameters should return the same result. + + Determinism is not guaranteed, and you should refer to the `system_fingerprint` response + parameter to monitor changes in the backend. + x-oaiMeta: + beta: true + stop: + oneOf: + - $ref: '#/components/schemas/Stop' + nullable: true + description: Up to 4 sequences where the API will stop generating further tokens. + default: null + stream: + type: boolean + nullable: true + description: |- + If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only + [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) + as they become available, with the stream terminated by a `data: [DONE]` message. + [Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions). + default: false + temperature: + type: number + format: double + nullable: true + minimum: 0 + maximum: 2 + description: |- + What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output + more random, while lower values like 0.2 will make it more focused and deterministic. + + We generally recommend altering this or `top_p` but not both. + default: 1 + top_p: + type: number + format: double + nullable: true + minimum: 0 + maximum: 1 + description: |- + An alternative to sampling with temperature, called nucleus sampling, where the model considers + the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising + the top 10% probability mass are considered. + + We generally recommend altering this or `temperature` but not both. + default: 1 + tools: + type: array + items: + $ref: '#/components/schemas/ChatCompletionTool' + description: |- + A list of tools the model may call. Currently, only functions are supported as a tool. Use this + to provide a list of functions the model may generate JSON inputs for. + tool_choice: + $ref: '#/components/schemas/ChatCompletionToolChoiceOption' + user: + allOf: + - $ref: '#/components/schemas/User' + description: |- + A unique identifier representing your end-user, which can help OpenAI to monitor and detect + abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + function_call: + anyOf: + - type: string + enum: + - none + - auto + - auto + - $ref: '#/components/schemas/ChatCompletionFunctionCallOption' + description: |- + Deprecated in favor of `tool_choice`. + + Controls which (if any) function is called by the model. `none` means the model will not call a + function and instead generates a message. `auto` means the model can pick between generating a + message or calling a function. Specifying a particular function via `{"name": "my_function"}` + forces the model to call that function. + + `none` is the default when no functions are present. `auto` is the default if functions are + present. + deprecated: true + x-oaiExpandable: true + functions: + type: array + items: + $ref: '#/components/schemas/ChatCompletionFunctions' + minItems: 1 + maxItems: 128 + description: |- + Deprecated in favor of `tools`. + + A list of functions the model may generate JSON inputs for. + deprecated: true + CreateChatCompletionResponse: + type: object + required: + - id + - choices + - created + - model + - object + properties: + id: + type: string + description: A unique identifier for the chat completion. + choices: + type: array + items: + type: object + properties: + finish_reason: + type: string + enum: + - stop + - length + - tool_calls + - content_filter + - function_call + - length + - content_filter + description: |- + The reason the model stopped generating tokens. This will be `stop` if the model hit a + natural stop point or a provided stop sequence, `length` if the maximum number of tokens + specified in the request was reached, `content_filter` if content was omitted due to a flag + from our content filters, `tool_calls` if the model called a tool, or `function_call` + (deprecated) if the model called a function. + index: + type: integer + format: int64 + description: The index of the choice in the list of choices. + message: + $ref: '#/components/schemas/ChatCompletionResponseMessage' + logprobs: + type: object + properties: + content: + type: array + items: + $ref: '#/components/schemas/ChatCompletionTokenLogprob' + nullable: true + required: + - content + nullable: true + description: Log probability information for the choice. + required: + - finish_reason + - index + - message + - logprobs + description: A list of chat completion choices. Can be more than one if `n` is greater than 1. + created: + type: integer + format: unixtime + description: The Unix timestamp (in seconds) of when the chat completion was created. + model: + type: string + description: The model used for the chat completion. + system_fingerprint: + type: string + description: |- + 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. + object: + type: string + enum: + - chat.completion + description: The object type, which is always `chat.completion`. + usage: + $ref: '#/components/schemas/CompletionUsage' + description: Represents a chat completion response returned by model, based on the provided input. + CreateCompletionRequest: + type: object + required: + - model + - prompt + properties: + model: + anyOf: + - type: string + - type: string + enum: + - gpt-3.5-turbo-instruct + - davinci-002 + - babbage-002 + description: |- + ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + see all of your available models, or see our [Model overview](/docs/models/overview) for + descriptions of them. + x-oaiTypeLabel: string + prompt: + oneOf: + - $ref: '#/components/schemas/Prompt' + nullable: true + description: |- + The prompt(s) to generate completions for, encoded as a string, array of strings, array of + tokens, or array of token arrays. + + Note that <|endoftext|> is the document separator that the model sees during training, so if a + prompt is not specified the model will generate as if from the beginning of a new document. + default: <|endoftext|> + best_of: + type: integer + format: int64 + nullable: true + minimum: 0 + maximum: 20 + description: |- + Generates `best_of` completions server-side and returns the "best" (the one with the highest + log probability per token). Results cannot be streamed. + + When used with `n`, `best_of` controls the number of candidate completions and `n` specifies + how many to return – `best_of` must be greater than `n`. + + **Note:** Because this parameter generates many completions, it can quickly consume your token + quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. + default: 1 + echo: + type: boolean + nullable: true + description: Echo back the prompt in addition to the completion + default: false + frequency_penalty: + type: number + format: double + nullable: true + minimum: -2 + maximum: 2 + description: |- + Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing + frequency in the text so far, decreasing the model's likelihood to repeat the same line + verbatim. + + [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) + default: 0 + logit_bias: + type: object + additionalProperties: + type: integer + format: int64 + nullable: true + description: |- + Modify the likelihood of specified tokens appearing in the completion. + + Accepts a JSON object that maps tokens (specified by their token ID in the GPT tokenizer) to an + associated bias value from -100 to 100. You can use this [tokenizer tool](/tokenizer?view=bpe) + to convert text to token IDs. Mathematically, the bias is added to the logits generated by the + model prior to sampling. The exact effect will vary per model, but values between -1 and 1 + should decrease or increase likelihood of selection; values like -100 or 100 should result in a + ban or exclusive selection of the relevant token. + + As an example, you can pass `{"50256": -100}` to prevent the <|endoftext|> token from being + generated. + x-oaiTypeLabel: map + default: null + logprobs: + type: integer + format: int64 + nullable: true + minimum: 0 + maximum: 5 + description: |- + Include the log probabilities on the `logprobs` most likely tokens, as well the chosen tokens. + For example, if `logprobs` is 5, the API will return a list of the 5 most likely tokens. The + API will always return the `logprob` of the sampled token, so there may be up to `logprobs+1` + elements in the response. + + The maximum value for `logprobs` is 5. + default: null + max_tokens: + type: integer + format: int64 + nullable: true + minimum: 0 + description: |- + The maximum number of [tokens](/tokenizer) to generate in the completion. + + The token count of your prompt plus `max_tokens` cannot exceed the model's context length. + [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) + for counting tokens. + default: 16 + n: + type: integer + format: int64 + nullable: true + minimum: 1 + maximum: 128 + description: |- + How many completions to generate for each prompt. + + **Note:** Because this parameter generates many completions, it can quickly consume your token + quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. + default: 1 + presence_penalty: + type: number + format: double + nullable: true + minimum: -2 + maximum: 2 + description: |- + Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear + in the text so far, increasing the model's likelihood to talk about new topics. + + [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) + default: 0 + seed: + type: integer + format: int64 + nullable: true + minimum: -9223372036854776000 + maximum: 9223372036854776000 + description: |- + If specified, our system will make a best effort to sample deterministically, such that + repeated requests with the same `seed` and parameters should return the same result. + + Determinism is not guaranteed, and you should refer to the `system_fingerprint` response + parameter to monitor changes in the backend. + x-oaiMeta: + beta: true + stop: + oneOf: + - $ref: '#/components/schemas/Stop' + nullable: true + description: Up to 4 sequences where the API will stop generating further tokens. + default: null + stream: + type: boolean + nullable: true + description: |- + If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only + [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) + as they become available, with the stream terminated by a `data: [DONE]` message. + [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_stream_completions.ipynb). + default: false + suffix: + type: string + nullable: true + description: The suffix that comes after a completion of inserted text. + default: null + temperature: + type: number + format: double + nullable: true + minimum: 0 + maximum: 2 + description: |- + What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output + more random, while lower values like 0.2 will make it more focused and deterministic. + + We generally recommend altering this or `top_p` but not both. + default: 1 + top_p: + type: number + format: double + nullable: true + minimum: 0 + maximum: 1 + description: |- + An alternative to sampling with temperature, called nucleus sampling, where the model considers + the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising + the top 10% probability mass are considered. + + We generally recommend altering this or `temperature` but not both. + default: 1 + user: + allOf: + - $ref: '#/components/schemas/User' + description: |- + A unique identifier representing your end-user, which can help OpenAI to monitor and detect + abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + CreateCompletionResponse: + type: object + required: + - id + - choices + - created + - model + - object + properties: + id: + type: string + description: A unique identifier for the completion. + choices: + type: array + items: + type: object + properties: + index: + type: integer + format: int64 + text: + type: string + logprobs: + type: object + properties: + tokens: + type: array + items: + type: string + token_logprobs: + type: array + items: + type: number + format: double + top_logprobs: + type: array + items: + type: object + additionalProperties: + type: integer + format: int64 + text_offset: + type: array + items: + type: integer + format: int64 + required: + - tokens + - token_logprobs + - top_logprobs + - text_offset + nullable: true + finish_reason: + type: string + enum: + - stop + - length + - tool_calls + - content_filter + - function_call + - length + - content_filter + description: |- + The reason the model stopped generating tokens. This will be `stop` if the model hit a + natural stop point or a provided stop sequence, or `content_filter` if content was omitted + due to a flag from our content filters, `length` if the maximum number of tokens specified + in the request was reached, or `content_filter` if content was omitted due to a flag from our + content filters. + required: + - index + - text + - logprobs + - finish_reason + description: The list of completion choices the model generated for the input. + created: + type: integer + format: unixtime + description: The Unix timestamp (in seconds) of when the completion was created. + model: + type: string + description: The model used for the completion. + system_fingerprint: + type: string + description: |- + 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. + object: + type: string + enum: + - text_completion + description: The object type, which is always `text_completion`. + usage: + allOf: + - $ref: '#/components/schemas/CompletionUsage' + description: Usage statistics for the completion request. + description: |- + Represents a completion response from the API. Note: both the streamed and non-streamed response + objects share the same shape (unlike the chat endpoint). + CreateEmbeddingRequest: + type: object + required: + - input + - model + properties: + input: + allOf: + - $ref: '#/components/schemas/CreateEmbeddingRequestInput' + description: |- + Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a + single request, pass an array of strings or array of token arrays. Each input must not exceed + the max input tokens for the model (8191 tokens for `text-embedding-ada-002`) and cannot be an + empty string. + [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) + for counting tokens. + x-oaiExpandable: true + model: + anyOf: + - type: string + - type: string + enum: + - text-embedding-ada-002 + - text-embedding-3-small + - text-embedding-3-large + description: |- + ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + see all of your available models, or see our [Model overview](/docs/models/overview) for + descriptions of them. + x-oaiTypeLabel: string + encoding_format: + type: string + enum: + - float + - base64 + description: |- + The format to return the embeddings in. Can be either `float` or + [`base64`](https://pypi.org/project/pybase64/). + default: float + dimensions: + type: integer + format: int64 + minimum: 1 + description: |- + The number of dimensions the resulting output embeddings should have. Only supported in + `text-embedding-3` and later models. + user: + allOf: + - $ref: '#/components/schemas/User' + description: |- + A unique identifier representing your end-user, which can help OpenAI to monitor and detect + abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + CreateEmbeddingRequestInput: + oneOf: + - type: string + - type: array + items: + type: string + - $ref: '#/components/schemas/TokenArrayItem' + - $ref: '#/components/schemas/TokenArrayArray' + CreateEmbeddingResponse: + type: object + required: + - data + - model + - object + - usage + properties: + data: + type: array + items: + $ref: '#/components/schemas/Embedding' + description: The list of embeddings generated by the model. + model: + type: string + description: The name of the model used to generate the embedding. + object: + type: string + enum: + - list + description: The object type, which is always "list". + usage: + type: object + properties: + prompt_tokens: + type: integer + format: int64 + description: The number of tokens used by the prompt. + total_tokens: + type: integer + format: int64 + description: The total number of tokens used by the request. + required: + - prompt_tokens + - total_tokens + description: The usage information for the request. + CreateFileRequestMultiPart: + type: object + required: + - file + - purpose + properties: + file: + type: string + format: binary + description: The file object (not file name) to be uploaded. + purpose: + type: string + enum: + - fine-tune + - assistants + description: |- + The intended purpose of the uploaded file. Use "fine-tune" for + [Fine-tuning](/docs/api-reference/fine-tuning) and "assistants" for + [Assistants](/docs/api-reference/assistants) and [Messages](/docs/api-reference/messages). This + allows us to validate the format of the uploaded file is correct for fine-tuning. + CreateFineTuneRequest: + type: object + required: + - training_file + properties: + training_file: + type: string + description: |- + The ID of an uploaded file that contains training data. + + See [upload file](/docs/api-reference/files/upload) for how to upload a file. + + Your dataset must be formatted as a JSONL file, where each training example is a JSON object + with the keys "prompt" and "completion". Additionally, you must upload your file with the + purpose `fine-tune`. + + See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more + details. + validation_file: + type: string + nullable: true + description: |- + The ID of an uploaded file that contains validation data. + + If you provide this file, the data is used to generate validation metrics periodically during + fine-tuning. These metrics can be viewed in the + [fine-tuning results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model). + Your train and validation data should be mutually exclusive. + + Your dataset must be formatted as a JSONL file, where each validation example is a JSON object + with the keys "prompt" and "completion". Additionally, you must upload your file with the + purpose `fine-tune`. + + See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more + details. + model: + anyOf: + - type: string + - type: string + enum: + - ada + - babbage + - curie + - davinci + nullable: true + description: |- + The name of the base model to fine-tune. You can select one of "ada", "babbage", "curie", + "davinci", or a fine-tuned model created after 2022-04-21 and before 2023-08-22. To learn more + about these models, see the [Models](/docs/models) documentation. + x-oaiTypeLabel: string + n_epochs: + type: integer + format: int64 + nullable: true + description: |- + The number of epochs to train the model for. An epoch refers to one full cycle through the + training dataset. + default: 4 + batch_size: + type: integer + format: int64 + nullable: true + description: |- + The batch size to use for training. The batch size is the number of training examples used to + train a single forward and backward pass. + + By default, the batch size will be dynamically configured to be ~0.2% of the number of examples + in the training set, capped at 256 - in general, we've found that larger batch sizes tend to + work better for larger datasets. + default: null + learning_rate_multiplier: + type: number + format: double + nullable: true + description: |- + The learning rate multiplier to use for training. The fine-tuning learning rate is the original + learning rate used for pretraining multiplied by this value. + + By default, the learning rate multiplier is the 0.05, 0.1, or 0.2 depending on final + `batch_size` (larger learning rates tend to perform better with larger batch sizes). We + recommend experimenting with values in the range 0.02 to 0.2 to see what produces the best + results. + default: null + prompt_loss_rate: + type: number + format: double + nullable: true + description: |- + The weight to use for loss on the prompt tokens. This controls how much the model tries to + learn to generate the prompt (as compared to the completion which always has a weight of 1.0), + and can add a stabilizing effect to training when completions are short. + + If prompts are extremely long (relative to completions), it may make sense to reduce this + weight so as to avoid over-prioritizing learning the prompt. + default: 0.01 + compute_classification_metrics: + type: boolean + nullable: true + description: |- + If set, we calculate classification-specific metrics such as accuracy and F-1 score using the + validation set at the end of every epoch. These metrics can be viewed in the + [results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model). + + In order to compute classification metrics, you must provide a `validation_file`. Additionally, + you must specify `classification_n_classes` for multiclass classification or + `classification_positive_class` for binary classification. + default: false + classification_n_classes: + type: integer + format: int64 + nullable: true + description: |- + The number of classes in a classification task. + + This parameter is required for multiclass classification. + default: null + classification_positive_class: + type: string + nullable: true + description: |- + The positive class in binary classification. + + This parameter is needed to generate precision, recall, and F1 metrics when doing binary + classification. + default: null + classification_betas: + type: array + items: + type: number + format: double + nullable: true + description: |- + If this is provided, we calculate F-beta scores at the specified beta values. The F-beta score + is a generalization of F-1 score. This is only used for binary classification. + + With a beta of 1 (i.e. the F-1 score), precision and recall are given the same weight. A larger + beta score puts more weight on recall and less on precision. A smaller beta score puts more + weight on precision and less on recall. + default: null + suffix: + oneOf: + - $ref: '#/components/schemas/SuffixString' + nullable: true + description: |- + 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 + `ada:ft-your-org:custom-model-name-2022-02-15-04-21-04`. + default: null + CreateFineTuningJobRequest: + type: object + required: + - training_file + - model + properties: + training_file: + type: string + description: |- + The ID of an uploaded file that contains training data. + + See [upload file](/docs/api-reference/files/upload) for how to upload a file. + + Your dataset must be formatted as a JSONL file. Additionally, you must upload your file with + the purpose `fine-tune`. + + See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. + validation_file: + type: string + nullable: true + description: |- + The ID of an uploaded file that contains validation data. + + If you provide this file, the data is used to generate validation metrics periodically during + fine-tuning. These metrics can be viewed in the fine-tuning results file. The same data should + not be present in both train and validation files. + + Your dataset must be formatted as a JSONL file. You must upload your file with the purpose + `fine-tune`. + + See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. + model: + anyOf: + - type: string + - type: string + enum: + - babbage-002 + - davinci-002 + - gpt-3.5-turbo + description: |- + The name of the model to fine-tune. You can select one of the + [supported models](/docs/guides/fine-tuning/what-models-can-be-fine-tuned). + x-oaiTypeLabel: string + hyperparameters: + type: object + properties: + n_epochs: + anyOf: + - type: string + enum: + - auto + - low + - high + - $ref: '#/components/schemas/NEpochs' + description: |- + The number of epochs to train the model for. An epoch refers to one full cycle through the + training dataset. + default: auto + description: The hyperparameters used for the fine-tuning job. + suffix: + oneOf: + - $ref: '#/components/schemas/SuffixString' + nullable: true + description: |- + 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`. + default: null + CreateImageEditRequestMultiPart: + type: object + required: + - image + - prompt + properties: + image: + type: string + format: binary + description: |- + The image to edit. Must be a valid PNG file, less than 4MB, and square. If mask is not + provided, image must have transparency, which will be used as the mask. + prompt: + type: string + maxLength: 1000 + description: A text description of the desired image(s). The maximum length is 1000 characters. + mask: + type: string + format: binary + description: |- + An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where + `image` should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions + as `image`. + model: + anyOf: + - type: string + - type: string + enum: + - dall-e-2 + description: The model to use for image generation. Only `dall-e-2` is supported at this time. + x-oaiTypeLabel: string + default: dall-e-2 + n: + oneOf: + - $ref: '#/components/schemas/ImagesN' + nullable: true + description: The number of images to generate. Must be between 1 and 10. + default: 1 + size: + type: string + enum: + - 256x256 + - 512x512 + - 1024x1024 + - 512x512 + - 1024x1024 + nullable: true + description: The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`. + default: 1024x1024 + response_format: + type: string + enum: + - url + - b64_json + - b64_json + nullable: true + description: The format in which the generated images are returned. Must be one of `url` or `b64_json`. + default: url + user: + allOf: + - $ref: '#/components/schemas/User' + description: |- + A unique identifier representing your end-user, which can help OpenAI to monitor and detect + abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + CreateImageRequest: + type: object + required: + - prompt + properties: + prompt: + type: string + description: |- + A text description of the desired image(s). The maximum length is 1000 characters for + `dall-e-2` and 4000 characters for `dall-e-3`. + model: + anyOf: + - type: string + - type: string + enum: + - dall-e-2 + - dall-e-3 + description: The model to use for image generation. + x-oaiTypeLabel: string + default: dall-e-2 + n: + oneOf: + - $ref: '#/components/schemas/ImagesN' + nullable: true + description: |- + The number of images to generate. Must be between 1 and 10. For `dall-e-3`, only `n=1` is + supported. + default: 1 + quality: + type: string + enum: + - standard + - hd + nullable: true + description: |- + The quality of the image that will be generated. `hd` creates images with finer details and + greater consistency across the image. This param is only supported for `dall-e-3`. + default: standard + response_format: + type: string + enum: + - url + - b64_json + nullable: true + description: The format in which the generated images are returned. Must be one of `url` or `b64_json`. + default: url + size: + type: string + enum: + - 256x256 + - 512x512 + - 1024x1024 + - 1792x1024 + - 1024x1792 + nullable: true + description: |- + 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. + default: 1024x1024 + style: + type: string + enum: + - vivid + - natural + nullable: true + description: |- + The style of the generated images. Must be one of `vivid` or `natural`. Vivid causes the model + to lean towards generating hyper-real and dramatic images. Natural causes the model to produce + more natural, less hyper-real looking images. This param is only supported for `dall-e-3`. + default: vivid + user: + allOf: + - $ref: '#/components/schemas/User' + description: |- + A unique identifier representing your end-user, which can help OpenAI to monitor and detect + abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + CreateImageVariationRequestMultiPart: + type: object + required: + - image + properties: + image: + type: string + format: binary + description: |- + The image to use as the basis for the variation(s). Must be a valid PNG file, less than 4MB, + and square. + model: + anyOf: + - type: string + - type: string + enum: + - dall-e-2 + description: The model to use for image generation. Only `dall-e-2` is supported at this time. + x-oaiTypeLabel: string + default: dall-e-2 + n: + oneOf: + - $ref: '#/components/schemas/ImagesN' + nullable: true + description: The number of images to generate. Must be between 1 and 10. + default: 1 + response_format: + type: string + enum: + - url + - b64_json + - b64_json + nullable: true + description: The format in which the generated images are returned. Must be one of `url` or `b64_json`. + default: url + size: + type: string + enum: + - 256x256 + - 512x512 + - 1024x1024 + - 512x512 + - 1024x1024 + nullable: true + description: The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`. + default: 1024x1024 + user: + allOf: + - $ref: '#/components/schemas/User' + description: |- + A unique identifier representing your end-user, which can help OpenAI to monitor and detect + abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + CreateMessageRequest: + type: object + required: + - role + - content + properties: + role: + type: string + enum: + - user + - assistant + description: The role of the entity that is creating the message. Currently only `user` is supported. + content: + type: string + minLength: 1 + maxLength: 32768 + description: The content of the message. + file_ids: + type: array + items: + type: string + minItems: 1 + maxItems: 10 + description: |- + A list of [File](/docs/api-reference/files) IDs that the message should use. There can be a + maximum of 10 files attached to a message. Useful for tools like `retrieval` and + `code_interpreter` that can access and use files. + default: [] + metadata: + type: object + additionalProperties: + type: string + nullable: true + description: |- + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + x-oaiTypeLabel: map + CreateModerationRequest: + type: object + required: + - input + properties: + input: + allOf: + - $ref: '#/components/schemas/CreateModerationRequestInput' + description: The input text to classify + model: + anyOf: + - type: string + - type: string + enum: + - text-moderation-latest + - text-moderation-stable + description: |- + Two content moderations models are available: `text-moderation-stable` and + `text-moderation-latest`. The default is `text-moderation-latest` which will be automatically + upgraded over time. This ensures you are always using our most accurate model. If you use + `text-moderation-stable`, we will provide advanced notice before updating the model. Accuracy + of `text-moderation-stable` may be slightly lower than for `text-moderation-latest`. + x-oaiTypeLabel: string + default: text-moderation-latest + CreateModerationRequestInput: + oneOf: + - type: string + - type: array + items: + type: string + CreateModerationResponse: + type: object + required: + - id + - model + - results + properties: + id: + type: string + description: The unique identifier for the moderation request. + model: + type: string + description: The model used to generate the moderation results. + results: + type: array + items: + type: object + properties: + flagged: + type: boolean + description: Whether the content violates [OpenAI's usage policies](/policies/usage-policies). + categories: + type: object + properties: + hate: + type: boolean + description: |- + Content that expresses, incites, or promotes hate based on race, gender, ethnicity, + religion, nationality, sexual orientation, disability status, or caste. Hateful content + aimed at non-protected groups (e.g., chess players) is harrassment. + hate/threatening: + type: boolean + description: |- + Hateful content that also includes violence or serious harm towards the targeted group + based on race, gender, ethnicity, religion, nationality, sexual orientation, disability + status, or caste. + harassment: + type: boolean + description: Content that expresses, incites, or promotes harassing language towards any target. + harassment/threatening: + type: boolean + description: Harassment content that also includes violence or serious harm towards any target. + self-harm: + type: boolean + description: |- + Content that promotes, encourages, or depicts acts of self-harm, such as suicide, cutting, + and eating disorders. + self-harm/intent: + type: boolean + description: |- + Content where the speaker expresses that they are engaging or intend to engage in acts of + self-harm, such as suicide, cutting, and eating disorders. + self-harm/instructions: + type: boolean + description: |- + Content that encourages performing acts of self-harm, such as suicide, cutting, and eating + disorders, or that gives instructions or advice on how to commit such acts. + sexual: + type: boolean + description: |- + Content meant to arouse sexual excitement, such as the description of sexual activity, or + that promotes sexual services (excluding sex education and wellness). + sexual/minors: + type: boolean + description: Sexual content that includes an individual who is under 18 years old. + violence: + type: boolean + description: Content that depicts death, violence, or physical injury. + violence/graphic: + type: boolean + description: Content that depicts death, violence, or physical injury in graphic detail. + required: + - hate + - hate/threatening + - harassment + - harassment/threatening + - self-harm + - self-harm/intent + - self-harm/instructions + - sexual + - sexual/minors + - violence + - violence/graphic + description: A list of the categories, and whether they are flagged or not. + category_scores: + type: object + properties: + hate: + type: number + format: double + description: The score for the category 'hate'. + hate/threatening: + type: number + format: double + description: The score for the category 'hate/threatening'. + harassment: + type: number + format: double + description: The score for the category 'harassment'. + harassment/threatening: + type: number + format: double + description: The score for the category 'harassment/threatening'. + self-harm: + type: number + format: double + description: The score for the category 'self-harm'. + self-harm/intent: + type: number + format: double + description: The score for the category 'self-harm/intent'. + self-harm/instructions: + type: number + format: double + description: The score for the category 'self-harm/instructive'. + sexual: + type: number + format: double + description: The score for the category 'sexual'. + sexual/minors: + type: number + format: double + description: The score for the category 'sexual/minors'. + violence: + type: number + format: double + description: The score for the category 'violence'. + violence/graphic: + type: number + format: double + description: The score for the category 'violence/graphic'. + required: + - hate + - hate/threatening + - harassment + - harassment/threatening + - self-harm + - self-harm/intent + - self-harm/instructions + - sexual + - sexual/minors + - violence + - violence/graphic + description: A list of the categories along with their scores as predicted by model. + required: + - flagged + - categories + - category_scores + description: A list of moderation objects. + description: Represents policy compliance report by OpenAI's content moderation model against a given input. + CreateRunRequest: + type: object + required: + - assistant_id + properties: + assistant_id: + type: string + description: The ID of the [assistant](/docs/api-reference/assistants) to use to execute this run. + model: + type: string + nullable: true + description: |- + The ID of the [Model](/docs/api-reference/models) to be used to execute this run. If a value + is provided here, it will override the model associated with the assistant. If not, the model + associated with the assistant will be used. + instructions: + type: string + nullable: true + description: |- + Overrides the [instructions](/docs/api-reference/assistants/createAssistant) of the assistant. + This is useful for modifying the behavior on a per-run basis. + additional_instructions: + type: string + nullable: true + description: |- + Appends additional instructions at the end of the instructions for the run. This is useful for + modifying the behavior on a per-run basis without overriding other instructions. + tools: + type: object + allOf: + - $ref: '#/components/schemas/CreateRunRequestToolsItem' + nullable: true + description: |- + Override the tools the assistant can use for this run. This is useful for modifying the + behavior on a per-run basis. + metadata: + type: object + additionalProperties: + type: string + nullable: true + description: |- + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + x-oaiTypeLabel: map + CreateRunRequestTool: + oneOf: + - $ref: '#/components/schemas/AssistantToolsCode' + - $ref: '#/components/schemas/AssistantToolsRetrieval' + - $ref: '#/components/schemas/AssistantToolsFunction' + x-oaiExpandable: true + CreateRunRequestToolsItem: + type: array + items: + $ref: '#/components/schemas/CreateRunRequestTool' + maxItems: 20 + CreateSpeechRequest: + type: object + required: + - model + - input + - voice + properties: + model: + anyOf: + - type: string + - type: string + enum: + - tts-1 + - tts-1-hd + description: 'One of the available [TTS models](/docs/models/tts): `tts-1` or `tts-1-hd`' + x-oaiTypeLabel: string + input: + type: string + maxLength: 4096 + description: The text to generate audio for. The maximum length is 4096 characters. + voice: + type: string + enum: + - alloy + - echo + - fable + - onyx + - nova + - shimmer + description: |- + The voice to use when generating the audio. Supported voices are `alloy`, `echo`, `fable`, + `onyx`, `nova`, and `shimmer`. Previews of the voices are available in the + [Text to speech guide](/docs/guides/text-to-speech/voice-options). + response_format: + type: string + enum: + - mp3 + - opus + - aac + - flac + description: The format to audio in. Supported formats are `mp3`, `opus`, `aac`, and `flac`. + default: mp3 + speed: + type: number + format: double + minimum: 0.25 + maximum: 4 + description: The speed of the generated audio. Select a value from `0.25` to `4.0`. `1.0` is the default. + default: 1 + CreateThreadAndRunRequest: + type: object + required: + - assistant_id + properties: + assistant_id: + type: string + description: The ID of the [assistant](/docs/api-reference/assistants) to use to execute this run. + thread: + allOf: + - $ref: '#/components/schemas/CreateThreadRequest' + description: If no thread is provided, an empty thread will be created. + model: + type: string + nullable: true + description: |- + The ID of the [Model](/docs/api-reference/models) to be used to execute this run. If a value is + provided here, it will override the model associated with the assistant. If not, the model + associated with the assistant will be used. + instructions: + type: string + nullable: true + description: |- + Override the default system message of the assistant. This is useful for modifying the behavior + on a per-run basis. + tools: + type: object + allOf: + - $ref: '#/components/schemas/CreateRunRequestToolsItem' + nullable: true + description: |- + Override the tools the assistant can use for this run. This is useful for modifying the + behavior on a per-run basis. + metadata: + type: object + additionalProperties: + type: string + nullable: true + description: |- + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + x-oaiTypeLabel: map + CreateThreadRequest: + type: object + properties: + messages: + type: array + items: + $ref: '#/components/schemas/CreateMessageRequest' + description: A list of [messages](/docs/api-reference/messages) to start the thread with. + metadata: + type: object + additionalProperties: + type: string + nullable: true + description: |- + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + CreateTranscriptionRequestMultiPart: + type: object + required: + - file + - model + properties: + file: + type: string + format: binary + description: |- + The audio file object (not file name) to transcribe, in one of these formats: flac, mp3, mp4, + mpeg, mpga, m4a, ogg, wav, or webm. + x-oaiTypeLabel: file + model: + anyOf: + - type: string + - type: string + enum: + - whisper-1 + description: ID of the model to use. Only `whisper-1` is currently available. + x-oaiTypeLabel: string + language: + type: string + description: |- + The language of the input audio. Supplying the input language in + [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) format will improve accuracy + and latency. + prompt: + type: string + description: |- + An optional text to guide the model's style or continue a previous audio segment. The + [prompt](/docs/guides/speech-to-text/prompting) should match the audio language. + response_format: + type: string + enum: + - json + - text + - srt + - verbose_json + - vtt + - text + - srt + - verbose_json + - vtt + description: |- + The format of the transcript output, in one of these options: json, text, srt, verbose_json, or + vtt. + default: json + temperature: + type: number + format: double + minimum: 0 + maximum: 1 + description: |- + The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more + random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, + the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to + automatically increase the temperature until certain thresholds are hit. + default: 0 + CreateTranscriptionResponse: + type: object + required: + - text + properties: + text: + type: string + description: The transcribed text for the provided audio data. + task: + type: string + enum: + - transcribe + description: The label that describes which operation type generated the accompanying response data. + language: + type: string + description: The spoken language that was detected in the audio data. + duration: + type: number + format: double + description: The total duration of the audio processed to produce accompanying transcription information. + segments: + type: array + items: + $ref: '#/components/schemas/AudioSegment' + description: |- + A collection of information about the timing, probabilities, and other detail of each processed + audio segment. + CreateTranslationRequestMultiPart: + type: object + required: + - file + - model + properties: + file: + type: string + format: binary + description: |- + The audio file object (not file name) to translate, in one of these formats: flac, mp3, mp4, + mpeg, mpga, m4a, ogg, wav, or webm. + x-oaiTypeLabel: file + model: + anyOf: + - type: string + - type: string + enum: + - whisper-1 + description: ID of the model to use. Only `whisper-1` is currently available. + x-oaiTypeLabel: string + prompt: + type: string + description: |- + An optional text to guide the model's style or continue a previous audio segment. The + [prompt](/docs/guides/speech-to-text/prompting) should match the audio language. + response_format: + type: string + enum: + - json + - text + - srt + - verbose_json + - vtt + - text + - srt + - verbose_json + - vtt + description: |- + The format of the transcript output, in one of these options: json, text, srt, verbose_json, or + vtt. + default: json + temperature: + type: number + format: double + minimum: 0 + maximum: 1 + description: |- + The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more + random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, + the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to + automatically increase the temperature until certain thresholds are hit. + default: 0 + CreateTranslationResponse: + type: object + required: + - text + properties: + text: + type: string + description: The translated text for the provided audio data. + task: + type: string + enum: + - translate + description: The label that describes which operation type generated the accompanying response data. + language: + type: string + description: The spoken language that was detected in the audio data. + duration: + type: number + format: double + description: The total duration of the audio processed to produce accompanying translation information. + segments: + type: array + items: + $ref: '#/components/schemas/AudioSegment' + description: |- + A collection of information about the timing, probabilities, and other detail of each processed + audio segment. + DeleteAssistantFileResponse: + type: object + required: + - id + - deleted + - object + properties: + id: + type: string + deleted: + type: boolean + object: + type: string + enum: + - assistant.file.deleted + description: |- + Deletes the association between the assistant and the file, but does not delete the + [File](/docs/api-reference/files) object itself. + DeleteAssistantResponse: + type: object + required: + - id + - deleted + - object + properties: + id: + type: string + deleted: + type: boolean + object: + type: string + enum: + - assistant.deleted + DeleteFileResponse: + type: object + required: + - id + - object + - deleted + properties: + id: + type: string + object: + type: string + enum: + - file + deleted: + type: boolean + DeleteModelResponse: + type: object + required: + - id + - deleted + - object + properties: + id: + type: string + deleted: + type: boolean + object: + type: string + enum: + - model + DeleteThreadResponse: + type: object + required: + - id + - deleted + - object + properties: + id: + type: string + deleted: + type: boolean + object: + type: string + enum: + - thread.deleted + Embedding: + type: object + required: + - index + - embedding + - object + properties: + index: + type: integer + format: int64 + description: The index of the embedding in the list of embeddings. + embedding: + anyOf: + - type: array + items: + type: number + format: double + - type: string + description: |- + The embedding vector, which is a list of floats. The length of vector depends on the model as + listed in the [embedding guide](/docs/guides/embeddings). + object: + type: string + enum: + - embedding + description: The object type, which is always "embedding". + description: Represents an embedding vector returned by embedding endpoint. + Error: + type: object + required: + - type + - message + - param + - code + properties: + type: + type: string + message: + type: string + param: + type: string + nullable: true + code: + type: string + nullable: true + ErrorResponse: + type: object + required: + - error + properties: + error: + $ref: '#/components/schemas/Error' + FineTune: + type: object + required: + - id + - object + - created_at + - updated_at + - model + - fine_tuned_model + - organization_id + - status + - hyperparams + - training_files + - validation_files + - result_files + properties: + id: + type: string + description: The object identifier, which can be referenced in the API endpoints. + object: + type: string + enum: + - fine-tune + - fine-tune-results + - assistants + - assistants_output + description: The object type, which is always "fine-tune". + created_at: + type: integer + format: unixtime + description: The Unix timestamp (in seconds) for when the fine-tuning job was created. + updated_at: + type: integer + format: unixtime + description: The Unix timestamp (in seconds) for when the fine-tuning job was last updated. + model: + type: string + description: The base model that is being fine-tuned. + fine_tuned_model: + type: string + nullable: true + description: The name of the fine-tuned model that is being created. + organization_id: + type: string + description: The organization that owns the fine-tuning job. + status: + type: string + enum: + - created + - pending + - running + - succeeded + - failed + - cancelled + - running + - succeeded + - failed + - cancelled + description: |- + The current status of the fine-tuning job, which can be either `created`, `running`, + `succeeded`, `failed`, or `cancelled`. + hyperparams: + type: object + properties: + n_epochs: + type: integer + format: int64 + description: |- + The number of epochs to train the model for. An epoch refers to one full cycle through the + training dataset. + batch_size: + type: integer + format: int64 + description: |- + The batch size to use for training. The batch size is the number of training examples used to + train a single forward and backward pass. + prompt_loss_weight: + type: number + format: double + description: The weight to use for loss on the prompt tokens. + learning_rate_multiplier: + type: number + format: double + description: The learning rate multiplier to use for training. + compute_classification_metrics: + type: boolean + description: The classification metrics to compute using the validation dataset at the end of every epoch. + classification_positive_class: + type: string + description: The positive class to use for computing classification metrics. + classification_n_classes: + type: integer + format: int64 + description: The number of classes to use for computing classification metrics. + required: + - n_epochs + - batch_size + - prompt_loss_weight + - learning_rate_multiplier + description: |- + The hyperparameters used for the fine-tuning job. See the + [fine-tuning guide](/docs/guides/legacy-fine-tuning/hyperparameters) for more details. + training_files: + type: array + items: + $ref: '#/components/schemas/OpenAIFile' + description: The list of files used for training. + validation_files: + type: array + items: + $ref: '#/components/schemas/OpenAIFile' + description: The list of files used for validation. + result_files: + type: array + items: + $ref: '#/components/schemas/OpenAIFile' + description: The compiled results files for the fine-tuning job. + events: + type: array + items: + $ref: '#/components/schemas/FineTuneEvent' + description: The list of events that have been observed in the lifecycle of the FineTune job. + description: The `FineTune` object represents a legacy fine-tune job that has been created through the API. + deprecated: true + FineTuneEvent: + type: object + required: + - object + - created_at + - level + - message + properties: + object: + type: string + created_at: + type: integer + format: unixtime + level: + type: string + message: + type: string + FineTuningEvent: + type: object + required: + - object + - created_at + - level + - message + properties: + object: + type: string + created_at: + type: integer + format: unixtime + level: + type: string + message: + type: string + data: + type: object + additionalProperties: {} + nullable: true + type: + type: string + enum: + - message + - metrics + FineTuningJob: + type: object + required: + - id + - object + - created_at + - finished_at + - model + - fine_tuned_model + - organization_id + - status + - hyperparameters + - training_file + - validation_file + - result_files + - trained_tokens + - error + properties: + id: + type: string + description: The object identifier, which can be referenced in the API endpoints. + object: + type: string + enum: + - fine_tuning.job + description: The object type, which is always "fine_tuning.job". + created_at: + type: integer + format: unixtime + description: The Unix timestamp (in seconds) for when the fine-tuning job was created. + finished_at: + type: string + format: date-time + nullable: true + description: |- + The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be + null if the fine-tuning job is still running. + model: + type: string + description: The base model that is being fine-tuned. + fine_tuned_model: + type: string + nullable: true + description: |- + The name of the fine-tuned model that is being created. The value will be null if the + fine-tuning job is still running. + organization_id: + type: string + description: The organization that owns the fine-tuning job. + status: + type: string + enum: + - created + - pending + - running + - succeeded + - failed + - cancelled + - running + - succeeded + - failed + - cancelled + description: |- + The current status of the fine-tuning job, which can be either `created`, `pending`, `running`, + `succeeded`, `failed`, or `cancelled`. + hyperparameters: + type: object + properties: + n_epochs: + anyOf: + - type: string + enum: + - auto + - low + - high + - $ref: '#/components/schemas/NEpochs' + description: |- + The number of epochs to train the model for. An epoch refers to one full cycle through the + training dataset. + + "Auto" decides the optimal number of epochs based on the size of the dataset. If setting the + number manually, we support any number between 1 and 50 epochs. + default: auto + description: |- + The hyperparameters used for the fine-tuning job. See the + [fine-tuning guide](/docs/guides/fine-tuning) for more details. + training_file: + type: string + description: |- + The file ID used for training. You can retrieve the training data with the + [Files API](/docs/api-reference/files/retrieve-contents). + validation_file: + type: string + nullable: true + description: |- + The file ID used for validation. You can retrieve the validation results with the + [Files API](/docs/api-reference/files/retrieve-contents). + result_files: + type: array + items: + type: string + description: |- + The compiled results file ID(s) for the fine-tuning job. You can retrieve the results with the + [Files API](/docs/api-reference/files/retrieve-contents). + trained_tokens: + type: integer + format: int64 + nullable: true + description: |- + The total number of billable tokens processed by this fine tuning job. The value will be null + if the fine-tuning job is still running. + error: + type: object + properties: + message: + type: string + description: A human-readable error message. + code: + type: string + description: A machine-readable error code. + param: + type: string + nullable: true + description: |- + The parameter that was invalid, usually `training_file` or `validation_file`. This field + will be null if the failure was not parameter-specific. + nullable: true + description: |- + For fine-tuning jobs that have `failed`, this will contain more information on the cause of the + failure. + FineTuningJobEvent: + type: object + required: + - id + - object + - created_at + - level + - message + properties: + id: + type: string + object: + type: string + created_at: + type: integer + format: unixtime + level: + type: string + enum: + - info + - warn + - error + message: + type: string + FunctionObject: + type: object + required: + - name + properties: + description: + type: string + description: |- + A description of what the function does, used by the model to choose when and how to call the + function. + name: + type: string + description: |- + The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and + dashes, with a maximum length of 64. + parameters: + $ref: '#/components/schemas/FunctionParameters' + FunctionParameters: + type: object + additionalProperties: {} + description: |- + The parameters the functions accepts, described as a JSON Schema object. See the + [guide](/docs/guides/gpt/function-calling) for examples, and the + [JSON Schema reference](https://json-schema.org/understanding-json-schema/) for documentation + about the format.\n\nTo describe a function that accepts no parameters, provide the value + `{\"type\": \"object\", \"properties\": {}}`. + Image: + type: object + properties: + b64_json: + type: string + format: base64 + description: The base64-encoded JSON of the generated image, if `response_format` is `b64_json`. + url: + type: string + format: uri + description: The URL of the generated image, if `response_format` is `url` (default). + revised_prompt: + type: string + description: The prompt that was used to generate the image, if there was any revision to the prompt. + description: Represents the url or the content of an image generated by the OpenAI API. + ImagesN: + type: integer + format: int64 + minimum: 1 + maximum: 10 + ImagesResponse: + type: object + required: + - created + - data + properties: + created: + type: integer + format: unixtime + data: + type: array + items: + $ref: '#/components/schemas/Image' + ListAssistantFilesResponse: + type: object + required: + - object + - data + - first_id + - last_id + - has_more + properties: + object: + type: string + enum: + - list + data: + type: array + items: + $ref: '#/components/schemas/AssistantFileObject' + first_id: + type: string + last_id: + type: string + has_more: + type: boolean + ListAssistantsResponse: + type: object + required: + - object + - data + - first_id + - last_id + - has_more + properties: + object: + type: string + enum: + - list + data: + type: array + items: + $ref: '#/components/schemas/AssistantObject' + first_id: + type: string + last_id: + type: string + has_more: + type: boolean + ListFilesResponse: + type: object + required: + - data + - object + properties: + data: + type: array + items: + $ref: '#/components/schemas/OpenAIFile' + object: + type: string + enum: + - list + ListFineTuneEventsResponse: + type: object + required: + - object + - data + properties: + object: + type: string + data: + type: array + items: + $ref: '#/components/schemas/FineTuneEvent' + ListFineTunesResponse: + type: object + required: + - object + - data + properties: + object: + type: string + data: + type: array + items: + $ref: '#/components/schemas/FineTune' + ListFineTuningJobEventsResponse: + type: object + required: + - object + - data + properties: + object: + type: string + data: + type: array + items: + $ref: '#/components/schemas/FineTuningJobEvent' + ListMessageFilesResponse: + type: object + required: + - object + - data + - first_id + - last_id + - has_more + properties: + object: + type: string + enum: + - list + data: + type: array + items: + $ref: '#/components/schemas/MessageFileObject' + first_id: + type: string + last_id: + type: string + has_more: + type: boolean + ListMessagesResponse: + type: object + required: + - object + - data + - first_id + - last_id + - has_more + properties: + object: + type: string + enum: + - list + data: + type: array + items: + $ref: '#/components/schemas/MessageObject' + first_id: + type: string + last_id: + type: string + has_more: + type: boolean + ListModelsResponse: + type: object + required: + - object + - data + properties: + object: + type: string + enum: + - list + data: + type: array + items: + $ref: '#/components/schemas/Model' + ListOrder: + type: string + enum: + - asc + - desc + ListPaginatedFineTuningJobsResponse: + type: object + required: + - object + - data + - has_more + properties: + object: + type: string + data: + type: array + items: + $ref: '#/components/schemas/FineTuningJob' + has_more: + type: boolean + ListRunStepsResponse: + type: object + required: + - object + - data + - first_id + - last_id + - has_more + properties: + object: + type: string + enum: + - list + data: + type: array + items: + $ref: '#/components/schemas/RunStepObject' + first_id: + type: string + last_id: + type: string + has_more: + type: boolean + ListRunsResponse: + type: object + required: + - object + - data + - first_id + - last_id + - has_more + properties: + object: + type: string + enum: + - list + data: + type: array + items: + $ref: '#/components/schemas/RunObject' + first_id: + type: string + last_id: + type: string + has_more: + type: boolean + MessageContentImageFileObject: + type: object + required: + - type + - image_file + properties: + type: + type: string + enum: + - image_file + description: Always `image_file`. + image_file: + type: object + properties: + file_id: + type: string + description: The [File](/docs/api-reference/files) ID of the image in the message content. + required: + - file_id + description: References an image [File](/docs/api-reference/files) in the content of a message. + MessageContentTextAnnotationsFileCitationObject: + type: object + required: + - type + - text + - file_citation + - start_index + - end_index + properties: + type: + type: string + enum: + - file_citation + description: Always `file_citation`. + text: + type: string + description: The text in the message content that needs to be replaced. + file_citation: + type: object + properties: + file_id: + type: string + description: The ID of the specific File the citation is from. + quote: + type: string + description: The specific quote in the file. + required: + - file_id + - quote + start_index: + type: integer + format: int64 + minimum: 0 + end_index: + type: integer + format: int64 + minimum: 0 + description: |- + A citation within the message that points to a specific quote from a specific File associated + with the assistant or the message. Generated when the assistant uses the "retrieval" tool to + search files. + MessageContentTextAnnotationsFilePathObject: + type: object + required: + - type + - text + - file_path + - start_index + - end_index + properties: + type: + type: string + enum: + - file_path + description: Always `file_path`. + text: + type: string + description: The text in the message content that needs to be replaced. + file_path: + type: object + properties: + file_id: + type: string + description: The ID of the file that was generated. + required: + - file_id + start_index: + type: integer + format: int64 + minimum: 0 + end_index: + type: integer + format: int64 + minimum: 0 + description: |- + A URL for the file that's generated when the assistant used the `code_interpreter` tool to + generate a file. + MessageContentTextObject: + type: object + required: + - type + - text + properties: + type: + type: string + enum: + - text + - json_object + description: Always `text`. + text: + type: object + properties: + value: + type: string + description: The data that makes up the text. + annotations: + type: array + items: + $ref: '#/components/schemas/MessageContentTextObjectAnnotations' + required: + - value + - annotations + description: The text content that is part of a message. + MessageContentTextObjectAnnotations: + oneOf: + - $ref: '#/components/schemas/MessageContentTextAnnotationsFileCitationObject' + - $ref: '#/components/schemas/MessageContentTextAnnotationsFilePathObject' + x-oaiExpandable: true + MessageFileObject: + type: object + required: + - id + - object + - created_at + - message_id + properties: + id: + type: string + description: TThe identifier, which can be referenced in API endpoints. + object: + type: string + enum: + - thread.message.file + description: The object type, which is always `thread.message.file`. + created_at: + type: integer + format: unixtime + description: The Unix timestamp (in seconds) for when the message file was created. + message_id: + type: string + description: The ID of the [message](/docs/api-reference/messages) that the [File](/docs/api-reference/files) is attached to. + description: A list of files attached to a `message`. + MessageObject: + type: object + required: + - id + - object + - created_at + - thread_id + - role + - content + - assistant_id + - run_id + - file_ids + - metadata + properties: + id: + type: string + description: The identifier, which can be referenced in API endpoints. + object: + type: string + enum: + - thread.message + description: The object type, which is always `thread.message`. + created_at: + type: integer + format: unixtime + description: The Unix timestamp (in seconds) for when the message was created. + thread_id: + type: string + description: The [thread](/docs/api-reference/threads) ID that this message belongs to. + role: + type: string + enum: + - user + - assistant + description: The entity that produced the message. One of `user` or `assistant`. + content: + type: array + items: + $ref: '#/components/schemas/MessageObjectContent' + description: The content of the message in array of text and/or images. + assistant_id: + type: string + nullable: true + description: |- + If applicable, the ID of the [assistant](/docs/api-reference/assistants) that authored this + message. + run_id: + type: string + nullable: true + description: |- + If applicable, the ID of the [run](/docs/api-reference/runs) associated with the authoring of + this message. + file_ids: + type: array + items: + type: string + maxItems: 10 + description: |- + A list of [file](/docs/api-reference/files) IDs that the assistant should use. Useful for + tools like retrieval and code_interpreter that can access files. A maximum of 10 files can be + attached to a message. + default: [] + metadata: + type: object + additionalProperties: + type: string + nullable: true + description: |- + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + x-oaiTypeLabel: map + MessageObjectContent: + oneOf: + - $ref: '#/components/schemas/MessageContentImageFileObject' + - $ref: '#/components/schemas/MessageContentTextObject' + x-oaiExpandable: true + Model: + type: object + required: + - id + - created + - object + - owned_by + properties: + id: + type: string + description: The model identifier, which can be referenced in the API endpoints. + created: + type: integer + format: unixtime + description: The Unix timestamp (in seconds) when the model was created. + object: + type: string + enum: + - model + description: The object type, which is always "model". + owned_by: + type: string + description: The organization that owns the model. + description: Describes an OpenAI model offering that can be used with the API. + ModifyAssistantRequest: + type: object + properties: + model: + type: string + description: |- + ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + see all of your available models, or see our [Model overview](/docs/models/overview) for + descriptions of them. + name: + type: string + nullable: true + maxLength: 256 + description: The name of the assistant. The maximum length is 256 characters. + description: + type: string + nullable: true + maxLength: 512 + description: The description of the assistant. The maximum length is 512 characters. + instructions: + type: string + nullable: true + maxLength: 32768 + description: The system instructions that the assistant uses. The maximum length is 32768 characters. + tools: + allOf: + - $ref: '#/components/schemas/CreateAssistantRequestToolsItem' + description: |- + A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. + Tools can be of types `code_interpreter`, `retrieval`, or `function`. + default: [] + file_ids: + type: array + items: + type: string + maxItems: 20 + description: |- + A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a + maximum of 20 files attached to the assistant. Files are ordered by their creation date in + ascending order. + default: [] + metadata: + type: object + additionalProperties: + type: string + nullable: true + description: |- + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + x-oaiTypeLabel: map + ModifyMessageRequest: + type: object + properties: + metadata: + type: object + additionalProperties: + type: string + nullable: true + description: |- + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + x-oaiTypeLabel: map + ModifyRunRequest: + type: object + properties: + metadata: + type: object + additionalProperties: + type: string + nullable: true + description: |- + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + x-oaiTypeLabel: map + ModifyThreadRequest: + type: object + properties: + metadata: + type: object + additionalProperties: + type: string + nullable: true + description: |- + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + NEpochs: + type: integer + format: int64 + minimum: 1 + maximum: 50 + OpenAIFile: + type: object + required: + - id + - bytes + - created_at + - filename + - object + - purpose + - status + properties: + id: + type: string + description: The file identifier, which can be referenced in the API endpoints. + bytes: + type: integer + format: int64 + description: The size of the file, in bytes. + created_at: + type: integer + format: unixtime + description: The Unix timestamp (in seconds) for when the file was created. + filename: + type: string + description: The name of the file. + object: + type: string + enum: + - file + description: The object type, which is always "file". + purpose: + type: string + enum: + - fine-tune + - fine-tune-results + - assistants + - assistants_output + description: |- + The intended purpose of the file. Supported values are `fine-tune`, `fine-tune-results`, + `assistants`, and `assistants_output`. + status: + type: string + enum: + - uploaded + - processed + - error + description: |- + Deprecated. The current status of the file, which can be either `uploaded`, `processed`, or + `error`. + deprecated: true + status_details: + type: string + description: |- + Deprecated. For details on why a fine-tuning training file failed validation, see the `error` + field on `fine_tuning.job`. + deprecated: true + description: The `File` object represents a document that has been uploaded to OpenAI. + Prompt: + oneOf: + - type: string + - type: array + items: + type: string + - $ref: '#/components/schemas/TokenArrayItem' + - $ref: '#/components/schemas/TokenArrayArray' + RunCompletionUsage: + type: object + required: + - completion_tokens + - prompt_tokens + - total_tokens + properties: + completion_tokens: + type: integer + format: int64 + description: Number of completion tokens used over the course of the run. + prompt_tokens: + type: integer + format: int64 + description: Number of prompt tokens used over the course of the run. + total_tokens: + type: integer + format: int64 + description: Total number of tokens used (prompt + completion). + description: |- + Usage statistics related to the run. This value will be `null` if the run is not in a terminal + state (i.e. `in_progress`, `queued`, etc.). + RunObject: + type: object + required: + - id + - object + - created_at + - thread_id + - assistant_id + - status + - required_action + - last_error + - expires_at + - started_at + - cancelled_at + - failed_at + - completed_at + - model + - instructions + - tools + - file_ids + - metadata + - usage + properties: + id: + type: string + description: The identifier, which can be referenced in API endpoints. + object: + type: string + enum: + - thread.run + description: The object type, which is always `thread.run`. + created_at: + type: integer + format: unixtime + description: The Unix timestamp (in seconds) for when the run was created. + thread_id: + type: string + description: |- + The ID of the [thread](/docs/api-reference/threads) that was executed on as a part of this + run. + assistant_id: + type: string + description: The ID of the [assistant](/docs/api-reference/assistants) used for execution of this run. + status: + type: string + enum: + - queued + - in_progress + - requires_action + - cancelling + - cancelled + - failed + - completed + - expired + description: |- + The status of the run, which can be either `queued`, `in_progress`, `requires_action`, + `cancelling`, `cancelled`, `failed`, `completed`, or `expired`. + required_action: + type: object + properties: + type: + type: string + enum: + - submit_tool_outputs + description: For now, this is always `submit_tool_outputs`. + submit_tool_outputs: + type: object + properties: + tool_calls: + type: array + items: + $ref: '#/components/schemas/RunToolCallObject' + description: A list of the relevant tool calls. + required: + - tool_calls + description: Details on the tool outputs needed for this run to continue. + required: + - type + - submit_tool_outputs + nullable: true + description: |- + Details on the action required to continue the run. Will be `null` if no action is + required. + last_error: + type: object + properties: + code: + type: string + enum: + - server_error + - rate_limit_exceeded + description: One of `server_error` or `rate_limit_exceeded`. + message: + type: string + description: A human-readable description of the error. + required: + - code + - message + nullable: true + description: The last error associated with this run. Will be `null` if there are no errors. + expires_at: + type: integer + format: unixtime + description: The Unix timestamp (in seconds) for when the run will expire. + started_at: + type: string + format: date-time + nullable: true + description: The Unix timestamp (in seconds) for when the run was started. + cancelled_at: + type: string + format: date-time + nullable: true + description: The Unix timestamp (in seconds) for when the run was cancelled. + failed_at: + type: string + format: date-time + nullable: true + description: The Unix timestamp (in seconds) for when the run failed. + completed_at: + type: string + format: date-time + nullable: true + description: The Unix timestamp (in seconds) for when the run was completed. + model: + type: string + description: The model that the [assistant](/docs/api-reference/assistants) used for this run. + instructions: + type: string + description: The instructions that the [assistant](/docs/api-reference/assistants) used for this run. + tools: + allOf: + - $ref: '#/components/schemas/CreateRunRequestToolsItem' + description: The list of tools that the [assistant](/docs/api-reference/assistants) used for this run. + file_ids: + type: array + items: + type: string + description: |- + The list of [File](/docs/api-reference/files) IDs the + [assistant](/docs/api-reference/assistants) used for this run. + default: [] + metadata: + type: object + additionalProperties: + type: string + nullable: true + description: |- + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + x-oaiTypeLabel: map + usage: + type: object + allOf: + - $ref: '#/components/schemas/RunCompletionUsage' + nullable: true + description: Represents an execution run on a [thread](/docs/api-reference/threads). + RunStepCompletionUsage: + type: object + required: + - completion_tokens + - prompt_tokens + - total_tokens + properties: + completion_tokens: + type: integer + format: int64 + description: Number of completion tokens used over the course of the run step. + prompt_tokens: + type: integer + format: int64 + description: Number of prompt tokens used over the course of the run step. + total_tokens: + type: integer + format: int64 + description: Total number of tokens used (prompt + completion). + description: |- + Usage statistics related to the run step. This value will be `null` while the run step's status + is `in_progress`. + RunStepDetails: + oneOf: + - $ref: '#/components/schemas/RunStepDetailsMessageCreationObject' + - $ref: '#/components/schemas/RunStepDetailsToolCallsObject' + x-oaiExpandable: true + RunStepDetailsMessageCreationObject: + type: object + required: + - type + - message_creation + properties: + type: + type: string + enum: + - message_creation + description: Details of the message creation by the run step. + message_creation: + type: object + properties: + message_id: + type: string + description: The ID of the message that was created by this run step. + required: + - message_id + description: Details of the message creation by the run step. + RunStepDetailsToolCallsCodeObject: + type: object + required: + - id + - type + - code_interpreter + properties: + id: + type: string + description: The ID of the tool call. + type: + type: string + enum: + - code_interpreter + description: |- + The type of tool call. This is always going to be `code_interpreter` for this type of tool + call. + code_interpreter: + type: object + properties: + input: + type: string + description: The input to the Code Interpreter tool call. + outputs: + allOf: + - $ref: '#/components/schemas/RunStepDetailsToolCallsCodeOutputs' + description: |- + The outputs from the Code Interpreter tool call. Code Interpreter can output one or more + items, including text (`logs`) or images (`image`). Each of these are represented by a + different object type. + required: + - input + - outputs + description: The Code Interpreter tool call definition. + description: Details of the Code Interpreter tool call the run step was involved in. + RunStepDetailsToolCallsCodeOutput: + oneOf: + - $ref: '#/components/schemas/RunStepDetailsToolCallsCodeOutputLogsObject' + - $ref: '#/components/schemas/RunStepDetailsToolCallsCodeOutputImageObject' + x-oaiExpandable: true + RunStepDetailsToolCallsCodeOutputImageObject: + type: object + required: + - type + - image + properties: + type: + type: string + enum: + - image + description: Always `image`. + image: + type: object + properties: + file_id: + type: string + description: The [file](/docs/api-reference/files) ID of the image. + required: + - file_id + RunStepDetailsToolCallsCodeOutputLogsObject: + type: object + required: + - type + - logs + properties: + type: + type: string + enum: + - logs + description: Always `logs`. + logs: + type: string + description: The text output from the Code Interpreter tool call. + description: Text output from the Code Interpreter tool call as part of a run step. + RunStepDetailsToolCallsCodeOutputs: + type: array + items: + $ref: '#/components/schemas/RunStepDetailsToolCallsCodeOutput' + RunStepDetailsToolCallsFunctionObject: + type: object + required: + - id + - type + - function + properties: + id: + type: string + description: The ID of the tool call object. + type: + type: string + enum: + - function + description: The type of tool call. This is always going to be `function` for this type of tool call. + function: + type: object + properties: + name: + type: string + description: The name of the function. + arguments: + type: string + description: The arguments passed to the function. + output: + type: string + nullable: true + description: |- + The output of the function. This will be `null` if the outputs have not been + [submitted](/docs/api-reference/runs/submitToolOutputs) yet. + required: + - name + - arguments + - output + description: The definition of the function that was called. + RunStepDetailsToolCallsObject: + type: object + required: + - type + - tool_calls + properties: + type: + type: string + enum: + - tool_calls + description: Always `tool_calls`. + tool_calls: + allOf: + - $ref: '#/components/schemas/RunStepDetailsToolCallsObjectToolCallsItem' + description: |- + An array of tool calls the run step was involved in. These can be associated with one of three + types of tools: `code_interpreter`, `retrieval`, or `function`. + description: Details of the tool call. + RunStepDetailsToolCallsObjectToolCall: + oneOf: + - $ref: '#/components/schemas/RunStepDetailsToolCallsCodeObject' + - $ref: '#/components/schemas/RunStepDetailsToolCallsRetrievalObject' + - $ref: '#/components/schemas/RunStepDetailsToolCallsFunctionObject' + x-oaiExpandable: true + RunStepDetailsToolCallsObjectToolCallsItem: + type: array + items: + $ref: '#/components/schemas/RunStepDetailsToolCallsObjectToolCall' + RunStepDetailsToolCallsRetrievalObject: + type: object + required: + - id + - type + - retrieval + properties: + id: + type: string + description: The ID of the tool call object. + type: + type: string + enum: + - retrieval + description: The type of tool call. This is always going to be `retrieval` for this type of tool call. + retrieval: + type: object + description: For now, this is always going to be an empty object. + x-oaiTypeLabel: map + RunStepObject: + type: object + required: + - id + - object + - created_at + - assistant_id + - thread_id + - run_id + - type + - status + - step_details + - last_error + - expires_at + - cancelled_at + - failed_at + - completed_at + - metadata + - usage + properties: + id: + type: string + description: The identifier of the run step, which can be referenced in API endpoints. + object: + type: string + enum: + - thread.run.step + description: The object type, which is always `thread.run.step`. + created_at: + type: integer + format: unixtime + description: The Unix timestamp (in seconds) for when the run step was created. + assistant_id: + type: string + description: The ID of the [assistant](/docs/api-reference/assistants) associated with the run step. + thread_id: + type: string + description: The ID of the [thread](/docs/api-reference/threads) that was run. + run_id: + type: string + description: The ID of the [run](/docs/api-reference/runs) that this run step is a part of. + type: + type: string + enum: + - message_creation + - tool_calls + description: The type of run step, which can be either `message_creation` or `tool_calls`. + status: + type: string + enum: + - in_progress + - cancelled + - failed + - completed + - expired + description: |- + The status of the run step, which can be either `in_progress`, `cancelled`, `failed`, + `completed`, or `expired`. + step_details: + allOf: + - $ref: '#/components/schemas/RunStepDetails' + description: The details of the run step. + last_error: + type: object + properties: + code: + type: string + enum: + - server_error + - rate_limit_exceeded + description: One of `server_error` or `rate_limit_exceeded`. + message: + type: string + description: A human-readable description of the error. + required: + - code + - message + nullable: true + description: The last error associated with this run step. Will be `null` if there are no errors. + expires_at: + type: string + format: date-time + nullable: true + description: |- + The Unix timestamp (in seconds) for when the run step expired. A step is considered expired + if the parent run is expired. + cancelled_at: + type: string + format: date-time + nullable: true + description: The Unix timestamp (in seconds) for when the run step was cancelled. + failed_at: + type: string + format: date-time + nullable: true + description: The Unix timestamp (in seconds) for when the run step failed. + completed_at: + type: string + format: date-time + nullable: true + description: T The Unix timestamp (in seconds) for when the run step completed.. + metadata: + type: object + additionalProperties: + type: string + nullable: true + description: |- + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + x-oaiTypeLabel: map + usage: + type: object + allOf: + - $ref: '#/components/schemas/RunCompletionUsage' + nullable: true + description: Represents a step in execution of a run. + RunToolCallObject: + type: object + required: + - id + - type + - function + properties: + id: + type: string + description: |- + The ID of the tool call. This ID must be referenced when you submit the tool outputs in using + the [Submit tool outputs to run](/docs/api-reference/runs/submitToolOutputs) endpoint. + type: + type: string + enum: + - function + description: The type of tool call the output is required for. For now, this is always `function`. + function: + type: object + properties: + name: + type: string + description: The name of the function. + arguments: + type: string + description: The arguments that the model expects you to pass to the function. + required: + - name + - arguments + description: The function definition. + description: Tool call objects + Stop: + oneOf: + - type: string + - $ref: '#/components/schemas/StopSequences' + StopSequences: + type: array + items: + type: string + minItems: 1 + maxItems: 4 + SubmitToolOutputsRunRequest: + type: object + required: + - tool_outputs + properties: + tool_outputs: + type: object + properties: + tool_call_id: + type: string + description: |- + The ID of the tool call in the `required_action` object within the run object the output is + being submitted for. + output: + type: string + description: The output of the tool call to be submitted to continue the run. + description: A list of tools for which the outputs are being submitted. + SuffixString: + type: string + minLength: 1 + maxLength: 40 + ThreadObject: + type: object + required: + - id + - object + - created_at + - metadata + properties: + id: + type: string + description: The identifier, which can be referenced in API endpoints. + object: + type: string + enum: + - thread + description: The object type, which is always `thread`. + created_at: + type: integer + format: unixtime + description: The Unix timestamp (in seconds) for when the thread was created. + metadata: + type: object + additionalProperties: + type: string + nullable: true + description: |- + Set of 16 key-value pairs that can be attached to an object. This can be useful for storing + additional information about the object in a structured format. Keys can be a maximum of 64 + characters long and values can be a maxium of 512 characters long. + x-oaiTypeLabel: map + description: Represents a thread that contains [messages](/docs/api-reference/messages). + TokenArrayArray: + type: array + items: + $ref: '#/components/schemas/TokenArrayItem' + minItems: 1 + TokenArrayItem: + type: array + items: + type: integer + format: int64 + minItems: 1 + User: + type: string + securitySchemes: + BearerAuth: + type: http + scheme: bearer +servers: + - url: https://api.openai.com/v1 + description: OpenAI Endpoint + variables: {} diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..5a3c43f3f --- /dev/null +++ b/.gitignore @@ -0,0 +1,178 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates +.vs/ +*.lock.json +developer/ +launch.json +launchSettings.json + +# Default Assets restore directory +.assets + +# Build results +binaries/ +[Dd]ebug*/ +[Rr]elease/ +build/ +restoredPackages/ +PolicheckOutput/ +tools/net46/ +tools/SdkBuildTools/ +tools/Microsoft.WindowsAzure.Build.Tasks/packages/ +PublishedNugets/ +src/NuGet.Config +tools/7-zip/ +#tools/LocalNugetFeed/Microsoft.Internal.NetSdkBuild.Mgmt.Tools.*.nupkg + +[Tt]est[Rr]esult +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.vspscc +*.vssscc +.builds + +*.pidb + +*.log +*.scc +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf + +# Visual Studio profiler +*.psess +*.vsp + +# VS Code +**/.vscode/* +!.vscode/cspell.json + +# Code analysis +*.CodeAnalysisLog.xml + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ + +*.[Rr]e[Ss]harper + +# Rider IDE +.idea + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish + +# Publish Web Output +*.Publish.xml + +# Others +[Bb]in +[Oo]bj +TestResults +[Tt]est[Rr]esult* +*.Cache +ClientBin +~$* +*.dbmdl + +*.[Pp]ublish.xml + +Generated_Code #added for RIA/Silverlight projects + +# Build tasks +tools/*.dll + +# Sensitive files +*.keys +!Azure.Extensions.AspNetCore.DataProtection.Keys +!Azure.Security.KeyVault.Keys +*.pfx +TestConfigurations.xml +*.json.env +*.bicep.env + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML + +# NuGet +packages +packages/repositories.config +testPackages + +# Mac development +.DS_Store + +# Specification DLLs +*.Specification.dll + +# Generated readme.txt files # +src/*/readme.txt + +build.out +.nuget/ + +# Azure Project +csx/ +*.GhostDoc.xml +pingme.txt + +# TS/Node files +dist/ +node_modules/ + +# MSBuild binary log files +msbuild.binlog + +# BenchmarkDotNet +BenchmarkDotNet.Artifacts + +artifacts +.assets + +# Temporary typespec folders for typespec generation +TempTypeSpecFiles/ diff --git a/assistants/operations.tsp b/assistants/operations.tsp index 350f68d7b..e462c6f5b 100644 --- a/assistants/operations.tsp +++ b/assistants/operations.tsp @@ -1,6 +1,7 @@ import "@typespec/http"; import "@typespec/openapi"; +import "../common/models.tsp"; import "../common/errors.tsp"; import "./models.tsp"; @@ -34,7 +35,7 @@ interface Assistants { * Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` * for descending order. */ - @query order?: "asc" | "desc" = "desc"; + @query order?: ListOrder = ListOrder.desc; /** * A cursor for use in pagination. `after` is an object ID that defines your place in the list. @@ -116,7 +117,7 @@ interface Assistants { * Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` * for descending order. */ - @query order?: "asc" | "desc" = "desc"; + @query order?: ListOrder = ListOrder.desc; /** * A cursor for use in pagination. `after` is an object ID that defines your place in the list. diff --git a/common/models.tsp b/common/models.tsp index 611e53e7a..13ab11ca2 100644 --- a/common/models.tsp +++ b/common/models.tsp @@ -10,6 +10,11 @@ model TokenArray is safeint[]; @minItems(1) model TokenArrayArray is TokenArray[]; +enum ListOrder { + asc: "asc", + desc: "desc", +} + model FunctionObject { /** * A description of what the function does, used by the model to choose when and how to call the diff --git a/files/operations.tsp b/files/operations.tsp index dda5f95b8..94320fa3d 100644 --- a/files/operations.tsp +++ b/files/operations.tsp @@ -36,7 +36,7 @@ interface Files { listFiles( /** Only return files with the given purpose. */ // NOTE: This is just a string in the OpenAPI spec. - @query purpose?: FILE_PURPOSE, + @query purpose?: string, ): ListFilesResponse | ErrorResponse; @route("{file_id}") diff --git a/messages/operations.tsp b/messages/operations.tsp index 0c9843e0a..652b79007 100644 --- a/messages/operations.tsp +++ b/messages/operations.tsp @@ -1,6 +1,7 @@ import "@typespec/http"; import "@typespec/openapi"; +import "../common/models.tsp"; import "../common/errors.tsp"; import "./models.tsp"; @@ -40,7 +41,7 @@ interface Messages { * Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` * for descending order. */ - @query order?: "asc" | "desc" = "desc"; + @query order?: ListOrder = ListOrder.desc; /** * A cursor for use in pagination. `after` is an object ID that defines your place in the list. @@ -107,7 +108,7 @@ interface Messages { * Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` * for descending order. */ - @query order?: "asc" | "desc" = "desc"; + @query order?: ListOrder = ListOrder.desc; /** * A cursor for use in pagination. `after` is an object ID that defines your place in the list. diff --git a/runs/operations.tsp b/runs/operations.tsp index 8bf1f0df1..69a96e03c 100644 --- a/runs/operations.tsp +++ b/runs/operations.tsp @@ -1,6 +1,7 @@ import "@typespec/http"; import "@typespec/openapi"; +import "../common/models.tsp"; import "../common/errors.tsp"; import "./models.tsp"; @@ -51,7 +52,7 @@ interface Runs { * Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` * for descending order. */ - @query order?: "asc" | "desc" = "desc"; + @query order?: ListOrder = ListOrder.desc; /** * A cursor for use in pagination. `after` is an object ID that defines your place in the list. @@ -150,7 +151,7 @@ interface Runs { * Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` * for descending order. */ - @query order?: "asc" | "desc" = "desc"; + @query order?: ListOrder = ListOrder.desc; /** * A cursor for use in pagination. `after` is an object ID that defines your place in the list. diff --git a/tsp-output/@typespec/openapi3/openapi.yaml b/tsp-output/@typespec/openapi3/openapi.yaml index 8f62d8667..346061391 100644 --- a/tsp-output/@typespec/openapi3/openapi.yaml +++ b/tsp-output/@typespec/openapi3/openapi.yaml @@ -64,15 +64,7 @@ paths: Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` for descending order. schema: - type: string - enum: - - asc - - desc - - desc - - desc - - desc - - desc - - desc + $ref: '#/components/schemas/ListOrder' default: desc - name: after in: query @@ -250,15 +242,7 @@ paths: Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` for descending order. schema: - type: string - enum: - - asc - - desc - - desc - - desc - - desc - - desc - - desc + $ref: '#/components/schemas/ListOrder' default: desc - name: after in: query @@ -563,11 +547,6 @@ paths: description: Only return files with the given purpose. schema: type: string - enum: - - fine-tune - - fine-tune-results - - assistants - - assistants_output responses: '200': description: The request has succeeded. @@ -1339,15 +1318,7 @@ paths: Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` for descending order. schema: - type: string - enum: - - asc - - desc - - desc - - desc - - desc - - desc - - desc + $ref: '#/components/schemas/ListOrder' default: desc - name: after in: query @@ -1485,15 +1456,7 @@ paths: Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` for descending order. schema: - type: string - enum: - - asc - - desc - - desc - - desc - - desc - - desc - - desc + $ref: '#/components/schemas/ListOrder' default: desc - name: after in: query @@ -1625,15 +1588,7 @@ paths: Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` for descending order. schema: - type: string - enum: - - asc - - desc - - desc - - desc - - desc - - desc - - desc + $ref: '#/components/schemas/ListOrder' default: desc - name: after in: query @@ -1803,15 +1758,7 @@ paths: Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` for descending order. schema: - type: string - enum: - - asc - - desc - - desc - - desc - - desc - - desc - - desc + $ref: '#/components/schemas/ListOrder' default: desc - name: after in: query @@ -4974,6 +4921,13 @@ components: type: array items: $ref: '#/components/schemas/Model' + ListOrder: + anyOf: + - type: string + - type: string + enum: + - asc + - desc ListPaginatedFineTuningJobsResponse: type: object required: diff --git a/tspconfig.yaml b/tspconfig.yaml new file mode 100644 index 000000000..3788a1428 --- /dev/null +++ b/tspconfig.yaml @@ -0,0 +1,4 @@ +options: + "@azure-tools/typespec-csharp": + branded: false + generate-test-project: true \ No newline at end of file From 43dd97bef97a8a995551d5362e54c7a73a8ccd6f Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado Date: Tue, 20 Feb 2024 01:29:27 -0800 Subject: [PATCH 10/50] Fix fine-tuning operations.tsp --- .dotnet/src/Generated/FineTunes.cs | 736 -- .dotnet/src/Generated/FineTuning.cs | 661 +- .dotnet/src/Generated/FineTuningJobs.cs | 710 -- .../CreateFineTuneRequest.Serialization.cs | 386 -- .../Generated/Models/CreateFineTuneRequest.cs | 295 - .../Models/CreateFineTuneRequestModel.cs | 54 - .../Models/FineTune.Serialization.cs | 287 - .dotnet/src/Generated/Models/FineTune.cs | 169 - .../Models/FineTuneEvent.Serialization.cs | 156 - .dotnet/src/Generated/Models/FineTuneEvent.cs | 93 - .../FineTuneHyperparams.Serialization.cs | 197 - .../Generated/Models/FineTuneHyperparams.cs | 117 - .../src/Generated/Models/FineTuneObject.cs | 45 - .../src/Generated/Models/FineTuneStatus.cs | 57 - ...istFineTuneEventsResponse.Serialization.cs | 150 - .../Models/ListFineTuneEventsResponse.cs | 81 - .../ListFineTunesResponse.Serialization.cs | 150 - .../Generated/Models/ListFineTunesResponse.cs | 81 - .dotnet/src/Generated/OpenAIClient.cs | 15 +- .dotnet/src/Generated/OpenAIModelFactory.cs | 374 +- ...eTuningJobsTests.cs => FineTuningTests.cs} | 4 +- .../@typespec/openapi3/openapi.yaml | 6019 ----------------- fine-tuning/operations.tsp | 162 +- tsp-output/@typespec/openapi3/openapi.yaml | 170 +- 24 files changed, 809 insertions(+), 10360 deletions(-) delete mode 100644 .dotnet/src/Generated/FineTunes.cs delete mode 100644 .dotnet/src/Generated/FineTuningJobs.cs delete mode 100644 .dotnet/src/Generated/Models/CreateFineTuneRequest.Serialization.cs delete mode 100644 .dotnet/src/Generated/Models/CreateFineTuneRequest.cs delete mode 100644 .dotnet/src/Generated/Models/CreateFineTuneRequestModel.cs delete mode 100644 .dotnet/src/Generated/Models/FineTune.Serialization.cs delete mode 100644 .dotnet/src/Generated/Models/FineTune.cs delete mode 100644 .dotnet/src/Generated/Models/FineTuneEvent.Serialization.cs delete mode 100644 .dotnet/src/Generated/Models/FineTuneEvent.cs delete mode 100644 .dotnet/src/Generated/Models/FineTuneHyperparams.Serialization.cs delete mode 100644 .dotnet/src/Generated/Models/FineTuneHyperparams.cs delete mode 100644 .dotnet/src/Generated/Models/FineTuneObject.cs delete mode 100644 .dotnet/src/Generated/Models/FineTuneStatus.cs delete mode 100644 .dotnet/src/Generated/Models/ListFineTuneEventsResponse.Serialization.cs delete mode 100644 .dotnet/src/Generated/Models/ListFineTuneEventsResponse.cs delete mode 100644 .dotnet/src/Generated/Models/ListFineTunesResponse.Serialization.cs delete mode 100644 .dotnet/src/Generated/Models/ListFineTunesResponse.cs rename .dotnet/tests/Generated/Tests/{FineTuningJobsTests.cs => FineTuningTests.cs} (70%) delete mode 100644 .dotnet/tsp-output/@typespec/openapi3/openapi.yaml diff --git a/.dotnet/src/Generated/FineTunes.cs b/.dotnet/src/Generated/FineTunes.cs deleted file mode 100644 index 04c8bae74..000000000 --- a/.dotnet/src/Generated/FineTunes.cs +++ /dev/null @@ -1,736 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel; -using System.ClientModel.Internal; -using System.ClientModel.Primitives; -using System.ClientModel.Primitives.Pipeline; -using System.Threading; -using System.Threading.Tasks; -using OpenAI.Models; - -namespace OpenAI -{ - // Data plane generated sub-client. - /// The FineTunes sub-client. - public partial class FineTunes - { - private const string AuthorizationHeader = "Authorization"; - private readonly KeyCredential _keyCredential; - private const string AuthorizationApiKeyPrefix = "Bearer"; - private readonly MessagePipeline _pipeline; - private readonly Uri _endpoint; - - /// The ClientDiagnostics is used to provide tracing support for the client library. - internal TelemetrySource ClientDiagnostics { get; } - - /// The HTTP pipeline for sending and receiving REST requests and responses. - public virtual MessagePipeline Pipeline => _pipeline; - - /// Initializes a new instance of FineTunes for mocking. - protected FineTunes() - { - } - - /// Initializes a new instance of FineTunes. - /// The handler for diagnostic messaging in the client. - /// The HTTP pipeline for sending and receiving REST requests and responses. - /// The key credential to copy. - /// OpenAI Endpoint. - internal FineTunes(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) - { - ClientDiagnostics = clientDiagnostics; - _pipeline = pipeline; - _keyCredential = keyCredential; - _endpoint = endpoint; - } - - /// - /// Creates a job that fine-tunes a specified model from a given dataset. - /// - /// Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete. - /// - /// [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) - /// - /// The to use. - /// The cancellation token to use. - /// is null. - [Obsolete("deprecated")] - public virtual async Task> CreateFineTuneAsync(CreateFineTuneRequest fineTune, CancellationToken cancellationToken = default) - { - ClientUtilities.AssertNotNull(fineTune, nameof(fineTune)); - - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = fineTune.ToRequestBody(); - Result result = await CreateFineTuneAsync(content, context).ConfigureAwait(false); - return Result.FromValue(FineTune.FromResponse(result.GetRawResponse()), result.GetRawResponse()); - } - - /// - /// Creates a job that fine-tunes a specified model from a given dataset. - /// - /// Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete. - /// - /// [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) - /// - /// The to use. - /// The cancellation token to use. - /// is null. - [Obsolete("deprecated")] - public virtual Result CreateFineTune(CreateFineTuneRequest fineTune, CancellationToken cancellationToken = default) - { - ClientUtilities.AssertNotNull(fineTune, nameof(fineTune)); - - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = fineTune.ToRequestBody(); - Result result = CreateFineTune(content, context); - return Result.FromValue(FineTune.FromResponse(result.GetRawResponse()), result.GetRawResponse()); - } - - /// - /// [Protocol Method] Creates a job that fine-tunes a specified model from a given dataset. - /// - /// Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete. - /// - /// [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) - /// - /// - /// - /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. - /// - /// - /// - /// - /// Please try the simpler convenience overload with strongly typed models first. - /// - /// - /// - /// - /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// is null. - /// Service returned a non-success status code. - /// The response returned from the service. - [Obsolete("deprecated")] - public virtual async Task CreateFineTuneAsync(RequestBody content, RequestOptions context = null) - { - ClientUtilities.AssertNotNull(content, nameof(content)); - - using var scope = ClientDiagnostics.CreateSpan("FineTunes.CreateFineTune"); - scope.Start(); - try - { - using PipelineMessage message = CreateCreateFineTuneRequest(content, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; - } - } - - /// - /// [Protocol Method] Creates a job that fine-tunes a specified model from a given dataset. - /// - /// Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete. - /// - /// [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) - /// - /// - /// - /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. - /// - /// - /// - /// - /// Please try the simpler convenience overload with strongly typed models first. - /// - /// - /// - /// - /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// is null. - /// Service returned a non-success status code. - /// The response returned from the service. - [Obsolete("deprecated")] - public virtual Result CreateFineTune(RequestBody content, RequestOptions context = null) - { - ClientUtilities.AssertNotNull(content, nameof(content)); - - using var scope = ClientDiagnostics.CreateSpan("FineTunes.CreateFineTune"); - scope.Start(); - try - { - using PipelineMessage message = CreateCreateFineTuneRequest(content, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; - } - } - - /// List your organization's fine-tuning jobs. - /// The cancellation token to use. - [Obsolete("deprecated")] - public virtual async Task> GetFineTunesAsync(CancellationToken cancellationToken = default) - { - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await GetFineTunesAsync(context).ConfigureAwait(false); - return Result.FromValue(ListFineTunesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); - } - - /// List your organization's fine-tuning jobs. - /// The cancellation token to use. - [Obsolete("deprecated")] - public virtual Result GetFineTunes(CancellationToken cancellationToken = default) - { - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = GetFineTunes(context); - return Result.FromValue(ListFineTunesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); - } - - /// - /// [Protocol Method] List your organization's fine-tuning jobs - /// - /// - /// - /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. - /// - /// - /// - /// - /// Please try the simpler convenience overload with strongly typed models first. - /// - /// - /// - /// - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// Service returned a non-success status code. - /// The response returned from the service. - [Obsolete("deprecated")] - public virtual async Task GetFineTunesAsync(RequestOptions context) - { - using var scope = ClientDiagnostics.CreateSpan("FineTunes.GetFineTunes"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetFineTunesRequest(context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; - } - } - - /// - /// [Protocol Method] List your organization's fine-tuning jobs - /// - /// - /// - /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. - /// - /// - /// - /// - /// Please try the simpler convenience overload with strongly typed models first. - /// - /// - /// - /// - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// Service returned a non-success status code. - /// The response returned from the service. - [Obsolete("deprecated")] - public virtual Result GetFineTunes(RequestOptions context) - { - using var scope = ClientDiagnostics.CreateSpan("FineTunes.GetFineTunes"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetFineTunesRequest(context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; - } - } - - /// - /// Gets info about the fine-tune job. - /// - /// [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) - /// - /// The ID of the fine-tune job. - /// The cancellation token to use. - /// is null. - /// is an empty string, and was expected to be non-empty. - [Obsolete("deprecated")] - public virtual async Task> RetrieveFineTuneAsync(string fineTuneId, CancellationToken cancellationToken = default) - { - ClientUtilities.AssertNotNullOrEmpty(fineTuneId, nameof(fineTuneId)); - - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await RetrieveFineTuneAsync(fineTuneId, context).ConfigureAwait(false); - return Result.FromValue(FineTune.FromResponse(result.GetRawResponse()), result.GetRawResponse()); - } - - /// - /// Gets info about the fine-tune job. - /// - /// [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) - /// - /// The ID of the fine-tune job. - /// The cancellation token to use. - /// is null. - /// is an empty string, and was expected to be non-empty. - [Obsolete("deprecated")] - public virtual Result RetrieveFineTune(string fineTuneId, CancellationToken cancellationToken = default) - { - ClientUtilities.AssertNotNullOrEmpty(fineTuneId, nameof(fineTuneId)); - - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = RetrieveFineTune(fineTuneId, context); - return Result.FromValue(FineTune.FromResponse(result.GetRawResponse()), result.GetRawResponse()); - } - - /// - /// [Protocol Method] Gets info about the fine-tune job. - /// - /// [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) - /// - /// - /// - /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. - /// - /// - /// - /// - /// Please try the simpler convenience overload with strongly typed models first. - /// - /// - /// - /// - /// The ID of the fine-tune job. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// is null. - /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. - /// The response returned from the service. - [Obsolete("deprecated")] - public virtual async Task RetrieveFineTuneAsync(string fineTuneId, RequestOptions context) - { - ClientUtilities.AssertNotNullOrEmpty(fineTuneId, nameof(fineTuneId)); - - using var scope = ClientDiagnostics.CreateSpan("FineTunes.RetrieveFineTune"); - scope.Start(); - try - { - using PipelineMessage message = CreateRetrieveFineTuneRequest(fineTuneId, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; - } - } - - /// - /// [Protocol Method] Gets info about the fine-tune job. - /// - /// [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) - /// - /// - /// - /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. - /// - /// - /// - /// - /// Please try the simpler convenience overload with strongly typed models first. - /// - /// - /// - /// - /// The ID of the fine-tune job. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// is null. - /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. - /// The response returned from the service. - [Obsolete("deprecated")] - public virtual Result RetrieveFineTune(string fineTuneId, RequestOptions context) - { - ClientUtilities.AssertNotNullOrEmpty(fineTuneId, nameof(fineTuneId)); - - using var scope = ClientDiagnostics.CreateSpan("FineTunes.RetrieveFineTune"); - scope.Start(); - try - { - using PipelineMessage message = CreateRetrieveFineTuneRequest(fineTuneId, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; - } - } - - /// Get fine-grained status updates for a fine-tune job. - /// The ID of the fine-tune job to get events for. - /// - /// Whether to stream events for the fine-tune job. If set to true, events will be sent as - /// data-only - /// [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) - /// as they become available. The stream will terminate with a `data: [DONE]` message when the - /// job is finished (succeeded, cancelled, or failed). - /// - /// If set to false, only events generated so far will be returned. - /// - /// The cancellation token to use. - /// is null. - /// is an empty string, and was expected to be non-empty. - [Obsolete("deprecated")] - public virtual async Task> GetFineTuneEventsAsync(string fineTuneId, bool? stream = null, CancellationToken cancellationToken = default) - { - ClientUtilities.AssertNotNullOrEmpty(fineTuneId, nameof(fineTuneId)); - - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await GetFineTuneEventsAsync(fineTuneId, stream, context).ConfigureAwait(false); - return Result.FromValue(ListFineTuneEventsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); - } - - /// Get fine-grained status updates for a fine-tune job. - /// The ID of the fine-tune job to get events for. - /// - /// Whether to stream events for the fine-tune job. If set to true, events will be sent as - /// data-only - /// [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) - /// as they become available. The stream will terminate with a `data: [DONE]` message when the - /// job is finished (succeeded, cancelled, or failed). - /// - /// If set to false, only events generated so far will be returned. - /// - /// The cancellation token to use. - /// is null. - /// is an empty string, and was expected to be non-empty. - [Obsolete("deprecated")] - public virtual Result GetFineTuneEvents(string fineTuneId, bool? stream = null, CancellationToken cancellationToken = default) - { - ClientUtilities.AssertNotNullOrEmpty(fineTuneId, nameof(fineTuneId)); - - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = GetFineTuneEvents(fineTuneId, stream, context); - return Result.FromValue(ListFineTuneEventsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); - } - - /// - /// [Protocol Method] Get fine-grained status updates for a fine-tune job. - /// - /// - /// - /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. - /// - /// - /// - /// - /// Please try the simpler convenience overload with strongly typed models first. - /// - /// - /// - /// - /// The ID of the fine-tune job to get events for. - /// - /// Whether to stream events for the fine-tune job. If set to true, events will be sent as - /// data-only - /// [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) - /// as they become available. The stream will terminate with a `data: [DONE]` message when the - /// job is finished (succeeded, cancelled, or failed). - /// - /// If set to false, only events generated so far will be returned. - /// - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// is null. - /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. - /// The response returned from the service. - [Obsolete("deprecated")] - public virtual async Task GetFineTuneEventsAsync(string fineTuneId, bool? stream, RequestOptions context) - { - ClientUtilities.AssertNotNullOrEmpty(fineTuneId, nameof(fineTuneId)); - - using var scope = ClientDiagnostics.CreateSpan("FineTunes.GetFineTuneEvents"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetFineTuneEventsRequest(fineTuneId, stream, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; - } - } - - /// - /// [Protocol Method] Get fine-grained status updates for a fine-tune job. - /// - /// - /// - /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. - /// - /// - /// - /// - /// Please try the simpler convenience overload with strongly typed models first. - /// - /// - /// - /// - /// The ID of the fine-tune job to get events for. - /// - /// Whether to stream events for the fine-tune job. If set to true, events will be sent as - /// data-only - /// [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) - /// as they become available. The stream will terminate with a `data: [DONE]` message when the - /// job is finished (succeeded, cancelled, or failed). - /// - /// If set to false, only events generated so far will be returned. - /// - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// is null. - /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. - /// The response returned from the service. - [Obsolete("deprecated")] - public virtual Result GetFineTuneEvents(string fineTuneId, bool? stream, RequestOptions context) - { - ClientUtilities.AssertNotNullOrEmpty(fineTuneId, nameof(fineTuneId)); - - using var scope = ClientDiagnostics.CreateSpan("FineTunes.GetFineTuneEvents"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetFineTuneEventsRequest(fineTuneId, stream, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; - } - } - - /// Immediately cancel a fine-tune job. - /// The ID of the fine-tune job to cancel. - /// The cancellation token to use. - /// is null. - /// is an empty string, and was expected to be non-empty. - [Obsolete("deprecated")] - public virtual async Task> CancelFineTuneAsync(string fineTuneId, CancellationToken cancellationToken = default) - { - ClientUtilities.AssertNotNullOrEmpty(fineTuneId, nameof(fineTuneId)); - - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await CancelFineTuneAsync(fineTuneId, context).ConfigureAwait(false); - return Result.FromValue(FineTune.FromResponse(result.GetRawResponse()), result.GetRawResponse()); - } - - /// Immediately cancel a fine-tune job. - /// The ID of the fine-tune job to cancel. - /// The cancellation token to use. - /// is null. - /// is an empty string, and was expected to be non-empty. - [Obsolete("deprecated")] - public virtual Result CancelFineTune(string fineTuneId, CancellationToken cancellationToken = default) - { - ClientUtilities.AssertNotNullOrEmpty(fineTuneId, nameof(fineTuneId)); - - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = CancelFineTune(fineTuneId, context); - return Result.FromValue(FineTune.FromResponse(result.GetRawResponse()), result.GetRawResponse()); - } - - /// - /// [Protocol Method] Immediately cancel a fine-tune job. - /// - /// - /// - /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. - /// - /// - /// - /// - /// Please try the simpler convenience overload with strongly typed models first. - /// - /// - /// - /// - /// The ID of the fine-tune job to cancel. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// is null. - /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. - /// The response returned from the service. - [Obsolete("deprecated")] - public virtual async Task CancelFineTuneAsync(string fineTuneId, RequestOptions context) - { - ClientUtilities.AssertNotNullOrEmpty(fineTuneId, nameof(fineTuneId)); - - using var scope = ClientDiagnostics.CreateSpan("FineTunes.CancelFineTune"); - scope.Start(); - try - { - using PipelineMessage message = CreateCancelFineTuneRequest(fineTuneId, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; - } - } - - /// - /// [Protocol Method] Immediately cancel a fine-tune job. - /// - /// - /// - /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. - /// - /// - /// - /// - /// Please try the simpler convenience overload with strongly typed models first. - /// - /// - /// - /// - /// The ID of the fine-tune job to cancel. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// is null. - /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. - /// The response returned from the service. - [Obsolete("deprecated")] - public virtual Result CancelFineTune(string fineTuneId, RequestOptions context) - { - ClientUtilities.AssertNotNullOrEmpty(fineTuneId, nameof(fineTuneId)); - - using var scope = ClientDiagnostics.CreateSpan("FineTunes.CancelFineTune"); - scope.Start(); - try - { - using PipelineMessage message = CreateCancelFineTuneRequest(fineTuneId, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; - } - } - - internal PipelineMessage CreateCreateFineTuneRequest(RequestBody content, RequestOptions context) - { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/fine-tunes", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - request.SetHeaderValue("Content-Type", "application/json"); - request.Content = content; - return message; - } - - internal PipelineMessage CreateGetFineTunesRequest(RequestOptions context) - { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("GET"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/fine-tunes", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - return message; - } - - internal PipelineMessage CreateRetrieveFineTuneRequest(string fineTuneId, RequestOptions context) - { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("GET"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/fine-tunes/", false); - uri.AppendPath(fineTuneId, true); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - return message; - } - - internal PipelineMessage CreateGetFineTuneEventsRequest(string fineTuneId, bool? stream, RequestOptions context) - { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("GET"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/fine-tunes/", false); - uri.AppendPath(fineTuneId, true); - uri.AppendPath("/events", false); - if (stream != null) - { - uri.AppendQuery("stream", stream.Value, true); - } - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - return message; - } - - internal PipelineMessage CreateCancelFineTuneRequest(string fineTuneId, RequestOptions context) - { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/fine-tunes/", false); - uri.AppendPath(fineTuneId, true); - uri.AppendPath("/cancel", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - return message; - } - - private static RequestOptions DefaultRequestContext = new RequestOptions(); - internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) - { - if (!cancellationToken.CanBeCanceled) - { - return DefaultRequestContext; - } - - return new RequestOptions() { CancellationToken = cancellationToken }; - } - - private static ResponseErrorClassifier _responseErrorClassifier200; - private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); - } -} diff --git a/.dotnet/src/Generated/FineTuning.cs b/.dotnet/src/Generated/FineTuning.cs index 40f208a6e..a8038525b 100644 --- a/.dotnet/src/Generated/FineTuning.cs +++ b/.dotnet/src/Generated/FineTuning.cs @@ -4,9 +4,12 @@ using System; using System.ClientModel; +using System.ClientModel.Internal; using System.ClientModel.Primitives; using System.ClientModel.Primitives.Pipeline; using System.Threading; +using System.Threading.Tasks; +using OpenAI.Models; namespace OpenAI { @@ -44,12 +47,662 @@ internal FineTuning(TelemetrySource clientDiagnostics, MessagePipeline pipeline, _endpoint = endpoint; } - private FineTuningJobs _cachedFineTuningJobs; + /// + /// Creates a fine-tuning job which begins the process of creating a new model from a given dataset. + /// + /// Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete. + /// + /// [Learn more about fine-tuning](/docs/guides/fine-tuning) + /// + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual async Task> CreateFineTuningJobAsync(CreateFineTuningJobRequest job, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(job, nameof(job)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = job.ToRequestBody(); + Result result = await CreateFineTuningJobAsync(content, context).ConfigureAwait(false); + return Result.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// Creates a fine-tuning job which begins the process of creating a new model from a given dataset. + /// + /// Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete. + /// + /// [Learn more about fine-tuning](/docs/guides/fine-tuning) + /// + /// The to use. + /// The cancellation token to use. + /// is null. + public virtual Result CreateFineTuningJob(CreateFineTuningJobRequest job, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNull(job, nameof(job)); + + RequestOptions context = FromCancellationToken(cancellationToken); + using RequestBody content = job.ToRequestBody(); + Result result = CreateFineTuningJob(content, context); + return Result.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Creates a fine-tuning job which begins the process of creating a new model from a given dataset. + /// + /// Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete. + /// + /// [Learn more about fine-tuning](/docs/guides/fine-tuning) + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task CreateFineTuningJobAsync(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("FineTuning.CreateFineTuningJob"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateFineTuningJobRequest(content, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Creates a fine-tuning job which begins the process of creating a new model from a given dataset. + /// + /// Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete. + /// + /// [Learn more about fine-tuning](/docs/guides/fine-tuning) + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result CreateFineTuningJob(RequestBody content, RequestOptions context = null) + { + ClientUtilities.AssertNotNull(content, nameof(content)); + + using var scope = ClientDiagnostics.CreateSpan("FineTuning.CreateFineTuningJob"); + scope.Start(); + try + { + using PipelineMessage message = CreateCreateFineTuningJobRequest(content, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// List your organization's fine-tuning jobs. + /// Identifier for the last job from the previous pagination request. + /// Number of fine-tuning jobs to retrieve. + /// The cancellation token to use. + public virtual async Task> GetPaginatedFineTuningJobsAsync(string after = null, long? limit = null, CancellationToken cancellationToken = default) + { + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await GetPaginatedFineTuningJobsAsync(after, limit, context).ConfigureAwait(false); + return Result.FromValue(ListPaginatedFineTuningJobsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// List your organization's fine-tuning jobs. + /// Identifier for the last job from the previous pagination request. + /// Number of fine-tuning jobs to retrieve. + /// The cancellation token to use. + public virtual Result GetPaginatedFineTuningJobs(string after = null, long? limit = null, CancellationToken cancellationToken = default) + { + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = GetPaginatedFineTuningJobs(after, limit, context); + return Result.FromValue(ListPaginatedFineTuningJobsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] List your organization's fine-tuning jobs + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// Identifier for the last job from the previous pagination request. + /// Number of fine-tuning jobs to retrieve. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task GetPaginatedFineTuningJobsAsync(string after, long? limit, RequestOptions context) + { + using var scope = ClientDiagnostics.CreateSpan("FineTuning.GetPaginatedFineTuningJobs"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetPaginatedFineTuningJobsRequest(after, limit, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] List your organization's fine-tuning jobs + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// Identifier for the last job from the previous pagination request. + /// Number of fine-tuning jobs to retrieve. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result GetPaginatedFineTuningJobs(string after, long? limit, RequestOptions context) + { + using var scope = ClientDiagnostics.CreateSpan("FineTuning.GetPaginatedFineTuningJobs"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetPaginatedFineTuningJobsRequest(after, limit, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// Get info about a fine-tuning job. + /// + /// [Learn more about fine-tuning](/docs/guides/fine-tuning) + /// + /// The to use. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual async Task> RetrieveFineTuningJobAsync(string fineTuningJobId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await RetrieveFineTuningJobAsync(fineTuningJobId, context).ConfigureAwait(false); + return Result.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// Get info about a fine-tuning job. + /// + /// [Learn more about fine-tuning](/docs/guides/fine-tuning) + /// + /// The to use. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual Result RetrieveFineTuningJob(string fineTuningJobId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = RetrieveFineTuningJob(fineTuningJobId, context); + return Result.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Get info about a fine-tuning job. + /// + /// [Learn more about fine-tuning](/docs/guides/fine-tuning) + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The to use. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task RetrieveFineTuningJobAsync(string fineTuningJobId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + + using var scope = ClientDiagnostics.CreateSpan("FineTuning.RetrieveFineTuningJob"); + scope.Start(); + try + { + using PipelineMessage message = CreateRetrieveFineTuningJobRequest(fineTuningJobId, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Get info about a fine-tuning job. + /// + /// [Learn more about fine-tuning](/docs/guides/fine-tuning) + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The to use. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result RetrieveFineTuningJob(string fineTuningJobId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + + using var scope = ClientDiagnostics.CreateSpan("FineTuning.RetrieveFineTuningJob"); + scope.Start(); + try + { + using PipelineMessage message = CreateRetrieveFineTuningJobRequest(fineTuningJobId, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Immediately cancel a fine-tune job. + /// The ID of the fine-tuning job to cancel. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual async Task> CancelFineTuningJobAsync(string fineTuningJobId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await CancelFineTuningJobAsync(fineTuningJobId, context).ConfigureAwait(false); + return Result.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Immediately cancel a fine-tune job. + /// The ID of the fine-tuning job to cancel. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual Result CancelFineTuningJob(string fineTuningJobId, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = CancelFineTuningJob(fineTuningJobId, context); + return Result.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Immediately cancel a fine-tune job. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the fine-tuning job to cancel. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task CancelFineTuningJobAsync(string fineTuningJobId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + + using var scope = ClientDiagnostics.CreateSpan("FineTuning.CancelFineTuningJob"); + scope.Start(); + try + { + using PipelineMessage message = CreateCancelFineTuningJobRequest(fineTuningJobId, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Immediately cancel a fine-tune job. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the fine-tuning job to cancel. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result CancelFineTuningJob(string fineTuningJobId, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + + using var scope = ClientDiagnostics.CreateSpan("FineTuning.CancelFineTuningJob"); + scope.Start(); + try + { + using PipelineMessage message = CreateCancelFineTuningJobRequest(fineTuningJobId, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Get status updates for a fine-tuning job. + /// The ID of the fine-tuning job to get events for. + /// Identifier for the last event from the previous pagination request. + /// Number of events to retrieve. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual async Task> GetFineTuningEventsAsync(string fineTuningJobId, string after = null, int? limit = null, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = await GetFineTuningEventsAsync(fineTuningJobId, after, limit, context).ConfigureAwait(false); + return Result.FromValue(ListFineTuningJobEventsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// Get status updates for a fine-tuning job. + /// The ID of the fine-tuning job to get events for. + /// Identifier for the last event from the previous pagination request. + /// Number of events to retrieve. + /// The cancellation token to use. + /// is null. + /// is an empty string, and was expected to be non-empty. + public virtual Result GetFineTuningEvents(string fineTuningJobId, string after = null, int? limit = null, CancellationToken cancellationToken = default) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + + RequestOptions context = FromCancellationToken(cancellationToken); + Result result = GetFineTuningEvents(fineTuningJobId, after, limit, context); + return Result.FromValue(ListFineTuningJobEventsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + } + + /// + /// [Protocol Method] Get status updates for a fine-tuning job. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the fine-tuning job to get events for. + /// Identifier for the last event from the previous pagination request. + /// Number of events to retrieve. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual async Task GetFineTuningEventsAsync(string fineTuningJobId, string after, int? limit, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); - /// Initializes a new instance of FineTuningJobs. - public virtual FineTuningJobs GetFineTuningJobsClient() + using var scope = ClientDiagnostics.CreateSpan("FineTuning.GetFineTuningEvents"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetFineTuningEventsRequest(fineTuningJobId, after, limit, context); + return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// [Protocol Method] Get status updates for a fine-tuning job. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The ID of the fine-tuning job to get events for. + /// Identifier for the last event from the previous pagination request. + /// Number of events to retrieve. + /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + public virtual Result GetFineTuningEvents(string fineTuningJobId, string after, int? limit, RequestOptions context) + { + ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + + using var scope = ClientDiagnostics.CreateSpan("FineTuning.GetFineTuningEvents"); + scope.Start(); + try + { + using PipelineMessage message = CreateGetFineTuningEventsRequest(fineTuningJobId, after, limit, context); + return Result.FromResponse(_pipeline.ProcessMessage(message, context)); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + internal PipelineMessage CreateCreateFineTuningJobRequest(RequestBody content, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/fine_tuning/jobs", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + request.SetHeaderValue("Content-Type", "application/json"); + request.Content = content; + return message; + } + + internal PipelineMessage CreateGetPaginatedFineTuningJobsRequest(string after, long? limit, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("GET"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/fine_tuning/jobs", false); + if (after != null) + { + uri.AppendQuery("after", after, true); + } + if (limit != null) + { + uri.AppendQuery("limit", limit.Value, true); + } + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + internal PipelineMessage CreateRetrieveFineTuningJobRequest(string fineTuningJobId, RequestOptions context) { - return Volatile.Read(ref _cachedFineTuningJobs) ?? Interlocked.CompareExchange(ref _cachedFineTuningJobs, new FineTuningJobs(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedFineTuningJobs; + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("GET"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/fine_tuning/jobs/", false); + uri.AppendPath(fineTuningJobId, true); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; } + + internal PipelineMessage CreateCancelFineTuningJobRequest(string fineTuningJobId, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("POST"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/fine_tuning/jobs/", false); + uri.AppendPath(fineTuningJobId, true); + uri.AppendPath("/cancel", false); + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + internal PipelineMessage CreateGetFineTuningEventsRequest(string fineTuningJobId, string after, int? limit, RequestOptions context) + { + var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); + var request = message.Request; + request.SetMethod("GET"); + var uri = new RequestUri(); + uri.Reset(_endpoint); + uri.AppendPath("/fine_tuning/jobs/", false); + uri.AppendPath(fineTuningJobId, true); + uri.AppendPath("/events", false); + if (after != null) + { + uri.AppendQuery("after", after, true); + } + if (limit != null) + { + uri.AppendQuery("limit", limit.Value, true); + } + request.Uri = uri.ToUri(); + request.SetHeaderValue("Accept", "application/json"); + return message; + } + + private static RequestOptions DefaultRequestContext = new RequestOptions(); + internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) + { + if (!cancellationToken.CanBeCanceled) + { + return DefaultRequestContext; + } + + return new RequestOptions() { CancellationToken = cancellationToken }; + } + + private static ResponseErrorClassifier _responseErrorClassifier200; + private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); } } diff --git a/.dotnet/src/Generated/FineTuningJobs.cs b/.dotnet/src/Generated/FineTuningJobs.cs deleted file mode 100644 index 669480a3d..000000000 --- a/.dotnet/src/Generated/FineTuningJobs.cs +++ /dev/null @@ -1,710 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel; -using System.ClientModel.Internal; -using System.ClientModel.Primitives; -using System.ClientModel.Primitives.Pipeline; -using System.Threading; -using System.Threading.Tasks; -using OpenAI.Models; - -namespace OpenAI -{ - // Data plane generated sub-client. - /// The FineTuningJobs sub-client. - public partial class FineTuningJobs - { - private const string AuthorizationHeader = "Authorization"; - private readonly KeyCredential _keyCredential; - private const string AuthorizationApiKeyPrefix = "Bearer"; - private readonly MessagePipeline _pipeline; - private readonly Uri _endpoint; - - /// The ClientDiagnostics is used to provide tracing support for the client library. - internal TelemetrySource ClientDiagnostics { get; } - - /// The HTTP pipeline for sending and receiving REST requests and responses. - public virtual MessagePipeline Pipeline => _pipeline; - - /// Initializes a new instance of FineTuningJobs for mocking. - protected FineTuningJobs() - { - } - - /// Initializes a new instance of FineTuningJobs. - /// The handler for diagnostic messaging in the client. - /// The HTTP pipeline for sending and receiving REST requests and responses. - /// The key credential to copy. - /// OpenAI Endpoint. - internal FineTuningJobs(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) - { - ClientDiagnostics = clientDiagnostics; - _pipeline = pipeline; - _keyCredential = keyCredential; - _endpoint = endpoint; - } - - /// - /// Creates a job that fine-tunes a specified model from a given dataset. - /// - /// Response includes details of the enqueued job including job status and the name of the - /// fine-tuned models once complete. - /// - /// [Learn more about fine-tuning](/docs/guides/fine-tuning) - /// - /// The to use. - /// The cancellation token to use. - /// is null. - public virtual async Task> CreateFineTuningJobAsync(CreateFineTuningJobRequest job, CancellationToken cancellationToken = default) - { - ClientUtilities.AssertNotNull(job, nameof(job)); - - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = job.ToRequestBody(); - Result result = await CreateFineTuningJobAsync(content, context).ConfigureAwait(false); - return Result.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); - } - - /// - /// Creates a job that fine-tunes a specified model from a given dataset. - /// - /// Response includes details of the enqueued job including job status and the name of the - /// fine-tuned models once complete. - /// - /// [Learn more about fine-tuning](/docs/guides/fine-tuning) - /// - /// The to use. - /// The cancellation token to use. - /// is null. - public virtual Result CreateFineTuningJob(CreateFineTuningJobRequest job, CancellationToken cancellationToken = default) - { - ClientUtilities.AssertNotNull(job, nameof(job)); - - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = job.ToRequestBody(); - Result result = CreateFineTuningJob(content, context); - return Result.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); - } - - /// - /// [Protocol Method] Creates a job that fine-tunes a specified model from a given dataset. - /// - /// Response includes details of the enqueued job including job status and the name of the - /// fine-tuned models once complete. - /// - /// [Learn more about fine-tuning](/docs/guides/fine-tuning) - /// - /// - /// - /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. - /// - /// - /// - /// - /// Please try the simpler convenience overload with strongly typed models first. - /// - /// - /// - /// - /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// is null. - /// Service returned a non-success status code. - /// The response returned from the service. - public virtual async Task CreateFineTuningJobAsync(RequestBody content, RequestOptions context = null) - { - ClientUtilities.AssertNotNull(content, nameof(content)); - - using var scope = ClientDiagnostics.CreateSpan("FineTuningJobs.CreateFineTuningJob"); - scope.Start(); - try - { - using PipelineMessage message = CreateCreateFineTuningJobRequest(content, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; - } - } - - /// - /// [Protocol Method] Creates a job that fine-tunes a specified model from a given dataset. - /// - /// Response includes details of the enqueued job including job status and the name of the - /// fine-tuned models once complete. - /// - /// [Learn more about fine-tuning](/docs/guides/fine-tuning) - /// - /// - /// - /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. - /// - /// - /// - /// - /// Please try the simpler convenience overload with strongly typed models first. - /// - /// - /// - /// - /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// is null. - /// Service returned a non-success status code. - /// The response returned from the service. - public virtual Result CreateFineTuningJob(RequestBody content, RequestOptions context = null) - { - ClientUtilities.AssertNotNull(content, nameof(content)); - - using var scope = ClientDiagnostics.CreateSpan("FineTuningJobs.CreateFineTuningJob"); - scope.Start(); - try - { - using PipelineMessage message = CreateCreateFineTuningJobRequest(content, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; - } - } - - /// Identifier for the last job from the previous pagination request. - /// Number of fine-tuning jobs to retrieve. - /// The cancellation token to use. - public virtual async Task> GetPaginatedFineTuningJobsAsync(string after = null, long? limit = null, CancellationToken cancellationToken = default) - { - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await GetPaginatedFineTuningJobsAsync(after, limit, context).ConfigureAwait(false); - return Result.FromValue(ListPaginatedFineTuningJobsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); - } - - /// Identifier for the last job from the previous pagination request. - /// Number of fine-tuning jobs to retrieve. - /// The cancellation token to use. - public virtual Result GetPaginatedFineTuningJobs(string after = null, long? limit = null, CancellationToken cancellationToken = default) - { - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = GetPaginatedFineTuningJobs(after, limit, context); - return Result.FromValue(ListPaginatedFineTuningJobsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); - } - - /// - /// [Protocol Method] - /// - /// - /// - /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. - /// - /// - /// - /// - /// Please try the simpler convenience overload with strongly typed models first. - /// - /// - /// - /// - /// Identifier for the last job from the previous pagination request. - /// Number of fine-tuning jobs to retrieve. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// Service returned a non-success status code. - /// The response returned from the service. - public virtual async Task GetPaginatedFineTuningJobsAsync(string after, long? limit, RequestOptions context) - { - using var scope = ClientDiagnostics.CreateSpan("FineTuningJobs.GetPaginatedFineTuningJobs"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetPaginatedFineTuningJobsRequest(after, limit, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; - } - } - - /// - /// [Protocol Method] - /// - /// - /// - /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. - /// - /// - /// - /// - /// Please try the simpler convenience overload with strongly typed models first. - /// - /// - /// - /// - /// Identifier for the last job from the previous pagination request. - /// Number of fine-tuning jobs to retrieve. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// Service returned a non-success status code. - /// The response returned from the service. - public virtual Result GetPaginatedFineTuningJobs(string after, long? limit, RequestOptions context) - { - using var scope = ClientDiagnostics.CreateSpan("FineTuningJobs.GetPaginatedFineTuningJobs"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetPaginatedFineTuningJobsRequest(after, limit, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; - } - } - - /// - /// Get info about a fine-tuning job. - /// - /// [Learn more about fine-tuning](/docs/guides/fine-tuning) - /// - /// The to use. - /// The cancellation token to use. - /// is null. - /// is an empty string, and was expected to be non-empty. - public virtual async Task> RetrieveFineTuningJobAsync(string fineTuningJobId, CancellationToken cancellationToken = default) - { - ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); - - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await RetrieveFineTuningJobAsync(fineTuningJobId, context).ConfigureAwait(false); - return Result.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); - } - - /// - /// Get info about a fine-tuning job. - /// - /// [Learn more about fine-tuning](/docs/guides/fine-tuning) - /// - /// The to use. - /// The cancellation token to use. - /// is null. - /// is an empty string, and was expected to be non-empty. - public virtual Result RetrieveFineTuningJob(string fineTuningJobId, CancellationToken cancellationToken = default) - { - ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); - - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = RetrieveFineTuningJob(fineTuningJobId, context); - return Result.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); - } - - /// - /// [Protocol Method] Get info about a fine-tuning job. - /// - /// [Learn more about fine-tuning](/docs/guides/fine-tuning) - /// - /// - /// - /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. - /// - /// - /// - /// - /// Please try the simpler convenience overload with strongly typed models first. - /// - /// - /// - /// - /// The to use. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// is null. - /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. - /// The response returned from the service. - public virtual async Task RetrieveFineTuningJobAsync(string fineTuningJobId, RequestOptions context) - { - ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); - - using var scope = ClientDiagnostics.CreateSpan("FineTuningJobs.RetrieveFineTuningJob"); - scope.Start(); - try - { - using PipelineMessage message = CreateRetrieveFineTuningJobRequest(fineTuningJobId, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; - } - } - - /// - /// [Protocol Method] Get info about a fine-tuning job. - /// - /// [Learn more about fine-tuning](/docs/guides/fine-tuning) - /// - /// - /// - /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. - /// - /// - /// - /// - /// Please try the simpler convenience overload with strongly typed models first. - /// - /// - /// - /// - /// The to use. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// is null. - /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. - /// The response returned from the service. - public virtual Result RetrieveFineTuningJob(string fineTuningJobId, RequestOptions context) - { - ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); - - using var scope = ClientDiagnostics.CreateSpan("FineTuningJobs.RetrieveFineTuningJob"); - scope.Start(); - try - { - using PipelineMessage message = CreateRetrieveFineTuningJobRequest(fineTuningJobId, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; - } - } - - /// Get status updates for a fine-tuning job. - /// The ID of the fine-tuning job to get events for. - /// Identifier for the last event from the previous pagination request. - /// Number of events to retrieve. - /// The cancellation token to use. - /// is null. - /// is an empty string, and was expected to be non-empty. - public virtual async Task> GetFineTuningEventsAsync(string fineTuningJobId, string after = null, int? limit = null, CancellationToken cancellationToken = default) - { - ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); - - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await GetFineTuningEventsAsync(fineTuningJobId, after, limit, context).ConfigureAwait(false); - return Result.FromValue(ListFineTuningJobEventsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); - } - - /// Get status updates for a fine-tuning job. - /// The ID of the fine-tuning job to get events for. - /// Identifier for the last event from the previous pagination request. - /// Number of events to retrieve. - /// The cancellation token to use. - /// is null. - /// is an empty string, and was expected to be non-empty. - public virtual Result GetFineTuningEvents(string fineTuningJobId, string after = null, int? limit = null, CancellationToken cancellationToken = default) - { - ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); - - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = GetFineTuningEvents(fineTuningJobId, after, limit, context); - return Result.FromValue(ListFineTuningJobEventsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); - } - - /// - /// [Protocol Method] Get status updates for a fine-tuning job. - /// - /// - /// - /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. - /// - /// - /// - /// - /// Please try the simpler convenience overload with strongly typed models first. - /// - /// - /// - /// - /// The ID of the fine-tuning job to get events for. - /// Identifier for the last event from the previous pagination request. - /// Number of events to retrieve. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// is null. - /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. - /// The response returned from the service. - public virtual async Task GetFineTuningEventsAsync(string fineTuningJobId, string after, int? limit, RequestOptions context) - { - ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); - - using var scope = ClientDiagnostics.CreateSpan("FineTuningJobs.GetFineTuningEvents"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetFineTuningEventsRequest(fineTuningJobId, after, limit, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; - } - } - - /// - /// [Protocol Method] Get status updates for a fine-tuning job. - /// - /// - /// - /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. - /// - /// - /// - /// - /// Please try the simpler convenience overload with strongly typed models first. - /// - /// - /// - /// - /// The ID of the fine-tuning job to get events for. - /// Identifier for the last event from the previous pagination request. - /// Number of events to retrieve. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// is null. - /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. - /// The response returned from the service. - public virtual Result GetFineTuningEvents(string fineTuningJobId, string after, int? limit, RequestOptions context) - { - ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); - - using var scope = ClientDiagnostics.CreateSpan("FineTuningJobs.GetFineTuningEvents"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetFineTuningEventsRequest(fineTuningJobId, after, limit, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; - } - } - - /// Immediately cancel a fine-tune job. - /// The ID of the fine-tuning job to cancel. - /// The cancellation token to use. - /// is null. - /// is an empty string, and was expected to be non-empty. - public virtual async Task> CancelFineTuningJobAsync(string fineTuningJobId, CancellationToken cancellationToken = default) - { - ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); - - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await CancelFineTuningJobAsync(fineTuningJobId, context).ConfigureAwait(false); - return Result.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); - } - - /// Immediately cancel a fine-tune job. - /// The ID of the fine-tuning job to cancel. - /// The cancellation token to use. - /// is null. - /// is an empty string, and was expected to be non-empty. - public virtual Result CancelFineTuningJob(string fineTuningJobId, CancellationToken cancellationToken = default) - { - ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); - - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = CancelFineTuningJob(fineTuningJobId, context); - return Result.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); - } - - /// - /// [Protocol Method] Immediately cancel a fine-tune job. - /// - /// - /// - /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. - /// - /// - /// - /// - /// Please try the simpler convenience overload with strongly typed models first. - /// - /// - /// - /// - /// The ID of the fine-tuning job to cancel. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// is null. - /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. - /// The response returned from the service. - public virtual async Task CancelFineTuningJobAsync(string fineTuningJobId, RequestOptions context) - { - ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); - - using var scope = ClientDiagnostics.CreateSpan("FineTuningJobs.CancelFineTuningJob"); - scope.Start(); - try - { - using PipelineMessage message = CreateCancelFineTuningJobRequest(fineTuningJobId, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; - } - } - - /// - /// [Protocol Method] Immediately cancel a fine-tune job. - /// - /// - /// - /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. - /// - /// - /// - /// - /// Please try the simpler convenience overload with strongly typed models first. - /// - /// - /// - /// - /// The ID of the fine-tuning job to cancel. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// is null. - /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. - /// The response returned from the service. - public virtual Result CancelFineTuningJob(string fineTuningJobId, RequestOptions context) - { - ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); - - using var scope = ClientDiagnostics.CreateSpan("FineTuningJobs.CancelFineTuningJob"); - scope.Start(); - try - { - using PipelineMessage message = CreateCancelFineTuningJobRequest(fineTuningJobId, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; - } - } - - internal PipelineMessage CreateCreateFineTuningJobRequest(RequestBody content, RequestOptions context) - { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/fine_tuning/jobs", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - request.SetHeaderValue("Content-Type", "application/json"); - request.Content = content; - return message; - } - - internal PipelineMessage CreateGetPaginatedFineTuningJobsRequest(string after, long? limit, RequestOptions context) - { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("GET"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/fine_tuning/jobs", false); - if (after != null) - { - uri.AppendQuery("after", after, true); - } - if (limit != null) - { - uri.AppendQuery("limit", limit.Value, true); - } - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - return message; - } - - internal PipelineMessage CreateRetrieveFineTuningJobRequest(string fineTuningJobId, RequestOptions context) - { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("GET"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/fine_tuning/jobs/", false); - uri.AppendPath(fineTuningJobId, true); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - return message; - } - - internal PipelineMessage CreateGetFineTuningEventsRequest(string fineTuningJobId, string after, int? limit, RequestOptions context) - { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("GET"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/fine_tuning/jobs/", false); - uri.AppendPath(fineTuningJobId, true); - uri.AppendPath("/events", false); - if (after != null) - { - uri.AppendQuery("after", after, true); - } - if (limit != null) - { - uri.AppendQuery("limit", limit.Value, true); - } - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - return message; - } - - internal PipelineMessage CreateCancelFineTuningJobRequest(string fineTuningJobId, RequestOptions context) - { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/fine_tuning/jobs/", false); - uri.AppendPath(fineTuningJobId, true); - uri.AppendPath("/cancel", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - return message; - } - - private static RequestOptions DefaultRequestContext = new RequestOptions(); - internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) - { - if (!cancellationToken.CanBeCanceled) - { - return DefaultRequestContext; - } - - return new RequestOptions() { CancellationToken = cancellationToken }; - } - - private static ResponseErrorClassifier _responseErrorClassifier200; - private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); - } -} diff --git a/.dotnet/src/Generated/Models/CreateFineTuneRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateFineTuneRequest.Serialization.cs deleted file mode 100644 index c83a0246a..000000000 --- a/.dotnet/src/Generated/Models/CreateFineTuneRequest.Serialization.cs +++ /dev/null @@ -1,386 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel.Internal; -using System.ClientModel.Primitives; -using System.Collections.Generic; -using System.Text.Json; - -namespace OpenAI.Models -{ - public partial class CreateFineTuneRequest : IUtf8JsonWriteable, IJsonModel - { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - if (format != "J") - { - throw new FormatException($"The model {nameof(CreateFineTuneRequest)} does not support '{format}' format."); - } - - writer.WriteStartObject(); - writer.WritePropertyName("training_file"u8); - writer.WriteStringValue(TrainingFile); - if (OptionalProperty.IsDefined(ValidationFile)) - { - if (ValidationFile != null) - { - writer.WritePropertyName("validation_file"u8); - writer.WriteStringValue(ValidationFile); - } - else - { - writer.WriteNull("validation_file"); - } - } - if (OptionalProperty.IsDefined(Model)) - { - writer.WritePropertyName("model"u8); - writer.WriteStringValue(Model.Value.ToString()); - } - if (OptionalProperty.IsDefined(NEpochs)) - { - if (NEpochs != null) - { - writer.WritePropertyName("n_epochs"u8); - writer.WriteNumberValue(NEpochs.Value); - } - else - { - writer.WriteNull("n_epochs"); - } - } - if (OptionalProperty.IsDefined(BatchSize)) - { - if (BatchSize != null) - { - writer.WritePropertyName("batch_size"u8); - writer.WriteNumberValue(BatchSize.Value); - } - else - { - writer.WriteNull("batch_size"); - } - } - if (OptionalProperty.IsDefined(LearningRateMultiplier)) - { - if (LearningRateMultiplier != null) - { - writer.WritePropertyName("learning_rate_multiplier"u8); - writer.WriteNumberValue(LearningRateMultiplier.Value); - } - else - { - writer.WriteNull("learning_rate_multiplier"); - } - } - if (OptionalProperty.IsDefined(PromptLossRate)) - { - if (PromptLossRate != null) - { - writer.WritePropertyName("prompt_loss_rate"u8); - writer.WriteNumberValue(PromptLossRate.Value); - } - else - { - writer.WriteNull("prompt_loss_rate"); - } - } - if (OptionalProperty.IsDefined(ComputeClassificationMetrics)) - { - if (ComputeClassificationMetrics != null) - { - writer.WritePropertyName("compute_classification_metrics"u8); - writer.WriteBooleanValue(ComputeClassificationMetrics.Value); - } - else - { - writer.WriteNull("compute_classification_metrics"); - } - } - if (OptionalProperty.IsDefined(ClassificationNClasses)) - { - if (ClassificationNClasses != null) - { - writer.WritePropertyName("classification_n_classes"u8); - writer.WriteNumberValue(ClassificationNClasses.Value); - } - else - { - writer.WriteNull("classification_n_classes"); - } - } - if (OptionalProperty.IsDefined(ClassificationPositiveClass)) - { - if (ClassificationPositiveClass != null) - { - writer.WritePropertyName("classification_positive_class"u8); - writer.WriteStringValue(ClassificationPositiveClass); - } - else - { - writer.WriteNull("classification_positive_class"); - } - } - if (OptionalProperty.IsCollectionDefined(ClassificationBetas)) - { - if (ClassificationBetas != null) - { - writer.WritePropertyName("classification_betas"u8); - writer.WriteStartArray(); - foreach (var item in ClassificationBetas) - { - writer.WriteNumberValue(item); - } - writer.WriteEndArray(); - } - else - { - writer.WriteNull("classification_betas"); - } - } - if (OptionalProperty.IsDefined(Suffix)) - { - if (Suffix != null) - { - writer.WritePropertyName("suffix"u8); - writer.WriteStringValue(Suffix); - } - else - { - writer.WriteNull("suffix"); - } - } - if (options.Format != "W" && _serializedAdditionalRawData != null) - { - foreach (var item in _serializedAdditionalRawData) - { - writer.WritePropertyName(item.Key); -#if NET6_0_OR_GREATER - writer.WriteRawValue(item.Value); -#else - using (JsonDocument document = JsonDocument.Parse(item.Value)) - { - JsonSerializer.Serialize(writer, document.RootElement); - } -#endif - } - } - writer.WriteEndObject(); - } - - CreateFineTuneRequest IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - if (format != "J") - { - throw new FormatException($"The model {nameof(CreateFineTuneRequest)} does not support '{format}' format."); - } - - using JsonDocument document = JsonDocument.ParseValue(ref reader); - return DeserializeCreateFineTuneRequest(document.RootElement, options); - } - - internal static CreateFineTuneRequest DeserializeCreateFineTuneRequest(JsonElement element, ModelReaderWriterOptions options = null) - { - options ??= new ModelReaderWriterOptions("W"); - - if (element.ValueKind == JsonValueKind.Null) - { - return null; - } - string trainingFile = default; - OptionalProperty validationFile = default; - OptionalProperty model = default; - OptionalProperty nEpochs = default; - OptionalProperty batchSize = default; - OptionalProperty learningRateMultiplier = default; - OptionalProperty promptLossRate = default; - OptionalProperty computeClassificationMetrics = default; - OptionalProperty classificationNClasses = default; - OptionalProperty classificationPositiveClass = default; - OptionalProperty> classificationBetas = default; - OptionalProperty suffix = default; - IDictionary serializedAdditionalRawData = default; - Dictionary additionalPropertiesDictionary = new Dictionary(); - foreach (var property in element.EnumerateObject()) - { - if (property.NameEquals("training_file"u8)) - { - trainingFile = property.Value.GetString(); - continue; - } - if (property.NameEquals("validation_file"u8)) - { - if (property.Value.ValueKind == JsonValueKind.Null) - { - validationFile = null; - continue; - } - validationFile = property.Value.GetString(); - continue; - } - if (property.NameEquals("model"u8)) - { - if (property.Value.ValueKind == JsonValueKind.Null) - { - continue; - } - model = new CreateFineTuneRequestModel(property.Value.GetString()); - continue; - } - if (property.NameEquals("n_epochs"u8)) - { - if (property.Value.ValueKind == JsonValueKind.Null) - { - nEpochs = null; - continue; - } - nEpochs = property.Value.GetInt64(); - continue; - } - if (property.NameEquals("batch_size"u8)) - { - if (property.Value.ValueKind == JsonValueKind.Null) - { - batchSize = null; - continue; - } - batchSize = property.Value.GetInt64(); - continue; - } - if (property.NameEquals("learning_rate_multiplier"u8)) - { - if (property.Value.ValueKind == JsonValueKind.Null) - { - learningRateMultiplier = null; - continue; - } - learningRateMultiplier = property.Value.GetDouble(); - continue; - } - if (property.NameEquals("prompt_loss_rate"u8)) - { - if (property.Value.ValueKind == JsonValueKind.Null) - { - promptLossRate = null; - continue; - } - promptLossRate = property.Value.GetDouble(); - continue; - } - if (property.NameEquals("compute_classification_metrics"u8)) - { - if (property.Value.ValueKind == JsonValueKind.Null) - { - computeClassificationMetrics = null; - continue; - } - computeClassificationMetrics = property.Value.GetBoolean(); - continue; - } - if (property.NameEquals("classification_n_classes"u8)) - { - if (property.Value.ValueKind == JsonValueKind.Null) - { - classificationNClasses = null; - continue; - } - classificationNClasses = property.Value.GetInt64(); - continue; - } - if (property.NameEquals("classification_positive_class"u8)) - { - if (property.Value.ValueKind == JsonValueKind.Null) - { - classificationPositiveClass = null; - continue; - } - classificationPositiveClass = property.Value.GetString(); - continue; - } - if (property.NameEquals("classification_betas"u8)) - { - if (property.Value.ValueKind == JsonValueKind.Null) - { - continue; - } - List array = new List(); - foreach (var item in property.Value.EnumerateArray()) - { - array.Add(item.GetDouble()); - } - classificationBetas = array; - continue; - } - if (property.NameEquals("suffix"u8)) - { - if (property.Value.ValueKind == JsonValueKind.Null) - { - suffix = null; - continue; - } - suffix = property.Value.GetString(); - continue; - } - if (options.Format != "W") - { - additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); - } - } - serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateFineTuneRequest(trainingFile, validationFile.Value, OptionalProperty.ToNullable(model), OptionalProperty.ToNullable(nEpochs), OptionalProperty.ToNullable(batchSize), OptionalProperty.ToNullable(learningRateMultiplier), OptionalProperty.ToNullable(promptLossRate), OptionalProperty.ToNullable(computeClassificationMetrics), OptionalProperty.ToNullable(classificationNClasses), classificationPositiveClass.Value, OptionalProperty.ToList(classificationBetas), suffix.Value, serializedAdditionalRawData); - } - - BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - - switch (format) - { - case "J": - return ModelReaderWriter.Write(this, options); - default: - throw new FormatException($"The model {nameof(CreateFineTuneRequest)} does not support '{options.Format}' format."); - } - } - - CreateFineTuneRequest IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - - switch (format) - { - case "J": - { - using JsonDocument document = JsonDocument.Parse(data); - return DeserializeCreateFineTuneRequest(document.RootElement, options); - } - default: - throw new FormatException($"The model {nameof(CreateFineTuneRequest)} does not support '{options.Format}' format."); - } - } - - string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; - - /// Deserializes the model from a raw response. - /// The result to deserialize the model from. - internal static CreateFineTuneRequest FromResponse(PipelineResponse response) - { - using var document = JsonDocument.Parse(response.Content); - return DeserializeCreateFineTuneRequest(document.RootElement); - } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } - } -} diff --git a/.dotnet/src/Generated/Models/CreateFineTuneRequest.cs b/.dotnet/src/Generated/Models/CreateFineTuneRequest.cs deleted file mode 100644 index 31b410dcb..000000000 --- a/.dotnet/src/Generated/Models/CreateFineTuneRequest.cs +++ /dev/null @@ -1,295 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel.Internal; -using System.Collections.Generic; - -namespace OpenAI.Models -{ - /// The CreateFineTuneRequest. - public partial class CreateFineTuneRequest - { - /// - /// Keeps track of any properties unknown to the library. - /// - /// To assign an object to the value of this property use . - /// - /// - /// To assign an already formatted json string to this property use . - /// - /// - /// Examples: - /// - /// - /// BinaryData.FromObjectAsJson("foo") - /// Creates a payload of "foo". - /// - /// - /// BinaryData.FromString("\"foo\"") - /// Creates a payload of "foo". - /// - /// - /// BinaryData.FromObjectAsJson(new { key = "value" }) - /// Creates a payload of { "key": "value" }. - /// - /// - /// BinaryData.FromString("{\"key\": \"value\"}") - /// Creates a payload of { "key": "value" }. - /// - /// - /// - /// - private IDictionary _serializedAdditionalRawData; - - /// Initializes a new instance of . - /// - /// The ID of an uploaded file that contains training data. - /// - /// See [upload file](/docs/api-reference/files/upload) for how to upload a file. - /// - /// Your dataset must be formatted as a JSONL file, where each training example is a JSON object - /// with the keys "prompt" and "completion". Additionally, you must upload your file with the - /// purpose `fine-tune`. - /// - /// See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more - /// details. - /// - /// is null. - public CreateFineTuneRequest(string trainingFile) - { - ClientUtilities.AssertNotNull(trainingFile, nameof(trainingFile)); - - TrainingFile = trainingFile; - ClassificationBetas = new OptionalList(); - } - - /// Initializes a new instance of . - /// - /// The ID of an uploaded file that contains training data. - /// - /// See [upload file](/docs/api-reference/files/upload) for how to upload a file. - /// - /// Your dataset must be formatted as a JSONL file, where each training example is a JSON object - /// with the keys "prompt" and "completion". Additionally, you must upload your file with the - /// purpose `fine-tune`. - /// - /// See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more - /// details. - /// - /// - /// The ID of an uploaded file that contains validation data. - /// - /// If you provide this file, the data is used to generate validation metrics periodically during - /// fine-tuning. These metrics can be viewed in the - /// [fine-tuning results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model). - /// Your train and validation data should be mutually exclusive. - /// - /// Your dataset must be formatted as a JSONL file, where each validation example is a JSON object - /// with the keys "prompt" and "completion". Additionally, you must upload your file with the - /// purpose `fine-tune`. - /// - /// See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more - /// details. - /// - /// - /// The name of the base model to fine-tune. You can select one of "ada", "babbage", "curie", - /// "davinci", or a fine-tuned model created after 2022-04-21 and before 2023-08-22. To learn more - /// about these models, see the [Models](/docs/models) documentation. - /// - /// - /// The number of epochs to train the model for. An epoch refers to one full cycle through the - /// training dataset. - /// - /// - /// The batch size to use for training. The batch size is the number of training examples used to - /// train a single forward and backward pass. - /// - /// By default, the batch size will be dynamically configured to be ~0.2% of the number of examples - /// in the training set, capped at 256 - in general, we've found that larger batch sizes tend to - /// work better for larger datasets. - /// - /// - /// The learning rate multiplier to use for training. The fine-tuning learning rate is the original - /// learning rate used for pretraining multiplied by this value. - /// - /// By default, the learning rate multiplier is the 0.05, 0.1, or 0.2 depending on final - /// `batch_size` (larger learning rates tend to perform better with larger batch sizes). We - /// recommend experimenting with values in the range 0.02 to 0.2 to see what produces the best - /// results. - /// - /// - /// The weight to use for loss on the prompt tokens. This controls how much the model tries to - /// learn to generate the prompt (as compared to the completion which always has a weight of 1.0), - /// and can add a stabilizing effect to training when completions are short. - /// - /// If prompts are extremely long (relative to completions), it may make sense to reduce this - /// weight so as to avoid over-prioritizing learning the prompt. - /// - /// - /// If set, we calculate classification-specific metrics such as accuracy and F-1 score using the - /// validation set at the end of every epoch. These metrics can be viewed in the - /// [results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model). - /// - /// In order to compute classification metrics, you must provide a `validation_file`. Additionally, - /// you must specify `classification_n_classes` for multiclass classification or - /// `classification_positive_class` for binary classification. - /// - /// - /// The number of classes in a classification task. - /// - /// This parameter is required for multiclass classification. - /// - /// - /// The positive class in binary classification. - /// - /// This parameter is needed to generate precision, recall, and F1 metrics when doing binary - /// classification. - /// - /// - /// If this is provided, we calculate F-beta scores at the specified beta values. The F-beta score - /// is a generalization of F-1 score. This is only used for binary classification. - /// - /// With a beta of 1 (i.e. the F-1 score), precision and recall are given the same weight. A larger - /// beta score puts more weight on recall and less on precision. A smaller beta score puts more - /// weight on precision and less on recall. - /// - /// - /// 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 - /// `ada:ft-your-org:custom-model-name-2022-02-15-04-21-04`. - /// - /// Keeps track of any properties unknown to the library. - internal CreateFineTuneRequest(string trainingFile, string validationFile, CreateFineTuneRequestModel? model, long? nEpochs, long? batchSize, double? learningRateMultiplier, double? promptLossRate, bool? computeClassificationMetrics, long? classificationNClasses, string classificationPositiveClass, IList classificationBetas, string suffix, IDictionary serializedAdditionalRawData) - { - TrainingFile = trainingFile; - ValidationFile = validationFile; - Model = model; - NEpochs = nEpochs; - BatchSize = batchSize; - LearningRateMultiplier = learningRateMultiplier; - PromptLossRate = promptLossRate; - ComputeClassificationMetrics = computeClassificationMetrics; - ClassificationNClasses = classificationNClasses; - ClassificationPositiveClass = classificationPositiveClass; - ClassificationBetas = classificationBetas; - Suffix = suffix; - _serializedAdditionalRawData = serializedAdditionalRawData; - } - - /// Initializes a new instance of for deserialization. - internal CreateFineTuneRequest() - { - } - - /// - /// The ID of an uploaded file that contains training data. - /// - /// See [upload file](/docs/api-reference/files/upload) for how to upload a file. - /// - /// Your dataset must be formatted as a JSONL file, where each training example is a JSON object - /// with the keys "prompt" and "completion". Additionally, you must upload your file with the - /// purpose `fine-tune`. - /// - /// See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more - /// details. - /// - public string TrainingFile { get; } - /// - /// The ID of an uploaded file that contains validation data. - /// - /// If you provide this file, the data is used to generate validation metrics periodically during - /// fine-tuning. These metrics can be viewed in the - /// [fine-tuning results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model). - /// Your train and validation data should be mutually exclusive. - /// - /// Your dataset must be formatted as a JSONL file, where each validation example is a JSON object - /// with the keys "prompt" and "completion". Additionally, you must upload your file with the - /// purpose `fine-tune`. - /// - /// See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more - /// details. - /// - public string ValidationFile { get; set; } - /// - /// The name of the base model to fine-tune. You can select one of "ada", "babbage", "curie", - /// "davinci", or a fine-tuned model created after 2022-04-21 and before 2023-08-22. To learn more - /// about these models, see the [Models](/docs/models) documentation. - /// - public CreateFineTuneRequestModel? Model { get; set; } - /// - /// The number of epochs to train the model for. An epoch refers to one full cycle through the - /// training dataset. - /// - public long? NEpochs { get; set; } - /// - /// The batch size to use for training. The batch size is the number of training examples used to - /// train a single forward and backward pass. - /// - /// By default, the batch size will be dynamically configured to be ~0.2% of the number of examples - /// in the training set, capped at 256 - in general, we've found that larger batch sizes tend to - /// work better for larger datasets. - /// - public long? BatchSize { get; set; } - /// - /// The learning rate multiplier to use for training. The fine-tuning learning rate is the original - /// learning rate used for pretraining multiplied by this value. - /// - /// By default, the learning rate multiplier is the 0.05, 0.1, or 0.2 depending on final - /// `batch_size` (larger learning rates tend to perform better with larger batch sizes). We - /// recommend experimenting with values in the range 0.02 to 0.2 to see what produces the best - /// results. - /// - public double? LearningRateMultiplier { get; set; } - /// - /// The weight to use for loss on the prompt tokens. This controls how much the model tries to - /// learn to generate the prompt (as compared to the completion which always has a weight of 1.0), - /// and can add a stabilizing effect to training when completions are short. - /// - /// If prompts are extremely long (relative to completions), it may make sense to reduce this - /// weight so as to avoid over-prioritizing learning the prompt. - /// - public double? PromptLossRate { get; set; } - /// - /// If set, we calculate classification-specific metrics such as accuracy and F-1 score using the - /// validation set at the end of every epoch. These metrics can be viewed in the - /// [results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model). - /// - /// In order to compute classification metrics, you must provide a `validation_file`. Additionally, - /// you must specify `classification_n_classes` for multiclass classification or - /// `classification_positive_class` for binary classification. - /// - public bool? ComputeClassificationMetrics { get; set; } - /// - /// The number of classes in a classification task. - /// - /// This parameter is required for multiclass classification. - /// - public long? ClassificationNClasses { get; set; } - /// - /// The positive class in binary classification. - /// - /// This parameter is needed to generate precision, recall, and F1 metrics when doing binary - /// classification. - /// - public string ClassificationPositiveClass { get; set; } - /// - /// If this is provided, we calculate F-beta scores at the specified beta values. The F-beta score - /// is a generalization of F-1 score. This is only used for binary classification. - /// - /// With a beta of 1 (i.e. the F-1 score), precision and recall are given the same weight. A larger - /// beta score puts more weight on recall and less on precision. A smaller beta score puts more - /// weight on precision and less on recall. - /// - public IList ClassificationBetas { get; set; } - /// - /// 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 - /// `ada:ft-your-org:custom-model-name-2022-02-15-04-21-04`. - /// - public string Suffix { get; set; } - } -} diff --git a/.dotnet/src/Generated/Models/CreateFineTuneRequestModel.cs b/.dotnet/src/Generated/Models/CreateFineTuneRequestModel.cs deleted file mode 100644 index de5b6f368..000000000 --- a/.dotnet/src/Generated/Models/CreateFineTuneRequestModel.cs +++ /dev/null @@ -1,54 +0,0 @@ -// - -#nullable disable - -using System; -using System.ComponentModel; - -namespace OpenAI.Models -{ - /// Enum for model in CreateFineTuneRequest. - public readonly partial struct CreateFineTuneRequestModel : IEquatable - { - private readonly string _value; - - /// Initializes a new instance of . - /// is null. - public CreateFineTuneRequestModel(string value) - { - _value = value ?? throw new ArgumentNullException(nameof(value)); - } - - private const string AdaValue = "ada"; - private const string BabbageValue = "babbage"; - private const string CurieValue = "curie"; - private const string DavinciValue = "davinci"; - - /// ada. - public static CreateFineTuneRequestModel Ada { get; } = new CreateFineTuneRequestModel(AdaValue); - /// babbage. - public static CreateFineTuneRequestModel Babbage { get; } = new CreateFineTuneRequestModel(BabbageValue); - /// curie. - public static CreateFineTuneRequestModel Curie { get; } = new CreateFineTuneRequestModel(CurieValue); - /// davinci. - public static CreateFineTuneRequestModel Davinci { get; } = new CreateFineTuneRequestModel(DavinciValue); - /// Determines if two values are the same. - public static bool operator ==(CreateFineTuneRequestModel left, CreateFineTuneRequestModel right) => left.Equals(right); - /// Determines if two values are not the same. - public static bool operator !=(CreateFineTuneRequestModel left, CreateFineTuneRequestModel right) => !left.Equals(right); - /// Converts a string to a . - public static implicit operator CreateFineTuneRequestModel(string value) => new CreateFineTuneRequestModel(value); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public override bool Equals(object obj) => obj is CreateFineTuneRequestModel other && Equals(other); - /// - public bool Equals(CreateFineTuneRequestModel other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public override int GetHashCode() => _value?.GetHashCode() ?? 0; - /// - public override string ToString() => _value; - } -} diff --git a/.dotnet/src/Generated/Models/FineTune.Serialization.cs b/.dotnet/src/Generated/Models/FineTune.Serialization.cs deleted file mode 100644 index cdbb27bb0..000000000 --- a/.dotnet/src/Generated/Models/FineTune.Serialization.cs +++ /dev/null @@ -1,287 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel.Internal; -using System.ClientModel.Primitives; -using System.Collections.Generic; -using System.Text.Json; - -namespace OpenAI.Models -{ - public partial class FineTune : IUtf8JsonWriteable, IJsonModel - { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - if (format != "J") - { - throw new FormatException($"The model {nameof(FineTune)} does not support '{format}' format."); - } - - writer.WriteStartObject(); - writer.WritePropertyName("id"u8); - writer.WriteStringValue(Id); - writer.WritePropertyName("object"u8); - writer.WriteStringValue(Object.ToString()); - writer.WritePropertyName("created_at"u8); - writer.WriteNumberValue(CreatedAt, "U"); - writer.WritePropertyName("updated_at"u8); - writer.WriteNumberValue(UpdatedAt, "U"); - writer.WritePropertyName("model"u8); - writer.WriteStringValue(Model); - if (FineTunedModel != null) - { - writer.WritePropertyName("fine_tuned_model"u8); - writer.WriteStringValue(FineTunedModel); - } - else - { - writer.WriteNull("fine_tuned_model"); - } - writer.WritePropertyName("organization_id"u8); - writer.WriteStringValue(OrganizationId); - writer.WritePropertyName("status"u8); - writer.WriteStringValue(Status.ToString()); - writer.WritePropertyName("hyperparams"u8); - writer.WriteObjectValue(Hyperparams); - writer.WritePropertyName("training_files"u8); - writer.WriteStartArray(); - foreach (var item in TrainingFiles) - { - writer.WriteObjectValue(item); - } - writer.WriteEndArray(); - writer.WritePropertyName("validation_files"u8); - writer.WriteStartArray(); - foreach (var item in ValidationFiles) - { - writer.WriteObjectValue(item); - } - writer.WriteEndArray(); - writer.WritePropertyName("result_files"u8); - writer.WriteStartArray(); - foreach (var item in ResultFiles) - { - writer.WriteObjectValue(item); - } - writer.WriteEndArray(); - if (OptionalProperty.IsCollectionDefined(Events)) - { - writer.WritePropertyName("events"u8); - writer.WriteStartArray(); - foreach (var item in Events) - { - writer.WriteObjectValue(item); - } - writer.WriteEndArray(); - } - if (options.Format != "W" && _serializedAdditionalRawData != null) - { - foreach (var item in _serializedAdditionalRawData) - { - writer.WritePropertyName(item.Key); -#if NET6_0_OR_GREATER - writer.WriteRawValue(item.Value); -#else - using (JsonDocument document = JsonDocument.Parse(item.Value)) - { - JsonSerializer.Serialize(writer, document.RootElement); - } -#endif - } - } - writer.WriteEndObject(); - } - - FineTune IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - if (format != "J") - { - throw new FormatException($"The model {nameof(FineTune)} does not support '{format}' format."); - } - - using JsonDocument document = JsonDocument.ParseValue(ref reader); - return DeserializeFineTune(document.RootElement, options); - } - - internal static FineTune DeserializeFineTune(JsonElement element, ModelReaderWriterOptions options = null) - { - options ??= new ModelReaderWriterOptions("W"); - - if (element.ValueKind == JsonValueKind.Null) - { - return null; - } - string id = default; - FineTuneObject @object = default; - DateTimeOffset createdAt = default; - DateTimeOffset updatedAt = default; - string model = default; - string fineTunedModel = default; - string organizationId = default; - FineTuneStatus status = default; - FineTuneHyperparams hyperparams = default; - IReadOnlyList trainingFiles = default; - IReadOnlyList validationFiles = default; - IReadOnlyList resultFiles = default; - OptionalProperty> events = default; - IDictionary serializedAdditionalRawData = default; - Dictionary additionalPropertiesDictionary = new Dictionary(); - foreach (var property in element.EnumerateObject()) - { - if (property.NameEquals("id"u8)) - { - id = property.Value.GetString(); - continue; - } - if (property.NameEquals("object"u8)) - { - @object = new FineTuneObject(property.Value.GetString()); - continue; - } - if (property.NameEquals("created_at"u8)) - { - createdAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); - continue; - } - if (property.NameEquals("updated_at"u8)) - { - updatedAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); - continue; - } - if (property.NameEquals("model"u8)) - { - model = property.Value.GetString(); - continue; - } - if (property.NameEquals("fine_tuned_model"u8)) - { - if (property.Value.ValueKind == JsonValueKind.Null) - { - fineTunedModel = null; - continue; - } - fineTunedModel = property.Value.GetString(); - continue; - } - if (property.NameEquals("organization_id"u8)) - { - organizationId = property.Value.GetString(); - continue; - } - if (property.NameEquals("status"u8)) - { - status = new FineTuneStatus(property.Value.GetString()); - continue; - } - if (property.NameEquals("hyperparams"u8)) - { - hyperparams = FineTuneHyperparams.DeserializeFineTuneHyperparams(property.Value); - continue; - } - if (property.NameEquals("training_files"u8)) - { - List array = new List(); - foreach (var item in property.Value.EnumerateArray()) - { - array.Add(OpenAIFile.DeserializeOpenAIFile(item)); - } - trainingFiles = array; - continue; - } - if (property.NameEquals("validation_files"u8)) - { - List array = new List(); - foreach (var item in property.Value.EnumerateArray()) - { - array.Add(OpenAIFile.DeserializeOpenAIFile(item)); - } - validationFiles = array; - continue; - } - if (property.NameEquals("result_files"u8)) - { - List array = new List(); - foreach (var item in property.Value.EnumerateArray()) - { - array.Add(OpenAIFile.DeserializeOpenAIFile(item)); - } - resultFiles = array; - continue; - } - if (property.NameEquals("events"u8)) - { - if (property.Value.ValueKind == JsonValueKind.Null) - { - continue; - } - List array = new List(); - foreach (var item in property.Value.EnumerateArray()) - { - array.Add(FineTuneEvent.DeserializeFineTuneEvent(item)); - } - events = array; - continue; - } - if (options.Format != "W") - { - additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); - } - } - serializedAdditionalRawData = additionalPropertiesDictionary; - return new FineTune(id, @object, createdAt, updatedAt, model, fineTunedModel, organizationId, status, hyperparams, trainingFiles, validationFiles, resultFiles, OptionalProperty.ToList(events), serializedAdditionalRawData); - } - - BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - - switch (format) - { - case "J": - return ModelReaderWriter.Write(this, options); - default: - throw new FormatException($"The model {nameof(FineTune)} does not support '{options.Format}' format."); - } - } - - FineTune IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - - switch (format) - { - case "J": - { - using JsonDocument document = JsonDocument.Parse(data); - return DeserializeFineTune(document.RootElement, options); - } - default: - throw new FormatException($"The model {nameof(FineTune)} does not support '{options.Format}' format."); - } - } - - string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; - - /// Deserializes the model from a raw response. - /// The result to deserialize the model from. - internal static FineTune FromResponse(PipelineResponse response) - { - using var document = JsonDocument.Parse(response.Content); - return DeserializeFineTune(document.RootElement); - } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } - } -} diff --git a/.dotnet/src/Generated/Models/FineTune.cs b/.dotnet/src/Generated/Models/FineTune.cs deleted file mode 100644 index 6300b6a99..000000000 --- a/.dotnet/src/Generated/Models/FineTune.cs +++ /dev/null @@ -1,169 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel.Internal; -using System.Collections.Generic; -using System.Linq; - -namespace OpenAI.Models -{ - /// The `FineTune` object represents a legacy fine-tune job that has been created through the API. - [Obsolete("deprecated")] - public partial class FineTune - { - /// - /// Keeps track of any properties unknown to the library. - /// - /// To assign an object to the value of this property use . - /// - /// - /// To assign an already formatted json string to this property use . - /// - /// - /// Examples: - /// - /// - /// BinaryData.FromObjectAsJson("foo") - /// Creates a payload of "foo". - /// - /// - /// BinaryData.FromString("\"foo\"") - /// Creates a payload of "foo". - /// - /// - /// BinaryData.FromObjectAsJson(new { key = "value" }) - /// Creates a payload of { "key": "value" }. - /// - /// - /// BinaryData.FromString("{\"key\": \"value\"}") - /// Creates a payload of { "key": "value" }. - /// - /// - /// - /// - private IDictionary _serializedAdditionalRawData; - - /// Initializes a new instance of . - /// The object identifier, which can be referenced in the API endpoints. - /// The Unix timestamp (in seconds) for when the fine-tuning job was created. - /// The Unix timestamp (in seconds) for when the fine-tuning job was last updated. - /// The base model that is being fine-tuned. - /// The name of the fine-tuned model that is being created. - /// The organization that owns the fine-tuning job. - /// - /// The current status of the fine-tuning job, which can be either `created`, `running`, - /// `succeeded`, `failed`, or `cancelled`. - /// - /// - /// The hyperparameters used for the fine-tuning job. See the - /// [fine-tuning guide](/docs/guides/legacy-fine-tuning/hyperparameters) for more details. - /// - /// The list of files used for training. - /// The list of files used for validation. - /// The compiled results files for the fine-tuning job. - /// , , , , , or is null. - internal FineTune(string id, DateTimeOffset createdAt, DateTimeOffset updatedAt, string model, string fineTunedModel, string organizationId, FineTuneStatus status, FineTuneHyperparams hyperparams, IEnumerable trainingFiles, IEnumerable validationFiles, IEnumerable resultFiles) - { - ClientUtilities.AssertNotNull(id, nameof(id)); - ClientUtilities.AssertNotNull(model, nameof(model)); - ClientUtilities.AssertNotNull(organizationId, nameof(organizationId)); - ClientUtilities.AssertNotNull(hyperparams, nameof(hyperparams)); - ClientUtilities.AssertNotNull(trainingFiles, nameof(trainingFiles)); - ClientUtilities.AssertNotNull(validationFiles, nameof(validationFiles)); - ClientUtilities.AssertNotNull(resultFiles, nameof(resultFiles)); - - Id = id; - CreatedAt = createdAt; - UpdatedAt = updatedAt; - Model = model; - FineTunedModel = fineTunedModel; - OrganizationId = organizationId; - Status = status; - Hyperparams = hyperparams; - TrainingFiles = trainingFiles.ToList(); - ValidationFiles = validationFiles.ToList(); - ResultFiles = resultFiles.ToList(); - Events = new OptionalList(); - } - - /// Initializes a new instance of . - /// The object identifier, which can be referenced in the API endpoints. - /// The object type, which is always "fine-tune". - /// The Unix timestamp (in seconds) for when the fine-tuning job was created. - /// The Unix timestamp (in seconds) for when the fine-tuning job was last updated. - /// The base model that is being fine-tuned. - /// The name of the fine-tuned model that is being created. - /// The organization that owns the fine-tuning job. - /// - /// The current status of the fine-tuning job, which can be either `created`, `running`, - /// `succeeded`, `failed`, or `cancelled`. - /// - /// - /// The hyperparameters used for the fine-tuning job. See the - /// [fine-tuning guide](/docs/guides/legacy-fine-tuning/hyperparameters) for more details. - /// - /// The list of files used for training. - /// The list of files used for validation. - /// The compiled results files for the fine-tuning job. - /// The list of events that have been observed in the lifecycle of the FineTune job. - /// Keeps track of any properties unknown to the library. - internal FineTune(string id, FineTuneObject @object, DateTimeOffset createdAt, DateTimeOffset updatedAt, string model, string fineTunedModel, string organizationId, FineTuneStatus status, FineTuneHyperparams hyperparams, IReadOnlyList trainingFiles, IReadOnlyList validationFiles, IReadOnlyList resultFiles, IReadOnlyList events, IDictionary serializedAdditionalRawData) - { - Id = id; - Object = @object; - CreatedAt = createdAt; - UpdatedAt = updatedAt; - Model = model; - FineTunedModel = fineTunedModel; - OrganizationId = organizationId; - Status = status; - Hyperparams = hyperparams; - TrainingFiles = trainingFiles; - ValidationFiles = validationFiles; - ResultFiles = resultFiles; - Events = events; - _serializedAdditionalRawData = serializedAdditionalRawData; - } - - /// Initializes a new instance of for deserialization. - internal FineTune() - { - } - - /// The object identifier, which can be referenced in the API endpoints. - public string Id { get; } - /// The object type, which is always "fine-tune". - public FineTuneObject Object { get; } = FineTuneObject.FineTune; - - /// The Unix timestamp (in seconds) for when the fine-tuning job was created. - public DateTimeOffset CreatedAt { get; } - /// The Unix timestamp (in seconds) for when the fine-tuning job was last updated. - public DateTimeOffset UpdatedAt { get; } - /// The base model that is being fine-tuned. - public string Model { get; } - /// The name of the fine-tuned model that is being created. - public string FineTunedModel { get; } - /// The organization that owns the fine-tuning job. - public string OrganizationId { get; } - /// - /// The current status of the fine-tuning job, which can be either `created`, `running`, - /// `succeeded`, `failed`, or `cancelled`. - /// - public FineTuneStatus Status { get; } - /// - /// The hyperparameters used for the fine-tuning job. See the - /// [fine-tuning guide](/docs/guides/legacy-fine-tuning/hyperparameters) for more details. - /// - public FineTuneHyperparams Hyperparams { get; } - /// The list of files used for training. - public IReadOnlyList TrainingFiles { get; } - /// The list of files used for validation. - public IReadOnlyList ValidationFiles { get; } - /// The compiled results files for the fine-tuning job. - public IReadOnlyList ResultFiles { get; } - /// The list of events that have been observed in the lifecycle of the FineTune job. - public IReadOnlyList Events { get; } - } -} diff --git a/.dotnet/src/Generated/Models/FineTuneEvent.Serialization.cs b/.dotnet/src/Generated/Models/FineTuneEvent.Serialization.cs deleted file mode 100644 index 185b9830f..000000000 --- a/.dotnet/src/Generated/Models/FineTuneEvent.Serialization.cs +++ /dev/null @@ -1,156 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel.Internal; -using System.ClientModel.Primitives; -using System.Collections.Generic; -using System.Text.Json; - -namespace OpenAI.Models -{ - public partial class FineTuneEvent : IUtf8JsonWriteable, IJsonModel - { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - if (format != "J") - { - throw new FormatException($"The model {nameof(FineTuneEvent)} does not support '{format}' format."); - } - - writer.WriteStartObject(); - writer.WritePropertyName("object"u8); - writer.WriteStringValue(Object); - writer.WritePropertyName("created_at"u8); - writer.WriteNumberValue(CreatedAt, "U"); - writer.WritePropertyName("level"u8); - writer.WriteStringValue(Level); - writer.WritePropertyName("message"u8); - writer.WriteStringValue(Message); - if (options.Format != "W" && _serializedAdditionalRawData != null) - { - foreach (var item in _serializedAdditionalRawData) - { - writer.WritePropertyName(item.Key); -#if NET6_0_OR_GREATER - writer.WriteRawValue(item.Value); -#else - using (JsonDocument document = JsonDocument.Parse(item.Value)) - { - JsonSerializer.Serialize(writer, document.RootElement); - } -#endif - } - } - writer.WriteEndObject(); - } - - FineTuneEvent IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - if (format != "J") - { - throw new FormatException($"The model {nameof(FineTuneEvent)} does not support '{format}' format."); - } - - using JsonDocument document = JsonDocument.ParseValue(ref reader); - return DeserializeFineTuneEvent(document.RootElement, options); - } - - internal static FineTuneEvent DeserializeFineTuneEvent(JsonElement element, ModelReaderWriterOptions options = null) - { - options ??= new ModelReaderWriterOptions("W"); - - if (element.ValueKind == JsonValueKind.Null) - { - return null; - } - string @object = default; - DateTimeOffset createdAt = default; - string level = default; - string message = default; - IDictionary serializedAdditionalRawData = default; - Dictionary additionalPropertiesDictionary = new Dictionary(); - foreach (var property in element.EnumerateObject()) - { - if (property.NameEquals("object"u8)) - { - @object = property.Value.GetString(); - continue; - } - if (property.NameEquals("created_at"u8)) - { - createdAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); - continue; - } - if (property.NameEquals("level"u8)) - { - level = property.Value.GetString(); - continue; - } - if (property.NameEquals("message"u8)) - { - message = property.Value.GetString(); - continue; - } - if (options.Format != "W") - { - additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); - } - } - serializedAdditionalRawData = additionalPropertiesDictionary; - return new FineTuneEvent(@object, createdAt, level, message, serializedAdditionalRawData); - } - - BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - - switch (format) - { - case "J": - return ModelReaderWriter.Write(this, options); - default: - throw new FormatException($"The model {nameof(FineTuneEvent)} does not support '{options.Format}' format."); - } - } - - FineTuneEvent IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - - switch (format) - { - case "J": - { - using JsonDocument document = JsonDocument.Parse(data); - return DeserializeFineTuneEvent(document.RootElement, options); - } - default: - throw new FormatException($"The model {nameof(FineTuneEvent)} does not support '{options.Format}' format."); - } - } - - string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; - - /// Deserializes the model from a raw response. - /// The result to deserialize the model from. - internal static FineTuneEvent FromResponse(PipelineResponse response) - { - using var document = JsonDocument.Parse(response.Content); - return DeserializeFineTuneEvent(document.RootElement); - } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } - } -} diff --git a/.dotnet/src/Generated/Models/FineTuneEvent.cs b/.dotnet/src/Generated/Models/FineTuneEvent.cs deleted file mode 100644 index dcf13faa4..000000000 --- a/.dotnet/src/Generated/Models/FineTuneEvent.cs +++ /dev/null @@ -1,93 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel.Internal; -using System.Collections.Generic; - -namespace OpenAI.Models -{ - /// The FineTuneEvent. - public partial class FineTuneEvent - { - /// - /// Keeps track of any properties unknown to the library. - /// - /// To assign an object to the value of this property use . - /// - /// - /// To assign an already formatted json string to this property use . - /// - /// - /// Examples: - /// - /// - /// BinaryData.FromObjectAsJson("foo") - /// Creates a payload of "foo". - /// - /// - /// BinaryData.FromString("\"foo\"") - /// Creates a payload of "foo". - /// - /// - /// BinaryData.FromObjectAsJson(new { key = "value" }) - /// Creates a payload of { "key": "value" }. - /// - /// - /// BinaryData.FromString("{\"key\": \"value\"}") - /// Creates a payload of { "key": "value" }. - /// - /// - /// - /// - private IDictionary _serializedAdditionalRawData; - - /// Initializes a new instance of . - /// - /// - /// - /// - /// , or is null. - internal FineTuneEvent(string @object, DateTimeOffset createdAt, string level, string message) - { - ClientUtilities.AssertNotNull(@object, nameof(@object)); - ClientUtilities.AssertNotNull(level, nameof(level)); - ClientUtilities.AssertNotNull(message, nameof(message)); - - Object = @object; - CreatedAt = createdAt; - Level = level; - Message = message; - } - - /// Initializes a new instance of . - /// - /// - /// - /// - /// Keeps track of any properties unknown to the library. - internal FineTuneEvent(string @object, DateTimeOffset createdAt, string level, string message, IDictionary serializedAdditionalRawData) - { - Object = @object; - CreatedAt = createdAt; - Level = level; - Message = message; - _serializedAdditionalRawData = serializedAdditionalRawData; - } - - /// Initializes a new instance of for deserialization. - internal FineTuneEvent() - { - } - - /// Gets the object. - public string Object { get; } - /// Gets the created at. - public DateTimeOffset CreatedAt { get; } - /// Gets the level. - public string Level { get; } - /// Gets the message. - public string Message { get; } - } -} diff --git a/.dotnet/src/Generated/Models/FineTuneHyperparams.Serialization.cs b/.dotnet/src/Generated/Models/FineTuneHyperparams.Serialization.cs deleted file mode 100644 index 8e6588b67..000000000 --- a/.dotnet/src/Generated/Models/FineTuneHyperparams.Serialization.cs +++ /dev/null @@ -1,197 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel.Internal; -using System.ClientModel.Primitives; -using System.Collections.Generic; -using System.Text.Json; - -namespace OpenAI.Models -{ - public partial class FineTuneHyperparams : IUtf8JsonWriteable, IJsonModel - { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - if (format != "J") - { - throw new FormatException($"The model {nameof(FineTuneHyperparams)} does not support '{format}' format."); - } - - writer.WriteStartObject(); - writer.WritePropertyName("n_epochs"u8); - writer.WriteNumberValue(NEpochs); - writer.WritePropertyName("batch_size"u8); - writer.WriteNumberValue(BatchSize); - writer.WritePropertyName("prompt_loss_weight"u8); - writer.WriteNumberValue(PromptLossWeight); - writer.WritePropertyName("learning_rate_multiplier"u8); - writer.WriteNumberValue(LearningRateMultiplier); - if (OptionalProperty.IsDefined(ComputeClassificationMetrics)) - { - writer.WritePropertyName("compute_classification_metrics"u8); - writer.WriteBooleanValue(ComputeClassificationMetrics.Value); - } - if (OptionalProperty.IsDefined(ClassificationPositiveClass)) - { - writer.WritePropertyName("classification_positive_class"u8); - writer.WriteStringValue(ClassificationPositiveClass); - } - if (OptionalProperty.IsDefined(ClassificationNClasses)) - { - writer.WritePropertyName("classification_n_classes"u8); - writer.WriteNumberValue(ClassificationNClasses.Value); - } - if (options.Format != "W" && _serializedAdditionalRawData != null) - { - foreach (var item in _serializedAdditionalRawData) - { - writer.WritePropertyName(item.Key); -#if NET6_0_OR_GREATER - writer.WriteRawValue(item.Value); -#else - using (JsonDocument document = JsonDocument.Parse(item.Value)) - { - JsonSerializer.Serialize(writer, document.RootElement); - } -#endif - } - } - writer.WriteEndObject(); - } - - FineTuneHyperparams IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - if (format != "J") - { - throw new FormatException($"The model {nameof(FineTuneHyperparams)} does not support '{format}' format."); - } - - using JsonDocument document = JsonDocument.ParseValue(ref reader); - return DeserializeFineTuneHyperparams(document.RootElement, options); - } - - internal static FineTuneHyperparams DeserializeFineTuneHyperparams(JsonElement element, ModelReaderWriterOptions options = null) - { - options ??= new ModelReaderWriterOptions("W"); - - if (element.ValueKind == JsonValueKind.Null) - { - return null; - } - long nEpochs = default; - long batchSize = default; - double promptLossWeight = default; - double learningRateMultiplier = default; - OptionalProperty computeClassificationMetrics = default; - OptionalProperty classificationPositiveClass = default; - OptionalProperty classificationNClasses = default; - IDictionary serializedAdditionalRawData = default; - Dictionary additionalPropertiesDictionary = new Dictionary(); - foreach (var property in element.EnumerateObject()) - { - if (property.NameEquals("n_epochs"u8)) - { - nEpochs = property.Value.GetInt64(); - continue; - } - if (property.NameEquals("batch_size"u8)) - { - batchSize = property.Value.GetInt64(); - continue; - } - if (property.NameEquals("prompt_loss_weight"u8)) - { - promptLossWeight = property.Value.GetDouble(); - continue; - } - if (property.NameEquals("learning_rate_multiplier"u8)) - { - learningRateMultiplier = property.Value.GetDouble(); - continue; - } - if (property.NameEquals("compute_classification_metrics"u8)) - { - if (property.Value.ValueKind == JsonValueKind.Null) - { - continue; - } - computeClassificationMetrics = property.Value.GetBoolean(); - continue; - } - if (property.NameEquals("classification_positive_class"u8)) - { - classificationPositiveClass = property.Value.GetString(); - continue; - } - if (property.NameEquals("classification_n_classes"u8)) - { - if (property.Value.ValueKind == JsonValueKind.Null) - { - continue; - } - classificationNClasses = property.Value.GetInt64(); - continue; - } - if (options.Format != "W") - { - additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); - } - } - serializedAdditionalRawData = additionalPropertiesDictionary; - return new FineTuneHyperparams(nEpochs, batchSize, promptLossWeight, learningRateMultiplier, OptionalProperty.ToNullable(computeClassificationMetrics), classificationPositiveClass.Value, OptionalProperty.ToNullable(classificationNClasses), serializedAdditionalRawData); - } - - BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - - switch (format) - { - case "J": - return ModelReaderWriter.Write(this, options); - default: - throw new FormatException($"The model {nameof(FineTuneHyperparams)} does not support '{options.Format}' format."); - } - } - - FineTuneHyperparams IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - - switch (format) - { - case "J": - { - using JsonDocument document = JsonDocument.Parse(data); - return DeserializeFineTuneHyperparams(document.RootElement, options); - } - default: - throw new FormatException($"The model {nameof(FineTuneHyperparams)} does not support '{options.Format}' format."); - } - } - - string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; - - /// Deserializes the model from a raw response. - /// The result to deserialize the model from. - internal static FineTuneHyperparams FromResponse(PipelineResponse response) - { - using var document = JsonDocument.Parse(response.Content); - return DeserializeFineTuneHyperparams(document.RootElement); - } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } - } -} diff --git a/.dotnet/src/Generated/Models/FineTuneHyperparams.cs b/.dotnet/src/Generated/Models/FineTuneHyperparams.cs deleted file mode 100644 index f45f7fe7a..000000000 --- a/.dotnet/src/Generated/Models/FineTuneHyperparams.cs +++ /dev/null @@ -1,117 +0,0 @@ -// - -#nullable disable - -using System; -using System.Collections.Generic; - -namespace OpenAI.Models -{ - /// The FineTuneHyperparams. - public partial class FineTuneHyperparams - { - /// - /// Keeps track of any properties unknown to the library. - /// - /// To assign an object to the value of this property use . - /// - /// - /// To assign an already formatted json string to this property use . - /// - /// - /// Examples: - /// - /// - /// BinaryData.FromObjectAsJson("foo") - /// Creates a payload of "foo". - /// - /// - /// BinaryData.FromString("\"foo\"") - /// Creates a payload of "foo". - /// - /// - /// BinaryData.FromObjectAsJson(new { key = "value" }) - /// Creates a payload of { "key": "value" }. - /// - /// - /// BinaryData.FromString("{\"key\": \"value\"}") - /// Creates a payload of { "key": "value" }. - /// - /// - /// - /// - private IDictionary _serializedAdditionalRawData; - - /// Initializes a new instance of . - /// - /// The number of epochs to train the model for. An epoch refers to one full cycle through the - /// training dataset. - /// - /// - /// The batch size to use for training. The batch size is the number of training examples used to - /// train a single forward and backward pass. - /// - /// The weight to use for loss on the prompt tokens. - /// The learning rate multiplier to use for training. - internal FineTuneHyperparams(long nEpochs, long batchSize, double promptLossWeight, double learningRateMultiplier) - { - NEpochs = nEpochs; - BatchSize = batchSize; - PromptLossWeight = promptLossWeight; - LearningRateMultiplier = learningRateMultiplier; - } - - /// Initializes a new instance of . - /// - /// The number of epochs to train the model for. An epoch refers to one full cycle through the - /// training dataset. - /// - /// - /// The batch size to use for training. The batch size is the number of training examples used to - /// train a single forward and backward pass. - /// - /// The weight to use for loss on the prompt tokens. - /// The learning rate multiplier to use for training. - /// The classification metrics to compute using the validation dataset at the end of every epoch. - /// The positive class to use for computing classification metrics. - /// The number of classes to use for computing classification metrics. - /// Keeps track of any properties unknown to the library. - internal FineTuneHyperparams(long nEpochs, long batchSize, double promptLossWeight, double learningRateMultiplier, bool? computeClassificationMetrics, string classificationPositiveClass, long? classificationNClasses, IDictionary serializedAdditionalRawData) - { - NEpochs = nEpochs; - BatchSize = batchSize; - PromptLossWeight = promptLossWeight; - LearningRateMultiplier = learningRateMultiplier; - ComputeClassificationMetrics = computeClassificationMetrics; - ClassificationPositiveClass = classificationPositiveClass; - ClassificationNClasses = classificationNClasses; - _serializedAdditionalRawData = serializedAdditionalRawData; - } - - /// Initializes a new instance of for deserialization. - internal FineTuneHyperparams() - { - } - - /// - /// The number of epochs to train the model for. An epoch refers to one full cycle through the - /// training dataset. - /// - public long NEpochs { get; } - /// - /// The batch size to use for training. The batch size is the number of training examples used to - /// train a single forward and backward pass. - /// - public long BatchSize { get; } - /// The weight to use for loss on the prompt tokens. - public double PromptLossWeight { get; } - /// The learning rate multiplier to use for training. - public double LearningRateMultiplier { get; } - /// The classification metrics to compute using the validation dataset at the end of every epoch. - public bool? ComputeClassificationMetrics { get; } - /// The positive class to use for computing classification metrics. - public string ClassificationPositiveClass { get; } - /// The number of classes to use for computing classification metrics. - public long? ClassificationNClasses { get; } - } -} diff --git a/.dotnet/src/Generated/Models/FineTuneObject.cs b/.dotnet/src/Generated/Models/FineTuneObject.cs deleted file mode 100644 index 7c848fe16..000000000 --- a/.dotnet/src/Generated/Models/FineTuneObject.cs +++ /dev/null @@ -1,45 +0,0 @@ -// - -#nullable disable - -using System; -using System.ComponentModel; - -namespace OpenAI.Models -{ - /// The FineTune_object. - public readonly partial struct FineTuneObject : IEquatable - { - private readonly string _value; - - /// Initializes a new instance of . - /// is null. - public FineTuneObject(string value) - { - _value = value ?? throw new ArgumentNullException(nameof(value)); - } - - private const string FineTuneValue = "fine-tune"; - - /// fine-tune. - public static FineTuneObject FineTune { get; } = new FineTuneObject(FineTuneValue); - /// Determines if two values are the same. - public static bool operator ==(FineTuneObject left, FineTuneObject right) => left.Equals(right); - /// Determines if two values are not the same. - public static bool operator !=(FineTuneObject left, FineTuneObject right) => !left.Equals(right); - /// Converts a string to a . - public static implicit operator FineTuneObject(string value) => new FineTuneObject(value); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public override bool Equals(object obj) => obj is FineTuneObject other && Equals(other); - /// - public bool Equals(FineTuneObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public override int GetHashCode() => _value?.GetHashCode() ?? 0; - /// - public override string ToString() => _value; - } -} diff --git a/.dotnet/src/Generated/Models/FineTuneStatus.cs b/.dotnet/src/Generated/Models/FineTuneStatus.cs deleted file mode 100644 index 00121f091..000000000 --- a/.dotnet/src/Generated/Models/FineTuneStatus.cs +++ /dev/null @@ -1,57 +0,0 @@ -// - -#nullable disable - -using System; -using System.ComponentModel; - -namespace OpenAI.Models -{ - /// Enum for status in FineTune. - public readonly partial struct FineTuneStatus : IEquatable - { - private readonly string _value; - - /// Initializes a new instance of . - /// is null. - public FineTuneStatus(string value) - { - _value = value ?? throw new ArgumentNullException(nameof(value)); - } - - private const string CreatedValue = "created"; - private const string RunningValue = "running"; - private const string SucceededValue = "succeeded"; - private const string FailedValue = "failed"; - private const string CancelledValue = "cancelled"; - - /// created. - public static FineTuneStatus Created { get; } = new FineTuneStatus(CreatedValue); - /// running. - public static FineTuneStatus Running { get; } = new FineTuneStatus(RunningValue); - /// succeeded. - public static FineTuneStatus Succeeded { get; } = new FineTuneStatus(SucceededValue); - /// failed. - public static FineTuneStatus Failed { get; } = new FineTuneStatus(FailedValue); - /// cancelled. - public static FineTuneStatus Cancelled { get; } = new FineTuneStatus(CancelledValue); - /// Determines if two values are the same. - public static bool operator ==(FineTuneStatus left, FineTuneStatus right) => left.Equals(right); - /// Determines if two values are not the same. - public static bool operator !=(FineTuneStatus left, FineTuneStatus right) => !left.Equals(right); - /// Converts a string to a . - public static implicit operator FineTuneStatus(string value) => new FineTuneStatus(value); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public override bool Equals(object obj) => obj is FineTuneStatus other && Equals(other); - /// - public bool Equals(FineTuneStatus other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public override int GetHashCode() => _value?.GetHashCode() ?? 0; - /// - public override string ToString() => _value; - } -} diff --git a/.dotnet/src/Generated/Models/ListFineTuneEventsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListFineTuneEventsResponse.Serialization.cs deleted file mode 100644 index bd3431eed..000000000 --- a/.dotnet/src/Generated/Models/ListFineTuneEventsResponse.Serialization.cs +++ /dev/null @@ -1,150 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel.Internal; -using System.ClientModel.Primitives; -using System.Collections.Generic; -using System.Text.Json; - -namespace OpenAI.Models -{ - public partial class ListFineTuneEventsResponse : IUtf8JsonWriteable, IJsonModel - { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - if (format != "J") - { - throw new FormatException($"The model {nameof(ListFineTuneEventsResponse)} does not support '{format}' format."); - } - - writer.WriteStartObject(); - writer.WritePropertyName("object"u8); - writer.WriteStringValue(Object); - writer.WritePropertyName("data"u8); - writer.WriteStartArray(); - foreach (var item in Data) - { - writer.WriteObjectValue(item); - } - writer.WriteEndArray(); - if (options.Format != "W" && _serializedAdditionalRawData != null) - { - foreach (var item in _serializedAdditionalRawData) - { - writer.WritePropertyName(item.Key); -#if NET6_0_OR_GREATER - writer.WriteRawValue(item.Value); -#else - using (JsonDocument document = JsonDocument.Parse(item.Value)) - { - JsonSerializer.Serialize(writer, document.RootElement); - } -#endif - } - } - writer.WriteEndObject(); - } - - ListFineTuneEventsResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - if (format != "J") - { - throw new FormatException($"The model {nameof(ListFineTuneEventsResponse)} does not support '{format}' format."); - } - - using JsonDocument document = JsonDocument.ParseValue(ref reader); - return DeserializeListFineTuneEventsResponse(document.RootElement, options); - } - - internal static ListFineTuneEventsResponse DeserializeListFineTuneEventsResponse(JsonElement element, ModelReaderWriterOptions options = null) - { - options ??= new ModelReaderWriterOptions("W"); - - if (element.ValueKind == JsonValueKind.Null) - { - return null; - } - string @object = default; - IReadOnlyList data = default; - IDictionary serializedAdditionalRawData = default; - Dictionary additionalPropertiesDictionary = new Dictionary(); - foreach (var property in element.EnumerateObject()) - { - if (property.NameEquals("object"u8)) - { - @object = property.Value.GetString(); - continue; - } - if (property.NameEquals("data"u8)) - { - List array = new List(); - foreach (var item in property.Value.EnumerateArray()) - { - array.Add(FineTuneEvent.DeserializeFineTuneEvent(item)); - } - data = array; - continue; - } - if (options.Format != "W") - { - additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); - } - } - serializedAdditionalRawData = additionalPropertiesDictionary; - return new ListFineTuneEventsResponse(@object, data, serializedAdditionalRawData); - } - - BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - - switch (format) - { - case "J": - return ModelReaderWriter.Write(this, options); - default: - throw new FormatException($"The model {nameof(ListFineTuneEventsResponse)} does not support '{options.Format}' format."); - } - } - - ListFineTuneEventsResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - - switch (format) - { - case "J": - { - using JsonDocument document = JsonDocument.Parse(data); - return DeserializeListFineTuneEventsResponse(document.RootElement, options); - } - default: - throw new FormatException($"The model {nameof(ListFineTuneEventsResponse)} does not support '{options.Format}' format."); - } - } - - string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; - - /// Deserializes the model from a raw response. - /// The result to deserialize the model from. - internal static ListFineTuneEventsResponse FromResponse(PipelineResponse response) - { - using var document = JsonDocument.Parse(response.Content); - return DeserializeListFineTuneEventsResponse(document.RootElement); - } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } - } -} diff --git a/.dotnet/src/Generated/Models/ListFineTuneEventsResponse.cs b/.dotnet/src/Generated/Models/ListFineTuneEventsResponse.cs deleted file mode 100644 index 743f4ee68..000000000 --- a/.dotnet/src/Generated/Models/ListFineTuneEventsResponse.cs +++ /dev/null @@ -1,81 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel.Internal; -using System.Collections.Generic; -using System.Linq; - -namespace OpenAI.Models -{ - /// The ListFineTuneEventsResponse. - public partial class ListFineTuneEventsResponse - { - /// - /// Keeps track of any properties unknown to the library. - /// - /// To assign an object to the value of this property use . - /// - /// - /// To assign an already formatted json string to this property use . - /// - /// - /// Examples: - /// - /// - /// BinaryData.FromObjectAsJson("foo") - /// Creates a payload of "foo". - /// - /// - /// BinaryData.FromString("\"foo\"") - /// Creates a payload of "foo". - /// - /// - /// BinaryData.FromObjectAsJson(new { key = "value" }) - /// Creates a payload of { "key": "value" }. - /// - /// - /// BinaryData.FromString("{\"key\": \"value\"}") - /// Creates a payload of { "key": "value" }. - /// - /// - /// - /// - private IDictionary _serializedAdditionalRawData; - - /// Initializes a new instance of . - /// - /// - /// or is null. - internal ListFineTuneEventsResponse(string @object, IEnumerable data) - { - ClientUtilities.AssertNotNull(@object, nameof(@object)); - ClientUtilities.AssertNotNull(data, nameof(data)); - - Object = @object; - Data = data.ToList(); - } - - /// Initializes a new instance of . - /// - /// - /// Keeps track of any properties unknown to the library. - internal ListFineTuneEventsResponse(string @object, IReadOnlyList data, IDictionary serializedAdditionalRawData) - { - Object = @object; - Data = data; - _serializedAdditionalRawData = serializedAdditionalRawData; - } - - /// Initializes a new instance of for deserialization. - internal ListFineTuneEventsResponse() - { - } - - /// Gets the object. - public string Object { get; } - /// Gets the data. - public IReadOnlyList Data { get; } - } -} diff --git a/.dotnet/src/Generated/Models/ListFineTunesResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListFineTunesResponse.Serialization.cs deleted file mode 100644 index bfd1f5cf9..000000000 --- a/.dotnet/src/Generated/Models/ListFineTunesResponse.Serialization.cs +++ /dev/null @@ -1,150 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel.Internal; -using System.ClientModel.Primitives; -using System.Collections.Generic; -using System.Text.Json; - -namespace OpenAI.Models -{ - public partial class ListFineTunesResponse : IUtf8JsonWriteable, IJsonModel - { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - if (format != "J") - { - throw new FormatException($"The model {nameof(ListFineTunesResponse)} does not support '{format}' format."); - } - - writer.WriteStartObject(); - writer.WritePropertyName("object"u8); - writer.WriteStringValue(Object); - writer.WritePropertyName("data"u8); - writer.WriteStartArray(); - foreach (var item in Data) - { - writer.WriteObjectValue(item); - } - writer.WriteEndArray(); - if (options.Format != "W" && _serializedAdditionalRawData != null) - { - foreach (var item in _serializedAdditionalRawData) - { - writer.WritePropertyName(item.Key); -#if NET6_0_OR_GREATER - writer.WriteRawValue(item.Value); -#else - using (JsonDocument document = JsonDocument.Parse(item.Value)) - { - JsonSerializer.Serialize(writer, document.RootElement); - } -#endif - } - } - writer.WriteEndObject(); - } - - ListFineTunesResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - if (format != "J") - { - throw new FormatException($"The model {nameof(ListFineTunesResponse)} does not support '{format}' format."); - } - - using JsonDocument document = JsonDocument.ParseValue(ref reader); - return DeserializeListFineTunesResponse(document.RootElement, options); - } - - internal static ListFineTunesResponse DeserializeListFineTunesResponse(JsonElement element, ModelReaderWriterOptions options = null) - { - options ??= new ModelReaderWriterOptions("W"); - - if (element.ValueKind == JsonValueKind.Null) - { - return null; - } - string @object = default; - IReadOnlyList data = default; - IDictionary serializedAdditionalRawData = default; - Dictionary additionalPropertiesDictionary = new Dictionary(); - foreach (var property in element.EnumerateObject()) - { - if (property.NameEquals("object"u8)) - { - @object = property.Value.GetString(); - continue; - } - if (property.NameEquals("data"u8)) - { - List array = new List(); - foreach (var item in property.Value.EnumerateArray()) - { - array.Add(FineTune.DeserializeFineTune(item)); - } - data = array; - continue; - } - if (options.Format != "W") - { - additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); - } - } - serializedAdditionalRawData = additionalPropertiesDictionary; - return new ListFineTunesResponse(@object, data, serializedAdditionalRawData); - } - - BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - - switch (format) - { - case "J": - return ModelReaderWriter.Write(this, options); - default: - throw new FormatException($"The model {nameof(ListFineTunesResponse)} does not support '{options.Format}' format."); - } - } - - ListFineTunesResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) - { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; - - switch (format) - { - case "J": - { - using JsonDocument document = JsonDocument.Parse(data); - return DeserializeListFineTunesResponse(document.RootElement, options); - } - default: - throw new FormatException($"The model {nameof(ListFineTunesResponse)} does not support '{options.Format}' format."); - } - } - - string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; - - /// Deserializes the model from a raw response. - /// The result to deserialize the model from. - internal static ListFineTunesResponse FromResponse(PipelineResponse response) - { - using var document = JsonDocument.Parse(response.Content); - return DeserializeListFineTunesResponse(document.RootElement); - } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } - } -} diff --git a/.dotnet/src/Generated/Models/ListFineTunesResponse.cs b/.dotnet/src/Generated/Models/ListFineTunesResponse.cs deleted file mode 100644 index 1355ef3be..000000000 --- a/.dotnet/src/Generated/Models/ListFineTunesResponse.cs +++ /dev/null @@ -1,81 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel.Internal; -using System.Collections.Generic; -using System.Linq; - -namespace OpenAI.Models -{ - /// The ListFineTunesResponse. - public partial class ListFineTunesResponse - { - /// - /// Keeps track of any properties unknown to the library. - /// - /// To assign an object to the value of this property use . - /// - /// - /// To assign an already formatted json string to this property use . - /// - /// - /// Examples: - /// - /// - /// BinaryData.FromObjectAsJson("foo") - /// Creates a payload of "foo". - /// - /// - /// BinaryData.FromString("\"foo\"") - /// Creates a payload of "foo". - /// - /// - /// BinaryData.FromObjectAsJson(new { key = "value" }) - /// Creates a payload of { "key": "value" }. - /// - /// - /// BinaryData.FromString("{\"key\": \"value\"}") - /// Creates a payload of { "key": "value" }. - /// - /// - /// - /// - private IDictionary _serializedAdditionalRawData; - - /// Initializes a new instance of . - /// - /// - /// or is null. - internal ListFineTunesResponse(string @object, IEnumerable data) - { - ClientUtilities.AssertNotNull(@object, nameof(@object)); - ClientUtilities.AssertNotNull(data, nameof(data)); - - Object = @object; - Data = data.ToList(); - } - - /// Initializes a new instance of . - /// - /// - /// Keeps track of any properties unknown to the library. - internal ListFineTunesResponse(string @object, IReadOnlyList data, IDictionary serializedAdditionalRawData) - { - Object = @object; - Data = data; - _serializedAdditionalRawData = serializedAdditionalRawData; - } - - /// Initializes a new instance of for deserialization. - internal ListFineTunesResponse() - { - } - - /// Gets the object. - public string Object { get; } - /// Gets the data. - public IReadOnlyList Data { get; } - } -} diff --git a/.dotnet/src/Generated/OpenAIClient.cs b/.dotnet/src/Generated/OpenAIClient.cs index ba4da1bc6..67ceeca49 100644 --- a/.dotnet/src/Generated/OpenAIClient.cs +++ b/.dotnet/src/Generated/OpenAIClient.cs @@ -56,14 +56,13 @@ public OpenAIClient(Uri endpoint, KeyCredential credential, OpenAIClientOptions _endpoint = endpoint; } - private FineTuning _cachedFineTuning; private Audio _cachedAudio; private Assistants _cachedAssistants; private Chat _cachedChat; private Completions _cachedCompletions; private Embeddings _cachedEmbeddings; private Files _cachedFiles; - private FineTunes _cachedFineTunes; + private FineTuning _cachedFineTuning; private Images _cachedImages; private Messages _cachedMessages; private ModelsOps _cachedModelsOps; @@ -71,12 +70,6 @@ public OpenAIClient(Uri endpoint, KeyCredential credential, OpenAIClientOptions private Runs _cachedRuns; private Threads _cachedThreads; - /// Initializes a new instance of FineTuning. - public virtual FineTuning GetFineTuningClient() - { - return Volatile.Read(ref _cachedFineTuning) ?? Interlocked.CompareExchange(ref _cachedFineTuning, new FineTuning(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedFineTuning; - } - /// Initializes a new instance of Audio. public virtual Audio GetAudioClient() { @@ -113,10 +106,10 @@ public virtual Files GetFilesClient() return Volatile.Read(ref _cachedFiles) ?? Interlocked.CompareExchange(ref _cachedFiles, new Files(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedFiles; } - /// Initializes a new instance of FineTunes. - public virtual FineTunes GetFineTunesClient() + /// Initializes a new instance of FineTuning. + public virtual FineTuning GetFineTuningClient() { - return Volatile.Read(ref _cachedFineTunes) ?? Interlocked.CompareExchange(ref _cachedFineTunes, new FineTunes(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedFineTunes; + return Volatile.Read(ref _cachedFineTuning) ?? Interlocked.CompareExchange(ref _cachedFineTuning, new FineTuning(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedFineTuning; } /// Initializes a new instance of Images. diff --git a/.dotnet/src/Generated/OpenAIModelFactory.cs b/.dotnet/src/Generated/OpenAIModelFactory.cs index ae070eb8a..494ab0f0a 100644 --- a/.dotnet/src/Generated/OpenAIModelFactory.cs +++ b/.dotnet/src/Generated/OpenAIModelFactory.cs @@ -11,158 +11,6 @@ namespace OpenAI.Models /// Model factory for models. public static partial class OpenAIModelFactory { - /// Initializes a new instance of . - /// - /// The ID of an uploaded file that contains training data. - /// - /// See [upload file](/docs/api-reference/files/upload) for how to upload a file. - /// - /// Your dataset must be formatted as a JSONL file. Additionally, you must upload your file with - /// the purpose `fine-tune`. - /// - /// See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. - /// - /// - /// The ID of an uploaded file that contains validation data. - /// - /// If you provide this file, the data is used to generate validation metrics periodically during - /// fine-tuning. These metrics can be viewed in the fine-tuning results file. The same data should - /// not be present in both train and validation files. - /// - /// Your dataset must be formatted as a JSONL file. You must upload your file with the purpose - /// `fine-tune`. - /// - /// See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. - /// - /// - /// The name of the model to fine-tune. You can select one of the - /// [supported models](/docs/guides/fine-tuning/what-models-can-be-fine-tuned). - /// - /// The hyperparameters used for the fine-tuning job. - /// - /// 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`. - /// - /// A new instance for mocking. - public static CreateFineTuningJobRequest CreateFineTuningJobRequest(string trainingFile = null, string validationFile = null, CreateFineTuningJobRequestModel model = default, CreateFineTuningJobRequestHyperparameters hyperparameters = null, string suffix = null) - { - return new CreateFineTuningJobRequest(trainingFile, validationFile, model, hyperparameters, suffix, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// The object identifier, which can be referenced in the API endpoints. - /// The object type, which is always "fine_tuning.job". - /// The Unix timestamp (in seconds) for when the fine-tuning job was created. - /// - /// The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be - /// null if the fine-tuning job is still running. - /// - /// The base model that is being fine-tuned. - /// - /// The name of the fine-tuned model that is being created. The value will be null if the - /// fine-tuning job is still running. - /// - /// The organization that owns the fine-tuning job. - /// - /// The current status of the fine-tuning job, which can be either `created`, `pending`, `running`, - /// `succeeded`, `failed`, or `cancelled`. - /// - /// - /// The hyperparameters used for the fine-tuning job. See the - /// [fine-tuning guide](/docs/guides/fine-tuning) for more details. - /// - /// - /// The file ID used for training. You can retrieve the training data with the - /// [Files API](/docs/api-reference/files/retrieve-contents). - /// - /// - /// The file ID used for validation. You can retrieve the validation results with the - /// [Files API](/docs/api-reference/files/retrieve-contents). - /// - /// - /// The compiled results file ID(s) for the fine-tuning job. You can retrieve the results with the - /// [Files API](/docs/api-reference/files/retrieve-contents). - /// - /// - /// The total number of billable tokens processed by this fine tuning job. The value will be null - /// if the fine-tuning job is still running. - /// - /// - /// For fine-tuning jobs that have `failed`, this will contain more information on the cause of the - /// failure. - /// - /// A new instance for mocking. - public static FineTuningJob FineTuningJob(string id = null, FineTuningJobObject @object = default, DateTimeOffset createdAt = default, DateTimeOffset? finishedAt = null, string model = null, string fineTunedModel = null, string organizationId = null, FineTuningJobStatus status = default, FineTuningJobHyperparameters hyperparameters = null, string trainingFile = null, string validationFile = null, IEnumerable resultFiles = null, long? trainedTokens = null, FineTuningJobError error = null) - { - resultFiles ??= new List(); - - return new FineTuningJob(id, @object, createdAt, finishedAt, model, fineTunedModel, organizationId, status, hyperparameters, trainingFile, validationFile, resultFiles?.ToList(), trainedTokens, error, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// - /// The number of epochs to train the model for. An epoch refers to one full cycle through the - /// training dataset. - /// - /// "Auto" decides the optimal number of epochs based on the size of the dataset. If setting the - /// number manually, we support any number between 1 and 50 epochs. - /// - /// A new instance for mocking. - public static FineTuningJobHyperparameters FineTuningJobHyperparameters(BinaryData nEpochs = null) - { - return new FineTuningJobHyperparameters(nEpochs, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// A human-readable error message. - /// A machine-readable error code. - /// - /// The parameter that was invalid, usually `training_file` or `validation_file`. This field - /// will be null if the failure was not parameter-specific. - /// - /// A new instance for mocking. - public static FineTuningJobError FineTuningJobError(string message = null, string code = null, string param = null) - { - return new FineTuningJobError(message, code, param, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// - /// - /// - /// A new instance for mocking. - public static ListPaginatedFineTuningJobsResponse ListPaginatedFineTuningJobsResponse(string @object = null, IEnumerable data = null, bool hasMore = default) - { - data ??= new List(); - - return new ListPaginatedFineTuningJobsResponse(@object, data?.ToList(), hasMore, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// - /// - /// A new instance for mocking. - public static ListFineTuningJobEventsResponse ListFineTuningJobEventsResponse(string @object = null, IEnumerable data = null) - { - data ??= new List(); - - return new ListFineTuningJobEventsResponse(@object, data?.ToList(), serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// - /// - /// - /// - /// - /// A new instance for mocking. - public static FineTuningJobEvent FineTuningJobEvent(string id = null, string @object = null, DateTimeOffset createdAt = default, FineTuningJobEventLevel level = default, string message = null) - { - return new FineTuningJobEvent(id, @object, createdAt, level, message, serializedAdditionalRawData: null); - } - /// Initializes a new instance of . /// One of the available [TTS models](/docs/models/tts): `tts-1` or `tts-1-hd`. /// The text to generate audio for. The maximum length is 4096 characters. @@ -990,192 +838,156 @@ public static DeleteFileResponse DeleteFileResponse(string id = null, DeleteFile return new DeleteFileResponse(id, @object, deleted, serializedAdditionalRawData: null); } - /// Initializes a new instance of . + /// Initializes a new instance of . /// /// The ID of an uploaded file that contains training data. /// /// See [upload file](/docs/api-reference/files/upload) for how to upload a file. /// - /// Your dataset must be formatted as a JSONL file, where each training example is a JSON object - /// with the keys "prompt" and "completion". Additionally, you must upload your file with the - /// purpose `fine-tune`. + /// Your dataset must be formatted as a JSONL file. Additionally, you must upload your file with + /// the purpose `fine-tune`. /// - /// See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more - /// details. + /// See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. /// /// /// The ID of an uploaded file that contains validation data. /// /// If you provide this file, the data is used to generate validation metrics periodically during - /// fine-tuning. These metrics can be viewed in the - /// [fine-tuning results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model). - /// Your train and validation data should be mutually exclusive. + /// fine-tuning. These metrics can be viewed in the fine-tuning results file. The same data should + /// not be present in both train and validation files. /// - /// Your dataset must be formatted as a JSONL file, where each validation example is a JSON object - /// with the keys "prompt" and "completion". Additionally, you must upload your file with the - /// purpose `fine-tune`. + /// Your dataset must be formatted as a JSONL file. You must upload your file with the purpose + /// `fine-tune`. /// - /// See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more - /// details. + /// See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. /// /// - /// The name of the base model to fine-tune. You can select one of "ada", "babbage", "curie", - /// "davinci", or a fine-tuned model created after 2022-04-21 and before 2023-08-22. To learn more - /// about these models, see the [Models](/docs/models) documentation. - /// - /// - /// The number of epochs to train the model for. An epoch refers to one full cycle through the - /// training dataset. - /// - /// - /// The batch size to use for training. The batch size is the number of training examples used to - /// train a single forward and backward pass. - /// - /// By default, the batch size will be dynamically configured to be ~0.2% of the number of examples - /// in the training set, capped at 256 - in general, we've found that larger batch sizes tend to - /// work better for larger datasets. - /// - /// - /// The learning rate multiplier to use for training. The fine-tuning learning rate is the original - /// learning rate used for pretraining multiplied by this value. - /// - /// By default, the learning rate multiplier is the 0.05, 0.1, or 0.2 depending on final - /// `batch_size` (larger learning rates tend to perform better with larger batch sizes). We - /// recommend experimenting with values in the range 0.02 to 0.2 to see what produces the best - /// results. - /// - /// - /// The weight to use for loss on the prompt tokens. This controls how much the model tries to - /// learn to generate the prompt (as compared to the completion which always has a weight of 1.0), - /// and can add a stabilizing effect to training when completions are short. - /// - /// If prompts are extremely long (relative to completions), it may make sense to reduce this - /// weight so as to avoid over-prioritizing learning the prompt. - /// - /// - /// If set, we calculate classification-specific metrics such as accuracy and F-1 score using the - /// validation set at the end of every epoch. These metrics can be viewed in the - /// [results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model). - /// - /// In order to compute classification metrics, you must provide a `validation_file`. Additionally, - /// you must specify `classification_n_classes` for multiclass classification or - /// `classification_positive_class` for binary classification. - /// - /// - /// The number of classes in a classification task. - /// - /// This parameter is required for multiclass classification. - /// - /// - /// The positive class in binary classification. - /// - /// This parameter is needed to generate precision, recall, and F1 metrics when doing binary - /// classification. - /// - /// - /// If this is provided, we calculate F-beta scores at the specified beta values. The F-beta score - /// is a generalization of F-1 score. This is only used for binary classification. - /// - /// With a beta of 1 (i.e. the F-1 score), precision and recall are given the same weight. A larger - /// beta score puts more weight on recall and less on precision. A smaller beta score puts more - /// weight on precision and less on recall. + /// The name of the model to fine-tune. You can select one of the + /// [supported models](/docs/guides/fine-tuning/what-models-can-be-fine-tuned). /// + /// The hyperparameters used for the fine-tuning job. /// /// 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 - /// `ada:ft-your-org:custom-model-name-2022-02-15-04-21-04`. + /// `ft:gpt-3.5-turbo:openai:custom-model-name:7p4lURel`. /// - /// A new instance for mocking. - public static CreateFineTuneRequest CreateFineTuneRequest(string trainingFile = null, string validationFile = null, CreateFineTuneRequestModel? model = null, long? nEpochs = null, long? batchSize = null, double? learningRateMultiplier = null, double? promptLossRate = null, bool? computeClassificationMetrics = null, long? classificationNClasses = null, string classificationPositiveClass = null, IEnumerable classificationBetas = null, string suffix = null) + /// A new instance for mocking. + public static CreateFineTuningJobRequest CreateFineTuningJobRequest(string trainingFile = null, string validationFile = null, CreateFineTuningJobRequestModel model = default, CreateFineTuningJobRequestHyperparameters hyperparameters = null, string suffix = null) { - classificationBetas ??= new List(); - - return new CreateFineTuneRequest(trainingFile, validationFile, model, nEpochs, batchSize, learningRateMultiplier, promptLossRate, computeClassificationMetrics, classificationNClasses, classificationPositiveClass, classificationBetas?.ToList(), suffix, serializedAdditionalRawData: null); + return new CreateFineTuningJobRequest(trainingFile, validationFile, model, hyperparameters, suffix, serializedAdditionalRawData: null); } - /// Initializes a new instance of . + /// Initializes a new instance of . /// The object identifier, which can be referenced in the API endpoints. - /// The object type, which is always "fine-tune". + /// The object type, which is always "fine_tuning.job". /// The Unix timestamp (in seconds) for when the fine-tuning job was created. - /// The Unix timestamp (in seconds) for when the fine-tuning job was last updated. + /// + /// The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be + /// null if the fine-tuning job is still running. + /// /// The base model that is being fine-tuned. - /// The name of the fine-tuned model that is being created. + /// + /// The name of the fine-tuned model that is being created. The value will be null if the + /// fine-tuning job is still running. + /// /// The organization that owns the fine-tuning job. /// - /// The current status of the fine-tuning job, which can be either `created`, `running`, + /// The current status of the fine-tuning job, which can be either `created`, `pending`, `running`, /// `succeeded`, `failed`, or `cancelled`. /// - /// + /// /// The hyperparameters used for the fine-tuning job. See the - /// [fine-tuning guide](/docs/guides/legacy-fine-tuning/hyperparameters) for more details. + /// [fine-tuning guide](/docs/guides/fine-tuning) for more details. + /// + /// + /// The file ID used for training. You can retrieve the training data with the + /// [Files API](/docs/api-reference/files/retrieve-contents). + /// + /// + /// The file ID used for validation. You can retrieve the validation results with the + /// [Files API](/docs/api-reference/files/retrieve-contents). + /// + /// + /// The compiled results file ID(s) for the fine-tuning job. You can retrieve the results with the + /// [Files API](/docs/api-reference/files/retrieve-contents). + /// + /// + /// The total number of billable tokens processed by this fine tuning job. The value will be null + /// if the fine-tuning job is still running. + /// + /// + /// For fine-tuning jobs that have `failed`, this will contain more information on the cause of the + /// failure. /// - /// The list of files used for training. - /// The list of files used for validation. - /// The compiled results files for the fine-tuning job. - /// The list of events that have been observed in the lifecycle of the FineTune job. - /// A new instance for mocking. - public static FineTune FineTune(string id = null, FineTuneObject @object = default, DateTimeOffset createdAt = default, DateTimeOffset updatedAt = default, string model = null, string fineTunedModel = null, string organizationId = null, FineTuneStatus status = default, FineTuneHyperparams hyperparams = null, IEnumerable trainingFiles = null, IEnumerable validationFiles = null, IEnumerable resultFiles = null, IEnumerable events = null) + /// A new instance for mocking. + public static FineTuningJob FineTuningJob(string id = null, FineTuningJobObject @object = default, DateTimeOffset createdAt = default, DateTimeOffset? finishedAt = null, string model = null, string fineTunedModel = null, string organizationId = null, FineTuningJobStatus status = default, FineTuningJobHyperparameters hyperparameters = null, string trainingFile = null, string validationFile = null, IEnumerable resultFiles = null, long? trainedTokens = null, FineTuningJobError error = null) { - trainingFiles ??= new List(); - validationFiles ??= new List(); - resultFiles ??= new List(); - events ??= new List(); + resultFiles ??= new List(); - return new FineTune(id, @object, createdAt, updatedAt, model, fineTunedModel, organizationId, status, hyperparams, trainingFiles?.ToList(), validationFiles?.ToList(), resultFiles?.ToList(), events?.ToList(), serializedAdditionalRawData: null); + return new FineTuningJob(id, @object, createdAt, finishedAt, model, fineTunedModel, organizationId, status, hyperparameters, trainingFile, validationFile, resultFiles?.ToList(), trainedTokens, error, serializedAdditionalRawData: null); } - /// Initializes a new instance of . + /// Initializes a new instance of . /// /// The number of epochs to train the model for. An epoch refers to one full cycle through the /// training dataset. + /// + /// "Auto" decides the optimal number of epochs based on the size of the dataset. If setting the + /// number manually, we support any number between 1 and 50 epochs. /// - /// - /// The batch size to use for training. The batch size is the number of training examples used to - /// train a single forward and backward pass. - /// - /// The weight to use for loss on the prompt tokens. - /// The learning rate multiplier to use for training. - /// The classification metrics to compute using the validation dataset at the end of every epoch. - /// The positive class to use for computing classification metrics. - /// The number of classes to use for computing classification metrics. - /// A new instance for mocking. - public static FineTuneHyperparams FineTuneHyperparams(long nEpochs = default, long batchSize = default, double promptLossWeight = default, double learningRateMultiplier = default, bool? computeClassificationMetrics = null, string classificationPositiveClass = null, long? classificationNClasses = null) + /// A new instance for mocking. + public static FineTuningJobHyperparameters FineTuningJobHyperparameters(BinaryData nEpochs = null) { - return new FineTuneHyperparams(nEpochs, batchSize, promptLossWeight, learningRateMultiplier, computeClassificationMetrics, classificationPositiveClass, classificationNClasses, serializedAdditionalRawData: null); + return new FineTuningJobHyperparameters(nEpochs, serializedAdditionalRawData: null); } - /// Initializes a new instance of . - /// - /// - /// - /// - /// A new instance for mocking. - public static FineTuneEvent FineTuneEvent(string @object = null, DateTimeOffset createdAt = default, string level = null, string message = null) + /// Initializes a new instance of . + /// A human-readable error message. + /// A machine-readable error code. + /// + /// The parameter that was invalid, usually `training_file` or `validation_file`. This field + /// will be null if the failure was not parameter-specific. + /// + /// A new instance for mocking. + public static FineTuningJobError FineTuningJobError(string message = null, string code = null, string param = null) { - return new FineTuneEvent(@object, createdAt, level, message, serializedAdditionalRawData: null); + return new FineTuningJobError(message, code, param, serializedAdditionalRawData: null); } - /// Initializes a new instance of . + /// Initializes a new instance of . /// /// - /// A new instance for mocking. - public static ListFineTunesResponse ListFineTunesResponse(string @object = null, IEnumerable data = null) + /// + /// A new instance for mocking. + public static ListPaginatedFineTuningJobsResponse ListPaginatedFineTuningJobsResponse(string @object = null, IEnumerable data = null, bool hasMore = default) { - data ??= new List(); + data ??= new List(); - return new ListFineTunesResponse(@object, data?.ToList(), serializedAdditionalRawData: null); + return new ListPaginatedFineTuningJobsResponse(@object, data?.ToList(), hasMore, serializedAdditionalRawData: null); } - /// Initializes a new instance of . + /// Initializes a new instance of . /// /// - /// A new instance for mocking. - public static ListFineTuneEventsResponse ListFineTuneEventsResponse(string @object = null, IEnumerable data = null) + /// A new instance for mocking. + public static ListFineTuningJobEventsResponse ListFineTuningJobEventsResponse(string @object = null, IEnumerable data = null) { - data ??= new List(); + data ??= new List(); + + return new ListFineTuningJobEventsResponse(@object, data?.ToList(), serializedAdditionalRawData: null); + } - return new ListFineTuneEventsResponse(@object, data?.ToList(), serializedAdditionalRawData: null); + /// Initializes a new instance of . + /// + /// + /// + /// + /// + /// A new instance for mocking. + public static FineTuningJobEvent FineTuningJobEvent(string id = null, string @object = null, DateTimeOffset createdAt = default, FineTuningJobEventLevel level = default, string message = null) + { + return new FineTuningJobEvent(id, @object, createdAt, level, message, serializedAdditionalRawData: null); } /// Initializes a new instance of . diff --git a/.dotnet/tests/Generated/Tests/FineTuningJobsTests.cs b/.dotnet/tests/Generated/Tests/FineTuningTests.cs similarity index 70% rename from .dotnet/tests/Generated/Tests/FineTuningJobsTests.cs rename to .dotnet/tests/Generated/Tests/FineTuningTests.cs index ea1fc2ad2..40abbe22d 100644 --- a/.dotnet/tests/Generated/Tests/FineTuningJobsTests.cs +++ b/.dotnet/tests/Generated/Tests/FineTuningTests.cs @@ -9,13 +9,13 @@ namespace OpenAI.Tests { - public partial class FineTuningJobsTests + public partial class FineTuningTests { [Test] public void SmokeTest() { KeyCredential credential = new KeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - FineTuningJobs client = new OpenAIClient(credential).GetFineTuningClient().GetFineTuningJobsClient(); + FineTuning client = new OpenAIClient(credential).GetFineTuningClient(); Assert.IsNotNull(client); } } diff --git a/.dotnet/tsp-output/@typespec/openapi3/openapi.yaml b/.dotnet/tsp-output/@typespec/openapi3/openapi.yaml deleted file mode 100644 index cc299da11..000000000 --- a/.dotnet/tsp-output/@typespec/openapi3/openapi.yaml +++ /dev/null @@ -1,6019 +0,0 @@ -openapi: 3.0.0 -info: - title: OpenAI API - version: 2.0.0 - description: The OpenAI REST API. Please see https://platform.openai.com/docs/api-reference for more details. -tags: - - name: Fine-tuning - - name: Audio - - name: Assistants - - name: Chat - - name: Completions - - name: Embeddings - - name: Files - - name: Images - - name: Models - - name: Moderations -paths: - /assistants: - post: - tags: - - Assistants - operationId: createAssistant - summary: Create an assistant with a model and instructions. - parameters: [] - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/AssistantObject' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateAssistantRequest' - get: - tags: - - Assistants - operationId: listAssistants - summary: Returns a list of assistants. - parameters: - - name: limit - in: query - required: false - description: |- - A limit on the number of objects to be returned. Limit can range between 1 and 100, and the - default is 20. - schema: - type: integer - format: int32 - default: 20 - - name: order - in: query - required: false - description: |- - Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` - for descending order. - schema: - $ref: '#/components/schemas/ListOrder' - default: desc - - name: after - in: query - required: false - description: |- - A cursor for use in pagination. `after` is an object ID that defines your place in the list. - For instance, if you make a list request and receive 100 objects, ending with obj_foo, your - subsequent call can include after=obj_foo in order to fetch the next page of the list. - schema: - type: string - - name: before - in: query - required: false - description: |- - A cursor for use in pagination. `before` is an object ID that defines your place in the list. - For instance, if you make a list request and receive 100 objects, ending with obj_foo, your - subsequent call can include before=obj_foo in order to fetch the previous page of the list. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/ListAssistantsResponse' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /assistants/{assistant_id}: - get: - tags: - - Assistants - operationId: getAssistant - summary: Retrieves an assistant. - parameters: - - name: assistant_id - in: path - required: true - description: The ID of the assistant to retrieve. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/AssistantObject' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - post: - tags: - - Assistants - operationId: modifyAssistant - summary: Modifies an assistant. - parameters: - - name: assistant_id - in: path - required: true - description: The ID of the assistant to modify. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/AssistantObject' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ModifyAssistantRequest' - delete: - tags: - - Assistants - operationId: deleteAssistant - summary: Delete an assistant. - parameters: - - name: assistant_id - in: path - required: true - description: The ID of the assistant to delete. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/DeleteAssistantResponse' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /assistants/{assistant_id}/files: - post: - tags: - - Assistants - operationId: createAssistantFile - summary: |- - Create an assistant file by attaching a [File](/docs/api-reference/files) to a - [assistant](/docs/api-reference/assistants). - parameters: - - name: assistant_id - in: path - required: true - description: The ID of the assistant for which to create a file. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/AssistantFileObject' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateAssistantFileRequest' - get: - tags: - - Assistants - operationId: listAssistantFiles - summary: Returns a list of assistant files. - parameters: - - name: assistant_id - in: path - required: true - description: The ID of the assistant the file belongs to. - schema: - type: string - - name: limit - in: query - required: false - description: |- - A limit on the number of objects to be returned. Limit can range between 1 and 100, and the - default is 20. - schema: - type: integer - format: int32 - default: 20 - - name: order - in: query - required: false - description: |- - Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` - for descending order. - schema: - $ref: '#/components/schemas/ListOrder' - default: desc - - name: after - in: query - required: false - description: |- - A cursor for use in pagination. `after` is an object ID that defines your place in the list. - For instance, if you make a list request and receive 100 objects, ending with obj_foo, your - subsequent call can include after=obj_foo in order to fetch the next page of the list. - schema: - type: string - - name: before - in: query - required: false - description: |- - A cursor for use in pagination. `before` is an object ID that defines your place in the list. - For instance, if you make a list request and receive 100 objects, ending with obj_foo, your - subsequent call can include before=obj_foo in order to fetch the previous page of the list. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/ListAssistantFilesResponse' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /assistants/{assistant_id}/files/{file_id}: - get: - tags: - - Assistants - operationId: getAssistantFile - summary: Retrieves an assistant file. - parameters: - - name: assistant_id - in: path - required: true - description: The ID of the assistant the file belongs to. - schema: - type: string - - name: file_id - in: path - required: true - description: The ID of the file we're getting. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/AssistantFileObject' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - delete: - tags: - - Assistants - operationId: deleteAssistantFile - summary: Delete an assistant file. - parameters: - - name: assistant_id - in: path - required: true - description: The ID of the assistant the file belongs to. - schema: - type: string - - name: file_id - in: path - required: true - description: The ID of the file to delete. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/DeleteAssistantFileResponse' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /audio/speech: - post: - tags: - - Audio - operationId: createSpeech - summary: Generates audio from the input text. - parameters: [] - responses: - '200': - description: The request has succeeded. - headers: - Transfer-Encoding: - required: false - description: chunked - schema: - type: string - content: - application/octet-stream: - schema: - type: string - format: binary - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateSpeechRequest' - /audio/transcriptions: - post: - tags: - - Audio - operationId: createTranscription - summary: Transcribes audio into the input language. - parameters: [] - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/CreateTranscriptionResponse' - text/plain: - schema: - type: string - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - multipart/form-data: - schema: - $ref: '#/components/schemas/CreateTranscriptionRequestMultiPart' - /audio/translations: - post: - tags: - - Audio - operationId: createTranslation - summary: Translates audio into English.. - parameters: [] - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/CreateTranslationResponse' - text/plain: - schema: - type: string - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - multipart/form-data: - schema: - $ref: '#/components/schemas/CreateTranslationRequestMultiPart' - /chat/completions: - post: - tags: - - Chat - operationId: createChatCompletion - summary: Creates a model response for the given chat conversation. - parameters: [] - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/CreateChatCompletionResponse' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateChatCompletionRequest' - /completions: - post: - tags: - - Completions - operationId: createCompletion - summary: Creates a completion for the provided prompt and parameters. - parameters: [] - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/CreateCompletionResponse' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateCompletionRequest' - /embeddings: - post: - tags: - - Embeddings - operationId: createEmbedding - summary: Creates an embedding vector representing the input text. - parameters: [] - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/CreateEmbeddingResponse' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateEmbeddingRequest' - /files: - post: - tags: - - Files - operationId: createFile - summary: |- - Upload a file that can be used across various endpoints. The size of all the files uploaded by - one organization can be up to 100 GB. - - The size of individual files can be a maximum of 512 MB or 2 million tokens for Assistants. See - the [Assistants Tools guide](/docs/assistants/tools) to learn more about the types of files - supported. The Fine-tuning API only supports `.jsonl` files. - - Please [contact us](https://help.openai.com/) if you need to increase these storage limits. - parameters: [] - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/OpenAIFile' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - multipart/form-data: - schema: - $ref: '#/components/schemas/CreateFileRequestMultiPart' - get: - tags: - - Files - operationId: listFiles - summary: Returns a list of files that belong to the user's organization. - parameters: - - name: purpose - in: query - required: false - description: Only return files with the given purpose. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/ListFilesResponse' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /files/{file_id}: - get: - tags: - - Files - operationId: retrieveFile - summary: Returns information about a specific file. - parameters: - - name: file_id - in: path - required: true - description: The ID of the file to use for this request. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/OpenAIFile' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - delete: - tags: - - Files - operationId: deleteFile - summary: Delete a file - parameters: - - name: file_id - in: path - required: true - description: The ID of the file to use for this request. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/DeleteFileResponse' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /files/{file_id}/content: - get: - tags: - - Files - operationId: downloadFile - summary: Returns the contents of the specified file. - parameters: - - name: file_id - in: path - required: true - description: The ID of the file to use for this request. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - type: string - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /fine-tunes: - post: - tags: - - Fine-tuning - operationId: createFineTune - summary: |- - Creates a job that fine-tunes a specified model from a given dataset. - - Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete. - - [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) - parameters: [] - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/FineTune' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateFineTuneRequest' - deprecated: true - get: - tags: - - Fine-tuning - operationId: listFineTunes - summary: List your organization's fine-tuning jobs - parameters: [] - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/ListFineTunesResponse' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - deprecated: true - /fine-tunes/{fine_tune_id}: - get: - tags: - - Fine-tuning - operationId: retrieveFineTune - summary: |- - Gets info about the fine-tune job. - - [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) - parameters: - - name: fine_tune_id - in: path - required: true - description: The ID of the fine-tune job - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/FineTune' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - deprecated: true - /fine-tunes/{fine_tune_id}/cancel: - post: - tags: - - Fine-tuning - operationId: cancelFineTune - summary: Immediately cancel a fine-tune job. - parameters: - - name: fine_tune_id - in: path - required: true - description: The ID of the fine-tune job to cancel - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/FineTune' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - deprecated: true - /fine-tunes/{fine_tune_id}/events: - get: - tags: - - Fine-tuning - operationId: listFineTuneEvents - summary: Get fine-grained status updates for a fine-tune job. - parameters: - - name: fine_tune_id - in: path - required: true - description: The ID of the fine-tune job to get events for. - schema: - type: string - - name: stream - in: query - required: false - description: |- - Whether to stream events for the fine-tune job. If set to true, events will be sent as - data-only - [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) - as they become available. The stream will terminate with a `data: [DONE]` message when the - job is finished (succeeded, cancelled, or failed). - - If set to false, only events generated so far will be returned. - schema: - type: boolean - default: false - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/ListFineTuneEventsResponse' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - deprecated: true - /fine_tuning/jobs: - post: - tags: - - Fine-tuning - operationId: createFineTuningJob - description: |- - Creates a job that fine-tunes a specified model from a given dataset. - - Response includes details of the enqueued job including job status and the name of the - fine-tuned models once complete. - - [Learn more about fine-tuning](/docs/guides/fine-tuning) - parameters: [] - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/FineTuningJob' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateFineTuningJobRequest' - get: - tags: - - Fine-tuning - operationId: listPaginatedFineTuningJobs - parameters: - - name: after - in: query - required: false - description: Identifier for the last job from the previous pagination request. - schema: - type: string - - name: limit - in: query - required: false - description: Number of fine-tuning jobs to retrieve. - schema: - type: integer - format: int64 - default: 20 - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/ListPaginatedFineTuningJobsResponse' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /fine_tuning/jobs/{fine_tuning_job_id}: - get: - tags: - - Fine-tuning - operationId: retrieveFineTuningJob - summary: |- - Get info about a fine-tuning job. - - [Learn more about fine-tuning](/docs/guides/fine-tuning) - parameters: - - name: fine_tuning_job_id - in: path - required: true - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/FineTuningJob' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /fine_tuning/jobs/{fine_tuning_job_id}/cancel: - post: - tags: - - Fine-tuning - operationId: cancelFineTuningJob - summary: Immediately cancel a fine-tune job. - parameters: - - name: fine_tuning_job_id - in: path - required: true - description: The ID of the fine-tuning job to cancel. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/FineTuningJob' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /fine_tuning/jobs/{fine_tuning_job_id}/events: - get: - tags: - - Fine-tuning - operationId: listFineTuningEvents - summary: Get status updates for a fine-tuning job. - parameters: - - name: fine_tuning_job_id - in: path - required: true - description: The ID of the fine-tuning job to get events for. - schema: - type: string - - name: after - in: query - required: false - description: Identifier for the last event from the previous pagination request. - schema: - type: string - - name: limit - in: query - required: false - description: Number of events to retrieve. - schema: - type: integer - default: 20 - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/ListFineTuningJobEventsResponse' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /images/edits: - post: - tags: - - Images - operationId: createImageEdit - summary: Creates an edited or extended image given an original image and a prompt. - parameters: [] - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/ImagesResponse' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - multipart/form-data: - schema: - $ref: '#/components/schemas/CreateImageEditRequestMultiPart' - /images/generations: - post: - tags: - - Images - operationId: createImage - summary: Creates an image given a prompt - parameters: [] - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/ImagesResponse' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateImageRequest' - /images/variations: - post: - tags: - - Images - operationId: createImageVariation - summary: Creates an edited or extended image given an original image and a prompt. - parameters: [] - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/ImagesResponse' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - multipart/form-data: - schema: - $ref: '#/components/schemas/CreateImageVariationRequestMultiPart' - /models: - get: - tags: - - Models - operationId: listModels - summary: |- - Lists the currently available models, and provides basic information about each one such as the - owner and availability. - parameters: [] - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/ListModelsResponse' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /models/{model}: - get: - tags: - - Models - operationId: retrieveModel - summary: |- - Retrieves a model instance, providing basic information about the model such as the owner and - permissioning. - parameters: - - name: model - in: path - required: true - description: The ID of the model to use for this request. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/Model' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - delete: - tags: - - Models - operationId: deleteModel - summary: Delete a fine-tuned model. You must have the Owner role in your organization to delete a model. - parameters: - - name: model - in: path - required: true - description: The model to delete - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/DeleteModelResponse' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /moderations: - post: - tags: - - Moderations - operationId: createModeration - summary: Classifies if text violates OpenAI's Content Policy - parameters: [] - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/CreateModerationResponse' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateModerationRequest' - /threads: - post: - tags: - - Assistants - operationId: createThread - summary: Create a thread. - parameters: [] - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/ThreadObject' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateThreadRequest' - /threads/runs: - post: - tags: - - Assistants - operationId: createThreadAndRun - summary: Create a thread and run it in one request. - parameters: [] - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/RunObject' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateThreadAndRunRequest' - /threads/{thread_id}: - get: - tags: - - Assistants - operationId: getThread - summary: Retrieves a thread. - parameters: - - name: thread_id - in: path - required: true - description: The ID of the thread to retrieve. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/ThreadObject' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - post: - tags: - - Assistants - operationId: modifyThread - summary: Modifies a thread. - parameters: - - name: thread_id - in: path - required: true - description: The ID of the thread to modify. Only the `metadata` can be modified. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/ThreadObject' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ModifyThreadRequest' - delete: - tags: - - Assistants - operationId: deleteThread - summary: Delete a thread. - parameters: - - name: thread_id - in: path - required: true - description: The ID of the thread to delete. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/DeleteThreadResponse' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /threads/{thread_id}/messages: - post: - tags: - - Assistants - operationId: createMessage - summary: Create a message. - parameters: - - name: thread_id - in: path - required: true - description: The ID of the [thread](/docs/api-reference/threads) to create a message for. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/MessageObject' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateMessageRequest' - get: - tags: - - Assistants - operationId: listMessages - summary: Returns a list of messages for a given thread. - parameters: - - name: thread_id - in: path - required: true - description: The ID of the [thread](/docs/api-reference/threads) the messages belong to. - schema: - type: string - - name: limit - in: query - required: false - description: |- - A limit on the number of objects to be returned. Limit can range between 1 and 100, and the - default is 20. - schema: - type: integer - format: int32 - default: 20 - - name: order - in: query - required: false - description: |- - Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` - for descending order. - schema: - $ref: '#/components/schemas/ListOrder' - default: desc - - name: after - in: query - required: false - description: |- - A cursor for use in pagination. `after` is an object ID that defines your place in the list. - For instance, if you make a list request and receive 100 objects, ending with obj_foo, your - subsequent call can include after=obj_foo in order to fetch the next page of the list. - schema: - type: string - - name: before - in: query - required: false - description: |- - A cursor for use in pagination. `before` is an object ID that defines your place in the list. - For instance, if you make a list request and receive 100 objects, ending with obj_foo, your - subsequent call can include before=obj_foo in order to fetch the previous page of the list. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/ListMessagesResponse' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /threads/{thread_id}/messages/{message_id}: - get: - tags: - - Assistants - operationId: getMessage - summary: Retrieve a message. - parameters: - - name: thread_id - in: path - required: true - description: The ID of the [thread](/docs/api-reference/threads) to which this message belongs. - schema: - type: string - - name: message_id - in: path - required: true - description: The ID of the message to retrieve. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/MessageObject' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - post: - tags: - - Assistants - operationId: modifyMessage - summary: Modifies a message. - parameters: - - name: thread_id - in: path - required: true - description: The ID of the thread to which this message belongs. - schema: - type: string - - name: message_id - in: path - required: true - description: The ID of the message to modify. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/MessageObject' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ModifyMessageRequest' - /threads/{thread_id}/messages/{message_id}/files: - get: - tags: - - Assistants - operationId: listMessageFiles - summary: Returns a list of message files. - parameters: - - name: thread_id - in: path - required: true - description: The ID of the thread that the message and files belong to. - schema: - type: string - - name: message_id - in: path - required: true - description: The ID of the message that the files belongs to. - schema: - type: string - - name: limit - in: query - required: false - description: |- - A limit on the number of objects to be returned. Limit can range between 1 and 100, and the - default is 20. - schema: - type: integer - format: int32 - default: 20 - - name: order - in: query - required: false - description: |- - Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` - for descending order. - schema: - $ref: '#/components/schemas/ListOrder' - default: desc - - name: after - in: query - required: false - description: |- - A cursor for use in pagination. `after` is an object ID that defines your place in the list. - For instance, if you make a list request and receive 100 objects, ending with obj_foo, your - subsequent call can include after=obj_foo in order to fetch the next page of the list. - schema: - type: string - - name: before - in: query - required: false - description: |- - A cursor for use in pagination. `before` is an object ID that defines your place in the list. - For instance, if you make a list request and receive 100 objects, ending with obj_foo, your - subsequent call can include before=obj_foo in order to fetch the previous page of the list. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/ListMessageFilesResponse' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /threads/{thread_id}/messages/{message_id}/files/{file_id}: - get: - tags: - - Assistants - operationId: getMessageFile - summary: Retrieves a message file. - parameters: - - name: thread_id - in: path - required: true - description: The ID of the thread to which the message and File belong. - schema: - type: string - - name: message_id - in: path - required: true - description: The ID of the message the file belongs to. - schema: - type: string - - name: file_id - in: path - required: true - description: The ID of the file being retrieved. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/MessageFileObject' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /threads/{thread_id}/runs: - post: - tags: - - Assistants - operationId: createRun - summary: Create a run. - parameters: - - name: thread_id - in: path - required: true - description: The ID of the thread to run. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/RunObject' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateRunRequest' - get: - tags: - - Assistants - operationId: listRuns - summary: Returns a list of runs belonging to a thread. - parameters: - - name: thread_id - in: path - required: true - description: The ID of the thread the run belongs to. - schema: - type: string - - name: limit - in: query - required: false - description: |- - A limit on the number of objects to be returned. Limit can range between 1 and 100, and the - default is 20. - schema: - type: integer - format: int32 - default: 20 - - name: order - in: query - required: false - description: |- - Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` - for descending order. - schema: - $ref: '#/components/schemas/ListOrder' - default: desc - - name: after - in: query - required: false - description: |- - A cursor for use in pagination. `after` is an object ID that defines your place in the list. - For instance, if you make a list request and receive 100 objects, ending with obj_foo, your - subsequent call can include after=obj_foo in order to fetch the next page of the list. - schema: - type: string - - name: before - in: query - required: false - description: |- - A cursor for use in pagination. `before` is an object ID that defines your place in the list. - For instance, if you make a list request and receive 100 objects, ending with obj_foo, your - subsequent call can include before=obj_foo in order to fetch the previous page of the list. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/ListRunsResponse' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /threads/{thread_id}/runs/{run_id}: - get: - tags: - - Assistants - operationId: getRun - summary: Retrieves a run. - parameters: - - name: thread_id - in: path - required: true - description: The ID of the [thread](/docs/api-reference/threads) that was run. - schema: - type: string - - name: run_id - in: path - required: true - description: The ID of the run to retrieve. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/RunObject' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - post: - tags: - - Assistants - operationId: modifyRun - summary: Modifies a run. - parameters: - - name: thread_id - in: path - required: true - description: The ID of the [thread](/docs/api-reference/threads) that was run. - schema: - type: string - - name: run_id - in: path - required: true - description: The ID of the run to modify. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/RunObject' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/ModifyRunRequest' - /threads/{thread_id}/runs/{run_id}/cancel: - post: - tags: - - Assistants - operationId: cancelRun - summary: Cancels a run that is `in_progress`. - parameters: - - name: thread_id - in: path - required: true - description: The ID of the thread to which this run belongs. - schema: - type: string - - name: run_id - in: path - required: true - description: The ID of the run to cancel. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/RunObject' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /threads/{thread_id}/runs/{run_id}/steps: - get: - tags: - - Assistants - operationId: listRunSteps - summary: Returns a list of run steps belonging to a run. - parameters: - - name: thread_id - in: path - required: true - description: The ID of the thread the run and run steps belong to. - schema: - type: string - - name: run_id - in: path - required: true - description: The ID of the run the run steps belong to. - schema: - type: string - - name: limit - in: query - required: false - description: |- - A limit on the number of objects to be returned. Limit can range between 1 and 100, and the - default is 20. - schema: - type: integer - format: int32 - default: 20 - - name: order - in: query - required: false - description: |- - Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and`desc` - for descending order. - schema: - $ref: '#/components/schemas/ListOrder' - default: desc - - name: after - in: query - required: false - description: |- - A cursor for use in pagination. `after` is an object ID that defines your place in the list. - For instance, if you make a list request and receive 100 objects, ending with obj_foo, your - subsequent call can include after=obj_foo in order to fetch the next page of the list. - schema: - type: string - - name: before - in: query - required: false - description: |- - A cursor for use in pagination. `before` is an object ID that defines your place in the list. - For instance, if you make a list request and receive 100 objects, ending with obj_foo, your - subsequent call can include before=obj_foo in order to fetch the previous page of the list. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/ListRunStepsResponse' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /threads/{thread_id}/runs/{run_id}/steps/{step_id}: - get: - tags: - - Assistants - operationId: getRunStep - summary: Retrieves a run step. - parameters: - - name: thread_id - in: path - required: true - description: The ID of the thread to which the run and run step belongs. - schema: - type: string - - name: run_id - in: path - required: true - description: The ID of the run to which the run step belongs. - schema: - type: string - - name: step_id - in: path - required: true - description: The ID of the run step to retrieve. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/RunStepObject' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - /threads/{thread_id}/runs/{run_id}/submit_tool_outputs: - post: - tags: - - Assistants - operationId: submitToolOuputsToRun - summary: |- - When a run has the `status: "requires_action"` and `required_action.type` is - `submit_tool_outputs`, this endpoint can be used to submit the outputs from the tool calls once - they're all completed. All outputs must be submitted in a single request. - parameters: - - name: thread_id - in: path - required: true - description: The ID of the [thread](/docs/api-reference/threads) to which this run belongs. - schema: - type: string - - name: run_id - in: path - required: true - description: The ID of the run that requires the tool output submission. - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/RunObject' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/SubmitToolOutputsRunRequest' -security: - - BearerAuth: [] -components: - schemas: - AssistantFileObject: - type: object - required: - - id - - object - - created_at - - assistant_id - properties: - id: - type: string - description: The identifier, which can be referenced in API endpoints. - object: - type: string - enum: - - assistant.file - description: The object type, which is always `assistant.file`. - created_at: - type: integer - format: unixtime - description: The Unix timestamp (in seconds) for when the assistant file was created. - assistant_id: - type: string - description: The assistant ID that the file is attached to. - description: A list of [Files](/docs/api-reference/files) attached to an `assistant`. - AssistantObject: - type: object - required: - - id - - object - - created_at - - name - - description - - model - - instructions - - tools - - file_ids - - metadata - properties: - id: - type: string - description: The identifier, which can be referenced in API endpoints. - object: - type: string - enum: - - assistant - description: The object type, which is always `assistant`. - created_at: - type: integer - format: unixtime - description: The Unix timestamp (in seconds) for when the assistant was created. - name: - type: string - nullable: true - maxLength: 256 - description: The name of the assistant. The maximum length is 256 characters. - description: - type: string - nullable: true - maxLength: 512 - description: The description of the assistant. The maximum length is 512 characters. - model: - type: string - description: |- - ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to - see all of your available models, or see our [Model overview](/docs/models/overview) for - descriptions of them. - instructions: - type: string - nullable: true - maxLength: 32768 - description: The system instructions that the assistant uses. The maximum length is 32768 characters. - tools: - allOf: - - $ref: '#/components/schemas/CreateAssistantRequestToolsItem' - description: |- - A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. - Tools can be of types `code_interpreter`, `retrieval`, or `function`. - default: [] - file_ids: - type: array - items: - type: string - maxItems: 20 - description: |- - A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a - maximum of 20 files attached to the assistant. Files are ordered by their creation date in - ascending order. - default: [] - metadata: - type: object - additionalProperties: - type: string - nullable: true - description: |- - Set of 16 key-value pairs that can be attached to an object. This can be useful for storing - additional information about the object in a structured format. Keys can be a maximum of 64 - characters long and values can be a maxium of 512 characters long. - x-oaiTypeLabel: map - description: Represents an `assistant` that can call the model and use tools. - AssistantToolsCode: - type: object - required: - - type - properties: - type: - type: string - enum: - - code_interpreter - description: 'The type of tool being defined: `code_interpreter`' - AssistantToolsFunction: - type: object - required: - - type - - function - properties: - type: - type: string - enum: - - function - description: 'The type of tool being defined: `function`' - function: - $ref: '#/components/schemas/FunctionObject' - AssistantToolsRetrieval: - type: object - required: - - type - properties: - type: - type: string - enum: - - retrieval - description: 'The type of tool being defined: `retrieval`' - AudioSegment: - type: object - required: - - id - - seek - - start - - end - - text - - tokens - - temperature - - avg_logprob - - compression_ratio - - no_speech_prob - properties: - id: - type: integer - format: int64 - description: The zero-based index of this segment. - seek: - type: integer - format: int64 - description: |- - The seek position associated with the processing of this audio segment. Seek positions are - expressed as hundredths of seconds. The model may process several segments from a single seek - position, so while the seek position will never represent a later time than the segment's - start, the segment's start may represent a significantly later time than the segment's - associated seek position. - start: - type: number - format: double - description: The time at which this segment started relative to the beginning of the audio. - end: - type: number - format: double - description: The time at which this segment ended relative to the beginning of the audio. - text: - type: string - description: The text that was part of this audio segment. - tokens: - allOf: - - $ref: '#/components/schemas/TokenArrayItem' - description: The token IDs matching the text in this audio segment. - temperature: - type: number - format: double - minimum: 0 - maximum: 1 - description: The temperature score associated with this audio segment. - avg_logprob: - type: number - format: double - description: The average log probability associated with this audio segment. - compression_ratio: - type: number - format: double - description: The compression ratio of this audio segment. - no_speech_prob: - type: number - format: double - description: The probability of no speech detection within this audio segment. - ChatCompletionFunctionCallOption: - type: object - required: - - name - properties: - name: - type: string - description: The name of the function to call. - description: |- - Specifying a particular function via `{"name": "my_function"}` forces the model to call that - function. - ChatCompletionFunctions: - type: object - required: - - name - properties: - description: - type: string - description: |- - A description of what the function does, used by the model to choose when and how to call the - function. - name: - type: string - description: |- - The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and - dashes, with a maximum length of 64. - parameters: - $ref: '#/components/schemas/FunctionParameters' - deprecated: true - ChatCompletionMessageToolCall: - type: object - required: - - id - - type - - function - properties: - id: - type: string - description: The ID of the tool call. - type: - type: string - enum: - - function - description: The type of the tool. Currently, only `function` is supported. - function: - type: object - properties: - name: - type: string - description: The name of the function to call. - arguments: - type: string - description: |- - The arguments to call the function with, as generated by the model in JSON format. Note that - the model does not always generate valid JSON, and may hallucinate parameters not defined by - your function schema. Validate the arguments in your code before calling your function. - required: - - name - - arguments - description: The function that the model called. - ChatCompletionMessageToolCallsItem: - type: array - items: - $ref: '#/components/schemas/ChatCompletionMessageToolCall' - description: The tool calls generated by the model, such as function calls. - ChatCompletionNamedToolChoice: - type: object - required: - - type - - function - properties: - type: - type: string - enum: - - function - description: The type of the tool. Currently, only `function` is supported. - function: - type: object - properties: - name: - type: string - description: The name of the function to call. - required: - - name - description: Specifies a tool the model should use. Use to force the model to call a specific function. - ChatCompletionRequestAssistantMessage: - type: object - required: - - role - properties: - content: - type: string - nullable: true - description: |- - The contents of the assistant message. Required unless `tool_calls` or `function_call` is' - specified. - role: - type: string - enum: - - assistant - description: The role of the messages author, in this case `assistant`. - name: - type: string - description: |- - An optional name for the participant. Provides the model information to differentiate between - participants of the same role. - tool_calls: - $ref: '#/components/schemas/ChatCompletionMessageToolCallsItem' - function_call: - type: object - properties: - arguments: - type: string - description: |- - The arguments to call the function with, as generated by the model in JSON format. Note that - the model does not always generate valid JSON, and may hallucinate parameters not defined by - your function schema. Validate the arguments in your code before calling your function. - name: - type: string - description: The name of the function to call. - required: - - arguments - - name - description: |- - Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be - called, as generated by the model. - deprecated: true - ChatCompletionRequestFunctionMessage: - type: object - required: - - role - - content - - name - properties: - role: - type: string - enum: - - function - description: The role of the messages author, in this case `function`. - content: - type: string - nullable: true - description: The contents of the function message. - name: - type: string - description: The name of the function to call. - ChatCompletionRequestMessage: - oneOf: - - $ref: '#/components/schemas/ChatCompletionRequestSystemMessage' - - $ref: '#/components/schemas/ChatCompletionRequestUserMessage' - - $ref: '#/components/schemas/ChatCompletionRequestAssistantMessage' - - $ref: '#/components/schemas/ChatCompletionRequestToolMessage' - - $ref: '#/components/schemas/ChatCompletionRequestFunctionMessage' - x-oaiExpandable: true - ChatCompletionRequestMessageContentPart: - oneOf: - - $ref: '#/components/schemas/ChatCompletionRequestMessageContentPartText' - - $ref: '#/components/schemas/ChatCompletionRequestMessageContentPartImage' - x-oaiExpandable: true - ChatCompletionRequestMessageContentPartImage: - type: object - required: - - type - - image_url - properties: - type: - type: string - enum: - - image_url - description: The type of the content part. - image_url: - type: object - properties: - url: - anyOf: - - type: string - format: uri - - type: string - description: Either a URL of the image or the base64 encoded image data. - detail: - type: string - enum: - - auto - - low - - high - description: |- - Specifies the detail level of the image. Learn more in the - [Vision guide](/docs/guides/vision/low-or-high-fidelity-image-understanding). - default: auto - required: - - url - ChatCompletionRequestMessageContentPartText: - type: object - required: - - type - - text - properties: - type: - type: string - enum: - - text - - json_object - description: The type of the content part. - text: - type: string - description: The text content. - ChatCompletionRequestMessageContentParts: - type: array - items: - $ref: '#/components/schemas/ChatCompletionRequestMessageContentPart' - minItems: 1 - ChatCompletionRequestSystemMessage: - type: object - required: - - content - - role - properties: - content: - type: string - description: The contents of the system message. - x-oaiExpandable: true - role: - type: string - enum: - - system - description: The role of the messages author, in this case `system`. - name: - type: string - description: |- - An optional name for the participant. Provides the model information to differentiate between - participants of the same role. - ChatCompletionRequestToolMessage: - type: object - required: - - role - - content - - tool_call_id - properties: - role: - type: string - enum: - - tool - description: The role of the messages author, in this case `tool`. - content: - type: string - description: The contents of the tool message. - tool_call_id: - type: string - description: Tool call that this message is responding to. - ChatCompletionRequestUserMessage: - type: object - required: - - content - - role - properties: - content: - allOf: - - $ref: '#/components/schemas/ChatCompletionRequestUserMessageContent' - description: The contents of the system message. - x-oaiExpandable: true - role: - type: string - enum: - - user - - assistant - description: The role of the messages author, in this case `user`. - name: - type: string - description: |- - An optional name for the participant. Provides the model information to differentiate between - participants of the same role. - ChatCompletionRequestUserMessageContent: - oneOf: - - type: string - - $ref: '#/components/schemas/ChatCompletionRequestMessageContentParts' - ChatCompletionResponseMessage: - type: object - required: - - content - - role - properties: - content: - type: string - nullable: true - description: The contents of the message. - tool_calls: - $ref: '#/components/schemas/ChatCompletionMessageToolCallsItem' - role: - type: string - enum: - - assistant - description: The role of the author of this message. - function_call: - type: object - properties: - arguments: - type: string - description: |- - The arguments to call the function with, as generated by the model in JSON format. Note that - the model does not always generate valid JSON, and may hallucinate parameters not defined by - your function schema. Validate the arguments in your code before calling your function. - name: - type: string - description: The name of the function to call. - required: - - arguments - - name - description: Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model. - deprecated: true - ChatCompletionTokenLogprob: - type: object - required: - - token - - logprob - - bytes - - top_logprobs - properties: - token: - type: string - description: The token. - logprob: - type: number - format: double - description: The log probability of this token. - bytes: - type: array - items: - type: integer - format: int64 - nullable: true - description: |- - A list of integers representing the UTF-8 bytes representation of the token. Useful in - instances where characters are represented by multiple tokens and their byte representations - must be combined to generate the correct text representation. Can be `null` if there is no - bytes representation for the token. - top_logprobs: - type: array - items: - type: object - properties: - token: - type: string - description: The token. - logprob: - type: number - format: double - description: The log probability of this token. - bytes: - type: array - items: - type: integer - format: int64 - nullable: true - description: |- - A list of integers representing the UTF-8 bytes representation of the token. Useful in - instances where characters are represented by multiple tokens and their byte representations - must be combined to generate the correct text representation. Can be `null` if there is no - bytes representation for the token. - required: - - token - - logprob - - bytes - description: |- - List of the most likely tokens and their log probability, at this token position. In rare - cases, there may be fewer than the number of requested `top_logprobs` returned. - ChatCompletionTool: - type: object - required: - - type - - function - properties: - type: - type: string - enum: - - function - description: The type of the tool. Currently, only `function` is supported. - function: - $ref: '#/components/schemas/FunctionObject' - ChatCompletionToolChoiceOption: - oneOf: - - type: string - enum: - - none - - auto - - auto - - $ref: '#/components/schemas/ChatCompletionNamedToolChoice' - description: |- - Controls which (if any) function is called by the model. `none` means the model will not call a - function and instead generates a message. `auto` means the model can pick between generating a - message or calling a function. Specifying a particular function via - `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that - function. - - `none` is the default when no functions are present. `auto` is the default if functions are - present. - x-oaiExpandable: true - CompletionUsage: - type: object - required: - - prompt_tokens - - completion_tokens - - total_tokens - properties: - prompt_tokens: - type: integer - format: int64 - description: Number of tokens in the prompt. - completion_tokens: - type: integer - format: int64 - description: Number of tokens in the generated completion - total_tokens: - type: integer - format: int64 - description: Total number of tokens used in the request (prompt + completion). - description: Usage statistics for the completion request. - CreateAssistantFileRequest: - type: object - required: - - file_id - properties: - file_id: - type: string - description: |- - A [File](/docs/api-reference/files) ID (with `purpose="assistants"`) that the assistant should - use. Useful for tools like `retrieval` and `code_interpreter` that can access files. - CreateAssistantRequest: - type: object - required: - - model - properties: - model: - type: string - description: |- - ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to - see all of your available models, or see our [Model overview](/docs/models/overview) for - descriptions of them. - name: - type: string - nullable: true - maxLength: 256 - description: The name of the assistant. The maximum length is 256 characters. - description: - type: string - nullable: true - maxLength: 512 - description: The description of the assistant. The maximum length is 512 characters. - instructions: - type: string - nullable: true - maxLength: 32768 - description: The system instructions that the assistant uses. The maximum length is 32768 characters. - tools: - allOf: - - $ref: '#/components/schemas/CreateAssistantRequestToolsItem' - description: |- - A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. - Tools can be of types `code_interpreter`, `retrieval`, or `function`. - default: [] - file_ids: - type: array - items: - type: string - maxItems: 20 - description: |- - A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a - maximum of 20 files attached to the assistant. Files are ordered by their creation date in - ascending order. - default: [] - metadata: - type: object - additionalProperties: - type: string - nullable: true - description: |- - Set of 16 key-value pairs that can be attached to an object. This can be useful for storing - additional information about the object in a structured format. Keys can be a maximum of 64 - characters long and values can be a maxium of 512 characters long. - x-oaiTypeLabel: map - CreateAssistantRequestTool: - oneOf: - - $ref: '#/components/schemas/AssistantToolsCode' - - $ref: '#/components/schemas/AssistantToolsRetrieval' - - $ref: '#/components/schemas/AssistantToolsFunction' - x-oaiExpandable: true - CreateAssistantRequestToolsItem: - type: array - items: - $ref: '#/components/schemas/CreateAssistantRequestTool' - maxItems: 128 - CreateChatCompletionRequest: - type: object - required: - - messages - - model - properties: - messages: - type: array - items: - $ref: '#/components/schemas/ChatCompletionRequestMessage' - minItems: 1 - description: |- - A list of messages comprising the conversation so far. - [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb). - model: - anyOf: - - type: string - - type: string - enum: - - gpt-4-0125-preview - - gpt-4-turbo-preview - - gpt-4-1106-preview - - gpt-4-vision-preview - - gpt-4 - - gpt-4-0314 - - gpt-4-0613 - - gpt-4-32k - - gpt-4-32k-0314 - - gpt-4-32k-0613 - - gpt-3.5-turbo - - gpt-3.5-turbo-16k - - gpt-3.5-turbo-0301 - - gpt-3.5-turbo-0613 - - gpt-3.5-turbo-1106 - - gpt-3.5-turbo-16k-0613 - description: |- - ID of the model to use. See the [model endpoint compatibility](/docs/models/model-endpoint-compatibility) - table for details on which models work with the Chat API. - x-oaiTypeLabel: string - frequency_penalty: - type: number - format: double - nullable: true - minimum: -2 - maximum: 2 - description: |- - Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing - frequency in the text so far, decreasing the model's likelihood to repeat the same line - verbatim. - - [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) - default: 0 - logit_bias: - type: object - additionalProperties: - type: integer - format: int64 - nullable: true - description: |- - Modify the likelihood of specified tokens appearing in the completion. - - Accepts a JSON object that maps tokens (specified by their token ID in the tokenizer) to an - associated bias value from -100 to 100. Mathematically, the bias is added to the logits - generated by the model prior to sampling. The exact effect will vary per model, but values - between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 - should result in a ban or exclusive selection of the relevant token. - x-oaiTypeLabel: map - default: null - logprobs: - type: boolean - nullable: true - description: |- - Whether to return log probabilities of the output tokens or not. If true, returns the log - probabilities of each output token returned in the `content` of `message`. This option is - currently not available on the `gpt-4-vision-preview` model. - default: false - top_logprobs: - type: integer - format: int64 - nullable: true - minimum: 0 - maximum: 5 - description: |- - An integer between 0 and 5 specifying the number of most likely tokens to return at each token - position, each with an associated log probability. `logprobs` must be set to `true` if this - parameter is used. - max_tokens: - type: integer - format: int64 - nullable: true - minimum: 0 - description: |- - The maximum number of [tokens](/tokenizer) that can be generated in the chat completion. - - The total length of input tokens and generated tokens is limited by the model's context length. - [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) - for counting tokens. - default: 16 - n: - type: integer - format: int64 - nullable: true - minimum: 1 - maximum: 128 - description: |- - How many chat completion choices to generate for each input message. Note that you will be - charged based on the number of generated tokens across all of the choices. Keep `n` as `1` to - minimize costs. - default: 1 - presence_penalty: - type: number - format: double - nullable: true - minimum: -2 - maximum: 2 - description: |- - Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear - in the text so far, increasing the model's likelihood to talk about new topics. - - [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) - default: 0 - response_format: - type: object - properties: - type: - type: string - enum: - - text - - json_object - description: Must be one of `text` or `json_object`. - default: text - description: |- - An object specifying the format that the model must output. Compatible with - [GPT-4 Turbo](/docs/models/gpt-4-and-gpt-4-turbo) and `gpt-3.5-turbo-1106`. - - 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. - seed: - type: integer - format: int64 - nullable: true - minimum: -9223372036854776000 - maximum: 9223372036854776000 - description: |- - This feature is in Beta. - - If specified, our system will make a best effort to sample deterministically, such that - repeated requests with the same `seed` and parameters should return the same result. - - Determinism is not guaranteed, and you should refer to the `system_fingerprint` response - parameter to monitor changes in the backend. - x-oaiMeta: - beta: true - stop: - oneOf: - - $ref: '#/components/schemas/Stop' - nullable: true - description: Up to 4 sequences where the API will stop generating further tokens. - default: null - stream: - type: boolean - nullable: true - description: |- - If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only - [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) - as they become available, with the stream terminated by a `data: [DONE]` message. - [Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions). - default: false - temperature: - type: number - format: double - nullable: true - minimum: 0 - maximum: 2 - description: |- - What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output - more random, while lower values like 0.2 will make it more focused and deterministic. - - We generally recommend altering this or `top_p` but not both. - default: 1 - top_p: - type: number - format: double - nullable: true - minimum: 0 - maximum: 1 - description: |- - An alternative to sampling with temperature, called nucleus sampling, where the model considers - the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising - the top 10% probability mass are considered. - - We generally recommend altering this or `temperature` but not both. - default: 1 - tools: - type: array - items: - $ref: '#/components/schemas/ChatCompletionTool' - description: |- - A list of tools the model may call. Currently, only functions are supported as a tool. Use this - to provide a list of functions the model may generate JSON inputs for. - tool_choice: - $ref: '#/components/schemas/ChatCompletionToolChoiceOption' - user: - allOf: - - $ref: '#/components/schemas/User' - description: |- - A unique identifier representing your end-user, which can help OpenAI to monitor and detect - abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). - function_call: - anyOf: - - type: string - enum: - - none - - auto - - auto - - $ref: '#/components/schemas/ChatCompletionFunctionCallOption' - description: |- - Deprecated in favor of `tool_choice`. - - Controls which (if any) function is called by the model. `none` means the model will not call a - function and instead generates a message. `auto` means the model can pick between generating a - message or calling a function. Specifying a particular function via `{"name": "my_function"}` - forces the model to call that function. - - `none` is the default when no functions are present. `auto` is the default if functions are - present. - deprecated: true - x-oaiExpandable: true - functions: - type: array - items: - $ref: '#/components/schemas/ChatCompletionFunctions' - minItems: 1 - maxItems: 128 - description: |- - Deprecated in favor of `tools`. - - A list of functions the model may generate JSON inputs for. - deprecated: true - CreateChatCompletionResponse: - type: object - required: - - id - - choices - - created - - model - - object - properties: - id: - type: string - description: A unique identifier for the chat completion. - choices: - type: array - items: - type: object - properties: - finish_reason: - type: string - enum: - - stop - - length - - tool_calls - - content_filter - - function_call - - length - - content_filter - description: |- - The reason the model stopped generating tokens. This will be `stop` if the model hit a - natural stop point or a provided stop sequence, `length` if the maximum number of tokens - specified in the request was reached, `content_filter` if content was omitted due to a flag - from our content filters, `tool_calls` if the model called a tool, or `function_call` - (deprecated) if the model called a function. - index: - type: integer - format: int64 - description: The index of the choice in the list of choices. - message: - $ref: '#/components/schemas/ChatCompletionResponseMessage' - logprobs: - type: object - properties: - content: - type: array - items: - $ref: '#/components/schemas/ChatCompletionTokenLogprob' - nullable: true - required: - - content - nullable: true - description: Log probability information for the choice. - required: - - finish_reason - - index - - message - - logprobs - description: A list of chat completion choices. Can be more than one if `n` is greater than 1. - created: - type: integer - format: unixtime - description: The Unix timestamp (in seconds) of when the chat completion was created. - model: - type: string - description: The model used for the chat completion. - system_fingerprint: - type: string - description: |- - 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. - object: - type: string - enum: - - chat.completion - description: The object type, which is always `chat.completion`. - usage: - $ref: '#/components/schemas/CompletionUsage' - description: Represents a chat completion response returned by model, based on the provided input. - CreateCompletionRequest: - type: object - required: - - model - - prompt - properties: - model: - anyOf: - - type: string - - type: string - enum: - - gpt-3.5-turbo-instruct - - davinci-002 - - babbage-002 - description: |- - ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to - see all of your available models, or see our [Model overview](/docs/models/overview) for - descriptions of them. - x-oaiTypeLabel: string - prompt: - oneOf: - - $ref: '#/components/schemas/Prompt' - nullable: true - description: |- - The prompt(s) to generate completions for, encoded as a string, array of strings, array of - tokens, or array of token arrays. - - Note that <|endoftext|> is the document separator that the model sees during training, so if a - prompt is not specified the model will generate as if from the beginning of a new document. - default: <|endoftext|> - best_of: - type: integer - format: int64 - nullable: true - minimum: 0 - maximum: 20 - description: |- - Generates `best_of` completions server-side and returns the "best" (the one with the highest - log probability per token). Results cannot be streamed. - - When used with `n`, `best_of` controls the number of candidate completions and `n` specifies - how many to return – `best_of` must be greater than `n`. - - **Note:** Because this parameter generates many completions, it can quickly consume your token - quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. - default: 1 - echo: - type: boolean - nullable: true - description: Echo back the prompt in addition to the completion - default: false - frequency_penalty: - type: number - format: double - nullable: true - minimum: -2 - maximum: 2 - description: |- - Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing - frequency in the text so far, decreasing the model's likelihood to repeat the same line - verbatim. - - [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) - default: 0 - logit_bias: - type: object - additionalProperties: - type: integer - format: int64 - nullable: true - description: |- - Modify the likelihood of specified tokens appearing in the completion. - - Accepts a JSON object that maps tokens (specified by their token ID in the GPT tokenizer) to an - associated bias value from -100 to 100. You can use this [tokenizer tool](/tokenizer?view=bpe) - to convert text to token IDs. Mathematically, the bias is added to the logits generated by the - model prior to sampling. The exact effect will vary per model, but values between -1 and 1 - should decrease or increase likelihood of selection; values like -100 or 100 should result in a - ban or exclusive selection of the relevant token. - - As an example, you can pass `{"50256": -100}` to prevent the <|endoftext|> token from being - generated. - x-oaiTypeLabel: map - default: null - logprobs: - type: integer - format: int64 - nullable: true - minimum: 0 - maximum: 5 - description: |- - Include the log probabilities on the `logprobs` most likely tokens, as well the chosen tokens. - For example, if `logprobs` is 5, the API will return a list of the 5 most likely tokens. The - API will always return the `logprob` of the sampled token, so there may be up to `logprobs+1` - elements in the response. - - The maximum value for `logprobs` is 5. - default: null - max_tokens: - type: integer - format: int64 - nullable: true - minimum: 0 - description: |- - The maximum number of [tokens](/tokenizer) to generate in the completion. - - The token count of your prompt plus `max_tokens` cannot exceed the model's context length. - [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) - for counting tokens. - default: 16 - n: - type: integer - format: int64 - nullable: true - minimum: 1 - maximum: 128 - description: |- - How many completions to generate for each prompt. - - **Note:** Because this parameter generates many completions, it can quickly consume your token - quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. - default: 1 - presence_penalty: - type: number - format: double - nullable: true - minimum: -2 - maximum: 2 - description: |- - Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear - in the text so far, increasing the model's likelihood to talk about new topics. - - [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) - default: 0 - seed: - type: integer - format: int64 - nullable: true - minimum: -9223372036854776000 - maximum: 9223372036854776000 - description: |- - If specified, our system will make a best effort to sample deterministically, such that - repeated requests with the same `seed` and parameters should return the same result. - - Determinism is not guaranteed, and you should refer to the `system_fingerprint` response - parameter to monitor changes in the backend. - x-oaiMeta: - beta: true - stop: - oneOf: - - $ref: '#/components/schemas/Stop' - nullable: true - description: Up to 4 sequences where the API will stop generating further tokens. - default: null - stream: - type: boolean - nullable: true - description: |- - If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only - [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) - as they become available, with the stream terminated by a `data: [DONE]` message. - [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_stream_completions.ipynb). - default: false - suffix: - type: string - nullable: true - description: The suffix that comes after a completion of inserted text. - default: null - temperature: - type: number - format: double - nullable: true - minimum: 0 - maximum: 2 - description: |- - What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output - more random, while lower values like 0.2 will make it more focused and deterministic. - - We generally recommend altering this or `top_p` but not both. - default: 1 - top_p: - type: number - format: double - nullable: true - minimum: 0 - maximum: 1 - description: |- - An alternative to sampling with temperature, called nucleus sampling, where the model considers - the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising - the top 10% probability mass are considered. - - We generally recommend altering this or `temperature` but not both. - default: 1 - user: - allOf: - - $ref: '#/components/schemas/User' - description: |- - A unique identifier representing your end-user, which can help OpenAI to monitor and detect - abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). - CreateCompletionResponse: - type: object - required: - - id - - choices - - created - - model - - object - properties: - id: - type: string - description: A unique identifier for the completion. - choices: - type: array - items: - type: object - properties: - index: - type: integer - format: int64 - text: - type: string - logprobs: - type: object - properties: - tokens: - type: array - items: - type: string - token_logprobs: - type: array - items: - type: number - format: double - top_logprobs: - type: array - items: - type: object - additionalProperties: - type: integer - format: int64 - text_offset: - type: array - items: - type: integer - format: int64 - required: - - tokens - - token_logprobs - - top_logprobs - - text_offset - nullable: true - finish_reason: - type: string - enum: - - stop - - length - - tool_calls - - content_filter - - function_call - - length - - content_filter - description: |- - The reason the model stopped generating tokens. This will be `stop` if the model hit a - natural stop point or a provided stop sequence, or `content_filter` if content was omitted - due to a flag from our content filters, `length` if the maximum number of tokens specified - in the request was reached, or `content_filter` if content was omitted due to a flag from our - content filters. - required: - - index - - text - - logprobs - - finish_reason - description: The list of completion choices the model generated for the input. - created: - type: integer - format: unixtime - description: The Unix timestamp (in seconds) of when the completion was created. - model: - type: string - description: The model used for the completion. - system_fingerprint: - type: string - description: |- - 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. - object: - type: string - enum: - - text_completion - description: The object type, which is always `text_completion`. - usage: - allOf: - - $ref: '#/components/schemas/CompletionUsage' - description: Usage statistics for the completion request. - description: |- - Represents a completion response from the API. Note: both the streamed and non-streamed response - objects share the same shape (unlike the chat endpoint). - CreateEmbeddingRequest: - type: object - required: - - input - - model - properties: - input: - allOf: - - $ref: '#/components/schemas/CreateEmbeddingRequestInput' - description: |- - Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a - single request, pass an array of strings or array of token arrays. Each input must not exceed - the max input tokens for the model (8191 tokens for `text-embedding-ada-002`) and cannot be an - empty string. - [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) - for counting tokens. - x-oaiExpandable: true - model: - anyOf: - - type: string - - type: string - enum: - - text-embedding-ada-002 - - text-embedding-3-small - - text-embedding-3-large - description: |- - ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to - see all of your available models, or see our [Model overview](/docs/models/overview) for - descriptions of them. - x-oaiTypeLabel: string - encoding_format: - type: string - enum: - - float - - base64 - description: |- - The format to return the embeddings in. Can be either `float` or - [`base64`](https://pypi.org/project/pybase64/). - default: float - dimensions: - type: integer - format: int64 - minimum: 1 - description: |- - The number of dimensions the resulting output embeddings should have. Only supported in - `text-embedding-3` and later models. - user: - allOf: - - $ref: '#/components/schemas/User' - description: |- - A unique identifier representing your end-user, which can help OpenAI to monitor and detect - abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). - CreateEmbeddingRequestInput: - oneOf: - - type: string - - type: array - items: - type: string - - $ref: '#/components/schemas/TokenArrayItem' - - $ref: '#/components/schemas/TokenArrayArray' - CreateEmbeddingResponse: - type: object - required: - - data - - model - - object - - usage - properties: - data: - type: array - items: - $ref: '#/components/schemas/Embedding' - description: The list of embeddings generated by the model. - model: - type: string - description: The name of the model used to generate the embedding. - object: - type: string - enum: - - list - description: The object type, which is always "list". - usage: - type: object - properties: - prompt_tokens: - type: integer - format: int64 - description: The number of tokens used by the prompt. - total_tokens: - type: integer - format: int64 - description: The total number of tokens used by the request. - required: - - prompt_tokens - - total_tokens - description: The usage information for the request. - CreateFileRequestMultiPart: - type: object - required: - - file - - purpose - properties: - file: - type: string - format: binary - description: The file object (not file name) to be uploaded. - purpose: - type: string - enum: - - fine-tune - - assistants - description: |- - The intended purpose of the uploaded file. Use "fine-tune" for - [Fine-tuning](/docs/api-reference/fine-tuning) and "assistants" for - [Assistants](/docs/api-reference/assistants) and [Messages](/docs/api-reference/messages). This - allows us to validate the format of the uploaded file is correct for fine-tuning. - CreateFineTuneRequest: - type: object - required: - - training_file - properties: - training_file: - type: string - description: |- - The ID of an uploaded file that contains training data. - - See [upload file](/docs/api-reference/files/upload) for how to upload a file. - - Your dataset must be formatted as a JSONL file, where each training example is a JSON object - with the keys "prompt" and "completion". Additionally, you must upload your file with the - purpose `fine-tune`. - - See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more - details. - validation_file: - type: string - nullable: true - description: |- - The ID of an uploaded file that contains validation data. - - If you provide this file, the data is used to generate validation metrics periodically during - fine-tuning. These metrics can be viewed in the - [fine-tuning results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model). - Your train and validation data should be mutually exclusive. - - Your dataset must be formatted as a JSONL file, where each validation example is a JSON object - with the keys "prompt" and "completion". Additionally, you must upload your file with the - purpose `fine-tune`. - - See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more - details. - model: - anyOf: - - type: string - - type: string - enum: - - ada - - babbage - - curie - - davinci - nullable: true - description: |- - The name of the base model to fine-tune. You can select one of "ada", "babbage", "curie", - "davinci", or a fine-tuned model created after 2022-04-21 and before 2023-08-22. To learn more - about these models, see the [Models](/docs/models) documentation. - x-oaiTypeLabel: string - n_epochs: - type: integer - format: int64 - nullable: true - description: |- - The number of epochs to train the model for. An epoch refers to one full cycle through the - training dataset. - default: 4 - batch_size: - type: integer - format: int64 - nullable: true - description: |- - The batch size to use for training. The batch size is the number of training examples used to - train a single forward and backward pass. - - By default, the batch size will be dynamically configured to be ~0.2% of the number of examples - in the training set, capped at 256 - in general, we've found that larger batch sizes tend to - work better for larger datasets. - default: null - learning_rate_multiplier: - type: number - format: double - nullable: true - description: |- - The learning rate multiplier to use for training. The fine-tuning learning rate is the original - learning rate used for pretraining multiplied by this value. - - By default, the learning rate multiplier is the 0.05, 0.1, or 0.2 depending on final - `batch_size` (larger learning rates tend to perform better with larger batch sizes). We - recommend experimenting with values in the range 0.02 to 0.2 to see what produces the best - results. - default: null - prompt_loss_rate: - type: number - format: double - nullable: true - description: |- - The weight to use for loss on the prompt tokens. This controls how much the model tries to - learn to generate the prompt (as compared to the completion which always has a weight of 1.0), - and can add a stabilizing effect to training when completions are short. - - If prompts are extremely long (relative to completions), it may make sense to reduce this - weight so as to avoid over-prioritizing learning the prompt. - default: 0.01 - compute_classification_metrics: - type: boolean - nullable: true - description: |- - If set, we calculate classification-specific metrics such as accuracy and F-1 score using the - validation set at the end of every epoch. These metrics can be viewed in the - [results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model). - - In order to compute classification metrics, you must provide a `validation_file`. Additionally, - you must specify `classification_n_classes` for multiclass classification or - `classification_positive_class` for binary classification. - default: false - classification_n_classes: - type: integer - format: int64 - nullable: true - description: |- - The number of classes in a classification task. - - This parameter is required for multiclass classification. - default: null - classification_positive_class: - type: string - nullable: true - description: |- - The positive class in binary classification. - - This parameter is needed to generate precision, recall, and F1 metrics when doing binary - classification. - default: null - classification_betas: - type: array - items: - type: number - format: double - nullable: true - description: |- - If this is provided, we calculate F-beta scores at the specified beta values. The F-beta score - is a generalization of F-1 score. This is only used for binary classification. - - With a beta of 1 (i.e. the F-1 score), precision and recall are given the same weight. A larger - beta score puts more weight on recall and less on precision. A smaller beta score puts more - weight on precision and less on recall. - default: null - suffix: - oneOf: - - $ref: '#/components/schemas/SuffixString' - nullable: true - description: |- - 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 - `ada:ft-your-org:custom-model-name-2022-02-15-04-21-04`. - default: null - CreateFineTuningJobRequest: - type: object - required: - - training_file - - model - properties: - training_file: - type: string - description: |- - The ID of an uploaded file that contains training data. - - See [upload file](/docs/api-reference/files/upload) for how to upload a file. - - Your dataset must be formatted as a JSONL file. Additionally, you must upload your file with - the purpose `fine-tune`. - - See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. - validation_file: - type: string - nullable: true - description: |- - The ID of an uploaded file that contains validation data. - - If you provide this file, the data is used to generate validation metrics periodically during - fine-tuning. These metrics can be viewed in the fine-tuning results file. The same data should - not be present in both train and validation files. - - Your dataset must be formatted as a JSONL file. You must upload your file with the purpose - `fine-tune`. - - See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. - model: - anyOf: - - type: string - - type: string - enum: - - babbage-002 - - davinci-002 - - gpt-3.5-turbo - description: |- - The name of the model to fine-tune. You can select one of the - [supported models](/docs/guides/fine-tuning/what-models-can-be-fine-tuned). - x-oaiTypeLabel: string - hyperparameters: - type: object - properties: - n_epochs: - anyOf: - - type: string - enum: - - auto - - low - - high - - $ref: '#/components/schemas/NEpochs' - description: |- - The number of epochs to train the model for. An epoch refers to one full cycle through the - training dataset. - default: auto - description: The hyperparameters used for the fine-tuning job. - suffix: - oneOf: - - $ref: '#/components/schemas/SuffixString' - nullable: true - description: |- - 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`. - default: null - CreateImageEditRequestMultiPart: - type: object - required: - - image - - prompt - properties: - image: - type: string - format: binary - description: |- - The image to edit. Must be a valid PNG file, less than 4MB, and square. If mask is not - provided, image must have transparency, which will be used as the mask. - prompt: - type: string - maxLength: 1000 - description: A text description of the desired image(s). The maximum length is 1000 characters. - mask: - type: string - format: binary - description: |- - An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where - `image` should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions - as `image`. - model: - anyOf: - - type: string - - type: string - enum: - - dall-e-2 - description: The model to use for image generation. Only `dall-e-2` is supported at this time. - x-oaiTypeLabel: string - default: dall-e-2 - n: - oneOf: - - $ref: '#/components/schemas/ImagesN' - nullable: true - description: The number of images to generate. Must be between 1 and 10. - default: 1 - size: - type: string - enum: - - 256x256 - - 512x512 - - 1024x1024 - - 512x512 - - 1024x1024 - nullable: true - description: The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`. - default: 1024x1024 - response_format: - type: string - enum: - - url - - b64_json - - b64_json - nullable: true - description: The format in which the generated images are returned. Must be one of `url` or `b64_json`. - default: url - user: - allOf: - - $ref: '#/components/schemas/User' - description: |- - A unique identifier representing your end-user, which can help OpenAI to monitor and detect - abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). - CreateImageRequest: - type: object - required: - - prompt - properties: - prompt: - type: string - description: |- - A text description of the desired image(s). The maximum length is 1000 characters for - `dall-e-2` and 4000 characters for `dall-e-3`. - model: - anyOf: - - type: string - - type: string - enum: - - dall-e-2 - - dall-e-3 - description: The model to use for image generation. - x-oaiTypeLabel: string - default: dall-e-2 - n: - oneOf: - - $ref: '#/components/schemas/ImagesN' - nullable: true - description: |- - The number of images to generate. Must be between 1 and 10. For `dall-e-3`, only `n=1` is - supported. - default: 1 - quality: - type: string - enum: - - standard - - hd - nullable: true - description: |- - The quality of the image that will be generated. `hd` creates images with finer details and - greater consistency across the image. This param is only supported for `dall-e-3`. - default: standard - response_format: - type: string - enum: - - url - - b64_json - nullable: true - description: The format in which the generated images are returned. Must be one of `url` or `b64_json`. - default: url - size: - type: string - enum: - - 256x256 - - 512x512 - - 1024x1024 - - 1792x1024 - - 1024x1792 - nullable: true - description: |- - 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. - default: 1024x1024 - style: - type: string - enum: - - vivid - - natural - nullable: true - description: |- - The style of the generated images. Must be one of `vivid` or `natural`. Vivid causes the model - to lean towards generating hyper-real and dramatic images. Natural causes the model to produce - more natural, less hyper-real looking images. This param is only supported for `dall-e-3`. - default: vivid - user: - allOf: - - $ref: '#/components/schemas/User' - description: |- - A unique identifier representing your end-user, which can help OpenAI to monitor and detect - abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). - CreateImageVariationRequestMultiPart: - type: object - required: - - image - properties: - image: - type: string - format: binary - description: |- - The image to use as the basis for the variation(s). Must be a valid PNG file, less than 4MB, - and square. - model: - anyOf: - - type: string - - type: string - enum: - - dall-e-2 - description: The model to use for image generation. Only `dall-e-2` is supported at this time. - x-oaiTypeLabel: string - default: dall-e-2 - n: - oneOf: - - $ref: '#/components/schemas/ImagesN' - nullable: true - description: The number of images to generate. Must be between 1 and 10. - default: 1 - response_format: - type: string - enum: - - url - - b64_json - - b64_json - nullable: true - description: The format in which the generated images are returned. Must be one of `url` or `b64_json`. - default: url - size: - type: string - enum: - - 256x256 - - 512x512 - - 1024x1024 - - 512x512 - - 1024x1024 - nullable: true - description: The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`. - default: 1024x1024 - user: - allOf: - - $ref: '#/components/schemas/User' - description: |- - A unique identifier representing your end-user, which can help OpenAI to monitor and detect - abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). - CreateMessageRequest: - type: object - required: - - role - - content - properties: - role: - type: string - enum: - - user - - assistant - description: The role of the entity that is creating the message. Currently only `user` is supported. - content: - type: string - minLength: 1 - maxLength: 32768 - description: The content of the message. - file_ids: - type: array - items: - type: string - minItems: 1 - maxItems: 10 - description: |- - A list of [File](/docs/api-reference/files) IDs that the message should use. There can be a - maximum of 10 files attached to a message. Useful for tools like `retrieval` and - `code_interpreter` that can access and use files. - default: [] - metadata: - type: object - additionalProperties: - type: string - nullable: true - description: |- - Set of 16 key-value pairs that can be attached to an object. This can be useful for storing - additional information about the object in a structured format. Keys can be a maximum of 64 - characters long and values can be a maxium of 512 characters long. - x-oaiTypeLabel: map - CreateModerationRequest: - type: object - required: - - input - properties: - input: - allOf: - - $ref: '#/components/schemas/CreateModerationRequestInput' - description: The input text to classify - model: - anyOf: - - type: string - - type: string - enum: - - text-moderation-latest - - text-moderation-stable - description: |- - Two content moderations models are available: `text-moderation-stable` and - `text-moderation-latest`. The default is `text-moderation-latest` which will be automatically - upgraded over time. This ensures you are always using our most accurate model. If you use - `text-moderation-stable`, we will provide advanced notice before updating the model. Accuracy - of `text-moderation-stable` may be slightly lower than for `text-moderation-latest`. - x-oaiTypeLabel: string - default: text-moderation-latest - CreateModerationRequestInput: - oneOf: - - type: string - - type: array - items: - type: string - CreateModerationResponse: - type: object - required: - - id - - model - - results - properties: - id: - type: string - description: The unique identifier for the moderation request. - model: - type: string - description: The model used to generate the moderation results. - results: - type: array - items: - type: object - properties: - flagged: - type: boolean - description: Whether the content violates [OpenAI's usage policies](/policies/usage-policies). - categories: - type: object - properties: - hate: - type: boolean - description: |- - Content that expresses, incites, or promotes hate based on race, gender, ethnicity, - religion, nationality, sexual orientation, disability status, or caste. Hateful content - aimed at non-protected groups (e.g., chess players) is harrassment. - hate/threatening: - type: boolean - description: |- - Hateful content that also includes violence or serious harm towards the targeted group - based on race, gender, ethnicity, religion, nationality, sexual orientation, disability - status, or caste. - harassment: - type: boolean - description: Content that expresses, incites, or promotes harassing language towards any target. - harassment/threatening: - type: boolean - description: Harassment content that also includes violence or serious harm towards any target. - self-harm: - type: boolean - description: |- - Content that promotes, encourages, or depicts acts of self-harm, such as suicide, cutting, - and eating disorders. - self-harm/intent: - type: boolean - description: |- - Content where the speaker expresses that they are engaging or intend to engage in acts of - self-harm, such as suicide, cutting, and eating disorders. - self-harm/instructions: - type: boolean - description: |- - Content that encourages performing acts of self-harm, such as suicide, cutting, and eating - disorders, or that gives instructions or advice on how to commit such acts. - sexual: - type: boolean - description: |- - Content meant to arouse sexual excitement, such as the description of sexual activity, or - that promotes sexual services (excluding sex education and wellness). - sexual/minors: - type: boolean - description: Sexual content that includes an individual who is under 18 years old. - violence: - type: boolean - description: Content that depicts death, violence, or physical injury. - violence/graphic: - type: boolean - description: Content that depicts death, violence, or physical injury in graphic detail. - required: - - hate - - hate/threatening - - harassment - - harassment/threatening - - self-harm - - self-harm/intent - - self-harm/instructions - - sexual - - sexual/minors - - violence - - violence/graphic - description: A list of the categories, and whether they are flagged or not. - category_scores: - type: object - properties: - hate: - type: number - format: double - description: The score for the category 'hate'. - hate/threatening: - type: number - format: double - description: The score for the category 'hate/threatening'. - harassment: - type: number - format: double - description: The score for the category 'harassment'. - harassment/threatening: - type: number - format: double - description: The score for the category 'harassment/threatening'. - self-harm: - type: number - format: double - description: The score for the category 'self-harm'. - self-harm/intent: - type: number - format: double - description: The score for the category 'self-harm/intent'. - self-harm/instructions: - type: number - format: double - description: The score for the category 'self-harm/instructive'. - sexual: - type: number - format: double - description: The score for the category 'sexual'. - sexual/minors: - type: number - format: double - description: The score for the category 'sexual/minors'. - violence: - type: number - format: double - description: The score for the category 'violence'. - violence/graphic: - type: number - format: double - description: The score for the category 'violence/graphic'. - required: - - hate - - hate/threatening - - harassment - - harassment/threatening - - self-harm - - self-harm/intent - - self-harm/instructions - - sexual - - sexual/minors - - violence - - violence/graphic - description: A list of the categories along with their scores as predicted by model. - required: - - flagged - - categories - - category_scores - description: A list of moderation objects. - description: Represents policy compliance report by OpenAI's content moderation model against a given input. - CreateRunRequest: - type: object - required: - - assistant_id - properties: - assistant_id: - type: string - description: The ID of the [assistant](/docs/api-reference/assistants) to use to execute this run. - model: - type: string - nullable: true - description: |- - The ID of the [Model](/docs/api-reference/models) to be used to execute this run. If a value - is provided here, it will override the model associated with the assistant. If not, the model - associated with the assistant will be used. - instructions: - type: string - nullable: true - description: |- - Overrides the [instructions](/docs/api-reference/assistants/createAssistant) of the assistant. - This is useful for modifying the behavior on a per-run basis. - additional_instructions: - type: string - nullable: true - description: |- - Appends additional instructions at the end of the instructions for the run. This is useful for - modifying the behavior on a per-run basis without overriding other instructions. - tools: - type: object - allOf: - - $ref: '#/components/schemas/CreateRunRequestToolsItem' - nullable: true - description: |- - Override the tools the assistant can use for this run. This is useful for modifying the - behavior on a per-run basis. - metadata: - type: object - additionalProperties: - type: string - nullable: true - description: |- - Set of 16 key-value pairs that can be attached to an object. This can be useful for storing - additional information about the object in a structured format. Keys can be a maximum of 64 - characters long and values can be a maxium of 512 characters long. - x-oaiTypeLabel: map - CreateRunRequestTool: - oneOf: - - $ref: '#/components/schemas/AssistantToolsCode' - - $ref: '#/components/schemas/AssistantToolsRetrieval' - - $ref: '#/components/schemas/AssistantToolsFunction' - x-oaiExpandable: true - CreateRunRequestToolsItem: - type: array - items: - $ref: '#/components/schemas/CreateRunRequestTool' - maxItems: 20 - CreateSpeechRequest: - type: object - required: - - model - - input - - voice - properties: - model: - anyOf: - - type: string - - type: string - enum: - - tts-1 - - tts-1-hd - description: 'One of the available [TTS models](/docs/models/tts): `tts-1` or `tts-1-hd`' - x-oaiTypeLabel: string - input: - type: string - maxLength: 4096 - description: The text to generate audio for. The maximum length is 4096 characters. - voice: - type: string - enum: - - alloy - - echo - - fable - - onyx - - nova - - shimmer - description: |- - The voice to use when generating the audio. Supported voices are `alloy`, `echo`, `fable`, - `onyx`, `nova`, and `shimmer`. Previews of the voices are available in the - [Text to speech guide](/docs/guides/text-to-speech/voice-options). - response_format: - type: string - enum: - - mp3 - - opus - - aac - - flac - description: The format to audio in. Supported formats are `mp3`, `opus`, `aac`, and `flac`. - default: mp3 - speed: - type: number - format: double - minimum: 0.25 - maximum: 4 - description: The speed of the generated audio. Select a value from `0.25` to `4.0`. `1.0` is the default. - default: 1 - CreateThreadAndRunRequest: - type: object - required: - - assistant_id - properties: - assistant_id: - type: string - description: The ID of the [assistant](/docs/api-reference/assistants) to use to execute this run. - thread: - allOf: - - $ref: '#/components/schemas/CreateThreadRequest' - description: If no thread is provided, an empty thread will be created. - model: - type: string - nullable: true - description: |- - The ID of the [Model](/docs/api-reference/models) to be used to execute this run. If a value is - provided here, it will override the model associated with the assistant. If not, the model - associated with the assistant will be used. - instructions: - type: string - nullable: true - description: |- - Override the default system message of the assistant. This is useful for modifying the behavior - on a per-run basis. - tools: - type: object - allOf: - - $ref: '#/components/schemas/CreateRunRequestToolsItem' - nullable: true - description: |- - Override the tools the assistant can use for this run. This is useful for modifying the - behavior on a per-run basis. - metadata: - type: object - additionalProperties: - type: string - nullable: true - description: |- - Set of 16 key-value pairs that can be attached to an object. This can be useful for storing - additional information about the object in a structured format. Keys can be a maximum of 64 - characters long and values can be a maxium of 512 characters long. - x-oaiTypeLabel: map - CreateThreadRequest: - type: object - properties: - messages: - type: array - items: - $ref: '#/components/schemas/CreateMessageRequest' - description: A list of [messages](/docs/api-reference/messages) to start the thread with. - metadata: - type: object - additionalProperties: - type: string - nullable: true - description: |- - Set of 16 key-value pairs that can be attached to an object. This can be useful for storing - additional information about the object in a structured format. Keys can be a maximum of 64 - characters long and values can be a maxium of 512 characters long. - CreateTranscriptionRequestMultiPart: - type: object - required: - - file - - model - properties: - file: - type: string - format: binary - description: |- - The audio file object (not file name) to transcribe, in one of these formats: flac, mp3, mp4, - mpeg, mpga, m4a, ogg, wav, or webm. - x-oaiTypeLabel: file - model: - anyOf: - - type: string - - type: string - enum: - - whisper-1 - description: ID of the model to use. Only `whisper-1` is currently available. - x-oaiTypeLabel: string - language: - type: string - description: |- - The language of the input audio. Supplying the input language in - [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) format will improve accuracy - and latency. - prompt: - type: string - description: |- - An optional text to guide the model's style or continue a previous audio segment. The - [prompt](/docs/guides/speech-to-text/prompting) should match the audio language. - response_format: - type: string - enum: - - json - - text - - srt - - verbose_json - - vtt - - text - - srt - - verbose_json - - vtt - description: |- - The format of the transcript output, in one of these options: json, text, srt, verbose_json, or - vtt. - default: json - temperature: - type: number - format: double - minimum: 0 - maximum: 1 - description: |- - The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more - random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, - the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to - automatically increase the temperature until certain thresholds are hit. - default: 0 - CreateTranscriptionResponse: - type: object - required: - - text - properties: - text: - type: string - description: The transcribed text for the provided audio data. - task: - type: string - enum: - - transcribe - description: The label that describes which operation type generated the accompanying response data. - language: - type: string - description: The spoken language that was detected in the audio data. - duration: - type: number - format: double - description: The total duration of the audio processed to produce accompanying transcription information. - segments: - type: array - items: - $ref: '#/components/schemas/AudioSegment' - description: |- - A collection of information about the timing, probabilities, and other detail of each processed - audio segment. - CreateTranslationRequestMultiPart: - type: object - required: - - file - - model - properties: - file: - type: string - format: binary - description: |- - The audio file object (not file name) to translate, in one of these formats: flac, mp3, mp4, - mpeg, mpga, m4a, ogg, wav, or webm. - x-oaiTypeLabel: file - model: - anyOf: - - type: string - - type: string - enum: - - whisper-1 - description: ID of the model to use. Only `whisper-1` is currently available. - x-oaiTypeLabel: string - prompt: - type: string - description: |- - An optional text to guide the model's style or continue a previous audio segment. The - [prompt](/docs/guides/speech-to-text/prompting) should match the audio language. - response_format: - type: string - enum: - - json - - text - - srt - - verbose_json - - vtt - - text - - srt - - verbose_json - - vtt - description: |- - The format of the transcript output, in one of these options: json, text, srt, verbose_json, or - vtt. - default: json - temperature: - type: number - format: double - minimum: 0 - maximum: 1 - description: |- - The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more - random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, - the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to - automatically increase the temperature until certain thresholds are hit. - default: 0 - CreateTranslationResponse: - type: object - required: - - text - properties: - text: - type: string - description: The translated text for the provided audio data. - task: - type: string - enum: - - translate - description: The label that describes which operation type generated the accompanying response data. - language: - type: string - description: The spoken language that was detected in the audio data. - duration: - type: number - format: double - description: The total duration of the audio processed to produce accompanying translation information. - segments: - type: array - items: - $ref: '#/components/schemas/AudioSegment' - description: |- - A collection of information about the timing, probabilities, and other detail of each processed - audio segment. - DeleteAssistantFileResponse: - type: object - required: - - id - - deleted - - object - properties: - id: - type: string - deleted: - type: boolean - object: - type: string - enum: - - assistant.file.deleted - description: |- - Deletes the association between the assistant and the file, but does not delete the - [File](/docs/api-reference/files) object itself. - DeleteAssistantResponse: - type: object - required: - - id - - deleted - - object - properties: - id: - type: string - deleted: - type: boolean - object: - type: string - enum: - - assistant.deleted - DeleteFileResponse: - type: object - required: - - id - - object - - deleted - properties: - id: - type: string - object: - type: string - enum: - - file - deleted: - type: boolean - DeleteModelResponse: - type: object - required: - - id - - deleted - - object - properties: - id: - type: string - deleted: - type: boolean - object: - type: string - enum: - - model - DeleteThreadResponse: - type: object - required: - - id - - deleted - - object - properties: - id: - type: string - deleted: - type: boolean - object: - type: string - enum: - - thread.deleted - Embedding: - type: object - required: - - index - - embedding - - object - properties: - index: - type: integer - format: int64 - description: The index of the embedding in the list of embeddings. - embedding: - anyOf: - - type: array - items: - type: number - format: double - - type: string - description: |- - The embedding vector, which is a list of floats. The length of vector depends on the model as - listed in the [embedding guide](/docs/guides/embeddings). - object: - type: string - enum: - - embedding - description: The object type, which is always "embedding". - description: Represents an embedding vector returned by embedding endpoint. - Error: - type: object - required: - - type - - message - - param - - code - properties: - type: - type: string - message: - type: string - param: - type: string - nullable: true - code: - type: string - nullable: true - ErrorResponse: - type: object - required: - - error - properties: - error: - $ref: '#/components/schemas/Error' - FineTune: - type: object - required: - - id - - object - - created_at - - updated_at - - model - - fine_tuned_model - - organization_id - - status - - hyperparams - - training_files - - validation_files - - result_files - properties: - id: - type: string - description: The object identifier, which can be referenced in the API endpoints. - object: - type: string - enum: - - fine-tune - - fine-tune-results - - assistants - - assistants_output - description: The object type, which is always "fine-tune". - created_at: - type: integer - format: unixtime - description: The Unix timestamp (in seconds) for when the fine-tuning job was created. - updated_at: - type: integer - format: unixtime - description: The Unix timestamp (in seconds) for when the fine-tuning job was last updated. - model: - type: string - description: The base model that is being fine-tuned. - fine_tuned_model: - type: string - nullable: true - description: The name of the fine-tuned model that is being created. - organization_id: - type: string - description: The organization that owns the fine-tuning job. - status: - type: string - enum: - - created - - pending - - running - - succeeded - - failed - - cancelled - - running - - succeeded - - failed - - cancelled - description: |- - The current status of the fine-tuning job, which can be either `created`, `running`, - `succeeded`, `failed`, or `cancelled`. - hyperparams: - type: object - properties: - n_epochs: - type: integer - format: int64 - description: |- - The number of epochs to train the model for. An epoch refers to one full cycle through the - training dataset. - batch_size: - type: integer - format: int64 - description: |- - The batch size to use for training. The batch size is the number of training examples used to - train a single forward and backward pass. - prompt_loss_weight: - type: number - format: double - description: The weight to use for loss on the prompt tokens. - learning_rate_multiplier: - type: number - format: double - description: The learning rate multiplier to use for training. - compute_classification_metrics: - type: boolean - description: The classification metrics to compute using the validation dataset at the end of every epoch. - classification_positive_class: - type: string - description: The positive class to use for computing classification metrics. - classification_n_classes: - type: integer - format: int64 - description: The number of classes to use for computing classification metrics. - required: - - n_epochs - - batch_size - - prompt_loss_weight - - learning_rate_multiplier - description: |- - The hyperparameters used for the fine-tuning job. See the - [fine-tuning guide](/docs/guides/legacy-fine-tuning/hyperparameters) for more details. - training_files: - type: array - items: - $ref: '#/components/schemas/OpenAIFile' - description: The list of files used for training. - validation_files: - type: array - items: - $ref: '#/components/schemas/OpenAIFile' - description: The list of files used for validation. - result_files: - type: array - items: - $ref: '#/components/schemas/OpenAIFile' - description: The compiled results files for the fine-tuning job. - events: - type: array - items: - $ref: '#/components/schemas/FineTuneEvent' - description: The list of events that have been observed in the lifecycle of the FineTune job. - description: The `FineTune` object represents a legacy fine-tune job that has been created through the API. - deprecated: true - FineTuneEvent: - type: object - required: - - object - - created_at - - level - - message - properties: - object: - type: string - created_at: - type: integer - format: unixtime - level: - type: string - message: - type: string - FineTuningEvent: - type: object - required: - - object - - created_at - - level - - message - properties: - object: - type: string - created_at: - type: integer - format: unixtime - level: - type: string - message: - type: string - data: - type: object - additionalProperties: {} - nullable: true - type: - type: string - enum: - - message - - metrics - FineTuningJob: - type: object - required: - - id - - object - - created_at - - finished_at - - model - - fine_tuned_model - - organization_id - - status - - hyperparameters - - training_file - - validation_file - - result_files - - trained_tokens - - error - properties: - id: - type: string - description: The object identifier, which can be referenced in the API endpoints. - object: - type: string - enum: - - fine_tuning.job - description: The object type, which is always "fine_tuning.job". - created_at: - type: integer - format: unixtime - description: The Unix timestamp (in seconds) for when the fine-tuning job was created. - finished_at: - type: string - format: date-time - nullable: true - description: |- - The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be - null if the fine-tuning job is still running. - model: - type: string - description: The base model that is being fine-tuned. - fine_tuned_model: - type: string - nullable: true - description: |- - The name of the fine-tuned model that is being created. The value will be null if the - fine-tuning job is still running. - organization_id: - type: string - description: The organization that owns the fine-tuning job. - status: - type: string - enum: - - created - - pending - - running - - succeeded - - failed - - cancelled - - running - - succeeded - - failed - - cancelled - description: |- - The current status of the fine-tuning job, which can be either `created`, `pending`, `running`, - `succeeded`, `failed`, or `cancelled`. - hyperparameters: - type: object - properties: - n_epochs: - anyOf: - - type: string - enum: - - auto - - low - - high - - $ref: '#/components/schemas/NEpochs' - description: |- - The number of epochs to train the model for. An epoch refers to one full cycle through the - training dataset. - - "Auto" decides the optimal number of epochs based on the size of the dataset. If setting the - number manually, we support any number between 1 and 50 epochs. - default: auto - description: |- - The hyperparameters used for the fine-tuning job. See the - [fine-tuning guide](/docs/guides/fine-tuning) for more details. - training_file: - type: string - description: |- - The file ID used for training. You can retrieve the training data with the - [Files API](/docs/api-reference/files/retrieve-contents). - validation_file: - type: string - nullable: true - description: |- - The file ID used for validation. You can retrieve the validation results with the - [Files API](/docs/api-reference/files/retrieve-contents). - result_files: - type: array - items: - type: string - description: |- - The compiled results file ID(s) for the fine-tuning job. You can retrieve the results with the - [Files API](/docs/api-reference/files/retrieve-contents). - trained_tokens: - type: integer - format: int64 - nullable: true - description: |- - The total number of billable tokens processed by this fine tuning job. The value will be null - if the fine-tuning job is still running. - error: - type: object - properties: - message: - type: string - description: A human-readable error message. - code: - type: string - description: A machine-readable error code. - param: - type: string - nullable: true - description: |- - The parameter that was invalid, usually `training_file` or `validation_file`. This field - will be null if the failure was not parameter-specific. - nullable: true - description: |- - For fine-tuning jobs that have `failed`, this will contain more information on the cause of the - failure. - FineTuningJobEvent: - type: object - required: - - id - - object - - created_at - - level - - message - properties: - id: - type: string - object: - type: string - created_at: - type: integer - format: unixtime - level: - type: string - enum: - - info - - warn - - error - message: - type: string - FunctionObject: - type: object - required: - - name - properties: - description: - type: string - description: |- - A description of what the function does, used by the model to choose when and how to call the - function. - name: - type: string - description: |- - The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and - dashes, with a maximum length of 64. - parameters: - $ref: '#/components/schemas/FunctionParameters' - FunctionParameters: - type: object - additionalProperties: {} - description: |- - The parameters the functions accepts, described as a JSON Schema object. See the - [guide](/docs/guides/gpt/function-calling) for examples, and the - [JSON Schema reference](https://json-schema.org/understanding-json-schema/) for documentation - about the format.\n\nTo describe a function that accepts no parameters, provide the value - `{\"type\": \"object\", \"properties\": {}}`. - Image: - type: object - properties: - b64_json: - type: string - format: base64 - description: The base64-encoded JSON of the generated image, if `response_format` is `b64_json`. - url: - type: string - format: uri - description: The URL of the generated image, if `response_format` is `url` (default). - revised_prompt: - type: string - description: The prompt that was used to generate the image, if there was any revision to the prompt. - description: Represents the url or the content of an image generated by the OpenAI API. - ImagesN: - type: integer - format: int64 - minimum: 1 - maximum: 10 - ImagesResponse: - type: object - required: - - created - - data - properties: - created: - type: integer - format: unixtime - data: - type: array - items: - $ref: '#/components/schemas/Image' - ListAssistantFilesResponse: - type: object - required: - - object - - data - - first_id - - last_id - - has_more - properties: - object: - type: string - enum: - - list - data: - type: array - items: - $ref: '#/components/schemas/AssistantFileObject' - first_id: - type: string - last_id: - type: string - has_more: - type: boolean - ListAssistantsResponse: - type: object - required: - - object - - data - - first_id - - last_id - - has_more - properties: - object: - type: string - enum: - - list - data: - type: array - items: - $ref: '#/components/schemas/AssistantObject' - first_id: - type: string - last_id: - type: string - has_more: - type: boolean - ListFilesResponse: - type: object - required: - - data - - object - properties: - data: - type: array - items: - $ref: '#/components/schemas/OpenAIFile' - object: - type: string - enum: - - list - ListFineTuneEventsResponse: - type: object - required: - - object - - data - properties: - object: - type: string - data: - type: array - items: - $ref: '#/components/schemas/FineTuneEvent' - ListFineTunesResponse: - type: object - required: - - object - - data - properties: - object: - type: string - data: - type: array - items: - $ref: '#/components/schemas/FineTune' - ListFineTuningJobEventsResponse: - type: object - required: - - object - - data - properties: - object: - type: string - data: - type: array - items: - $ref: '#/components/schemas/FineTuningJobEvent' - ListMessageFilesResponse: - type: object - required: - - object - - data - - first_id - - last_id - - has_more - properties: - object: - type: string - enum: - - list - data: - type: array - items: - $ref: '#/components/schemas/MessageFileObject' - first_id: - type: string - last_id: - type: string - has_more: - type: boolean - ListMessagesResponse: - type: object - required: - - object - - data - - first_id - - last_id - - has_more - properties: - object: - type: string - enum: - - list - data: - type: array - items: - $ref: '#/components/schemas/MessageObject' - first_id: - type: string - last_id: - type: string - has_more: - type: boolean - ListModelsResponse: - type: object - required: - - object - - data - properties: - object: - type: string - enum: - - list - data: - type: array - items: - $ref: '#/components/schemas/Model' - ListOrder: - type: string - enum: - - asc - - desc - ListPaginatedFineTuningJobsResponse: - type: object - required: - - object - - data - - has_more - properties: - object: - type: string - data: - type: array - items: - $ref: '#/components/schemas/FineTuningJob' - has_more: - type: boolean - ListRunStepsResponse: - type: object - required: - - object - - data - - first_id - - last_id - - has_more - properties: - object: - type: string - enum: - - list - data: - type: array - items: - $ref: '#/components/schemas/RunStepObject' - first_id: - type: string - last_id: - type: string - has_more: - type: boolean - ListRunsResponse: - type: object - required: - - object - - data - - first_id - - last_id - - has_more - properties: - object: - type: string - enum: - - list - data: - type: array - items: - $ref: '#/components/schemas/RunObject' - first_id: - type: string - last_id: - type: string - has_more: - type: boolean - MessageContentImageFileObject: - type: object - required: - - type - - image_file - properties: - type: - type: string - enum: - - image_file - description: Always `image_file`. - image_file: - type: object - properties: - file_id: - type: string - description: The [File](/docs/api-reference/files) ID of the image in the message content. - required: - - file_id - description: References an image [File](/docs/api-reference/files) in the content of a message. - MessageContentTextAnnotationsFileCitationObject: - type: object - required: - - type - - text - - file_citation - - start_index - - end_index - properties: - type: - type: string - enum: - - file_citation - description: Always `file_citation`. - text: - type: string - description: The text in the message content that needs to be replaced. - file_citation: - type: object - properties: - file_id: - type: string - description: The ID of the specific File the citation is from. - quote: - type: string - description: The specific quote in the file. - required: - - file_id - - quote - start_index: - type: integer - format: int64 - minimum: 0 - end_index: - type: integer - format: int64 - minimum: 0 - description: |- - A citation within the message that points to a specific quote from a specific File associated - with the assistant or the message. Generated when the assistant uses the "retrieval" tool to - search files. - MessageContentTextAnnotationsFilePathObject: - type: object - required: - - type - - text - - file_path - - start_index - - end_index - properties: - type: - type: string - enum: - - file_path - description: Always `file_path`. - text: - type: string - description: The text in the message content that needs to be replaced. - file_path: - type: object - properties: - file_id: - type: string - description: The ID of the file that was generated. - required: - - file_id - start_index: - type: integer - format: int64 - minimum: 0 - end_index: - type: integer - format: int64 - minimum: 0 - description: |- - A URL for the file that's generated when the assistant used the `code_interpreter` tool to - generate a file. - MessageContentTextObject: - type: object - required: - - type - - text - properties: - type: - type: string - enum: - - text - - json_object - description: Always `text`. - text: - type: object - properties: - value: - type: string - description: The data that makes up the text. - annotations: - type: array - items: - $ref: '#/components/schemas/MessageContentTextObjectAnnotations' - required: - - value - - annotations - description: The text content that is part of a message. - MessageContentTextObjectAnnotations: - oneOf: - - $ref: '#/components/schemas/MessageContentTextAnnotationsFileCitationObject' - - $ref: '#/components/schemas/MessageContentTextAnnotationsFilePathObject' - x-oaiExpandable: true - MessageFileObject: - type: object - required: - - id - - object - - created_at - - message_id - properties: - id: - type: string - description: TThe identifier, which can be referenced in API endpoints. - object: - type: string - enum: - - thread.message.file - description: The object type, which is always `thread.message.file`. - created_at: - type: integer - format: unixtime - description: The Unix timestamp (in seconds) for when the message file was created. - message_id: - type: string - description: The ID of the [message](/docs/api-reference/messages) that the [File](/docs/api-reference/files) is attached to. - description: A list of files attached to a `message`. - MessageObject: - type: object - required: - - id - - object - - created_at - - thread_id - - role - - content - - assistant_id - - run_id - - file_ids - - metadata - properties: - id: - type: string - description: The identifier, which can be referenced in API endpoints. - object: - type: string - enum: - - thread.message - description: The object type, which is always `thread.message`. - created_at: - type: integer - format: unixtime - description: The Unix timestamp (in seconds) for when the message was created. - thread_id: - type: string - description: The [thread](/docs/api-reference/threads) ID that this message belongs to. - role: - type: string - enum: - - user - - assistant - description: The entity that produced the message. One of `user` or `assistant`. - content: - type: array - items: - $ref: '#/components/schemas/MessageObjectContent' - description: The content of the message in array of text and/or images. - assistant_id: - type: string - nullable: true - description: |- - If applicable, the ID of the [assistant](/docs/api-reference/assistants) that authored this - message. - run_id: - type: string - nullable: true - description: |- - If applicable, the ID of the [run](/docs/api-reference/runs) associated with the authoring of - this message. - file_ids: - type: array - items: - type: string - maxItems: 10 - description: |- - A list of [file](/docs/api-reference/files) IDs that the assistant should use. Useful for - tools like retrieval and code_interpreter that can access files. A maximum of 10 files can be - attached to a message. - default: [] - metadata: - type: object - additionalProperties: - type: string - nullable: true - description: |- - Set of 16 key-value pairs that can be attached to an object. This can be useful for storing - additional information about the object in a structured format. Keys can be a maximum of 64 - characters long and values can be a maxium of 512 characters long. - x-oaiTypeLabel: map - MessageObjectContent: - oneOf: - - $ref: '#/components/schemas/MessageContentImageFileObject' - - $ref: '#/components/schemas/MessageContentTextObject' - x-oaiExpandable: true - Model: - type: object - required: - - id - - created - - object - - owned_by - properties: - id: - type: string - description: The model identifier, which can be referenced in the API endpoints. - created: - type: integer - format: unixtime - description: The Unix timestamp (in seconds) when the model was created. - object: - type: string - enum: - - model - description: The object type, which is always "model". - owned_by: - type: string - description: The organization that owns the model. - description: Describes an OpenAI model offering that can be used with the API. - ModifyAssistantRequest: - type: object - properties: - model: - type: string - description: |- - ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to - see all of your available models, or see our [Model overview](/docs/models/overview) for - descriptions of them. - name: - type: string - nullable: true - maxLength: 256 - description: The name of the assistant. The maximum length is 256 characters. - description: - type: string - nullable: true - maxLength: 512 - description: The description of the assistant. The maximum length is 512 characters. - instructions: - type: string - nullable: true - maxLength: 32768 - description: The system instructions that the assistant uses. The maximum length is 32768 characters. - tools: - allOf: - - $ref: '#/components/schemas/CreateAssistantRequestToolsItem' - description: |- - A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. - Tools can be of types `code_interpreter`, `retrieval`, or `function`. - default: [] - file_ids: - type: array - items: - type: string - maxItems: 20 - description: |- - A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a - maximum of 20 files attached to the assistant. Files are ordered by their creation date in - ascending order. - default: [] - metadata: - type: object - additionalProperties: - type: string - nullable: true - description: |- - Set of 16 key-value pairs that can be attached to an object. This can be useful for storing - additional information about the object in a structured format. Keys can be a maximum of 64 - characters long and values can be a maxium of 512 characters long. - x-oaiTypeLabel: map - ModifyMessageRequest: - type: object - properties: - metadata: - type: object - additionalProperties: - type: string - nullable: true - description: |- - Set of 16 key-value pairs that can be attached to an object. This can be useful for storing - additional information about the object in a structured format. Keys can be a maximum of 64 - characters long and values can be a maxium of 512 characters long. - x-oaiTypeLabel: map - ModifyRunRequest: - type: object - properties: - metadata: - type: object - additionalProperties: - type: string - nullable: true - description: |- - Set of 16 key-value pairs that can be attached to an object. This can be useful for storing - additional information about the object in a structured format. Keys can be a maximum of 64 - characters long and values can be a maxium of 512 characters long. - x-oaiTypeLabel: map - ModifyThreadRequest: - type: object - properties: - metadata: - type: object - additionalProperties: - type: string - nullable: true - description: |- - Set of 16 key-value pairs that can be attached to an object. This can be useful for storing - additional information about the object in a structured format. Keys can be a maximum of 64 - characters long and values can be a maxium of 512 characters long. - NEpochs: - type: integer - format: int64 - minimum: 1 - maximum: 50 - OpenAIFile: - type: object - required: - - id - - bytes - - created_at - - filename - - object - - purpose - - status - properties: - id: - type: string - description: The file identifier, which can be referenced in the API endpoints. - bytes: - type: integer - format: int64 - description: The size of the file, in bytes. - created_at: - type: integer - format: unixtime - description: The Unix timestamp (in seconds) for when the file was created. - filename: - type: string - description: The name of the file. - object: - type: string - enum: - - file - description: The object type, which is always "file". - purpose: - type: string - enum: - - fine-tune - - fine-tune-results - - assistants - - assistants_output - description: |- - The intended purpose of the file. Supported values are `fine-tune`, `fine-tune-results`, - `assistants`, and `assistants_output`. - status: - type: string - enum: - - uploaded - - processed - - error - description: |- - Deprecated. The current status of the file, which can be either `uploaded`, `processed`, or - `error`. - deprecated: true - status_details: - type: string - description: |- - Deprecated. For details on why a fine-tuning training file failed validation, see the `error` - field on `fine_tuning.job`. - deprecated: true - description: The `File` object represents a document that has been uploaded to OpenAI. - Prompt: - oneOf: - - type: string - - type: array - items: - type: string - - $ref: '#/components/schemas/TokenArrayItem' - - $ref: '#/components/schemas/TokenArrayArray' - RunCompletionUsage: - type: object - required: - - completion_tokens - - prompt_tokens - - total_tokens - properties: - completion_tokens: - type: integer - format: int64 - description: Number of completion tokens used over the course of the run. - prompt_tokens: - type: integer - format: int64 - description: Number of prompt tokens used over the course of the run. - total_tokens: - type: integer - format: int64 - description: Total number of tokens used (prompt + completion). - description: |- - Usage statistics related to the run. This value will be `null` if the run is not in a terminal - state (i.e. `in_progress`, `queued`, etc.). - RunObject: - type: object - required: - - id - - object - - created_at - - thread_id - - assistant_id - - status - - required_action - - last_error - - expires_at - - started_at - - cancelled_at - - failed_at - - completed_at - - model - - instructions - - tools - - file_ids - - metadata - - usage - properties: - id: - type: string - description: The identifier, which can be referenced in API endpoints. - object: - type: string - enum: - - thread.run - description: The object type, which is always `thread.run`. - created_at: - type: integer - format: unixtime - description: The Unix timestamp (in seconds) for when the run was created. - thread_id: - type: string - description: |- - The ID of the [thread](/docs/api-reference/threads) that was executed on as a part of this - run. - assistant_id: - type: string - description: The ID of the [assistant](/docs/api-reference/assistants) used for execution of this run. - status: - type: string - enum: - - queued - - in_progress - - requires_action - - cancelling - - cancelled - - failed - - completed - - expired - description: |- - The status of the run, which can be either `queued`, `in_progress`, `requires_action`, - `cancelling`, `cancelled`, `failed`, `completed`, or `expired`. - required_action: - type: object - properties: - type: - type: string - enum: - - submit_tool_outputs - description: For now, this is always `submit_tool_outputs`. - submit_tool_outputs: - type: object - properties: - tool_calls: - type: array - items: - $ref: '#/components/schemas/RunToolCallObject' - description: A list of the relevant tool calls. - required: - - tool_calls - description: Details on the tool outputs needed for this run to continue. - required: - - type - - submit_tool_outputs - nullable: true - description: |- - Details on the action required to continue the run. Will be `null` if no action is - required. - last_error: - type: object - properties: - code: - type: string - enum: - - server_error - - rate_limit_exceeded - description: One of `server_error` or `rate_limit_exceeded`. - message: - type: string - description: A human-readable description of the error. - required: - - code - - message - nullable: true - description: The last error associated with this run. Will be `null` if there are no errors. - expires_at: - type: integer - format: unixtime - description: The Unix timestamp (in seconds) for when the run will expire. - started_at: - type: string - format: date-time - nullable: true - description: The Unix timestamp (in seconds) for when the run was started. - cancelled_at: - type: string - format: date-time - nullable: true - description: The Unix timestamp (in seconds) for when the run was cancelled. - failed_at: - type: string - format: date-time - nullable: true - description: The Unix timestamp (in seconds) for when the run failed. - completed_at: - type: string - format: date-time - nullable: true - description: The Unix timestamp (in seconds) for when the run was completed. - model: - type: string - description: The model that the [assistant](/docs/api-reference/assistants) used for this run. - instructions: - type: string - description: The instructions that the [assistant](/docs/api-reference/assistants) used for this run. - tools: - allOf: - - $ref: '#/components/schemas/CreateRunRequestToolsItem' - description: The list of tools that the [assistant](/docs/api-reference/assistants) used for this run. - file_ids: - type: array - items: - type: string - description: |- - The list of [File](/docs/api-reference/files) IDs the - [assistant](/docs/api-reference/assistants) used for this run. - default: [] - metadata: - type: object - additionalProperties: - type: string - nullable: true - description: |- - Set of 16 key-value pairs that can be attached to an object. This can be useful for storing - additional information about the object in a structured format. Keys can be a maximum of 64 - characters long and values can be a maxium of 512 characters long. - x-oaiTypeLabel: map - usage: - type: object - allOf: - - $ref: '#/components/schemas/RunCompletionUsage' - nullable: true - description: Represents an execution run on a [thread](/docs/api-reference/threads). - RunStepCompletionUsage: - type: object - required: - - completion_tokens - - prompt_tokens - - total_tokens - properties: - completion_tokens: - type: integer - format: int64 - description: Number of completion tokens used over the course of the run step. - prompt_tokens: - type: integer - format: int64 - description: Number of prompt tokens used over the course of the run step. - total_tokens: - type: integer - format: int64 - description: Total number of tokens used (prompt + completion). - description: |- - Usage statistics related to the run step. This value will be `null` while the run step's status - is `in_progress`. - RunStepDetails: - oneOf: - - $ref: '#/components/schemas/RunStepDetailsMessageCreationObject' - - $ref: '#/components/schemas/RunStepDetailsToolCallsObject' - x-oaiExpandable: true - RunStepDetailsMessageCreationObject: - type: object - required: - - type - - message_creation - properties: - type: - type: string - enum: - - message_creation - description: Details of the message creation by the run step. - message_creation: - type: object - properties: - message_id: - type: string - description: The ID of the message that was created by this run step. - required: - - message_id - description: Details of the message creation by the run step. - RunStepDetailsToolCallsCodeObject: - type: object - required: - - id - - type - - code_interpreter - properties: - id: - type: string - description: The ID of the tool call. - type: - type: string - enum: - - code_interpreter - description: |- - The type of tool call. This is always going to be `code_interpreter` for this type of tool - call. - code_interpreter: - type: object - properties: - input: - type: string - description: The input to the Code Interpreter tool call. - outputs: - allOf: - - $ref: '#/components/schemas/RunStepDetailsToolCallsCodeOutputs' - description: |- - The outputs from the Code Interpreter tool call. Code Interpreter can output one or more - items, including text (`logs`) or images (`image`). Each of these are represented by a - different object type. - required: - - input - - outputs - description: The Code Interpreter tool call definition. - description: Details of the Code Interpreter tool call the run step was involved in. - RunStepDetailsToolCallsCodeOutput: - oneOf: - - $ref: '#/components/schemas/RunStepDetailsToolCallsCodeOutputLogsObject' - - $ref: '#/components/schemas/RunStepDetailsToolCallsCodeOutputImageObject' - x-oaiExpandable: true - RunStepDetailsToolCallsCodeOutputImageObject: - type: object - required: - - type - - image - properties: - type: - type: string - enum: - - image - description: Always `image`. - image: - type: object - properties: - file_id: - type: string - description: The [file](/docs/api-reference/files) ID of the image. - required: - - file_id - RunStepDetailsToolCallsCodeOutputLogsObject: - type: object - required: - - type - - logs - properties: - type: - type: string - enum: - - logs - description: Always `logs`. - logs: - type: string - description: The text output from the Code Interpreter tool call. - description: Text output from the Code Interpreter tool call as part of a run step. - RunStepDetailsToolCallsCodeOutputs: - type: array - items: - $ref: '#/components/schemas/RunStepDetailsToolCallsCodeOutput' - RunStepDetailsToolCallsFunctionObject: - type: object - required: - - id - - type - - function - properties: - id: - type: string - description: The ID of the tool call object. - type: - type: string - enum: - - function - description: The type of tool call. This is always going to be `function` for this type of tool call. - function: - type: object - properties: - name: - type: string - description: The name of the function. - arguments: - type: string - description: The arguments passed to the function. - output: - type: string - nullable: true - description: |- - The output of the function. This will be `null` if the outputs have not been - [submitted](/docs/api-reference/runs/submitToolOutputs) yet. - required: - - name - - arguments - - output - description: The definition of the function that was called. - RunStepDetailsToolCallsObject: - type: object - required: - - type - - tool_calls - properties: - type: - type: string - enum: - - tool_calls - description: Always `tool_calls`. - tool_calls: - allOf: - - $ref: '#/components/schemas/RunStepDetailsToolCallsObjectToolCallsItem' - description: |- - An array of tool calls the run step was involved in. These can be associated with one of three - types of tools: `code_interpreter`, `retrieval`, or `function`. - description: Details of the tool call. - RunStepDetailsToolCallsObjectToolCall: - oneOf: - - $ref: '#/components/schemas/RunStepDetailsToolCallsCodeObject' - - $ref: '#/components/schemas/RunStepDetailsToolCallsRetrievalObject' - - $ref: '#/components/schemas/RunStepDetailsToolCallsFunctionObject' - x-oaiExpandable: true - RunStepDetailsToolCallsObjectToolCallsItem: - type: array - items: - $ref: '#/components/schemas/RunStepDetailsToolCallsObjectToolCall' - RunStepDetailsToolCallsRetrievalObject: - type: object - required: - - id - - type - - retrieval - properties: - id: - type: string - description: The ID of the tool call object. - type: - type: string - enum: - - retrieval - description: The type of tool call. This is always going to be `retrieval` for this type of tool call. - retrieval: - type: object - description: For now, this is always going to be an empty object. - x-oaiTypeLabel: map - RunStepObject: - type: object - required: - - id - - object - - created_at - - assistant_id - - thread_id - - run_id - - type - - status - - step_details - - last_error - - expires_at - - cancelled_at - - failed_at - - completed_at - - metadata - - usage - properties: - id: - type: string - description: The identifier of the run step, which can be referenced in API endpoints. - object: - type: string - enum: - - thread.run.step - description: The object type, which is always `thread.run.step`. - created_at: - type: integer - format: unixtime - description: The Unix timestamp (in seconds) for when the run step was created. - assistant_id: - type: string - description: The ID of the [assistant](/docs/api-reference/assistants) associated with the run step. - thread_id: - type: string - description: The ID of the [thread](/docs/api-reference/threads) that was run. - run_id: - type: string - description: The ID of the [run](/docs/api-reference/runs) that this run step is a part of. - type: - type: string - enum: - - message_creation - - tool_calls - description: The type of run step, which can be either `message_creation` or `tool_calls`. - status: - type: string - enum: - - in_progress - - cancelled - - failed - - completed - - expired - description: |- - The status of the run step, which can be either `in_progress`, `cancelled`, `failed`, - `completed`, or `expired`. - step_details: - allOf: - - $ref: '#/components/schemas/RunStepDetails' - description: The details of the run step. - last_error: - type: object - properties: - code: - type: string - enum: - - server_error - - rate_limit_exceeded - description: One of `server_error` or `rate_limit_exceeded`. - message: - type: string - description: A human-readable description of the error. - required: - - code - - message - nullable: true - description: The last error associated with this run step. Will be `null` if there are no errors. - expires_at: - type: string - format: date-time - nullable: true - description: |- - The Unix timestamp (in seconds) for when the run step expired. A step is considered expired - if the parent run is expired. - cancelled_at: - type: string - format: date-time - nullable: true - description: The Unix timestamp (in seconds) for when the run step was cancelled. - failed_at: - type: string - format: date-time - nullable: true - description: The Unix timestamp (in seconds) for when the run step failed. - completed_at: - type: string - format: date-time - nullable: true - description: T The Unix timestamp (in seconds) for when the run step completed.. - metadata: - type: object - additionalProperties: - type: string - nullable: true - description: |- - Set of 16 key-value pairs that can be attached to an object. This can be useful for storing - additional information about the object in a structured format. Keys can be a maximum of 64 - characters long and values can be a maxium of 512 characters long. - x-oaiTypeLabel: map - usage: - type: object - allOf: - - $ref: '#/components/schemas/RunCompletionUsage' - nullable: true - description: Represents a step in execution of a run. - RunToolCallObject: - type: object - required: - - id - - type - - function - properties: - id: - type: string - description: |- - The ID of the tool call. This ID must be referenced when you submit the tool outputs in using - the [Submit tool outputs to run](/docs/api-reference/runs/submitToolOutputs) endpoint. - type: - type: string - enum: - - function - description: The type of tool call the output is required for. For now, this is always `function`. - function: - type: object - properties: - name: - type: string - description: The name of the function. - arguments: - type: string - description: The arguments that the model expects you to pass to the function. - required: - - name - - arguments - description: The function definition. - description: Tool call objects - Stop: - oneOf: - - type: string - - $ref: '#/components/schemas/StopSequences' - StopSequences: - type: array - items: - type: string - minItems: 1 - maxItems: 4 - SubmitToolOutputsRunRequest: - type: object - required: - - tool_outputs - properties: - tool_outputs: - type: object - properties: - tool_call_id: - type: string - description: |- - The ID of the tool call in the `required_action` object within the run object the output is - being submitted for. - output: - type: string - description: The output of the tool call to be submitted to continue the run. - description: A list of tools for which the outputs are being submitted. - SuffixString: - type: string - minLength: 1 - maxLength: 40 - ThreadObject: - type: object - required: - - id - - object - - created_at - - metadata - properties: - id: - type: string - description: The identifier, which can be referenced in API endpoints. - object: - type: string - enum: - - thread - description: The object type, which is always `thread`. - created_at: - type: integer - format: unixtime - description: The Unix timestamp (in seconds) for when the thread was created. - metadata: - type: object - additionalProperties: - type: string - nullable: true - description: |- - Set of 16 key-value pairs that can be attached to an object. This can be useful for storing - additional information about the object in a structured format. Keys can be a maximum of 64 - characters long and values can be a maxium of 512 characters long. - x-oaiTypeLabel: map - description: Represents a thread that contains [messages](/docs/api-reference/messages). - TokenArrayArray: - type: array - items: - $ref: '#/components/schemas/TokenArrayItem' - minItems: 1 - TokenArrayItem: - type: array - items: - type: integer - format: int64 - minItems: 1 - User: - type: string - securitySchemes: - BearerAuth: - type: http - scheme: bearer -servers: - - url: https://api.openai.com/v1 - description: OpenAI Endpoint - variables: {} diff --git a/fine-tuning/operations.tsp b/fine-tuning/operations.tsp index 07f48e802..f37e90cc7 100644 --- a/fine-tuning/operations.tsp +++ b/fine-tuning/operations.tsp @@ -10,145 +10,71 @@ using TypeSpec.OpenAPI; namespace OpenAI; @route("/fine_tuning") -namespace FineTuning { +interface FineTuning { @route("jobs") - interface Jobs { - /** - * Creates a job that fine-tunes a specified model from a given dataset. - * - * Response includes details of the enqueued job including job status and the name of the - * fine-tuned models once complete. - * - * [Learn more about fine-tuning](/docs/guides/fine-tuning) - */ - @post - @tag("Fine-tuning") - @operationId("createFineTuningJob") - createFineTuningJob( - @body job: CreateFineTuningJobRequest, - ): FineTuningJob | ErrorResponse; - - @get - @tag("Fine-tuning") - @operationId("listPaginatedFineTuningJobs") - listPaginatedFineTuningJobs( - /** Identifier for the last job from the previous pagination request. */ - @query after?: string, - - /** Number of fine-tuning jobs to retrieve. */ - @query limit?: safeint = 20, - ): ListPaginatedFineTuningJobsResponse | ErrorResponse; - - @summary(""" - Get info about a fine-tuning job. - - [Learn more about fine-tuning](/docs/guides/fine-tuning) - """) - @route("{fine_tuning_job_id}") - @tag("Fine-tuning") - @get - @operationId("retrieveFineTuningJob") - retrieveFineTuningJob( - @path fine_tuning_job_id: string, - ): FineTuningJob | ErrorResponse; - - @summary("Get status updates for a fine-tuning job.") - @tag("Fine-tuning") - @route("{fine_tuning_job_id}/events") - @get - @operationId("listFineTuningEvents") - listFineTuningEvents( - /** The ID of the fine-tuning job to get events for. */ - @path fine_tuning_job_id: string, - - /** Identifier for the last event from the previous pagination request. */ - @query after?: string, - - /** Number of events to retrieve. */ - @query limit?: integer = 20, - ): ListFineTuningJobEventsResponse | ErrorResponse; - - @summary("Immediately cancel a fine-tune job.") - @tag("Fine-tuning") - @route("{fine_tuning_job_id}/cancel") - @post - @operationId("cancelFineTuningJob") - cancelFineTuningJob( - /** The ID of the fine-tuning job to cancel. */ - @path fine_tuning_job_id: string, - ): FineTuningJob | ErrorResponse; - } -} - -@route("/fine-tunes") -interface FineTunes { - #deprecated "deprecated" @post + @operationId("createFineTuningJob") @tag("Fine-tuning") @summary(""" - Creates a job that fine-tunes a specified model from a given dataset. + Creates a fine-tuning job which begins the process of creating a new model from a given dataset. Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete. - [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) + [Learn more about fine-tuning](/docs/guides/fine-tuning) """) - @operationId("createFineTune") - createFineTune( - @body fine_tune: CreateFineTuneRequest, - ): FineTune | ErrorResponse; + createFineTuningJob( + @body job: CreateFineTuningJobRequest, + ): FineTuningJob | ErrorResponse; - #deprecated "deprecated" + @route("jobs") @get + @operationId("listPaginatedFineTuningJobs") @tag("Fine-tuning") @summary("List your organization's fine-tuning jobs") - @operationId("listFineTunes") - listFineTunes(): ListFineTunesResponse | ErrorResponse; + listPaginatedFineTuningJobs( + /** Identifier for the last job from the previous pagination request. */ + @query after?: string, - #deprecated "deprecated" + /** Number of fine-tuning jobs to retrieve. */ + @query limit?: safeint = 20, + ): ListPaginatedFineTuningJobsResponse | ErrorResponse; + + @route("jobs/{fine_tuning_job_id}") @get - @route("{fine_tune_id}") + @operationId("retrieveFineTuningJob") @tag("Fine-tuning") @summary(""" - Gets info about the fine-tune job. + Get info about a fine-tuning job. - [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) + [Learn more about fine-tuning](/docs/guides/fine-tuning) """) - @operationId("retrieveFineTune") - retrieveFineTune( - /** The ID of the fine-tune job */ - @path fine_tune_id: string, - ): FineTune | ErrorResponse; + retrieveFineTuningJob( + @path fine_tuning_job_id: string, + ): FineTuningJob | ErrorResponse; + + @route("jobs/{fine_tuning_job_id}/cancel") + @post + @operationId("cancelFineTuningJob") + @tag("Fine-tuning") + @summary("Immediately cancel a fine-tune job.") + cancelFineTuningJob( + /** The ID of the fine-tuning job to cancel. */ + @path fine_tuning_job_id: string, + ): FineTuningJob | ErrorResponse; - #deprecated "deprecated" - @route("{fine_tune_id}/events") + @route("jobs/{fine_tuning_job_id}/events") @get + @operationId("listFineTuningEvents") @tag("Fine-tuning") - @summary("Get fine-grained status updates for a fine-tune job.") - @operationId("listFineTuneEvents") - listFineTuneEvents( - /** The ID of the fine-tune job to get events for. */ - @path fine_tune_id: string, + @summary("Get status updates for a fine-tuning job.") + listFineTuningEvents( + /** The ID of the fine-tuning job to get events for. */ + @path fine_tuning_job_id: string, - /** - * Whether to stream events for the fine-tune job. If set to true, events will be sent as - * data-only - * [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) - * as they become available. The stream will terminate with a `data: [DONE]` message when the - * job is finished (succeeded, cancelled, or failed). - * - * If set to false, only events generated so far will be returned. - */ - @query stream?: boolean = false, - ): ListFineTuneEventsResponse | ErrorResponse; + /** Identifier for the last event from the previous pagination request. */ + @query after?: string, - #deprecated "deprecated" - @route("{fine_tune_id}/cancel") - @post - @tag("Fine-tuning") - @summary("Immediately cancel a fine-tune job.") - @operationId("cancelFineTune") - cancelFineTune( - /** The ID of the fine-tune job to cancel */ - @path fine_tune_id: string, - ): FineTune | ErrorResponse; + /** Number of events to retrieve. */ + @query limit?: integer = 20, + ): ListFineTuningJobEventsResponse | ErrorResponse; } \ No newline at end of file diff --git a/tsp-output/@typespec/openapi3/openapi.yaml b/tsp-output/@typespec/openapi3/openapi.yaml index 346061391..c96cc33ed 100644 --- a/tsp-output/@typespec/openapi3/openapi.yaml +++ b/tsp-output/@typespec/openapi3/openapi.yaml @@ -4,13 +4,13 @@ info: version: 2.0.0 description: The OpenAI REST API. Please see https://platform.openai.com/docs/api-reference for more details. tags: - - name: Fine-tuning - name: Audio - name: Assistants - name: Chat - name: Completions - name: Embeddings - name: Files + - name: Fine-tuning - name: Images - name: Models - name: Moderations @@ -637,166 +637,15 @@ paths: application/json: schema: $ref: '#/components/schemas/ErrorResponse' - /fine-tunes: - post: - tags: - - Fine-tuning - operationId: createFineTune - summary: |- - Creates a job that fine-tunes a specified model from a given dataset. - - Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete. - - [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) - parameters: [] - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/FineTune' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateFineTuneRequest' - deprecated: true - get: - tags: - - Fine-tuning - operationId: listFineTunes - summary: List your organization's fine-tuning jobs - parameters: [] - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/ListFineTunesResponse' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - deprecated: true - /fine-tunes/{fine_tune_id}: - get: - tags: - - Fine-tuning - operationId: retrieveFineTune - summary: |- - Gets info about the fine-tune job. - - [Learn more about fine-tuning](/docs/guides/legacy-fine-tuning) - parameters: - - name: fine_tune_id - in: path - required: true - description: The ID of the fine-tune job - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/FineTune' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - deprecated: true - /fine-tunes/{fine_tune_id}/cancel: - post: - tags: - - Fine-tuning - operationId: cancelFineTune - summary: Immediately cancel a fine-tune job. - parameters: - - name: fine_tune_id - in: path - required: true - description: The ID of the fine-tune job to cancel - schema: - type: string - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/FineTune' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - deprecated: true - /fine-tunes/{fine_tune_id}/events: - get: - tags: - - Fine-tuning - operationId: listFineTuneEvents - summary: Get fine-grained status updates for a fine-tune job. - parameters: - - name: fine_tune_id - in: path - required: true - description: The ID of the fine-tune job to get events for. - schema: - type: string - - name: stream - in: query - required: false - description: |- - Whether to stream events for the fine-tune job. If set to true, events will be sent as - data-only - [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) - as they become available. The stream will terminate with a `data: [DONE]` message when the - job is finished (succeeded, cancelled, or failed). - - If set to false, only events generated so far will be returned. - schema: - type: boolean - default: false - responses: - '200': - description: The request has succeeded. - content: - application/json: - schema: - $ref: '#/components/schemas/ListFineTuneEventsResponse' - default: - description: An unexpected error response. - content: - application/json: - schema: - $ref: '#/components/schemas/ErrorResponse' - deprecated: true /fine_tuning/jobs: post: tags: - Fine-tuning operationId: createFineTuningJob - description: |- - Creates a job that fine-tunes a specified model from a given dataset. + summary: |- + Creates a fine-tuning job which begins the process of creating a new model from a given dataset. - Response includes details of the enqueued job including job status and the name of the - fine-tuned models once complete. + Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete. [Learn more about fine-tuning](/docs/guides/fine-tuning) parameters: [] @@ -823,6 +672,7 @@ paths: tags: - Fine-tuning operationId: listPaginatedFineTuningJobs + summary: List your organization's fine-tuning jobs parameters: - name: after in: query @@ -4922,12 +4772,10 @@ components: items: $ref: '#/components/schemas/Model' ListOrder: - anyOf: - - type: string - - type: string - enum: - - asc - - desc + type: string + enum: + - asc + - desc ListPaginatedFineTuningJobsResponse: type: object required: From b16017af6338b477e80a2e9c92283d868bdfbbf6 Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado Date: Tue, 20 Feb 2024 02:03:08 -0800 Subject: [PATCH 11/50] Update System.ClientModel --- .dotnet/scripts/Update-ClientModel.ps1 | 197 +++ .../ModelReaderWriterExtensions.cs | 264 ++++ .../ClientShared/ModelReaderWriterHelper.cs | 31 + .../src/ClientShared/OptionalDictionary.cs | 214 +++ .dotnet/src/ClientShared/OptionalList.cs | 191 +++ .dotnet/src/ClientShared/OptionalProperty.cs | 117 ++ .dotnet/src/ClientShared/TypeFormatters.cs | 158 ++ .dotnet/src/Generated/Assistants.cs | 1124 ++++++++------- .dotnet/src/Generated/Audio.cs | 347 ++--- .dotnet/src/Generated/Chat.cs | 141 +- .dotnet/src/Generated/Completions.cs | 141 +- .dotnet/src/Generated/Embeddings.cs | 141 +- .dotnet/src/Generated/Files.cs | 564 ++++---- .dotnet/src/Generated/FineTuning.cs | 594 ++++---- .dotnet/src/Generated/Images.cs | 347 ++--- .dotnet/src/Generated/Messages.cs | 889 ++++++------ .../AssistantFileObject.Serialization.cs | 17 +- .../Generated/Models/AssistantFileObject.cs | 9 +- .../Models/AssistantFileObjectObject.cs | 3 +- .../Models/AssistantObject.Serialization.cs | 17 +- .../src/Generated/Models/AssistantObject.cs | 13 +- .../Generated/Models/AssistantObjectObject.cs | 3 +- .../Models/AudioSegment.Serialization.cs | 17 +- .dotnet/src/Generated/Models/AudioSegment.cs | 9 +- ...pletionFunctionCallOption.Serialization.cs | 17 +- .../ChatCompletionFunctionCallOption.cs | 7 +- .../ChatCompletionFunctions.Serialization.cs | 17 +- .../Models/ChatCompletionFunctions.cs | 7 +- ...CompletionMessageToolCall.Serialization.cs | 17 +- .../Models/ChatCompletionMessageToolCall.cs | 9 +- ...onMessageToolCallFunction.Serialization.cs | 17 +- .../ChatCompletionMessageToolCallFunction.cs | 9 +- .../ChatCompletionMessageToolCallType.cs | 3 +- ...CompletionNamedToolChoice.Serialization.cs | 17 +- .../Models/ChatCompletionNamedToolChoice.cs | 7 +- ...onNamedToolChoiceFunction.Serialization.cs | 17 +- .../ChatCompletionNamedToolChoiceFunction.cs | 7 +- .../ChatCompletionNamedToolChoiceType.cs | 3 +- ...CompletionResponseMessage.Serialization.cs | 17 +- .../Models/ChatCompletionResponseMessage.cs | 5 +- ...sponseMessageFunctionCall.Serialization.cs | 17 +- ...atCompletionResponseMessageFunctionCall.cs | 9 +- .../ChatCompletionResponseMessageRole.cs | 3 +- ...hatCompletionTokenLogprob.Serialization.cs | 17 +- .../Models/ChatCompletionTokenLogprob.cs | 9 +- ...ionTokenLogprobTopLogprob.Serialization.cs | 17 +- .../ChatCompletionTokenLogprobTopLogprob.cs | 7 +- .../ChatCompletionTool.Serialization.cs | 17 +- .../Generated/Models/ChatCompletionTool.cs | 7 +- .../Models/ChatCompletionToolType.cs | 3 +- .../Models/CompletionUsage.Serialization.cs | 17 +- .../src/Generated/Models/CompletionUsage.cs | 3 +- ...reateAssistantFileRequest.Serialization.cs | 17 +- .../Models/CreateAssistantFileRequest.cs | 7 +- .../CreateAssistantRequest.Serialization.cs | 17 +- .../Models/CreateAssistantRequest.cs | 7 +- ...eateChatCompletionRequest.Serialization.cs | 17 +- .../Models/CreateChatCompletionRequest.cs | 7 +- .../CreateChatCompletionRequestModel.cs | 3 +- ...tionRequestResponseFormat.Serialization.cs | 17 +- ...eateChatCompletionRequestResponseFormat.cs | 3 +- ...ChatCompletionRequestResponseFormatType.cs | 3 +- ...ateChatCompletionResponse.Serialization.cs | 17 +- .../Models/CreateChatCompletionResponse.cs | 11 +- ...tCompletionResponseChoice.Serialization.cs | 17 +- .../CreateChatCompletionResponseChoice.cs | 7 +- ...hatCompletionResponseChoiceFinishReason.cs | 3 +- ...ionResponseChoiceLogprobs.Serialization.cs | 17 +- ...ateChatCompletionResponseChoiceLogprobs.cs | 3 +- .../CreateChatCompletionResponseObject.cs | 3 +- .../CreateCompletionRequest.Serialization.cs | 17 +- .../Models/CreateCompletionRequest.cs | 5 +- .../Models/CreateCompletionRequestModel.cs | 3 +- .../CreateCompletionResponse.Serialization.cs | 17 +- .../Models/CreateCompletionResponse.cs | 11 +- ...eCompletionResponseChoice.Serialization.cs | 17 +- .../Models/CreateCompletionResponseChoice.cs | 7 +- ...ateCompletionResponseChoiceFinishReason.cs | 3 +- ...ionResponseChoiceLogprobs.Serialization.cs | 17 +- .../CreateCompletionResponseChoiceLogprobs.cs | 13 +- .../Models/CreateCompletionResponseObject.cs | 3 +- .../CreateEmbeddingRequest.Serialization.cs | 17 +- .../Models/CreateEmbeddingRequest.cs | 7 +- .../CreateEmbeddingRequestEncodingFormat.cs | 3 +- .../Models/CreateEmbeddingRequestModel.cs | 3 +- .../CreateEmbeddingResponse.Serialization.cs | 17 +- .../Models/CreateEmbeddingResponse.cs | 11 +- .../Models/CreateEmbeddingResponseObject.cs | 3 +- ...ateEmbeddingResponseUsage.Serialization.cs | 17 +- .../Models/CreateEmbeddingResponseUsage.cs | 3 +- .../Models/CreateFileRequest.Serialization.cs | 17 +- .../src/Generated/Models/CreateFileRequest.cs | 7 +- .../Models/CreateFileRequestPurpose.cs | 3 +- ...reateFineTuningJobRequest.Serialization.cs | 17 +- .../Models/CreateFineTuningJobRequest.cs | 7 +- ...JobRequestHyperparameters.Serialization.cs | 17 +- ...eateFineTuningJobRequestHyperparameters.cs | 3 +- .../Models/CreateFineTuningJobRequestModel.cs | 3 +- .../CreateImageEditRequest.Serialization.cs | 17 +- .../Models/CreateImageEditRequest.cs | 9 +- .../Models/CreateImageEditRequestModel.cs | 3 +- .../CreateImageEditRequestResponseFormat.cs | 3 +- .../Models/CreateImageEditRequestSize.cs | 3 +- .../CreateImageRequest.Serialization.cs | 17 +- .../Generated/Models/CreateImageRequest.cs | 7 +- .../Models/CreateImageRequestModel.cs | 3 +- .../Models/CreateImageRequestQuality.cs | 3 +- .../CreateImageRequestResponseFormat.cs | 3 +- .../Models/CreateImageRequestSize.cs | 3 +- .../Models/CreateImageRequestStyle.cs | 3 +- ...eateImageVariationRequest.Serialization.cs | 17 +- .../Models/CreateImageVariationRequest.cs | 7 +- .../CreateImageVariationRequestModel.cs | 3 +- ...eateImageVariationRequestResponseFormat.cs | 3 +- .../Models/CreateImageVariationRequestSize.cs | 3 +- .../CreateMessageRequest.Serialization.cs | 17 +- .../Generated/Models/CreateMessageRequest.cs | 7 +- .../Models/CreateMessageRequestRole.cs | 3 +- .../CreateModerationRequest.Serialization.cs | 17 +- .../Models/CreateModerationRequest.cs | 7 +- .../Models/CreateModerationRequestModel.cs | 3 +- .../CreateModerationResponse.Serialization.cs | 17 +- .../Models/CreateModerationResponse.cs | 11 +- ...eModerationResponseResult.Serialization.cs | 17 +- .../Models/CreateModerationResponseResult.cs | 9 +- ...nResponseResultCategories.Serialization.cs | 17 +- ...reateModerationResponseResultCategories.cs | 3 +- ...ponseResultCategoryScores.Serialization.cs | 17 +- ...eModerationResponseResultCategoryScores.cs | 3 +- .../Models/CreateRunRequest.Serialization.cs | 17 +- .../src/Generated/Models/CreateRunRequest.cs | 7 +- .../CreateSpeechRequest.Serialization.cs | 17 +- .../Generated/Models/CreateSpeechRequest.cs | 7 +- .../Models/CreateSpeechRequestModel.cs | 3 +- .../CreateSpeechRequestResponseFormat.cs | 3 +- .../Models/CreateSpeechRequestVoice.cs | 3 +- ...CreateThreadAndRunRequest.Serialization.cs | 17 +- .../Models/CreateThreadAndRunRequest.cs | 7 +- .../CreateThreadRequest.Serialization.cs | 17 +- .../Generated/Models/CreateThreadRequest.cs | 5 +- ...reateTranscriptionRequest.Serialization.cs | 17 +- .../Models/CreateTranscriptionRequest.cs | 7 +- .../Models/CreateTranscriptionRequestModel.cs | 3 +- ...reateTranscriptionRequestResponseFormat.cs | 3 +- ...eateTranscriptionResponse.Serialization.cs | 17 +- .../Models/CreateTranscriptionResponse.cs | 7 +- .../Models/CreateTranscriptionResponseTask.cs | 3 +- .../CreateTranslationRequest.Serialization.cs | 17 +- .../Models/CreateTranslationRequest.cs | 7 +- .../Models/CreateTranslationRequestModel.cs | 3 +- .../CreateTranslationRequestResponseFormat.cs | 3 +- ...CreateTranslationResponse.Serialization.cs | 17 +- .../Models/CreateTranslationResponse.cs | 7 +- .../Models/CreateTranslationResponseTask.cs | 3 +- ...leteAssistantFileResponse.Serialization.cs | 17 +- .../Models/DeleteAssistantFileResponse.cs | 7 +- .../DeleteAssistantFileResponseObject.cs | 3 +- .../DeleteAssistantResponse.Serialization.cs | 17 +- .../Models/DeleteAssistantResponse.cs | 7 +- .../Models/DeleteAssistantResponseObject.cs | 3 +- .../DeleteFileResponse.Serialization.cs | 17 +- .../Generated/Models/DeleteFileResponse.cs | 7 +- .../Models/DeleteFileResponseObject.cs | 3 +- .../DeleteModelResponse.Serialization.cs | 17 +- .../Generated/Models/DeleteModelResponse.cs | 7 +- .../Models/DeleteModelResponseObject.cs | 3 +- .../DeleteThreadResponse.Serialization.cs | 17 +- .../Generated/Models/DeleteThreadResponse.cs | 7 +- .../Models/DeleteThreadResponseObject.cs | 3 +- .../Models/Embedding.Serialization.cs | 17 +- .dotnet/src/Generated/Models/Embedding.cs | 7 +- .../src/Generated/Models/EmbeddingObject.cs | 3 +- .../Models/FineTuningJob.Serialization.cs | 17 +- .dotnet/src/Generated/Models/FineTuningJob.cs | 17 +- .../FineTuningJobError.Serialization.cs | 17 +- .../Generated/Models/FineTuningJobError.cs | 3 +- .../FineTuningJobEvent.Serialization.cs | 17 +- .../Generated/Models/FineTuningJobEvent.cs | 11 +- .../Models/FineTuningJobEventLevel.cs | 3 +- ...eTuningJobHyperparameters.Serialization.cs | 17 +- .../Models/FineTuningJobHyperparameters.cs | 3 +- .../Generated/Models/FineTuningJobObject.cs | 3 +- .../Generated/Models/FineTuningJobStatus.cs | 3 +- .../Models/FunctionObject.Serialization.cs | 17 +- .../src/Generated/Models/FunctionObject.cs | 7 +- .../FunctionParameters.Serialization.cs | 17 +- .../Generated/Models/FunctionParameters.cs | 5 +- .../Generated/Models/Image.Serialization.cs | 17 +- .dotnet/src/Generated/Models/Image.cs | 3 +- .../Models/ImagesResponse.Serialization.cs | 17 +- .../src/Generated/Models/ImagesResponse.cs | 7 +- ...istAssistantFilesResponse.Serialization.cs | 17 +- .../Models/ListAssistantFilesResponse.cs | 11 +- .../ListAssistantFilesResponseObject.cs | 3 +- .../ListAssistantsResponse.Serialization.cs | 17 +- .../Models/ListAssistantsResponse.cs | 11 +- .../Models/ListAssistantsResponseObject.cs | 3 +- .../Models/ListFilesResponse.Serialization.cs | 17 +- .../src/Generated/Models/ListFilesResponse.cs | 7 +- .../Models/ListFilesResponseObject.cs | 3 +- ...neTuningJobEventsResponse.Serialization.cs | 17 +- .../Models/ListFineTuningJobEventsResponse.cs | 9 +- .../ListMessageFilesResponse.Serialization.cs | 17 +- .../Models/ListMessageFilesResponse.cs | 11 +- .../Models/ListMessageFilesResponseObject.cs | 3 +- .../ListMessagesResponse.Serialization.cs | 17 +- .../Generated/Models/ListMessagesResponse.cs | 11 +- .../Models/ListMessagesResponseObject.cs | 3 +- .../ListModelsResponse.Serialization.cs | 17 +- .../Generated/Models/ListModelsResponse.cs | 7 +- .../Models/ListModelsResponseObject.cs | 3 +- .dotnet/src/Generated/Models/ListOrder.cs | 3 +- ...tedFineTuningJobsResponse.Serialization.cs | 17 +- .../ListPaginatedFineTuningJobsResponse.cs | 9 +- .../ListRunStepsResponse.Serialization.cs | 17 +- .../Generated/Models/ListRunStepsResponse.cs | 11 +- .../Models/ListRunStepsResponseObject.cs | 3 +- .../Models/ListRunsResponse.Serialization.cs | 17 +- .../src/Generated/Models/ListRunsResponse.cs | 11 +- .../Models/ListRunsResponseObject.cs | 3 +- .../Models/MessageFileObject.Serialization.cs | 17 +- .../src/Generated/Models/MessageFileObject.cs | 9 +- .../Models/MessageFileObjectObject.cs | 3 +- .../Models/MessageObject.Serialization.cs | 17 +- .dotnet/src/Generated/Models/MessageObject.cs | 13 +- .../Generated/Models/MessageObjectObject.cs | 3 +- .../src/Generated/Models/MessageObjectRole.cs | 3 +- .../Generated/Models/Model.Serialization.cs | 17 +- .dotnet/src/Generated/Models/Model.cs | 9 +- .dotnet/src/Generated/Models/ModelObject.cs | 3 +- .../ModifyAssistantRequest.Serialization.cs | 17 +- .../Models/ModifyAssistantRequest.cs | 5 +- .../ModifyMessageRequest.Serialization.cs | 17 +- .../Generated/Models/ModifyMessageRequest.cs | 5 +- .../Models/ModifyRunRequest.Serialization.cs | 17 +- .../src/Generated/Models/ModifyRunRequest.cs | 5 +- .../ModifyThreadRequest.Serialization.cs | 17 +- .../Generated/Models/ModifyThreadRequest.cs | 5 +- .../Models/OpenAIFile.Serialization.cs | 17 +- .dotnet/src/Generated/Models/OpenAIFile.cs | 9 +- .../src/Generated/Models/OpenAIFileObject.cs | 3 +- .../src/Generated/Models/OpenAIFilePurpose.cs | 3 +- .../src/Generated/Models/OpenAIFileStatus.cs | 3 +- .../RunCompletionUsage.Serialization.cs | 17 +- .../Generated/Models/RunCompletionUsage.cs | 3 +- .../Models/RunObject.Serialization.cs | 17 +- .dotnet/src/Generated/Models/RunObject.cs | 19 +- .../RunObjectLastError.Serialization.cs | 17 +- .../Generated/Models/RunObjectLastError.cs | 7 +- .../Models/RunObjectLastErrorCode.cs | 3 +- .../src/Generated/Models/RunObjectObject.cs | 3 +- .../RunObjectRequiredAction.Serialization.cs | 17 +- .../Models/RunObjectRequiredAction.cs | 7 +- ...edActionSubmitToolOutputs.Serialization.cs | 17 +- ...unObjectRequiredActionSubmitToolOutputs.cs | 7 +- .../Models/RunObjectRequiredActionType.cs | 3 +- .../src/Generated/Models/RunObjectStatus.cs | 3 +- ...ailsMessageCreationObject.Serialization.cs | 17 +- .../RunStepDetailsMessageCreationObject.cs | 7 +- ...tionObjectMessageCreation.Serialization.cs | 17 +- ...ilsMessageCreationObjectMessageCreation.cs | 7 +- ...RunStepDetailsMessageCreationObjectType.cs | 3 +- ...tepDetailsToolCallsObject.Serialization.cs | 17 +- .../Models/RunStepDetailsToolCallsObject.cs | 7 +- .../RunStepDetailsToolCallsObjectType.cs | 3 +- .../Models/RunStepObject.Serialization.cs | 17 +- .dotnet/src/Generated/Models/RunStepObject.cs | 15 +- .../RunStepObjectLastError.Serialization.cs | 17 +- .../Models/RunStepObjectLastError.cs | 7 +- .../Models/RunStepObjectLastErrorCode.cs | 3 +- .../Generated/Models/RunStepObjectObject.cs | 3 +- .../Generated/Models/RunStepObjectStatus.cs | 3 +- .../src/Generated/Models/RunStepObjectType.cs | 3 +- .../Models/RunToolCallObject.Serialization.cs | 17 +- .../src/Generated/Models/RunToolCallObject.cs | 9 +- ...RunToolCallObjectFunction.Serialization.cs | 17 +- .../Models/RunToolCallObjectFunction.cs | 9 +- .../Generated/Models/RunToolCallObjectType.cs | 3 +- ...bmitToolOutputsRunRequest.Serialization.cs | 17 +- .../Models/SubmitToolOutputsRunRequest.cs | 7 +- ...putsRunRequestToolOutputs.Serialization.cs | 17 +- .../SubmitToolOutputsRunRequestToolOutputs.cs | 3 +- .../Models/ThreadObject.Serialization.cs | 17 +- .dotnet/src/Generated/Models/ThreadObject.cs | 7 +- .../Generated/Models/ThreadObjectObject.cs | 3 +- .dotnet/src/Generated/ModelsOps.cs | 338 ++--- .dotnet/src/Generated/Moderations.cs | 141 +- .dotnet/src/Generated/OpenAIClient.cs | 58 +- .dotnet/src/Generated/OpenAIClientOptions.cs | 7 +- .dotnet/src/Generated/OpenAIModelFactory.cs | 5 +- .dotnet/src/Generated/Runs.cs | 1267 +++++++++-------- .dotnet/src/Generated/Threads.cs | 477 +++---- .dotnet/src/OpenAI.csproj | 2 +- .../tests/Generated/Tests/AssistantsTests.cs | 3 +- .dotnet/tests/Generated/Tests/AudioTests.cs | 3 +- .dotnet/tests/Generated/Tests/ChatTests.cs | 3 +- .../tests/Generated/Tests/CompletionsTests.cs | 3 +- .../tests/Generated/Tests/EmbeddingsTests.cs | 3 +- .dotnet/tests/Generated/Tests/FilesTests.cs | 3 +- .../tests/Generated/Tests/FineTuningTests.cs | 3 +- .dotnet/tests/Generated/Tests/ImagesTests.cs | 3 +- .../tests/Generated/Tests/MessagesTests.cs | 3 +- .../tests/Generated/Tests/ModelsOpsTests.cs | 3 +- .../tests/Generated/Tests/ModerationsTests.cs | 3 +- .dotnet/tests/Generated/Tests/RunsTests.cs | 3 +- .dotnet/tests/Generated/Tests/ThreadsTests.cs | 3 +- 306 files changed, 5144 insertions(+), 5243 deletions(-) create mode 100644 .dotnet/scripts/Update-ClientModel.ps1 create mode 100644 .dotnet/src/ClientShared/ModelReaderWriterExtensions.cs create mode 100644 .dotnet/src/ClientShared/ModelReaderWriterHelper.cs create mode 100644 .dotnet/src/ClientShared/OptionalDictionary.cs create mode 100644 .dotnet/src/ClientShared/OptionalList.cs create mode 100644 .dotnet/src/ClientShared/OptionalProperty.cs create mode 100644 .dotnet/src/ClientShared/TypeFormatters.cs diff --git a/.dotnet/scripts/Update-ClientModel.ps1 b/.dotnet/scripts/Update-ClientModel.ps1 new file mode 100644 index 000000000..b8a9a590f --- /dev/null +++ b/.dotnet/scripts/Update-ClientModel.ps1 @@ -0,0 +1,197 @@ +function Update-ClientModelPackage { + $root = Split-Path $PSScriptRoot -Parent + $directory = Join-Path -Path $root -ChildPath "src" + + $current = Get-Location + Set-Location -Path $directory + + dotnet build + dotnet remove "OpenAI.csproj" package "System.ClientModel" + dotnet add "OpenAI.csproj" package "System.ClientModel" --version "1.1.0-alpha.20240215.1" --source "https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-net/nuget/v3/index.json" + + Set-Location -Path $current +} + +function Update-OpenAIClient { + $root = Split-Path $PSScriptRoot -Parent + $directory = Join-Path -Path $root -ChildPath "src\Generated" + $file = Get-ChildItem -Path $directory -Filter "OpenAIClient.cs" + $content = Get-Content -Path $file -Raw + + Write-Output "Editing $($file.FullName)" + + $content = $content -creplace "\s+#nullable disable", "" + $content = $content -creplace "\s+using System\.ClientModel\.Internal;", "" + $content = $content -creplace "\s+using System\.ClientModel\.Primitives\.Pipeline;", "" + $content = $content -creplace " KeyCredential ", " ApiKeyCredential " + $content = $content -creplace " _keyCredential", " _credential" + $content = $content -creplace " MessagePipeline ", " ClientPipeline " + $content = $content -creplace "\s+\/\/\/ The ClientDiagnostics is used to provide tracing support for the client library. ", "" + $content = $content -creplace "\s+internal TelemetrySource ClientDiagnostics { get; }", "" + $content = $content -creplace "\(KeyCredential", "(ApiKeyCredential" + $content = $content -creplace "ClientUtilities.AssertNotNull\((?\w+), nameof\((\w+)\)\);", "if (`${var} is null) throw new ArgumentNullException(nameof(`${var}));" + $content = $content -creplace "\s+ClientDiagnostics = new TelemetrySource\(options, true\);", "" + $content = $content -creplace "_pipeline = MessagePipeline\.Create\(options, new IPipelinePolicy\[\] \{ new KeyCredentialPolicy\(_keyCredential, AuthorizationHeader, AuthorizationApiKeyPrefix\) \}, Array\.Empty>\(\)\);", "var authenticationPolicy = ApiKeyAuthenticationPolicy.CreateBearerAuthorizationPolicy(_credential);`r`n _pipeline = ClientPipeline.Create(options,`r`n perCallPolicies: ReadOnlySpan.Empty,`r`n perTryPolicies: new PipelinePolicy[] { authenticationPolicy },`r`n beforeTransportPolicies: ReadOnlySpan.Empty);" + $content = $content -creplace "\(ClientDiagnostics, ", "(" + + $content | Set-Content -Path $file.FullName +} + +function Update-OpenAIClientOptions { + $root = Split-Path $PSScriptRoot -Parent + $directory = Join-Path -Path $root -ChildPath "src\Generated" + $file = Get-ChildItem -Path $directory -Filter "OpenAIClientOptions.cs" + $content = Get-Content -Path $file -Raw + + Write-Output "Editing $($file.FullName)" + + $content = $content -creplace "\s+#nullable disable", "" + $content = $content -creplace "using System\.ClientModel;", "using System.ClientModel.Primitives;" + $content = $content -creplace ": RequestOptions", ": ClientPipelineOptions" + + $content | Set-Content -Path $file.FullName +} + +function Update-Subclients { + $root = Split-Path $PSScriptRoot -Parent + $directory = Join-Path -Path $root -ChildPath "src\Generated" + $files = Get-ChildItem -Path $($directory + "\*") -Include "*.cs" -Exclude "OpenAIClient.cs", "OpenAIClientOptions.cs" + + foreach ($file in $files) { + $content = Get-Content -Path $file -Raw + + Write-Output "Editing $($file.FullName)" + + # Delete #nullable + $content = $content -creplace "\s+#nullable disable", "" + + # Fix using statements + $content = $content -creplace "\s+using System.ClientModel.Internal;", "" + $content = $content -creplace "\s+using System.ClientModel.Primitives.Pipeline;", "" + $content = $content -creplace "using System.ClientModel.Primitives;", "using System.ClientModel.Primitives;`r`nusing System.Text;" + + # Fix ClientUtilities + $content = $content -creplace "ClientUtilities.AssertNotNull\((?\w+), nameof\((\w+)\)\);", "if (`${var} is null) throw new ArgumentNullException(nameof(`${var}));" + $content = $content -creplace "ClientUtilities.AssertNotNullOrEmpty\((?\w+), nameof\((\w+)\)\);", "if (`${var} is null) throw new ArgumentNullException(nameof(`${var}));`r`n if (string.IsNullOrEmpty(`${var})) throw new ArgumentException(nameof(`${var}));" + + # Delete TelemetrySource + $content = $content -creplace "\s+\/\/\/ The ClientDiagnostics is used to provide tracing support for the client library. ", "" + $content = $content -creplace "\s+internal TelemetrySource ClientDiagnostics { get; }", "" + + # Modify constructor + $content = $content -creplace "\s+\/\/\/ The handler for diagnostic messaging in the client. ", "" + $content = $content -creplace "", "" + $content = $content -creplace "internal (?\w+)\(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint\)", "internal `${name}(ClientPipeline pipeline, ApiKeyCredential credential, Uri endpoint)" + $content = $content -creplace "\s+ClientDiagnostics = clientDiagnostics;", "" + + # # Modify convenience methods + $content = $content -creplace "\s+\/\/\/ The cancellation token to use. ", "" + $content = $content -creplace ", CancellationToken cancellationToken = default\)", ")" + $content = $content -creplace "RequestOptions context = FromCancellationToken\(cancellationToken\);\s+", "" + $content = $content -creplace "using RequestBody content = (?\w+)\.ToRequestBody\(\);", "using BinaryContent content = BinaryContent.Create(`${var});" + $content = $content -creplace "using RequestBody content0 = (?\w+)\.ToRequestBody\(\);", "using BinaryContent content0 = BinaryContent.Create(`${var});" + $content = $content -creplace "Result result = await (?\w+)\(context\)\.ConfigureAwait\(false\);", "ClientResult result = await `${method}().ConfigureAwait(false);" + $content = $content -creplace "Result result = (?\w+)\(context\);", "ClientResult result = `${method}();" + $content = $content -creplace "Result result = await (?\w+)\((?[(\w+)(\?.ToString\(\)*)(,\s\w+)]*), context\)\.ConfigureAwait\(false\);", "ClientResult result = await `${method}(`${params}).ConfigureAwait(false);" + $content = $content -creplace "Result result = (?\w+)\((?[(\w+)(\?.ToString\(\)*)(,\s\w+)]*), context\);", "ClientResult result = `${method}(`${params});" + + # Modify protocol methods + $content = $content -creplace "\/\/\/ Please try the simpler \w+)\((?[(\w+)(\?*)(,\s\w+)]*),CancellationToken\)`"/> convenience overload with strongly typed models first.", "/// Please try the simpler convenience overload with strongly typed models first." + $content = $content -creplace "\/\/\/ The request context, which can override default behaviors of the client pipeline on a per-call basis. ", "/// The request options, which can override default behaviors of the client pipeline on a per-call basis. " + $content = $content -creplace "\/\/\/ ", "/// " + $content = $content -creplace " Task ", " Task " + $content = $content -creplace " Result ", " ClientResult " + $content = $content -creplace "\(RequestBody content", "(BinaryContent content" + $content = $content -creplace " RequestBody content", " BinaryContent content" + $content = $content -creplace "\(RequestOptions context", "(RequestOptions options" + $content = $content -creplace " RequestOptions context", " RequestOptions options" + $content = $content -creplace "\s+using var scope = ClientDiagnostics\.CreateSpan\(`"(\w+\.\w+)`"\);", "" + $content = $content -creplace "\s+scope\.Start\(\);", "" + $content = $content -creplace "(?s)\s+try\s+\{\s+using PipelineMessage message = (?\w+)\((?[(\w+)(,\s\w+)]*)context\);\s+return Result\.FromResponse\(await _pipeline\.ProcessMessageAsync\(message, context\)\.ConfigureAwait\(false\)\);\s+\}", "`r`n options ??= new RequestOptions();`r`n using PipelineMessage message = `${method}(`${params}options);`r`n await _pipeline.SendAsync(message).ConfigureAwait(false);`r`n PipelineResponse response = message.Response!;`r`n`r`n if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default)`r`n {`r`n throw await ClientResultException.CreateAsync(response).ConfigureAwait(false);`r`n }`r`n`r`n return ClientResult.FromResponse(response);" + $content = $content -creplace "(?s)\s+try\s+\{\s+using PipelineMessage message = (?\w+)\((?[(\w+)(,\s\w+)]*)context\);\s+return Result\.FromResponse\(_pipeline.ProcessMessage\(message, context\)\);\s+\}", "`r`n options ??= new RequestOptions();`r`n using PipelineMessage message = `${method}(`${params}options);`r`n _pipeline.Send(message);`r`n PipelineResponse response = message.Response!;`r`n`r`n if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default)`r`n {`r`n throw new ClientResultException(response);`r`n }`r`n`r`n return ClientResult.FromResponse(response);" + $content = $content -creplace "(?s)\s+catch \(Exception e\)\s+\{\s+scope\.Failed\(e\);\s+throw;\s+\}", "" + + # Create request + $content = $content -creplace "\(RequestBody content", "(BinaryContent content" + $content = $content -creplace " RequestBody content", " BinaryContent content" + $content = $content -creplace " RequestOptions context", " RequestOptions options" + $content = $content -creplace "var message = _pipeline\.CreateMessage\(context, ResponseErrorClassifier200\);", "PipelineMessage message = _pipeline.CreateMessage();`r`n message.ResponseClassifier = ResponseErrorClassifier200;" + $content = $content -creplace "var request = message\.Request;", "PipelineRequest request = message.Request;" + $content = $content -creplace "request\.SetMethod\(`"(?[\w\/]+)`"\);", "request.Method = `"`${name}`";" + $content = $content -creplace "var uri = new RequestUri\(\);", "UriBuilder uriBuilder = new(_endpoint.ToString());" + $content = $content -creplace "uri\.Reset\(_endpoint\);", "StringBuilder path = new();" + $content = $content -creplace "uri\.AppendPath\((?`"?[\w\/]+`"?), (\w+)\);", "path.Append(`${path});`r`n uriBuilder.Path += path.ToString();" + $content = $content -creplace "uri\.AppendQuery\(`"(?\w+)`", (?\w+(\.Value)?), (\w+)\);", "if (uriBuilder.Query != null && uriBuilder.Query.Length > 1)`r`n {`r`n uriBuilder.Query += $`"&`${key}={`${value}}`";`r`n }`r`n else`r`n {`r`n uriBuilder.Query = $`"`${key}={`${value}}`";`r`n }" + $content = $content -creplace "request\.Uri = uri\.ToUri\(\);", "request.Uri = uriBuilder.Uri;" + $content = $content -creplace "request\.SetHeaderValue", "request.Headers.Set" + $content = $content -creplace "request\.Content = content;", "request.Content = content;`r`n message.Apply(options);" + + # Delete DefaultRequestContext + $content = $content -creplace "\s+private static RequestOptions DefaultRequestContext = new RequestOptions\(\);", "" + + # Delete FromCancellationToken + $content = $content -creplace "(?s)\s+internal static RequestOptions FromCancellationToken\(CancellationToken cancellationToken = default\).*?return new RequestOptions\(\) \{ CancellationToken = cancellationToken \};.*?\}", "" + + # Clean up ApiKeyCredential + $content = $content -creplace " KeyCredential", " ApiKeyCredential" + $content = $content -creplace "_keyCredential", "_credential" + $content = $content -creplace " keyCredential", " credential" + + # Clean up ClientPipeline + $content = $content -creplace " MessagePipeline ", " ClientPipeline " + + # Clean up ClientResult + $content = $content -creplace " Result", " ClientResult" + $content = $content -creplace "Task _responseErrorClassifier200 \?\?= new StatusResponseClassifier\(stackalloc ushort\[\] \{ 200 \}\);", "private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 });" + + $content | Set-Content -Path $file.FullName + } +} + +function Update-Models { + $root = Split-Path $PSScriptRoot -Parent + $directory = Join-Path -Path $root -ChildPath "src\Generated\Models" + $files = Get-ChildItem -Path $directory -Filter "*.cs" + + foreach ($file in $files) { + $content = Get-Content -Path $file -Raw + + Write-Output "Editing $($file.FullName)" + + $content = $content -creplace "\s+#nullable disable", "" + $content = $content -creplace "ClientUtilities.AssertNotNull\((?@?\w+), nameof\((@?\w+)\)\);", "if (`${var} is null) throw new ArgumentNullException(nameof(`${var}));" + $content = $content -creplace "using System.ClientModel.Internal;", "using OpenAI.ClientShared.Internal;" + $content = $content -creplace ": IUtf8JsonWriteable,", ":" + $content = $content -creplace "\s+void IUtf8JsonWriteable\.Write\(Utf8JsonWriter writer\) => \(\(IJsonModel<(\w+)>\)this\)\.Write\(writer, new ModelReaderWriterOptions\(`"W`"\)\);`r`n", "" + $content = $content -creplace "(?s)\s+\/\/\/ Convert into a Utf8JsonRequestBody\. .*?return content;.*?\}", "" + + $content | Set-Content -Path $file.FullName + } +} + +function Update-Tests { + $root = Split-Path $PSScriptRoot -Parent + $directory = Join-Path -Path $root -ChildPath "tests\Generated\Tests" + $files = Get-ChildItem -Path $directory -Filter "*.cs" + + foreach ($file in $files) { + $content = Get-Content -Path $file -Raw + + Write-Output "Editing $($file.FullName)" + + $content = $content -creplace " KeyCredential", " ApiKeyCredential" + + $content | Set-Content -Path $file.FullName + } +} + +Update-ClientModelPackage +Update-OpenAIClient +Update-OpenAIClientOptions +Update-Subclients +Update-Models +Update-Tests \ No newline at end of file diff --git a/.dotnet/src/ClientShared/ModelReaderWriterExtensions.cs b/.dotnet/src/ClientShared/ModelReaderWriterExtensions.cs new file mode 100644 index 000000000..25be6cbb5 --- /dev/null +++ b/.dotnet/src/ClientShared/ModelReaderWriterExtensions.cs @@ -0,0 +1,264 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +using System; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Linq; +using System.Text.Json; + +namespace OpenAI.ClientShared.Internal; + +internal static class ModelReaderWriterExtensions +{ + // TODO: These are copied from shared source files. If they become + // public we need to refactor and consolidate to a single place. + + #region JsonElement + + public static object? GetObject(in this JsonElement element) + { + switch (element.ValueKind) + { + case JsonValueKind.String: + return element.GetString(); + case JsonValueKind.Number: + if (element.TryGetInt32(out int intValue)) + { + return intValue; + } + if (element.TryGetInt64(out long longValue)) + { + return longValue; + } + return element.GetDouble(); + case JsonValueKind.True: + return true; + case JsonValueKind.False: + return false; + case JsonValueKind.Undefined: + case JsonValueKind.Null: + return null; + case JsonValueKind.Object: + var dictionary = new Dictionary(); + foreach (JsonProperty jsonProperty in element.EnumerateObject()) + { + dictionary.Add(jsonProperty.Name, jsonProperty.Value.GetObject()); + } + return dictionary; + case JsonValueKind.Array: + var list = new List(); + foreach (JsonElement item in element.EnumerateArray()) + { + list.Add(item.GetObject()); + } + return list.ToArray(); + default: + throw new NotSupportedException("Not supported value kind " + element.ValueKind); + } + } + + public static byte[]? GetBytesFromBase64(in this JsonElement element, string format) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + + return format switch + { + "U" => TypeFormatters.FromBase64UrlString(element.GetRequiredString()), + "D" => element.GetBytesFromBase64(), + _ => throw new ArgumentException($"Format is not supported: '{format}'", nameof(format)) + }; + } + + public static DateTimeOffset GetDateTimeOffset(in this JsonElement element, string format) => format switch + { + "U" when element.ValueKind == JsonValueKind.Number => DateTimeOffset.FromUnixTimeSeconds(element.GetInt64()), + // relying on the param check of the inner call to throw ArgumentNullException if GetString() returns null + _ => TypeFormatters.ParseDateTimeOffset(element.GetString()!, format) + }; + + public static TimeSpan GetTimeSpan(in this JsonElement element, string format) => + // relying on the param check of the inner call to throw ArgumentNullException if GetString() returns null + TypeFormatters.ParseTimeSpan(element.GetString()!, format); + + public static char GetChar(this in JsonElement element) + { + if (element.ValueKind == JsonValueKind.String) + { + var text = element.GetString(); + if (text == null || text.Length != 1) + { + throw new NotSupportedException($"Cannot convert \"{text}\" to a Char"); + } + return text[0]; + } + else + { + throw new NotSupportedException($"Cannot convert {element.ValueKind} to a Char"); + } + } + + [Conditional("DEBUG")] + public static void ThrowNonNullablePropertyIsNull(this JsonProperty property) + { + throw new JsonException($"A property '{property.Name}' defined as non-nullable but received as null from the service. " + + $"This exception only happens in DEBUG builds of the library and would be ignored in the release build"); + } + + public static string GetRequiredString(in this JsonElement element) + { + var value = element.GetString(); + if (value == null) + throw new InvalidOperationException($"The requested operation requires an element of type 'String', but the target element has type '{element.ValueKind}'."); + + return value; + } + + #endregion + + #region Utf8JsonWriter + public static void WriteStringValue(this Utf8JsonWriter writer, DateTimeOffset value, string format) => + writer.WriteStringValue(TypeFormatters.ToString(value, format)); + + public static void WriteStringValue(this Utf8JsonWriter writer, DateTime value, string format) => + writer.WriteStringValue(TypeFormatters.ToString(value, format)); + + public static void WriteStringValue(this Utf8JsonWriter writer, TimeSpan value, string format) => + writer.WriteStringValue(TypeFormatters.ToString(value, format)); + + public static void WriteStringValue(this Utf8JsonWriter writer, char value) => + writer.WriteStringValue(value.ToString(CultureInfo.InvariantCulture)); + + public static void WriteNonEmptyArray(this Utf8JsonWriter writer, string name, IReadOnlyList values) + { + if (values.Any()) + { + writer.WriteStartArray(name); + foreach (var s in values) + { + writer.WriteStringValue(s); + } + + writer.WriteEndArray(); + } + } + + public static void WriteBase64StringValue(this Utf8JsonWriter writer, byte[] value, string format) + { + if (value == null) + { + writer.WriteNullValue(); + return; + } + + switch (format) + { + case "U": + writer.WriteStringValue(TypeFormatters.ToBase64UrlString(value)); + break; + case "D": + writer.WriteBase64StringValue(value); + break; + default: + throw new ArgumentException($"Format is not supported: '{format}'", nameof(format)); + } + } + + public static void WriteNumberValue(this Utf8JsonWriter writer, DateTimeOffset value, string format) + { + if (format != "U") throw new ArgumentOutOfRangeException(format, "Only 'U' format is supported when writing a DateTimeOffset as a Number."); + + writer.WriteNumberValue(value.ToUnixTimeSeconds()); + } + + public static void WriteObjectValue(this Utf8JsonWriter writer, object? value) + { + switch (value) + { + case null: + writer.WriteNullValue(); + break; + case IJsonModel writeable: + writeable.Write(writer, ModelReaderWriterHelper.WireOptions); + break; + case byte[] bytes: + writer.WriteBase64StringValue(bytes); + break; + case BinaryData bytes: + writer.WriteBase64StringValue(bytes); + break; + case JsonElement json: + json.WriteTo(writer); + break; + case int i: + writer.WriteNumberValue(i); + break; + case decimal d: + writer.WriteNumberValue(d); + break; + case double d: + if (double.IsNaN(d)) + { + writer.WriteStringValue("NaN"); + } + else + { + writer.WriteNumberValue(d); + } + break; + case float f: + writer.WriteNumberValue(f); + break; + case long l: + writer.WriteNumberValue(l); + break; + case string s: + writer.WriteStringValue(s); + break; + case bool b: + writer.WriteBooleanValue(b); + break; + case Guid g: + writer.WriteStringValue(g); + break; + case DateTimeOffset dateTimeOffset: + writer.WriteStringValue(dateTimeOffset, "O"); + break; + case DateTime dateTime: + writer.WriteStringValue(dateTime, "O"); + break; + case IEnumerable> enumerable: + writer.WriteStartObject(); + foreach (KeyValuePair pair in enumerable) + { + writer.WritePropertyName(pair.Key); + writer.WriteObjectValue(pair.Value); + } + writer.WriteEndObject(); + break; + case IEnumerable objectEnumerable: + writer.WriteStartArray(); + foreach (object item in objectEnumerable) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + break; + case TimeSpan timeSpan: + writer.WriteStringValue(timeSpan, "P"); + break; + + default: + throw new NotSupportedException("Not supported type " + value.GetType()); + } + } + + #endregion +} \ No newline at end of file diff --git a/.dotnet/src/ClientShared/ModelReaderWriterHelper.cs b/.dotnet/src/ClientShared/ModelReaderWriterHelper.cs new file mode 100644 index 000000000..21181d6d1 --- /dev/null +++ b/.dotnet/src/ClientShared/ModelReaderWriterHelper.cs @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +using System; +using System.ClientModel.Primitives; +using System.Runtime.CompilerServices; + +namespace OpenAI.ClientShared.Internal; + +internal static class ModelReaderWriterHelper +{ + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ValidateFormat(IPersistableModel model, string format) + { + bool implementsJson = model is IJsonModel; + bool isValid = (format == "J" && implementsJson) || format == "W"; + if (!isValid) + { + throw new FormatException($"The model {model.GetType().Name} does not support '{format}' format."); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ValidateFormat(IPersistableModel model, string format) + => ValidateFormat(model, format); + + private static ModelReaderWriterOptions? _wireOptions; + public static ModelReaderWriterOptions WireOptions => _wireOptions ??= new ModelReaderWriterOptions("W"); +} \ No newline at end of file diff --git a/.dotnet/src/ClientShared/OptionalDictionary.cs b/.dotnet/src/ClientShared/OptionalDictionary.cs new file mode 100644 index 000000000..138a936da --- /dev/null +++ b/.dotnet/src/ClientShared/OptionalDictionary.cs @@ -0,0 +1,214 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace OpenAI.ClientShared.Internal; + +internal class OptionalDictionary : IDictionary, IReadOnlyDictionary where TKey : notnull +{ + private IDictionary? _innerDictionary; + + public OptionalDictionary() + { + } + + public OptionalDictionary(OptionalProperty> optionalDictionary) : this(optionalDictionary.Value) + { + } + + public OptionalDictionary(OptionalProperty> optionalDictionary) : this(optionalDictionary.Value) + { + } + + private OptionalDictionary(IDictionary? dictionary) + { + if (dictionary == null) return; + + _innerDictionary = new Dictionary(dictionary); + } + + private OptionalDictionary(IReadOnlyDictionary? dictionary) + { + if (dictionary == null) return; + + _innerDictionary = new Dictionary(); + foreach (KeyValuePair pair in dictionary) + { + _innerDictionary.Add(pair); + } + } + + public bool IsUndefined => _innerDictionary == null; + + public IEnumerator> GetEnumerator() + { + if (IsUndefined) + { + IEnumerator> GetEmptyEnumerator() + { + yield break; + } + return GetEmptyEnumerator(); + } + return EnsureDictionary().GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public void Add(KeyValuePair item) + { + EnsureDictionary().Add(item); + } + + public void Clear() + { + EnsureDictionary().Clear(); + } + + public bool Contains(KeyValuePair item) + { + if (IsUndefined) + { + return false; + } + + return EnsureDictionary().Contains(item); + } + + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + if (IsUndefined) + { + return; + } + + EnsureDictionary().CopyTo(array, arrayIndex); + } + + public bool Remove(KeyValuePair item) + { + if (IsUndefined) + { + return false; + } + + return EnsureDictionary().Remove(item); + } + + public int Count + { + get + { + if (IsUndefined) + { + return 0; + } + + return EnsureDictionary().Count; + } + } + + public bool IsReadOnly + { + get + { + if (IsUndefined) + { + return false; + } + return EnsureDictionary().IsReadOnly; + } + } + + public void Add(TKey key, TValue value) + { + EnsureDictionary().Add(key, value); + } + + public bool ContainsKey(TKey key) + { + if (IsUndefined) + { + return false; + } + + return EnsureDictionary().ContainsKey(key); + } + + public bool Remove(TKey key) + { + if (IsUndefined) + { + return false; + } + + return EnsureDictionary().Remove(key); + } + + public bool TryGetValue(TKey key, out TValue value) + { + if (IsUndefined) + { + value = default!; + return false; + } + return EnsureDictionary().TryGetValue(key, out value!); + } + + public TValue this[TKey key] + { + get + { + if (IsUndefined) + { + throw new KeyNotFoundException(nameof(key)); + } + + return EnsureDictionary()[key]; + } + set => EnsureDictionary()[key] = value; + } + + IEnumerable IReadOnlyDictionary.Keys => Keys; + + IEnumerable IReadOnlyDictionary.Values => Values; + + public ICollection Keys + { + get + { + if (IsUndefined) + { + return Array.Empty(); + } + + return EnsureDictionary().Keys; + } + } + + public ICollection Values + { + get + { + if (IsUndefined) + { + return Array.Empty(); + } + + return EnsureDictionary().Values; + } + } + + private IDictionary EnsureDictionary() + { + return _innerDictionary ??= new Dictionary(); + } +} \ No newline at end of file diff --git a/.dotnet/src/ClientShared/OptionalList.cs b/.dotnet/src/ClientShared/OptionalList.cs new file mode 100644 index 000000000..cc95a17ea --- /dev/null +++ b/.dotnet/src/ClientShared/OptionalList.cs @@ -0,0 +1,191 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.ClientShared.Internal; + +internal class OptionalList : IList, IReadOnlyList +{ + private IList? _innerList; + + public OptionalList() + { + } + + public OptionalList(OptionalProperty> optionalList) : this(optionalList.Value) + { + } + + public OptionalList(OptionalProperty> optionalList) : this(optionalList.Value) + { + } + + private OptionalList(IEnumerable? innerList) + { + if (innerList == null) + { + return; + } + + _innerList = innerList.ToList(); + } + + private OptionalList(IList? innerList) + { + if (innerList == null) + { + return; + } + + _innerList = innerList; + } + + public bool IsUndefined => _innerList == null; + + public void Reset() + { + _innerList = null; + } + + public IEnumerator GetEnumerator() + { + if (IsUndefined) + { + IEnumerator EnumerateEmpty() + { + yield break; + } + + return EnumerateEmpty(); + } + return EnsureList().GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public void Add(T item) + { + EnsureList().Add(item); + } + + public void Clear() + { + EnsureList().Clear(); + } + + public bool Contains(T item) + { + if (IsUndefined) + { + return false; + } + + return EnsureList().Contains(item); + } + + public void CopyTo(T[] array, int arrayIndex) + { + if (IsUndefined) + { + return; + } + + EnsureList().CopyTo(array, arrayIndex); + } + + public bool Remove(T item) + { + if (IsUndefined) + { + return false; + } + + return EnsureList().Remove(item); + } + + public int Count + { + get + { + if (IsUndefined) + { + return 0; + } + return EnsureList().Count; + } + } + + public bool IsReadOnly + { + get + { + if (IsUndefined) + { + return false; + } + + return EnsureList().IsReadOnly; + } + } + + public int IndexOf(T item) + { + if (IsUndefined) + { + return -1; + } + + return EnsureList().IndexOf(item); + } + + public void Insert(int index, T item) + { + EnsureList().Insert(index, item); + } + + public void RemoveAt(int index) + { + if (IsUndefined) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + EnsureList().RemoveAt(index); + } + + public T this[int index] + { + get + { + if (IsUndefined) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + return EnsureList()[index]; + } + set + { + if (IsUndefined) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + EnsureList()[index] = value; + } + } + + private IList EnsureList() + { + return _innerList ??= new List(); + } +} \ No newline at end of file diff --git a/.dotnet/src/ClientShared/OptionalProperty.cs b/.dotnet/src/ClientShared/OptionalProperty.cs new file mode 100644 index 000000000..9ad960789 --- /dev/null +++ b/.dotnet/src/ClientShared/OptionalProperty.cs @@ -0,0 +1,117 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.ClientShared.Internal; + +internal static class OptionalProperty +{ + public static bool IsCollectionDefined(IEnumerable collection) + { + return !(collection is OptionalList changeTrackingList && changeTrackingList.IsUndefined); + } + + public static bool IsCollectionDefined(IReadOnlyDictionary collection) + where TKey : notnull + { + return !(collection is OptionalDictionary changeTrackingList && changeTrackingList.IsUndefined); + } + + public static bool IsCollectionDefined(IDictionary? collection) + where TKey : notnull + { + if (collection is null) + return false; + + return !(collection is OptionalDictionary changeTrackingList && changeTrackingList.IsUndefined); + } + + public static bool IsDefined(T? value) where T : struct + { + return value.HasValue; + } + public static bool IsDefined(object value) + { + return value != null; + } + public static bool IsDefined(string? value) + { + return value != null; + } + + public static bool IsDefined(JsonElement value) + { + return value.ValueKind != JsonValueKind.Undefined; + } + + public static IReadOnlyDictionary ToDictionary(OptionalProperty> optional) + where TKey : notnull + { + if (optional.HasValue) + { + return optional.Value!; + } + return new OptionalDictionary(optional); + } + + public static IDictionary ToDictionary(OptionalProperty> optional) + where TKey : notnull + { + if (optional.HasValue) + { + return optional.Value!; + } + return new OptionalDictionary(optional); + } + + public static IReadOnlyList ToList(OptionalProperty> optional) + { + if (optional.HasValue) + { + return optional.Value!; + } + return new OptionalList(optional); + } + + public static IList ToList(OptionalProperty> optional) + { + if (optional.HasValue) + { + return optional.Value!; + } + return new OptionalList(optional); + } + + public static T? ToNullable(OptionalProperty optional) where T : struct + { + if (optional.HasValue) + { + return optional.Value; + } + return default; + } + + public static T? ToNullable(OptionalProperty optional) where T : struct + { + return optional.Value; + } +} + +internal readonly struct OptionalProperty +{ + public OptionalProperty(T? value) : this() + { + Value = value; + HasValue = value is not null; + } + + public T? Value { get; } + public bool HasValue { get; } + + public static implicit operator OptionalProperty(T? value) => new OptionalProperty(value); + public static implicit operator T?(OptionalProperty optional) => optional.Value; +} \ No newline at end of file diff --git a/.dotnet/src/ClientShared/TypeFormatters.cs b/.dotnet/src/ClientShared/TypeFormatters.cs new file mode 100644 index 000000000..9a00edaf3 --- /dev/null +++ b/.dotnet/src/ClientShared/TypeFormatters.cs @@ -0,0 +1,158 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Xml; + +namespace OpenAI.ClientShared.Internal; + +internal class TypeFormatters +{ + private const string RoundtripZFormat = "yyyy-MM-ddTHH:mm:ss.fffffffZ"; + public static string DefaultNumberFormat { get; } = "G"; + + public static string ToString(bool value) => value ? "true" : "false"; + + public static string ToString(DateTime value, string format) => value.Kind switch + { + DateTimeKind.Utc => ToString((DateTimeOffset)value, format), + _ => throw new NotSupportedException($"DateTime {value} has a Kind of {value.Kind}. Azure SDK requires it to be UTC. You can call DateTime.SpecifyKind to change Kind property value to DateTimeKind.Utc.") + }; + + public static string ToString(DateTimeOffset value, string format) => format switch + { + "D" => value.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture), + "U" => value.ToUnixTimeSeconds().ToString(CultureInfo.InvariantCulture), + "O" => value.ToUniversalTime().ToString(RoundtripZFormat, CultureInfo.InvariantCulture), + "o" => value.ToUniversalTime().ToString(RoundtripZFormat, CultureInfo.InvariantCulture), + "R" => value.ToString("r", CultureInfo.InvariantCulture), + _ => value.ToString(format, CultureInfo.InvariantCulture) + }; + + public static string ToString(TimeSpan value, string format) => format switch + { + "P" => XmlConvert.ToString(value), + _ => value.ToString(format, CultureInfo.InvariantCulture) + }; + + public static string ToString(byte[] value, string format) => format switch + { + "U" => ToBase64UrlString(value), + "D" => Convert.ToBase64String(value), + _ => throw new ArgumentException($"Format is not supported: '{format}'", nameof(format)) + }; + + public static string ToBase64UrlString(byte[] value) + { + var numWholeOrPartialInputBlocks = checked(value.Length + 2) / 3; + var size = checked(numWholeOrPartialInputBlocks * 4); + var output = new char[size]; + + var numBase64Chars = Convert.ToBase64CharArray(value, 0, value.Length, output, 0); + + // Fix up '+' -> '-' and '/' -> '_'. Drop padding characters. + int i = 0; + for (; i < numBase64Chars; i++) + { + var ch = output[i]; + if (ch == '+') + { + output[i] = '-'; + } + else if (ch == '/') + { + output[i] = '_'; + } + else if (ch == '=') + { + // We've reached a padding character; truncate the remainder. + break; + } + } + + return new string(output, 0, i); + } + + public static byte[] FromBase64UrlString(string value) + { + var paddingCharsToAdd = GetNumBase64PaddingCharsToAddForDecode(value.Length); + + var output = new char[value.Length + paddingCharsToAdd]; + + int i; + for (i = 0; i < value.Length; i++) + { + var ch = value[i]; + if (ch == '-') + { + output[i] = '+'; + } + else if (ch == '_') + { + output[i] = '/'; + } + else + { + output[i] = ch; + } + } + + for (; i < output.Length; i++) + { + output[i] = '='; + } + + return Convert.FromBase64CharArray(output, 0, output.Length); + } + + private static int GetNumBase64PaddingCharsToAddForDecode(int inputLength) + { + switch (inputLength % 4) + { + case 0: + return 0; + case 2: + return 2; + case 3: + return 1; + default: + throw new InvalidOperationException("Malformed input"); + } + } + + public static DateTimeOffset ParseDateTimeOffset(string value, string format) + { + return format switch + { + "U" => DateTimeOffset.FromUnixTimeSeconds(long.Parse(value, CultureInfo.InvariantCulture)), + _ => DateTimeOffset.Parse(value, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal) + }; + } + + public static TimeSpan ParseTimeSpan(string value, string format) => format switch + { + "P" => XmlConvert.ToTimeSpan(value), + _ => TimeSpan.ParseExact(value, format, CultureInfo.InvariantCulture) + }; + + public static string ConvertToString(object? value, string? format = null) + => value switch + { + null => "null", + string s => s, + bool b => ToString(b), + int or float or double or long or decimal => ((IFormattable)value).ToString(DefaultNumberFormat, CultureInfo.InvariantCulture), + byte[] b when format != null => ToString(b, format), + IEnumerable s => string.Join(",", s), + DateTimeOffset dateTime when format != null => ToString(dateTime, format), + TimeSpan timeSpan when format != null => ToString(timeSpan, format), + TimeSpan timeSpan => XmlConvert.ToString(timeSpan), + Guid guid => guid.ToString(), + BinaryData binaryData => TypeFormatters.ConvertToString(binaryData.ToArray(), format), + _ => value.ToString()! + }; +} \ No newline at end of file diff --git a/.dotnet/src/Generated/Assistants.cs b/.dotnet/src/Generated/Assistants.cs index 748820476..afaac60ee 100644 --- a/.dotnet/src/Generated/Assistants.cs +++ b/.dotnet/src/Generated/Assistants.cs @@ -1,12 +1,9 @@ // -#nullable disable - using System; using System.ClientModel; -using System.ClientModel.Internal; using System.ClientModel.Primitives; -using System.ClientModel.Primitives.Pipeline; +using System.Text; using System.Threading; using System.Threading.Tasks; using OpenAI.Models; @@ -18,16 +15,13 @@ namespace OpenAI public partial class Assistants { private const string AuthorizationHeader = "Authorization"; - private readonly KeyCredential _keyCredential; + private readonly ApiKeyCredential _credential; private const string AuthorizationApiKeyPrefix = "Bearer"; - private readonly MessagePipeline _pipeline; + private readonly ClientPipeline _pipeline; private readonly Uri _endpoint; - /// The ClientDiagnostics is used to provide tracing support for the client library. - internal TelemetrySource ClientDiagnostics { get; } - /// The HTTP pipeline for sending and receiving REST requests and responses. - public virtual MessagePipeline Pipeline => _pipeline; + public virtual ClientPipeline Pipeline => _pipeline; /// Initializes a new instance of Assistants for mocking. protected Assistants() @@ -35,44 +29,38 @@ protected Assistants() } /// Initializes a new instance of Assistants. - /// The handler for diagnostic messaging in the client. /// The HTTP pipeline for sending and receiving REST requests and responses. - /// The key credential to copy. + /// The key credential to copy. /// OpenAI Endpoint. - internal Assistants(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + internal Assistants(ClientPipeline pipeline, ApiKeyCredential credential, Uri endpoint) { - ClientDiagnostics = clientDiagnostics; _pipeline = pipeline; - _keyCredential = keyCredential; + _credential = credential; _endpoint = endpoint; } /// Create an assistant with a model and instructions. /// The to use. - /// The cancellation token to use. /// is null. - public virtual async Task> CreateAssistantAsync(CreateAssistantRequest assistant, CancellationToken cancellationToken = default) + public virtual async Task> CreateAssistantAsync(CreateAssistantRequest assistant) { - ClientUtilities.AssertNotNull(assistant, nameof(assistant)); + if (assistant is null) throw new ArgumentNullException(nameof(assistant)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = assistant.ToRequestBody(); - Result result = await CreateAssistantAsync(content, context).ConfigureAwait(false); - return Result.FromValue(AssistantObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(assistant); + ClientResult result = await CreateAssistantAsync(content).ConfigureAwait(false); + return ClientResult.FromValue(AssistantObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Create an assistant with a model and instructions. /// The to use. - /// The cancellation token to use. /// is null. - public virtual Result CreateAssistant(CreateAssistantRequest assistant, CancellationToken cancellationToken = default) + public virtual ClientResult CreateAssistant(CreateAssistantRequest assistant) { - ClientUtilities.AssertNotNull(assistant, nameof(assistant)); + if (assistant is null) throw new ArgumentNullException(nameof(assistant)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = assistant.ToRequestBody(); - Result result = CreateAssistant(content, context); - return Result.FromValue(AssistantObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(assistant); + ClientResult result = CreateAssistant(content); + return ClientResult.FromValue(AssistantObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -85,32 +73,30 @@ public virtual Result CreateAssistant(CreateAssistantRequest as /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task CreateAssistantAsync(RequestBody content, RequestOptions context = null) + public virtual async Task CreateAssistantAsync(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateAssistantRequest(content, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Assistants.CreateAssistant"); - scope.Start(); - try + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateCreateAssistantRequest(content, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -123,32 +109,30 @@ public virtual async Task CreateAssistantAsync(RequestBody content, Requ /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result CreateAssistant(RequestBody content, RequestOptions context = null) + public virtual ClientResult CreateAssistant(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateAssistantRequest(content, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Assistants.CreateAssistant"); - scope.Start(); - try + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateCreateAssistantRequest(content, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Returns a list of assistants. @@ -170,12 +154,10 @@ public virtual Result CreateAssistant(RequestBody content, RequestOptions contex /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. /// - /// The cancellation token to use. - public virtual async Task> GetAssistantsAsync(int? limit = null, ListOrder? order = null, string after = null, string before = null, CancellationToken cancellationToken = default) + public virtual async Task> GetAssistantsAsync(int? limit = null, ListOrder? order = null, string after = null, string before = null) { - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await GetAssistantsAsync(limit, order?.ToString(), after, before, context).ConfigureAwait(false); - return Result.FromValue(ListAssistantsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = await GetAssistantsAsync(limit, order?.ToString(), after, before).ConfigureAwait(false); + return ClientResult.FromValue(ListAssistantsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Returns a list of assistants. @@ -197,12 +179,10 @@ public virtual async Task> GetAssistantsAsync(int /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. /// - /// The cancellation token to use. - public virtual Result GetAssistants(int? limit = null, ListOrder? order = null, string after = null, string before = null, CancellationToken cancellationToken = default) + public virtual ClientResult GetAssistants(int? limit = null, ListOrder? order = null, string after = null, string before = null) { - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = GetAssistants(limit, order?.ToString(), after, before, context); - return Result.FromValue(ListAssistantsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = GetAssistants(limit, order?.ToString(), after, before); + return ClientResult.FromValue(ListAssistantsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -215,7 +195,7 @@ public virtual Result GetAssistants(int? limit = null, L /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -238,23 +218,22 @@ public virtual Result GetAssistants(int? limit = null, L /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. /// - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// Service returned a non-success status code. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task GetAssistantsAsync(int? limit, string order, string after, string before, RequestOptions context) + public virtual async Task GetAssistantsAsync(int? limit, string order, string after, string before, RequestOptions options) { - using var scope = ClientDiagnostics.CreateSpan("Assistants.GetAssistants"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetAssistantsRequest(limit, order, after, before, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetAssistantsRequest(limit, order, after, before, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -267,7 +246,7 @@ public virtual async Task GetAssistantsAsync(int? limit, string order, s /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -290,51 +269,48 @@ public virtual async Task GetAssistantsAsync(int? limit, string order, s /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. /// - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// Service returned a non-success status code. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result GetAssistants(int? limit, string order, string after, string before, RequestOptions context) + public virtual ClientResult GetAssistants(int? limit, string order, string after, string before, RequestOptions options) { - using var scope = ClientDiagnostics.CreateSpan("Assistants.GetAssistants"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetAssistantsRequest(limit, order, after, before, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetAssistantsRequest(limit, order, after, before, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Retrieves an assistant. /// The ID of the assistant to retrieve. - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual async Task> GetAssistantAsync(string assistantId, CancellationToken cancellationToken = default) + public virtual async Task> GetAssistantAsync(string assistantId) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await GetAssistantAsync(assistantId, context).ConfigureAwait(false); - return Result.FromValue(AssistantObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = await GetAssistantAsync(assistantId).ConfigureAwait(false); + return ClientResult.FromValue(AssistantObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Retrieves an assistant. /// The ID of the assistant to retrieve. - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual Result GetAssistant(string assistantId, CancellationToken cancellationToken = default) + public virtual ClientResult GetAssistant(string assistantId) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = GetAssistant(assistantId, context); - return Result.FromValue(AssistantObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = GetAssistant(assistantId); + return ClientResult.FromValue(AssistantObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -347,33 +323,32 @@ public virtual Result GetAssistant(string assistantId, Cancella /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the assistant to retrieve. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task GetAssistantAsync(string assistantId, RequestOptions context) + public virtual async Task GetAssistantAsync(string assistantId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - - using var scope = ClientDiagnostics.CreateSpan("Assistants.GetAssistant"); - scope.Start(); - try + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetAssistantRequest(assistantId, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateGetAssistantRequest(assistantId, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -386,67 +361,64 @@ public virtual async Task GetAssistantAsync(string assistantId, RequestO /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the assistant to retrieve. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result GetAssistant(string assistantId, RequestOptions context) + public virtual ClientResult GetAssistant(string assistantId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - - using var scope = ClientDiagnostics.CreateSpan("Assistants.GetAssistant"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetAssistantRequest(assistantId, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetAssistantRequest(assistantId, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Modifies an assistant. /// The ID of the assistant to modify. /// The to use. - /// The cancellation token to use. /// or is null. /// is an empty string, and was expected to be non-empty. - public virtual async Task> ModifyAssistantAsync(string assistantId, ModifyAssistantRequest assistant, CancellationToken cancellationToken = default) + public virtual async Task> ModifyAssistantAsync(string assistantId, ModifyAssistantRequest assistant) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - ClientUtilities.AssertNotNull(assistant, nameof(assistant)); + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + if (assistant is null) throw new ArgumentNullException(nameof(assistant)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = assistant.ToRequestBody(); - Result result = await ModifyAssistantAsync(assistantId, content, context).ConfigureAwait(false); - return Result.FromValue(AssistantObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(assistant); + ClientResult result = await ModifyAssistantAsync(assistantId, content).ConfigureAwait(false); + return ClientResult.FromValue(AssistantObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Modifies an assistant. /// The ID of the assistant to modify. /// The to use. - /// The cancellation token to use. /// or is null. /// is an empty string, and was expected to be non-empty. - public virtual Result ModifyAssistant(string assistantId, ModifyAssistantRequest assistant, CancellationToken cancellationToken = default) + public virtual ClientResult ModifyAssistant(string assistantId, ModifyAssistantRequest assistant) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - ClientUtilities.AssertNotNull(assistant, nameof(assistant)); + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + if (assistant is null) throw new ArgumentNullException(nameof(assistant)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = assistant.ToRequestBody(); - Result result = ModifyAssistant(assistantId, content, context); - return Result.FromValue(AssistantObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(assistant); + ClientResult result = ModifyAssistant(assistantId, content); + return ClientResult.FromValue(AssistantObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -459,35 +431,34 @@ public virtual Result ModifyAssistant(string assistantId, Modif /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the assistant to modify. /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// or is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task ModifyAssistantAsync(string assistantId, RequestBody content, RequestOptions context = null) + public virtual async Task ModifyAssistantAsync(string assistantId, BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - ClientUtilities.AssertNotNull(content, nameof(content)); - - using var scope = ClientDiagnostics.CreateSpan("Assistants.ModifyAssistant"); - scope.Start(); - try + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateModifyAssistantRequest(assistantId, content, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateModifyAssistantRequest(assistantId, content, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -500,63 +471,60 @@ public virtual async Task ModifyAssistantAsync(string assistantId, Reque /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the assistant to modify. /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// or is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result ModifyAssistant(string assistantId, RequestBody content, RequestOptions context = null) + public virtual ClientResult ModifyAssistant(string assistantId, BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - ClientUtilities.AssertNotNull(content, nameof(content)); - - using var scope = ClientDiagnostics.CreateSpan("Assistants.ModifyAssistant"); - scope.Start(); - try - { - using PipelineMessage message = CreateModifyAssistantRequest(assistantId, content, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateModifyAssistantRequest(assistantId, content, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Delete an assistant. /// The ID of the assistant to delete. - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual async Task> DeleteAssistantAsync(string assistantId, CancellationToken cancellationToken = default) + public virtual async Task> DeleteAssistantAsync(string assistantId) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await DeleteAssistantAsync(assistantId, context).ConfigureAwait(false); - return Result.FromValue(DeleteAssistantResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = await DeleteAssistantAsync(assistantId).ConfigureAwait(false); + return ClientResult.FromValue(DeleteAssistantResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Delete an assistant. /// The ID of the assistant to delete. - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual Result DeleteAssistant(string assistantId, CancellationToken cancellationToken = default) + public virtual ClientResult DeleteAssistant(string assistantId) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = DeleteAssistant(assistantId, context); - return Result.FromValue(DeleteAssistantResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = DeleteAssistant(assistantId); + return ClientResult.FromValue(DeleteAssistantResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -569,33 +537,32 @@ public virtual Result DeleteAssistant(string assistantI /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the assistant to delete. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task DeleteAssistantAsync(string assistantId, RequestOptions context) + public virtual async Task DeleteAssistantAsync(string assistantId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - - using var scope = ClientDiagnostics.CreateSpan("Assistants.DeleteAssistant"); - scope.Start(); - try - { - using PipelineMessage message = CreateDeleteAssistantRequest(assistantId, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateDeleteAssistantRequest(assistantId, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -608,33 +575,32 @@ public virtual async Task DeleteAssistantAsync(string assistantId, Reque /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the assistant to delete. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result DeleteAssistant(string assistantId, RequestOptions context) + public virtual ClientResult DeleteAssistant(string assistantId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - - using var scope = ClientDiagnostics.CreateSpan("Assistants.DeleteAssistant"); - scope.Start(); - try + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateDeleteAssistantRequest(assistantId, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateDeleteAssistantRequest(assistantId, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// @@ -643,18 +609,17 @@ public virtual Result DeleteAssistant(string assistantId, RequestOptions context /// /// The ID of the assistant for which to create a file. /// The to use. - /// The cancellation token to use. /// or is null. /// is an empty string, and was expected to be non-empty. - public virtual async Task> CreateAssistantFileAsync(string assistantId, CreateAssistantFileRequest file, CancellationToken cancellationToken = default) + public virtual async Task> CreateAssistantFileAsync(string assistantId, CreateAssistantFileRequest file) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - ClientUtilities.AssertNotNull(file, nameof(file)); + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + if (file is null) throw new ArgumentNullException(nameof(file)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = file.ToRequestBody(); - Result result = await CreateAssistantFileAsync(assistantId, content, context).ConfigureAwait(false); - return Result.FromValue(AssistantFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(file); + ClientResult result = await CreateAssistantFileAsync(assistantId, content).ConfigureAwait(false); + return ClientResult.FromValue(AssistantFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -663,18 +628,17 @@ public virtual async Task> CreateAssistantFileAsync( /// /// The ID of the assistant for which to create a file. /// The to use. - /// The cancellation token to use. /// or is null. /// is an empty string, and was expected to be non-empty. - public virtual Result CreateAssistantFile(string assistantId, CreateAssistantFileRequest file, CancellationToken cancellationToken = default) + public virtual ClientResult CreateAssistantFile(string assistantId, CreateAssistantFileRequest file) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - ClientUtilities.AssertNotNull(file, nameof(file)); + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + if (file is null) throw new ArgumentNullException(nameof(file)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = file.ToRequestBody(); - Result result = CreateAssistantFile(assistantId, content, context); - return Result.FromValue(AssistantFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(file); + ClientResult result = CreateAssistantFile(assistantId, content); + return ClientResult.FromValue(AssistantFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -688,35 +652,34 @@ public virtual Result CreateAssistantFile(string assistantI /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the assistant for which to create a file. /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// or is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task CreateAssistantFileAsync(string assistantId, RequestBody content, RequestOptions context = null) + public virtual async Task CreateAssistantFileAsync(string assistantId, BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - ClientUtilities.AssertNotNull(content, nameof(content)); - - using var scope = ClientDiagnostics.CreateSpan("Assistants.CreateAssistantFile"); - scope.Start(); - try - { - using PipelineMessage message = CreateCreateAssistantFileRequest(assistantId, content, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateAssistantFileRequest(assistantId, content, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -730,35 +693,34 @@ public virtual async Task CreateAssistantFileAsync(string assistantId, R /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the assistant for which to create a file. /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// or is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result CreateAssistantFile(string assistantId, RequestBody content, RequestOptions context = null) + public virtual ClientResult CreateAssistantFile(string assistantId, BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - ClientUtilities.AssertNotNull(content, nameof(content)); - - using var scope = ClientDiagnostics.CreateSpan("Assistants.CreateAssistantFile"); - scope.Start(); - try + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateAssistantFileRequest(assistantId, content, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateCreateAssistantFileRequest(assistantId, content, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Returns a list of assistant files. @@ -781,16 +743,15 @@ public virtual Result CreateAssistantFile(string assistantId, RequestBody conten /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. /// - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual async Task> GetAssistantFilesAsync(string assistantId, int? limit = null, ListOrder? order = null, string after = null, string before = null, CancellationToken cancellationToken = default) + public virtual async Task> GetAssistantFilesAsync(string assistantId, int? limit = null, ListOrder? order = null, string after = null, string before = null) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await GetAssistantFilesAsync(assistantId, limit, order?.ToString(), after, before, context).ConfigureAwait(false); - return Result.FromValue(ListAssistantFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = await GetAssistantFilesAsync(assistantId, limit, order?.ToString(), after, before).ConfigureAwait(false); + return ClientResult.FromValue(ListAssistantFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Returns a list of assistant files. @@ -813,16 +774,15 @@ public virtual async Task> GetAssistantFilesA /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. /// - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual Result GetAssistantFiles(string assistantId, int? limit = null, ListOrder? order = null, string after = null, string before = null, CancellationToken cancellationToken = default) + public virtual ClientResult GetAssistantFiles(string assistantId, int? limit = null, ListOrder? order = null, string after = null, string before = null) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = GetAssistantFiles(assistantId, limit, order?.ToString(), after, before, context); - return Result.FromValue(ListAssistantFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = GetAssistantFiles(assistantId, limit, order?.ToString(), after, before); + return ClientResult.FromValue(ListAssistantFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -835,7 +795,7 @@ public virtual Result GetAssistantFiles(string assis /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -859,27 +819,26 @@ public virtual Result GetAssistantFiles(string assis /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. /// - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task GetAssistantFilesAsync(string assistantId, int? limit, string order, string after, string before, RequestOptions context) + public virtual async Task GetAssistantFilesAsync(string assistantId, int? limit, string order, string after, string before, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - - using var scope = ClientDiagnostics.CreateSpan("Assistants.GetAssistantFiles"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetAssistantFilesRequest(assistantId, limit, order, after, before, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetAssistantFilesRequest(assistantId, limit, order, after, before, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -892,7 +851,7 @@ public virtual async Task GetAssistantFilesAsync(string assistantId, int /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -916,59 +875,58 @@ public virtual async Task GetAssistantFilesAsync(string assistantId, int /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. /// - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result GetAssistantFiles(string assistantId, int? limit, string order, string after, string before, RequestOptions context) + public virtual ClientResult GetAssistantFiles(string assistantId, int? limit, string order, string after, string before, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - - using var scope = ClientDiagnostics.CreateSpan("Assistants.GetAssistantFiles"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetAssistantFilesRequest(assistantId, limit, order, after, before, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetAssistantFilesRequest(assistantId, limit, order, after, before, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Retrieves an assistant file. /// The ID of the assistant the file belongs to. /// The ID of the file we're getting. - /// The cancellation token to use. /// or is null. /// or is an empty string, and was expected to be non-empty. - public virtual async Task> GetAssistantFileAsync(string assistantId, string fileId, CancellationToken cancellationToken = default) + public virtual async Task> GetAssistantFileAsync(string assistantId, string fileId) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + if (fileId is null) throw new ArgumentNullException(nameof(fileId)); + if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await GetAssistantFileAsync(assistantId, fileId, context).ConfigureAwait(false); - return Result.FromValue(AssistantFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = await GetAssistantFileAsync(assistantId, fileId).ConfigureAwait(false); + return ClientResult.FromValue(AssistantFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Retrieves an assistant file. /// The ID of the assistant the file belongs to. /// The ID of the file we're getting. - /// The cancellation token to use. /// or is null. /// or is an empty string, and was expected to be non-empty. - public virtual Result GetAssistantFile(string assistantId, string fileId, CancellationToken cancellationToken = default) + public virtual ClientResult GetAssistantFile(string assistantId, string fileId) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + if (fileId is null) throw new ArgumentNullException(nameof(fileId)); + if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = GetAssistantFile(assistantId, fileId, context); - return Result.FromValue(AssistantFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = GetAssistantFile(assistantId, fileId); + return ClientResult.FromValue(AssistantFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -981,35 +939,35 @@ public virtual Result GetAssistantFile(string assistantId, /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the assistant the file belongs to. /// The ID of the file we're getting. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// or is null. /// or is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task GetAssistantFileAsync(string assistantId, string fileId, RequestOptions context) + public virtual async Task GetAssistantFileAsync(string assistantId, string fileId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); - - using var scope = ClientDiagnostics.CreateSpan("Assistants.GetAssistantFile"); - scope.Start(); - try + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + if (fileId is null) throw new ArgumentNullException(nameof(fileId)); + if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetAssistantFileRequest(assistantId, fileId, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateGetAssistantFileRequest(assistantId, fileId, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -1022,67 +980,67 @@ public virtual async Task GetAssistantFileAsync(string assistantId, stri /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the assistant the file belongs to. /// The ID of the file we're getting. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// or is null. /// or is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result GetAssistantFile(string assistantId, string fileId, RequestOptions context) + public virtual ClientResult GetAssistantFile(string assistantId, string fileId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); - - using var scope = ClientDiagnostics.CreateSpan("Assistants.GetAssistantFile"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetAssistantFileRequest(assistantId, fileId, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + if (fileId is null) throw new ArgumentNullException(nameof(fileId)); + if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetAssistantFileRequest(assistantId, fileId, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Delete an assistant file. /// The ID of the assistant the file belongs to. /// The ID of the file to delete. - /// The cancellation token to use. /// or is null. /// or is an empty string, and was expected to be non-empty. - public virtual async Task> DeleteAssistantFileAsync(string assistantId, string fileId, CancellationToken cancellationToken = default) + public virtual async Task> DeleteAssistantFileAsync(string assistantId, string fileId) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + if (fileId is null) throw new ArgumentNullException(nameof(fileId)); + if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await DeleteAssistantFileAsync(assistantId, fileId, context).ConfigureAwait(false); - return Result.FromValue(DeleteAssistantFileResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = await DeleteAssistantFileAsync(assistantId, fileId).ConfigureAwait(false); + return ClientResult.FromValue(DeleteAssistantFileResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Delete an assistant file. /// The ID of the assistant the file belongs to. /// The ID of the file to delete. - /// The cancellation token to use. /// or is null. /// or is an empty string, and was expected to be non-empty. - public virtual Result DeleteAssistantFile(string assistantId, string fileId, CancellationToken cancellationToken = default) + public virtual ClientResult DeleteAssistantFile(string assistantId, string fileId) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + if (fileId is null) throw new ArgumentNullException(nameof(fileId)); + if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = DeleteAssistantFile(assistantId, fileId, context); - return Result.FromValue(DeleteAssistantFileResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = DeleteAssistantFile(assistantId, fileId); + return ClientResult.FromValue(DeleteAssistantFileResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -1095,35 +1053,35 @@ public virtual Result DeleteAssistantFile(string as /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the assistant the file belongs to. /// The ID of the file to delete. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// or is null. /// or is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task DeleteAssistantFileAsync(string assistantId, string fileId, RequestOptions context) + public virtual async Task DeleteAssistantFileAsync(string assistantId, string fileId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); - - using var scope = ClientDiagnostics.CreateSpan("Assistants.DeleteAssistantFile"); - scope.Start(); - try + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + if (fileId is null) throw new ArgumentNullException(nameof(fileId)); + if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateDeleteAssistantFileRequest(assistantId, fileId, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateDeleteAssistantFileRequest(assistantId, fileId, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -1136,217 +1094,297 @@ public virtual async Task DeleteAssistantFileAsync(string assistantId, s /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the assistant the file belongs to. /// The ID of the file to delete. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// or is null. /// or is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result DeleteAssistantFile(string assistantId, string fileId, RequestOptions context) + public virtual ClientResult DeleteAssistantFile(string assistantId, string fileId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); - - using var scope = ClientDiagnostics.CreateSpan("Assistants.DeleteAssistantFile"); - scope.Start(); - try + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + if (fileId is null) throw new ArgumentNullException(nameof(fileId)); + if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateDeleteAssistantFileRequest(assistantId, fileId, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateDeleteAssistantFileRequest(assistantId, fileId, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } - internal PipelineMessage CreateCreateAssistantRequest(RequestBody content, RequestOptions context) + internal PipelineMessage CreateCreateAssistantRequest(BinaryContent content, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/assistants", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - request.SetHeaderValue("Content-Type", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/assistants"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); + request.Headers.Set("Content-Type", "application/json"); request.Content = content; + message.Apply(options); return message; } - internal PipelineMessage CreateGetAssistantsRequest(int? limit, string order, string after, string before, RequestOptions context) + internal PipelineMessage CreateGetAssistantsRequest(int? limit, string order, string after, string before, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("GET"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/assistants", false); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "GET"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/assistants"); + uriBuilder.Path += path.ToString(); if (limit != null) { - uri.AppendQuery("limit", limit.Value, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&limit={limit.Value}"; + } + else + { + uriBuilder.Query = $"limit={limit.Value}"; + } } if (order != null) { - uri.AppendQuery("order", order, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&order={order}"; + } + else + { + uriBuilder.Query = $"order={order}"; + } } if (after != null) { - uri.AppendQuery("after", after, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&after={after}"; + } + else + { + uriBuilder.Query = $"after={after}"; + } } if (before != null) { - uri.AppendQuery("before", before, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&before={before}"; + } + else + { + uriBuilder.Query = $"before={before}"; + } } - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); return message; } - internal PipelineMessage CreateGetAssistantRequest(string assistantId, RequestOptions context) + internal PipelineMessage CreateGetAssistantRequest(string assistantId, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("GET"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/assistants/", false); - uri.AppendPath(assistantId, true); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "GET"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/assistants/"); + uriBuilder.Path += path.ToString(); + path.Append(assistantId); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); return message; } - internal PipelineMessage CreateModifyAssistantRequest(string assistantId, RequestBody content, RequestOptions context) + internal PipelineMessage CreateModifyAssistantRequest(string assistantId, BinaryContent content, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/assistants/", false); - uri.AppendPath(assistantId, true); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - request.SetHeaderValue("Content-Type", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/assistants/"); + uriBuilder.Path += path.ToString(); + path.Append(assistantId); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); + request.Headers.Set("Content-Type", "application/json"); request.Content = content; + message.Apply(options); return message; } - internal PipelineMessage CreateDeleteAssistantRequest(string assistantId, RequestOptions context) + internal PipelineMessage CreateDeleteAssistantRequest(string assistantId, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("DELETE"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/assistants/", false); - uri.AppendPath(assistantId, true); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "DELETE"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/assistants/"); + uriBuilder.Path += path.ToString(); + path.Append(assistantId); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); return message; } - internal PipelineMessage CreateCreateAssistantFileRequest(string assistantId, RequestBody content, RequestOptions context) + internal PipelineMessage CreateCreateAssistantFileRequest(string assistantId, BinaryContent content, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/assistants/", false); - uri.AppendPath(assistantId, true); - uri.AppendPath("/files", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - request.SetHeaderValue("Content-Type", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/assistants/"); + uriBuilder.Path += path.ToString(); + path.Append(assistantId); + uriBuilder.Path += path.ToString(); + path.Append("/files"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); + request.Headers.Set("Content-Type", "application/json"); request.Content = content; + message.Apply(options); return message; } - internal PipelineMessage CreateGetAssistantFilesRequest(string assistantId, int? limit, string order, string after, string before, RequestOptions context) + internal PipelineMessage CreateGetAssistantFilesRequest(string assistantId, int? limit, string order, string after, string before, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("GET"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/assistants/", false); - uri.AppendPath(assistantId, true); - uri.AppendPath("/files", false); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "GET"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/assistants/"); + uriBuilder.Path += path.ToString(); + path.Append(assistantId); + uriBuilder.Path += path.ToString(); + path.Append("/files"); + uriBuilder.Path += path.ToString(); if (limit != null) { - uri.AppendQuery("limit", limit.Value, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&limit={limit.Value}"; + } + else + { + uriBuilder.Query = $"limit={limit.Value}"; + } } if (order != null) { - uri.AppendQuery("order", order, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&order={order}"; + } + else + { + uriBuilder.Query = $"order={order}"; + } } if (after != null) { - uri.AppendQuery("after", after, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&after={after}"; + } + else + { + uriBuilder.Query = $"after={after}"; + } } if (before != null) { - uri.AppendQuery("before", before, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&before={before}"; + } + else + { + uriBuilder.Query = $"before={before}"; + } } - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); return message; } - internal PipelineMessage CreateGetAssistantFileRequest(string assistantId, string fileId, RequestOptions context) + internal PipelineMessage CreateGetAssistantFileRequest(string assistantId, string fileId, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("GET"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/assistants/", false); - uri.AppendPath(assistantId, true); - uri.AppendPath("/files/", false); - uri.AppendPath(fileId, true); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "GET"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/assistants/"); + uriBuilder.Path += path.ToString(); + path.Append(assistantId); + uriBuilder.Path += path.ToString(); + path.Append("/files/"); + uriBuilder.Path += path.ToString(); + path.Append(fileId); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); return message; } - internal PipelineMessage CreateDeleteAssistantFileRequest(string assistantId, string fileId, RequestOptions context) + internal PipelineMessage CreateDeleteAssistantFileRequest(string assistantId, string fileId, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("DELETE"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/assistants/", false); - uri.AppendPath(assistantId, true); - uri.AppendPath("/files/", false); - uri.AppendPath(fileId, true); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "DELETE"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/assistants/"); + uriBuilder.Path += path.ToString(); + path.Append(assistantId); + uriBuilder.Path += path.ToString(); + path.Append("/files/"); + uriBuilder.Path += path.ToString(); + path.Append(fileId); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); return message; } - private static RequestOptions DefaultRequestContext = new RequestOptions(); - internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) - { - if (!cancellationToken.CanBeCanceled) - { - return DefaultRequestContext; - } - - return new RequestOptions() { CancellationToken = cancellationToken }; - } - - private static ResponseErrorClassifier _responseErrorClassifier200; - private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); + private static PipelineMessageClassifier _responseErrorClassifier200; + private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } } + diff --git a/.dotnet/src/Generated/Audio.cs b/.dotnet/src/Generated/Audio.cs index 6acfba501..d2bd5db96 100644 --- a/.dotnet/src/Generated/Audio.cs +++ b/.dotnet/src/Generated/Audio.cs @@ -1,12 +1,9 @@ // -#nullable disable - using System; using System.ClientModel; -using System.ClientModel.Internal; using System.ClientModel.Primitives; -using System.ClientModel.Primitives.Pipeline; +using System.Text; using System.Threading; using System.Threading.Tasks; using OpenAI.Models; @@ -18,16 +15,13 @@ namespace OpenAI public partial class Audio { private const string AuthorizationHeader = "Authorization"; - private readonly KeyCredential _keyCredential; + private readonly ApiKeyCredential _credential; private const string AuthorizationApiKeyPrefix = "Bearer"; - private readonly MessagePipeline _pipeline; + private readonly ClientPipeline _pipeline; private readonly Uri _endpoint; - /// The ClientDiagnostics is used to provide tracing support for the client library. - internal TelemetrySource ClientDiagnostics { get; } - /// The HTTP pipeline for sending and receiving REST requests and responses. - public virtual MessagePipeline Pipeline => _pipeline; + public virtual ClientPipeline Pipeline => _pipeline; /// Initializes a new instance of Audio for mocking. protected Audio() @@ -35,44 +29,38 @@ protected Audio() } /// Initializes a new instance of Audio. - /// The handler for diagnostic messaging in the client. /// The HTTP pipeline for sending and receiving REST requests and responses. - /// The key credential to copy. + /// The key credential to copy. /// OpenAI Endpoint. - internal Audio(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + internal Audio(ClientPipeline pipeline, ApiKeyCredential credential, Uri endpoint) { - ClientDiagnostics = clientDiagnostics; _pipeline = pipeline; - _keyCredential = keyCredential; + _credential = credential; _endpoint = endpoint; } /// Generates audio from the input text. /// The to use. - /// The cancellation token to use. /// is null. - public virtual async Task> CreateSpeechAsync(CreateSpeechRequest speech, CancellationToken cancellationToken = default) + public virtual async Task> CreateSpeechAsync(CreateSpeechRequest speech) { - ClientUtilities.AssertNotNull(speech, nameof(speech)); + if (speech is null) throw new ArgumentNullException(nameof(speech)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = speech.ToRequestBody(); - Result result = await CreateSpeechAsync(content, context).ConfigureAwait(false); - return Result.FromValue(result.GetRawResponse().Content, result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(speech); + ClientResult result = await CreateSpeechAsync(content).ConfigureAwait(false); + return ClientResult.FromValue(result.GetRawResponse().Content, result.GetRawResponse()); } /// Generates audio from the input text. /// The to use. - /// The cancellation token to use. /// is null. - public virtual Result CreateSpeech(CreateSpeechRequest speech, CancellationToken cancellationToken = default) + public virtual ClientResult CreateSpeech(CreateSpeechRequest speech) { - ClientUtilities.AssertNotNull(speech, nameof(speech)); + if (speech is null) throw new ArgumentNullException(nameof(speech)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = speech.ToRequestBody(); - Result result = CreateSpeech(content, context); - return Result.FromValue(result.GetRawResponse().Content, result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(speech); + ClientResult result = CreateSpeech(content); + return ClientResult.FromValue(result.GetRawResponse().Content, result.GetRawResponse()); } /// @@ -85,32 +73,30 @@ public virtual Result CreateSpeech(CreateSpeechRequest speech, Cance /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task CreateSpeechAsync(RequestBody content, RequestOptions context = null) + public virtual async Task CreateSpeechAsync(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateSpeechRequest(content, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Audio.CreateSpeech"); - scope.Start(); - try - { - using PipelineMessage message = CreateCreateSpeechRequest(content, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -123,60 +109,54 @@ public virtual async Task CreateSpeechAsync(RequestBody content, Request /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result CreateSpeech(RequestBody content, RequestOptions context = null) + public virtual ClientResult CreateSpeech(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateSpeechRequest(content, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Audio.CreateSpeech"); - scope.Start(); - try - { - using PipelineMessage message = CreateCreateSpeechRequest(content, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Transcribes audio into the input language. /// The to use. - /// The cancellation token to use. /// is null. - public virtual async Task> CreateTranscriptionAsync(CreateTranscriptionRequest audio, CancellationToken cancellationToken = default) + public virtual async Task> CreateTranscriptionAsync(CreateTranscriptionRequest audio) { - ClientUtilities.AssertNotNull(audio, nameof(audio)); + if (audio is null) throw new ArgumentNullException(nameof(audio)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = audio.ToRequestBody(); - Result result = await CreateTranscriptionAsync(content, context).ConfigureAwait(false); - return Result.FromValue(CreateTranscriptionResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(audio); + ClientResult result = await CreateTranscriptionAsync(content).ConfigureAwait(false); + return ClientResult.FromValue(CreateTranscriptionResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Transcribes audio into the input language. /// The to use. - /// The cancellation token to use. /// is null. - public virtual Result CreateTranscription(CreateTranscriptionRequest audio, CancellationToken cancellationToken = default) + public virtual ClientResult CreateTranscription(CreateTranscriptionRequest audio) { - ClientUtilities.AssertNotNull(audio, nameof(audio)); + if (audio is null) throw new ArgumentNullException(nameof(audio)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = audio.ToRequestBody(); - Result result = CreateTranscription(content, context); - return Result.FromValue(CreateTranscriptionResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(audio); + ClientResult result = CreateTranscription(content); + return ClientResult.FromValue(CreateTranscriptionResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -189,32 +169,30 @@ public virtual Result CreateTranscription(CreateTra /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task CreateTranscriptionAsync(RequestBody content, RequestOptions context = null) + public virtual async Task CreateTranscriptionAsync(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateTranscriptionRequest(content, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Audio.CreateTranscription"); - scope.Start(); - try - { - using PipelineMessage message = CreateCreateTranscriptionRequest(content, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -227,60 +205,54 @@ public virtual async Task CreateTranscriptionAsync(RequestBody content, /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result CreateTranscription(RequestBody content, RequestOptions context = null) + public virtual ClientResult CreateTranscription(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateTranscriptionRequest(content, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Audio.CreateTranscription"); - scope.Start(); - try + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateCreateTranscriptionRequest(content, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Translates audio into English.. /// The to use. - /// The cancellation token to use. /// is null. - public virtual async Task> CreateTranslationAsync(CreateTranslationRequest audio, CancellationToken cancellationToken = default) + public virtual async Task> CreateTranslationAsync(CreateTranslationRequest audio) { - ClientUtilities.AssertNotNull(audio, nameof(audio)); + if (audio is null) throw new ArgumentNullException(nameof(audio)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = audio.ToRequestBody(); - Result result = await CreateTranslationAsync(content, context).ConfigureAwait(false); - return Result.FromValue(CreateTranslationResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(audio); + ClientResult result = await CreateTranslationAsync(content).ConfigureAwait(false); + return ClientResult.FromValue(CreateTranslationResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Translates audio into English.. /// The to use. - /// The cancellation token to use. /// is null. - public virtual Result CreateTranslation(CreateTranslationRequest audio, CancellationToken cancellationToken = default) + public virtual ClientResult CreateTranslation(CreateTranslationRequest audio) { - ClientUtilities.AssertNotNull(audio, nameof(audio)); + if (audio is null) throw new ArgumentNullException(nameof(audio)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = audio.ToRequestBody(); - Result result = CreateTranslation(content, context); - return Result.FromValue(CreateTranslationResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(audio); + ClientResult result = CreateTranslation(content); + return ClientResult.FromValue(CreateTranslationResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -293,32 +265,30 @@ public virtual Result CreateTranslation(CreateTransla /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task CreateTranslationAsync(RequestBody content, RequestOptions context = null) + public virtual async Task CreateTranslationAsync(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateTranslationRequest(content, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Audio.CreateTranslation"); - scope.Start(); - try + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateCreateTranslationRequest(content, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -331,91 +301,88 @@ public virtual async Task CreateTranslationAsync(RequestBody content, Re /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result CreateTranslation(RequestBody content, RequestOptions context = null) + public virtual ClientResult CreateTranslation(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateTranslationRequest(content, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Audio.CreateTranslation"); - scope.Start(); - try + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateCreateTranslationRequest(content, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } - internal PipelineMessage CreateCreateSpeechRequest(RequestBody content, RequestOptions context) + internal PipelineMessage CreateCreateSpeechRequest(BinaryContent content, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/audio/speech", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/octet-stream"); - request.SetHeaderValue("Content-Type", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/audio/speech"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/octet-stream"); + request.Headers.Set("Content-Type", "application/json"); request.Content = content; + message.Apply(options); return message; } - internal PipelineMessage CreateCreateTranscriptionRequest(RequestBody content, RequestOptions context) + internal PipelineMessage CreateCreateTranscriptionRequest(BinaryContent content, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/audio/transcriptions", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - request.SetHeaderValue("content-type", "multipart/form-data"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/audio/transcriptions"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); + request.Headers.Set("content-type", "multipart/form-data"); request.Content = content; + message.Apply(options); return message; } - internal PipelineMessage CreateCreateTranslationRequest(RequestBody content, RequestOptions context) + internal PipelineMessage CreateCreateTranslationRequest(BinaryContent content, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/audio/translations", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - request.SetHeaderValue("content-type", "multipart/form-data"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/audio/translations"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); + request.Headers.Set("content-type", "multipart/form-data"); request.Content = content; + message.Apply(options); return message; } - private static RequestOptions DefaultRequestContext = new RequestOptions(); - internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) - { - if (!cancellationToken.CanBeCanceled) - { - return DefaultRequestContext; - } - - return new RequestOptions() { CancellationToken = cancellationToken }; - } - - private static ResponseErrorClassifier _responseErrorClassifier200; - private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); + private static PipelineMessageClassifier _responseErrorClassifier200; + private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } } + diff --git a/.dotnet/src/Generated/Chat.cs b/.dotnet/src/Generated/Chat.cs index 8c8e0546e..3fa357d90 100644 --- a/.dotnet/src/Generated/Chat.cs +++ b/.dotnet/src/Generated/Chat.cs @@ -1,12 +1,9 @@ // -#nullable disable - using System; using System.ClientModel; -using System.ClientModel.Internal; using System.ClientModel.Primitives; -using System.ClientModel.Primitives.Pipeline; +using System.Text; using System.Threading; using System.Threading.Tasks; using OpenAI.Models; @@ -18,16 +15,13 @@ namespace OpenAI public partial class Chat { private const string AuthorizationHeader = "Authorization"; - private readonly KeyCredential _keyCredential; + private readonly ApiKeyCredential _credential; private const string AuthorizationApiKeyPrefix = "Bearer"; - private readonly MessagePipeline _pipeline; + private readonly ClientPipeline _pipeline; private readonly Uri _endpoint; - /// The ClientDiagnostics is used to provide tracing support for the client library. - internal TelemetrySource ClientDiagnostics { get; } - /// The HTTP pipeline for sending and receiving REST requests and responses. - public virtual MessagePipeline Pipeline => _pipeline; + public virtual ClientPipeline Pipeline => _pipeline; /// Initializes a new instance of Chat for mocking. protected Chat() @@ -35,44 +29,38 @@ protected Chat() } /// Initializes a new instance of Chat. - /// The handler for diagnostic messaging in the client. /// The HTTP pipeline for sending and receiving REST requests and responses. - /// The key credential to copy. + /// The key credential to copy. /// OpenAI Endpoint. - internal Chat(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + internal Chat(ClientPipeline pipeline, ApiKeyCredential credential, Uri endpoint) { - ClientDiagnostics = clientDiagnostics; _pipeline = pipeline; - _keyCredential = keyCredential; + _credential = credential; _endpoint = endpoint; } /// Creates a model response for the given chat conversation. /// The to use. - /// The cancellation token to use. /// is null. - public virtual async Task> CreateChatCompletionAsync(CreateChatCompletionRequest createChatCompletionRequest, CancellationToken cancellationToken = default) + public virtual async Task> CreateChatCompletionAsync(CreateChatCompletionRequest createChatCompletionRequest) { - ClientUtilities.AssertNotNull(createChatCompletionRequest, nameof(createChatCompletionRequest)); + if (createChatCompletionRequest is null) throw new ArgumentNullException(nameof(createChatCompletionRequest)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = createChatCompletionRequest.ToRequestBody(); - Result result = await CreateChatCompletionAsync(content, context).ConfigureAwait(false); - return Result.FromValue(CreateChatCompletionResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(createChatCompletionRequest); + ClientResult result = await CreateChatCompletionAsync(content).ConfigureAwait(false); + return ClientResult.FromValue(CreateChatCompletionResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Creates a model response for the given chat conversation. /// The to use. - /// The cancellation token to use. /// is null. - public virtual Result CreateChatCompletion(CreateChatCompletionRequest createChatCompletionRequest, CancellationToken cancellationToken = default) + public virtual ClientResult CreateChatCompletion(CreateChatCompletionRequest createChatCompletionRequest) { - ClientUtilities.AssertNotNull(createChatCompletionRequest, nameof(createChatCompletionRequest)); + if (createChatCompletionRequest is null) throw new ArgumentNullException(nameof(createChatCompletionRequest)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = createChatCompletionRequest.ToRequestBody(); - Result result = CreateChatCompletion(content, context); - return Result.FromValue(CreateChatCompletionResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(createChatCompletionRequest); + ClientResult result = CreateChatCompletion(content); + return ClientResult.FromValue(CreateChatCompletionResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -85,32 +73,30 @@ public virtual Result CreateChatCompletion(CreateC /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task CreateChatCompletionAsync(RequestBody content, RequestOptions context = null) + public virtual async Task CreateChatCompletionAsync(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateChatCompletionRequest(content, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Chat.CreateChatCompletion"); - scope.Start(); - try - { - using PipelineMessage message = CreateCreateChatCompletionRequest(content, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -123,61 +109,52 @@ public virtual async Task CreateChatCompletionAsync(RequestBody content, /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result CreateChatCompletion(RequestBody content, RequestOptions context = null) + public virtual ClientResult CreateChatCompletion(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateChatCompletionRequest(content, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Chat.CreateChatCompletion"); - scope.Start(); - try - { - using PipelineMessage message = CreateCreateChatCompletionRequest(content, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } - internal PipelineMessage CreateCreateChatCompletionRequest(RequestBody content, RequestOptions context) + internal PipelineMessage CreateCreateChatCompletionRequest(BinaryContent content, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/chat/completions", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - request.SetHeaderValue("Content-Type", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/chat/completions"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); + request.Headers.Set("Content-Type", "application/json"); request.Content = content; + message.Apply(options); return message; } - private static RequestOptions DefaultRequestContext = new RequestOptions(); - internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) - { - if (!cancellationToken.CanBeCanceled) - { - return DefaultRequestContext; - } - - return new RequestOptions() { CancellationToken = cancellationToken }; - } - - private static ResponseErrorClassifier _responseErrorClassifier200; - private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); + private static PipelineMessageClassifier _responseErrorClassifier200; + private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } } + diff --git a/.dotnet/src/Generated/Completions.cs b/.dotnet/src/Generated/Completions.cs index aaa1f585d..779fa66c0 100644 --- a/.dotnet/src/Generated/Completions.cs +++ b/.dotnet/src/Generated/Completions.cs @@ -1,12 +1,9 @@ // -#nullable disable - using System; using System.ClientModel; -using System.ClientModel.Internal; using System.ClientModel.Primitives; -using System.ClientModel.Primitives.Pipeline; +using System.Text; using System.Threading; using System.Threading.Tasks; using OpenAI.Models; @@ -18,16 +15,13 @@ namespace OpenAI public partial class Completions { private const string AuthorizationHeader = "Authorization"; - private readonly KeyCredential _keyCredential; + private readonly ApiKeyCredential _credential; private const string AuthorizationApiKeyPrefix = "Bearer"; - private readonly MessagePipeline _pipeline; + private readonly ClientPipeline _pipeline; private readonly Uri _endpoint; - /// The ClientDiagnostics is used to provide tracing support for the client library. - internal TelemetrySource ClientDiagnostics { get; } - /// The HTTP pipeline for sending and receiving REST requests and responses. - public virtual MessagePipeline Pipeline => _pipeline; + public virtual ClientPipeline Pipeline => _pipeline; /// Initializes a new instance of Completions for mocking. protected Completions() @@ -35,44 +29,38 @@ protected Completions() } /// Initializes a new instance of Completions. - /// The handler for diagnostic messaging in the client. /// The HTTP pipeline for sending and receiving REST requests and responses. - /// The key credential to copy. + /// The key credential to copy. /// OpenAI Endpoint. - internal Completions(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + internal Completions(ClientPipeline pipeline, ApiKeyCredential credential, Uri endpoint) { - ClientDiagnostics = clientDiagnostics; _pipeline = pipeline; - _keyCredential = keyCredential; + _credential = credential; _endpoint = endpoint; } /// Creates a completion for the provided prompt and parameters. /// The to use. - /// The cancellation token to use. /// is null. - public virtual async Task> CreateCompletionAsync(CreateCompletionRequest createCompletionRequest, CancellationToken cancellationToken = default) + public virtual async Task> CreateCompletionAsync(CreateCompletionRequest createCompletionRequest) { - ClientUtilities.AssertNotNull(createCompletionRequest, nameof(createCompletionRequest)); + if (createCompletionRequest is null) throw new ArgumentNullException(nameof(createCompletionRequest)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = createCompletionRequest.ToRequestBody(); - Result result = await CreateCompletionAsync(content, context).ConfigureAwait(false); - return Result.FromValue(CreateCompletionResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(createCompletionRequest); + ClientResult result = await CreateCompletionAsync(content).ConfigureAwait(false); + return ClientResult.FromValue(CreateCompletionResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Creates a completion for the provided prompt and parameters. /// The to use. - /// The cancellation token to use. /// is null. - public virtual Result CreateCompletion(CreateCompletionRequest createCompletionRequest, CancellationToken cancellationToken = default) + public virtual ClientResult CreateCompletion(CreateCompletionRequest createCompletionRequest) { - ClientUtilities.AssertNotNull(createCompletionRequest, nameof(createCompletionRequest)); + if (createCompletionRequest is null) throw new ArgumentNullException(nameof(createCompletionRequest)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = createCompletionRequest.ToRequestBody(); - Result result = CreateCompletion(content, context); - return Result.FromValue(CreateCompletionResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(createCompletionRequest); + ClientResult result = CreateCompletion(content); + return ClientResult.FromValue(CreateCompletionResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -85,32 +73,30 @@ public virtual Result CreateCompletion(CreateCompletio /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task CreateCompletionAsync(RequestBody content, RequestOptions context = null) + public virtual async Task CreateCompletionAsync(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateCompletionRequest(content, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Completions.CreateCompletion"); - scope.Start(); - try - { - using PipelineMessage message = CreateCreateCompletionRequest(content, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -123,61 +109,52 @@ public virtual async Task CreateCompletionAsync(RequestBody content, Req /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result CreateCompletion(RequestBody content, RequestOptions context = null) + public virtual ClientResult CreateCompletion(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateCompletionRequest(content, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Completions.CreateCompletion"); - scope.Start(); - try - { - using PipelineMessage message = CreateCreateCompletionRequest(content, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } - internal PipelineMessage CreateCreateCompletionRequest(RequestBody content, RequestOptions context) + internal PipelineMessage CreateCreateCompletionRequest(BinaryContent content, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/completions", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - request.SetHeaderValue("Content-Type", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/completions"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); + request.Headers.Set("Content-Type", "application/json"); request.Content = content; + message.Apply(options); return message; } - private static RequestOptions DefaultRequestContext = new RequestOptions(); - internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) - { - if (!cancellationToken.CanBeCanceled) - { - return DefaultRequestContext; - } - - return new RequestOptions() { CancellationToken = cancellationToken }; - } - - private static ResponseErrorClassifier _responseErrorClassifier200; - private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); + private static PipelineMessageClassifier _responseErrorClassifier200; + private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } } + diff --git a/.dotnet/src/Generated/Embeddings.cs b/.dotnet/src/Generated/Embeddings.cs index d42141a8f..f935d7640 100644 --- a/.dotnet/src/Generated/Embeddings.cs +++ b/.dotnet/src/Generated/Embeddings.cs @@ -1,12 +1,9 @@ // -#nullable disable - using System; using System.ClientModel; -using System.ClientModel.Internal; using System.ClientModel.Primitives; -using System.ClientModel.Primitives.Pipeline; +using System.Text; using System.Threading; using System.Threading.Tasks; using OpenAI.Models; @@ -18,16 +15,13 @@ namespace OpenAI public partial class Embeddings { private const string AuthorizationHeader = "Authorization"; - private readonly KeyCredential _keyCredential; + private readonly ApiKeyCredential _credential; private const string AuthorizationApiKeyPrefix = "Bearer"; - private readonly MessagePipeline _pipeline; + private readonly ClientPipeline _pipeline; private readonly Uri _endpoint; - /// The ClientDiagnostics is used to provide tracing support for the client library. - internal TelemetrySource ClientDiagnostics { get; } - /// The HTTP pipeline for sending and receiving REST requests and responses. - public virtual MessagePipeline Pipeline => _pipeline; + public virtual ClientPipeline Pipeline => _pipeline; /// Initializes a new instance of Embeddings for mocking. protected Embeddings() @@ -35,44 +29,38 @@ protected Embeddings() } /// Initializes a new instance of Embeddings. - /// The handler for diagnostic messaging in the client. /// The HTTP pipeline for sending and receiving REST requests and responses. - /// The key credential to copy. + /// The key credential to copy. /// OpenAI Endpoint. - internal Embeddings(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + internal Embeddings(ClientPipeline pipeline, ApiKeyCredential credential, Uri endpoint) { - ClientDiagnostics = clientDiagnostics; _pipeline = pipeline; - _keyCredential = keyCredential; + _credential = credential; _endpoint = endpoint; } /// Creates an embedding vector representing the input text. /// The to use. - /// The cancellation token to use. /// is null. - public virtual async Task> CreateEmbeddingAsync(CreateEmbeddingRequest embedding, CancellationToken cancellationToken = default) + public virtual async Task> CreateEmbeddingAsync(CreateEmbeddingRequest embedding) { - ClientUtilities.AssertNotNull(embedding, nameof(embedding)); + if (embedding is null) throw new ArgumentNullException(nameof(embedding)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = embedding.ToRequestBody(); - Result result = await CreateEmbeddingAsync(content, context).ConfigureAwait(false); - return Result.FromValue(CreateEmbeddingResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(embedding); + ClientResult result = await CreateEmbeddingAsync(content).ConfigureAwait(false); + return ClientResult.FromValue(CreateEmbeddingResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Creates an embedding vector representing the input text. /// The to use. - /// The cancellation token to use. /// is null. - public virtual Result CreateEmbedding(CreateEmbeddingRequest embedding, CancellationToken cancellationToken = default) + public virtual ClientResult CreateEmbedding(CreateEmbeddingRequest embedding) { - ClientUtilities.AssertNotNull(embedding, nameof(embedding)); + if (embedding is null) throw new ArgumentNullException(nameof(embedding)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = embedding.ToRequestBody(); - Result result = CreateEmbedding(content, context); - return Result.FromValue(CreateEmbeddingResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(embedding); + ClientResult result = CreateEmbedding(content); + return ClientResult.FromValue(CreateEmbeddingResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -85,32 +73,30 @@ public virtual Result CreateEmbedding(CreateEmbeddingRe /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task CreateEmbeddingAsync(RequestBody content, RequestOptions context = null) + public virtual async Task CreateEmbeddingAsync(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateEmbeddingRequest(content, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Embeddings.CreateEmbedding"); - scope.Start(); - try - { - using PipelineMessage message = CreateCreateEmbeddingRequest(content, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -123,61 +109,52 @@ public virtual async Task CreateEmbeddingAsync(RequestBody content, Requ /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result CreateEmbedding(RequestBody content, RequestOptions context = null) + public virtual ClientResult CreateEmbedding(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateEmbeddingRequest(content, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Embeddings.CreateEmbedding"); - scope.Start(); - try - { - using PipelineMessage message = CreateCreateEmbeddingRequest(content, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } - internal PipelineMessage CreateCreateEmbeddingRequest(RequestBody content, RequestOptions context) + internal PipelineMessage CreateCreateEmbeddingRequest(BinaryContent content, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/embeddings", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - request.SetHeaderValue("Content-Type", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/embeddings"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); + request.Headers.Set("Content-Type", "application/json"); request.Content = content; + message.Apply(options); return message; } - private static RequestOptions DefaultRequestContext = new RequestOptions(); - internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) - { - if (!cancellationToken.CanBeCanceled) - { - return DefaultRequestContext; - } - - return new RequestOptions() { CancellationToken = cancellationToken }; - } - - private static ResponseErrorClassifier _responseErrorClassifier200; - private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); + private static PipelineMessageClassifier _responseErrorClassifier200; + private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } } + diff --git a/.dotnet/src/Generated/Files.cs b/.dotnet/src/Generated/Files.cs index 05aa7d834..10258b608 100644 --- a/.dotnet/src/Generated/Files.cs +++ b/.dotnet/src/Generated/Files.cs @@ -1,12 +1,9 @@ // -#nullable disable - using System; using System.ClientModel; -using System.ClientModel.Internal; using System.ClientModel.Primitives; -using System.ClientModel.Primitives.Pipeline; +using System.Text; using System.Threading; using System.Threading.Tasks; using OpenAI.Models; @@ -18,16 +15,13 @@ namespace OpenAI public partial class Files { private const string AuthorizationHeader = "Authorization"; - private readonly KeyCredential _keyCredential; + private readonly ApiKeyCredential _credential; private const string AuthorizationApiKeyPrefix = "Bearer"; - private readonly MessagePipeline _pipeline; + private readonly ClientPipeline _pipeline; private readonly Uri _endpoint; - /// The ClientDiagnostics is used to provide tracing support for the client library. - internal TelemetrySource ClientDiagnostics { get; } - /// The HTTP pipeline for sending and receiving REST requests and responses. - public virtual MessagePipeline Pipeline => _pipeline; + public virtual ClientPipeline Pipeline => _pipeline; /// Initializes a new instance of Files for mocking. protected Files() @@ -35,15 +29,13 @@ protected Files() } /// Initializes a new instance of Files. - /// The handler for diagnostic messaging in the client. /// The HTTP pipeline for sending and receiving REST requests and responses. - /// The key credential to copy. + /// The key credential to copy. /// OpenAI Endpoint. - internal Files(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + internal Files(ClientPipeline pipeline, ApiKeyCredential credential, Uri endpoint) { - ClientDiagnostics = clientDiagnostics; _pipeline = pipeline; - _keyCredential = keyCredential; + _credential = credential; _endpoint = endpoint; } @@ -58,16 +50,14 @@ internal Files(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyC /// Please [contact us](https://help.openai.com/) if you need to increase these storage limits. /// /// The to use. - /// The cancellation token to use. /// is null. - public virtual async Task> CreateFileAsync(CreateFileRequest file, CancellationToken cancellationToken = default) + public virtual async Task> CreateFileAsync(CreateFileRequest file) { - ClientUtilities.AssertNotNull(file, nameof(file)); + if (file is null) throw new ArgumentNullException(nameof(file)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = file.ToRequestBody(); - Result result = await CreateFileAsync(content, context).ConfigureAwait(false); - return Result.FromValue(OpenAIFile.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(file); + ClientResult result = await CreateFileAsync(content).ConfigureAwait(false); + return ClientResult.FromValue(OpenAIFile.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -81,16 +71,14 @@ public virtual async Task> CreateFileAsync(CreateFileRequest /// Please [contact us](https://help.openai.com/) if you need to increase these storage limits. /// /// The to use. - /// The cancellation token to use. /// is null. - public virtual Result CreateFile(CreateFileRequest file, CancellationToken cancellationToken = default) + public virtual ClientResult CreateFile(CreateFileRequest file) { - ClientUtilities.AssertNotNull(file, nameof(file)); + if (file is null) throw new ArgumentNullException(nameof(file)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = file.ToRequestBody(); - Result result = CreateFile(content, context); - return Result.FromValue(OpenAIFile.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(file); + ClientResult result = CreateFile(content); + return ClientResult.FromValue(OpenAIFile.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -110,32 +98,30 @@ public virtual Result CreateFile(CreateFileRequest file, Cancellatio /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task CreateFileAsync(RequestBody content, RequestOptions context = null) + public virtual async Task CreateFileAsync(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateFileRequest(content, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Files.CreateFile"); - scope.Start(); - try - { - using PipelineMessage message = CreateCreateFileRequest(content, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -155,52 +141,46 @@ public virtual async Task CreateFileAsync(RequestBody content, RequestOp /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result CreateFile(RequestBody content, RequestOptions context = null) + public virtual ClientResult CreateFile(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateFileRequest(content, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Files.CreateFile"); - scope.Start(); - try - { - using PipelineMessage message = CreateCreateFileRequest(content, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Returns a list of files that belong to the user's organization. /// Only return files with the given purpose. - /// The cancellation token to use. - public virtual async Task> GetFilesAsync(string purpose = null, CancellationToken cancellationToken = default) + public virtual async Task> GetFilesAsync(string purpose = null) { - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await GetFilesAsync(purpose, context).ConfigureAwait(false); - return Result.FromValue(ListFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = await GetFilesAsync(purpose).ConfigureAwait(false); + return ClientResult.FromValue(ListFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Returns a list of files that belong to the user's organization. /// Only return files with the given purpose. - /// The cancellation token to use. - public virtual Result GetFiles(string purpose = null, CancellationToken cancellationToken = default) + public virtual ClientResult GetFiles(string purpose = null) { - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = GetFiles(purpose, context); - return Result.FromValue(ListFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = GetFiles(purpose); + return ClientResult.FromValue(ListFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -213,29 +193,28 @@ public virtual Result GetFiles(string purpose = null, Cancell /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// Only return files with the given purpose. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// Service returned a non-success status code. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task GetFilesAsync(string purpose, RequestOptions context) + public virtual async Task GetFilesAsync(string purpose, RequestOptions options) { - using var scope = ClientDiagnostics.CreateSpan("Files.GetFiles"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetFilesRequest(purpose, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetFilesRequest(purpose, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -248,57 +227,54 @@ public virtual async Task GetFilesAsync(string purpose, RequestOptions c /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// Only return files with the given purpose. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// Service returned a non-success status code. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result GetFiles(string purpose, RequestOptions context) + public virtual ClientResult GetFiles(string purpose, RequestOptions options) { - using var scope = ClientDiagnostics.CreateSpan("Files.GetFiles"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetFilesRequest(purpose, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetFilesRequest(purpose, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Returns information about a specific file. /// The ID of the file to use for this request. - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual async Task> RetrieveFileAsync(string fileId, CancellationToken cancellationToken = default) + public virtual async Task> RetrieveFileAsync(string fileId) { - ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + if (fileId is null) throw new ArgumentNullException(nameof(fileId)); + if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await RetrieveFileAsync(fileId, context).ConfigureAwait(false); - return Result.FromValue(OpenAIFile.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = await RetrieveFileAsync(fileId).ConfigureAwait(false); + return ClientResult.FromValue(OpenAIFile.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Returns information about a specific file. /// The ID of the file to use for this request. - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual Result RetrieveFile(string fileId, CancellationToken cancellationToken = default) + public virtual ClientResult RetrieveFile(string fileId) { - ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + if (fileId is null) throw new ArgumentNullException(nameof(fileId)); + if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = RetrieveFile(fileId, context); - return Result.FromValue(OpenAIFile.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = RetrieveFile(fileId); + return ClientResult.FromValue(OpenAIFile.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -311,33 +287,32 @@ public virtual Result RetrieveFile(string fileId, CancellationToken /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the file to use for this request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task RetrieveFileAsync(string fileId, RequestOptions context) + public virtual async Task RetrieveFileAsync(string fileId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); - - using var scope = ClientDiagnostics.CreateSpan("Files.RetrieveFile"); - scope.Start(); - try - { - using PipelineMessage message = CreateRetrieveFileRequest(fileId, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (fileId is null) throw new ArgumentNullException(nameof(fileId)); + if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateRetrieveFileRequest(fileId, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -350,61 +325,58 @@ public virtual async Task RetrieveFileAsync(string fileId, RequestOption /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the file to use for this request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result RetrieveFile(string fileId, RequestOptions context) + public virtual ClientResult RetrieveFile(string fileId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); - - using var scope = ClientDiagnostics.CreateSpan("Files.RetrieveFile"); - scope.Start(); - try + if (fileId is null) throw new ArgumentNullException(nameof(fileId)); + if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateRetrieveFileRequest(fileId, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateRetrieveFileRequest(fileId, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Delete a file. /// The ID of the file to use for this request. - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual async Task> DeleteFileAsync(string fileId, CancellationToken cancellationToken = default) + public virtual async Task> DeleteFileAsync(string fileId) { - ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + if (fileId is null) throw new ArgumentNullException(nameof(fileId)); + if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await DeleteFileAsync(fileId, context).ConfigureAwait(false); - return Result.FromValue(DeleteFileResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = await DeleteFileAsync(fileId).ConfigureAwait(false); + return ClientResult.FromValue(DeleteFileResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Delete a file. /// The ID of the file to use for this request. - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual Result DeleteFile(string fileId, CancellationToken cancellationToken = default) + public virtual ClientResult DeleteFile(string fileId) { - ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + if (fileId is null) throw new ArgumentNullException(nameof(fileId)); + if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = DeleteFile(fileId, context); - return Result.FromValue(DeleteFileResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = DeleteFile(fileId); + return ClientResult.FromValue(DeleteFileResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -417,33 +389,32 @@ public virtual Result DeleteFile(string fileId, Cancellation /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the file to use for this request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task DeleteFileAsync(string fileId, RequestOptions context) + public virtual async Task DeleteFileAsync(string fileId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); - - using var scope = ClientDiagnostics.CreateSpan("Files.DeleteFile"); - scope.Start(); - try - { - using PipelineMessage message = CreateDeleteFileRequest(fileId, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (fileId is null) throw new ArgumentNullException(nameof(fileId)); + if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateDeleteFileRequest(fileId, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -456,61 +427,58 @@ public virtual async Task DeleteFileAsync(string fileId, RequestOptions /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the file to use for this request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result DeleteFile(string fileId, RequestOptions context) + public virtual ClientResult DeleteFile(string fileId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); - - using var scope = ClientDiagnostics.CreateSpan("Files.DeleteFile"); - scope.Start(); - try - { - using PipelineMessage message = CreateDeleteFileRequest(fileId, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + if (fileId is null) throw new ArgumentNullException(nameof(fileId)); + if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateDeleteFileRequest(fileId, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Returns the contents of the specified file. /// The ID of the file to use for this request. - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual async Task> DownloadFileAsync(string fileId, CancellationToken cancellationToken = default) + public virtual async Task> DownloadFileAsync(string fileId) { - ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + if (fileId is null) throw new ArgumentNullException(nameof(fileId)); + if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await DownloadFileAsync(fileId, context).ConfigureAwait(false); - return Result.FromValue(result.GetRawResponse().Content.ToObjectFromJson(), result.GetRawResponse()); + ClientResult result = await DownloadFileAsync(fileId).ConfigureAwait(false); + return ClientResult.FromValue(result.GetRawResponse().Content.ToObjectFromJson(), result.GetRawResponse()); } /// Returns the contents of the specified file. /// The ID of the file to use for this request. - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual Result DownloadFile(string fileId, CancellationToken cancellationToken = default) + public virtual ClientResult DownloadFile(string fileId) { - ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); + if (fileId is null) throw new ArgumentNullException(nameof(fileId)); + if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = DownloadFile(fileId, context); - return Result.FromValue(result.GetRawResponse().Content.ToObjectFromJson(), result.GetRawResponse()); + ClientResult result = DownloadFile(fileId); + return ClientResult.FromValue(result.GetRawResponse().Content.ToObjectFromJson(), result.GetRawResponse()); } /// @@ -523,33 +491,32 @@ public virtual Result DownloadFile(string fileId, CancellationToken canc /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the file to use for this request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task DownloadFileAsync(string fileId, RequestOptions context) + public virtual async Task DownloadFileAsync(string fileId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); - - using var scope = ClientDiagnostics.CreateSpan("Files.DownloadFile"); - scope.Start(); - try + if (fileId is null) throw new ArgumentNullException(nameof(fileId)); + if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateDownloadFileRequest(fileId, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateDownloadFileRequest(fileId, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -562,122 +529,133 @@ public virtual async Task DownloadFileAsync(string fileId, RequestOption /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the file to use for this request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result DownloadFile(string fileId, RequestOptions context) + public virtual ClientResult DownloadFile(string fileId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); - - using var scope = ClientDiagnostics.CreateSpan("Files.DownloadFile"); - scope.Start(); - try - { - using PipelineMessage message = CreateDownloadFileRequest(fileId, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + if (fileId is null) throw new ArgumentNullException(nameof(fileId)); + if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateDownloadFileRequest(fileId, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } - internal PipelineMessage CreateCreateFileRequest(RequestBody content, RequestOptions context) + internal PipelineMessage CreateCreateFileRequest(BinaryContent content, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/files", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - request.SetHeaderValue("content-type", "multipart/form-data"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/files"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); + request.Headers.Set("content-type", "multipart/form-data"); request.Content = content; + message.Apply(options); return message; } - internal PipelineMessage CreateGetFilesRequest(string purpose, RequestOptions context) + internal PipelineMessage CreateGetFilesRequest(string purpose, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("GET"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/files", false); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "GET"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/files"); + uriBuilder.Path += path.ToString(); if (purpose != null) { - uri.AppendQuery("purpose", purpose, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&purpose={purpose}"; + } + else + { + uriBuilder.Query = $"purpose={purpose}"; + } } - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); return message; } - internal PipelineMessage CreateRetrieveFileRequest(string fileId, RequestOptions context) + internal PipelineMessage CreateRetrieveFileRequest(string fileId, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("GET"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/files/", false); - uri.AppendPath(fileId, true); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "GET"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/files/"); + uriBuilder.Path += path.ToString(); + path.Append(fileId); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); return message; } - internal PipelineMessage CreateDeleteFileRequest(string fileId, RequestOptions context) + internal PipelineMessage CreateDeleteFileRequest(string fileId, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("DELETE"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/files/", false); - uri.AppendPath(fileId, true); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "DELETE"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/files/"); + uriBuilder.Path += path.ToString(); + path.Append(fileId); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); return message; } - internal PipelineMessage CreateDownloadFileRequest(string fileId, RequestOptions context) + internal PipelineMessage CreateDownloadFileRequest(string fileId, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("GET"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/files/", false); - uri.AppendPath(fileId, true); - uri.AppendPath("/content", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "GET"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/files/"); + uriBuilder.Path += path.ToString(); + path.Append(fileId); + uriBuilder.Path += path.ToString(); + path.Append("/content"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); return message; } - private static RequestOptions DefaultRequestContext = new RequestOptions(); - internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) - { - if (!cancellationToken.CanBeCanceled) - { - return DefaultRequestContext; - } - - return new RequestOptions() { CancellationToken = cancellationToken }; - } - - private static ResponseErrorClassifier _responseErrorClassifier200; - private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); + private static PipelineMessageClassifier _responseErrorClassifier200; + private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } } + diff --git a/.dotnet/src/Generated/FineTuning.cs b/.dotnet/src/Generated/FineTuning.cs index a8038525b..63c8b2f63 100644 --- a/.dotnet/src/Generated/FineTuning.cs +++ b/.dotnet/src/Generated/FineTuning.cs @@ -1,12 +1,9 @@ // -#nullable disable - using System; using System.ClientModel; -using System.ClientModel.Internal; using System.ClientModel.Primitives; -using System.ClientModel.Primitives.Pipeline; +using System.Text; using System.Threading; using System.Threading.Tasks; using OpenAI.Models; @@ -18,16 +15,13 @@ namespace OpenAI public partial class FineTuning { private const string AuthorizationHeader = "Authorization"; - private readonly KeyCredential _keyCredential; + private readonly ApiKeyCredential _credential; private const string AuthorizationApiKeyPrefix = "Bearer"; - private readonly MessagePipeline _pipeline; + private readonly ClientPipeline _pipeline; private readonly Uri _endpoint; - /// The ClientDiagnostics is used to provide tracing support for the client library. - internal TelemetrySource ClientDiagnostics { get; } - /// The HTTP pipeline for sending and receiving REST requests and responses. - public virtual MessagePipeline Pipeline => _pipeline; + public virtual ClientPipeline Pipeline => _pipeline; /// Initializes a new instance of FineTuning for mocking. protected FineTuning() @@ -35,15 +29,13 @@ protected FineTuning() } /// Initializes a new instance of FineTuning. - /// The handler for diagnostic messaging in the client. /// The HTTP pipeline for sending and receiving REST requests and responses. - /// The key credential to copy. + /// The key credential to copy. /// OpenAI Endpoint. - internal FineTuning(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + internal FineTuning(ClientPipeline pipeline, ApiKeyCredential credential, Uri endpoint) { - ClientDiagnostics = clientDiagnostics; _pipeline = pipeline; - _keyCredential = keyCredential; + _credential = credential; _endpoint = endpoint; } @@ -55,16 +47,14 @@ internal FineTuning(TelemetrySource clientDiagnostics, MessagePipeline pipeline, /// [Learn more about fine-tuning](/docs/guides/fine-tuning) /// /// The to use. - /// The cancellation token to use. /// is null. - public virtual async Task> CreateFineTuningJobAsync(CreateFineTuningJobRequest job, CancellationToken cancellationToken = default) + public virtual async Task> CreateFineTuningJobAsync(CreateFineTuningJobRequest job) { - ClientUtilities.AssertNotNull(job, nameof(job)); + if (job is null) throw new ArgumentNullException(nameof(job)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = job.ToRequestBody(); - Result result = await CreateFineTuningJobAsync(content, context).ConfigureAwait(false); - return Result.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(job); + ClientResult result = await CreateFineTuningJobAsync(content).ConfigureAwait(false); + return ClientResult.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -75,16 +65,14 @@ public virtual async Task> CreateFineTuningJobAsync(Create /// [Learn more about fine-tuning](/docs/guides/fine-tuning) /// /// The to use. - /// The cancellation token to use. /// is null. - public virtual Result CreateFineTuningJob(CreateFineTuningJobRequest job, CancellationToken cancellationToken = default) + public virtual ClientResult CreateFineTuningJob(CreateFineTuningJobRequest job) { - ClientUtilities.AssertNotNull(job, nameof(job)); + if (job is null) throw new ArgumentNullException(nameof(job)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = job.ToRequestBody(); - Result result = CreateFineTuningJob(content, context); - return Result.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(job); + ClientResult result = CreateFineTuningJob(content); + return ClientResult.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -101,32 +89,30 @@ public virtual Result CreateFineTuningJob(CreateFineTuningJobRequ /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task CreateFineTuningJobAsync(RequestBody content, RequestOptions context = null) + public virtual async Task CreateFineTuningJobAsync(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateFineTuningJobRequest(content, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("FineTuning.CreateFineTuningJob"); - scope.Start(); - try - { - using PipelineMessage message = CreateCreateFineTuningJobRequest(content, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -143,54 +129,48 @@ public virtual async Task CreateFineTuningJobAsync(RequestBody content, /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result CreateFineTuningJob(RequestBody content, RequestOptions context = null) + public virtual ClientResult CreateFineTuningJob(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateFineTuningJobRequest(content, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("FineTuning.CreateFineTuningJob"); - scope.Start(); - try - { - using PipelineMessage message = CreateCreateFineTuningJobRequest(content, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// List your organization's fine-tuning jobs. /// Identifier for the last job from the previous pagination request. /// Number of fine-tuning jobs to retrieve. - /// The cancellation token to use. - public virtual async Task> GetPaginatedFineTuningJobsAsync(string after = null, long? limit = null, CancellationToken cancellationToken = default) + public virtual async Task> GetPaginatedFineTuningJobsAsync(string after = null, long? limit = null) { - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await GetPaginatedFineTuningJobsAsync(after, limit, context).ConfigureAwait(false); - return Result.FromValue(ListPaginatedFineTuningJobsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = await GetPaginatedFineTuningJobsAsync(after, limit).ConfigureAwait(false); + return ClientResult.FromValue(ListPaginatedFineTuningJobsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// List your organization's fine-tuning jobs. /// Identifier for the last job from the previous pagination request. /// Number of fine-tuning jobs to retrieve. - /// The cancellation token to use. - public virtual Result GetPaginatedFineTuningJobs(string after = null, long? limit = null, CancellationToken cancellationToken = default) + public virtual ClientResult GetPaginatedFineTuningJobs(string after = null, long? limit = null) { - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = GetPaginatedFineTuningJobs(after, limit, context); - return Result.FromValue(ListPaginatedFineTuningJobsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = GetPaginatedFineTuningJobs(after, limit); + return ClientResult.FromValue(ListPaginatedFineTuningJobsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -203,30 +183,29 @@ public virtual Result GetPaginatedFineTunin /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// Identifier for the last job from the previous pagination request. /// Number of fine-tuning jobs to retrieve. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// Service returned a non-success status code. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task GetPaginatedFineTuningJobsAsync(string after, long? limit, RequestOptions context) + public virtual async Task GetPaginatedFineTuningJobsAsync(string after, long? limit, RequestOptions options) { - using var scope = ClientDiagnostics.CreateSpan("FineTuning.GetPaginatedFineTuningJobs"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetPaginatedFineTuningJobsRequest(after, limit, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetPaginatedFineTuningJobsRequest(after, limit, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -239,30 +218,29 @@ public virtual async Task GetPaginatedFineTuningJobsAsync(string after, /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// Identifier for the last job from the previous pagination request. /// Number of fine-tuning jobs to retrieve. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// Service returned a non-success status code. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result GetPaginatedFineTuningJobs(string after, long? limit, RequestOptions context) + public virtual ClientResult GetPaginatedFineTuningJobs(string after, long? limit, RequestOptions options) { - using var scope = ClientDiagnostics.CreateSpan("FineTuning.GetPaginatedFineTuningJobs"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetPaginatedFineTuningJobsRequest(after, limit, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetPaginatedFineTuningJobsRequest(after, limit, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// @@ -271,16 +249,15 @@ public virtual Result GetPaginatedFineTuningJobs(string after, long? limit, Requ /// [Learn more about fine-tuning](/docs/guides/fine-tuning) /// /// The to use. - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual async Task> RetrieveFineTuningJobAsync(string fineTuningJobId, CancellationToken cancellationToken = default) + public virtual async Task> RetrieveFineTuningJobAsync(string fineTuningJobId) { - ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); + if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await RetrieveFineTuningJobAsync(fineTuningJobId, context).ConfigureAwait(false); - return Result.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = await RetrieveFineTuningJobAsync(fineTuningJobId).ConfigureAwait(false); + return ClientResult.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -289,16 +266,15 @@ public virtual async Task> RetrieveFineTuningJobAsync(stri /// [Learn more about fine-tuning](/docs/guides/fine-tuning) /// /// The to use. - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual Result RetrieveFineTuningJob(string fineTuningJobId, CancellationToken cancellationToken = default) + public virtual ClientResult RetrieveFineTuningJob(string fineTuningJobId) { - ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); + if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = RetrieveFineTuningJob(fineTuningJobId, context); - return Result.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = RetrieveFineTuningJob(fineTuningJobId); + return ClientResult.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -313,33 +289,32 @@ public virtual Result RetrieveFineTuningJob(string fineTuningJobI /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The to use. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task RetrieveFineTuningJobAsync(string fineTuningJobId, RequestOptions context) + public virtual async Task RetrieveFineTuningJobAsync(string fineTuningJobId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); - - using var scope = ClientDiagnostics.CreateSpan("FineTuning.RetrieveFineTuningJob"); - scope.Start(); - try - { - using PipelineMessage message = CreateRetrieveFineTuningJobRequest(fineTuningJobId, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); + if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateRetrieveFineTuningJobRequest(fineTuningJobId, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -354,61 +329,58 @@ public virtual async Task RetrieveFineTuningJobAsync(string fineTuningJo /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The to use. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result RetrieveFineTuningJob(string fineTuningJobId, RequestOptions context) + public virtual ClientResult RetrieveFineTuningJob(string fineTuningJobId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); - - using var scope = ClientDiagnostics.CreateSpan("FineTuning.RetrieveFineTuningJob"); - scope.Start(); - try + if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); + if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateRetrieveFineTuningJobRequest(fineTuningJobId, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateRetrieveFineTuningJobRequest(fineTuningJobId, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Immediately cancel a fine-tune job. /// The ID of the fine-tuning job to cancel. - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual async Task> CancelFineTuningJobAsync(string fineTuningJobId, CancellationToken cancellationToken = default) + public virtual async Task> CancelFineTuningJobAsync(string fineTuningJobId) { - ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); + if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await CancelFineTuningJobAsync(fineTuningJobId, context).ConfigureAwait(false); - return Result.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = await CancelFineTuningJobAsync(fineTuningJobId).ConfigureAwait(false); + return ClientResult.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Immediately cancel a fine-tune job. /// The ID of the fine-tuning job to cancel. - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual Result CancelFineTuningJob(string fineTuningJobId, CancellationToken cancellationToken = default) + public virtual ClientResult CancelFineTuningJob(string fineTuningJobId) { - ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); + if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = CancelFineTuningJob(fineTuningJobId, context); - return Result.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = CancelFineTuningJob(fineTuningJobId); + return ClientResult.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -421,33 +393,32 @@ public virtual Result CancelFineTuningJob(string fineTuningJobId, /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the fine-tuning job to cancel. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task CancelFineTuningJobAsync(string fineTuningJobId, RequestOptions context) + public virtual async Task CancelFineTuningJobAsync(string fineTuningJobId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); - - using var scope = ClientDiagnostics.CreateSpan("FineTuning.CancelFineTuningJob"); - scope.Start(); - try - { - using PipelineMessage message = CreateCancelFineTuningJobRequest(fineTuningJobId, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); + if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCancelFineTuningJobRequest(fineTuningJobId, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -460,65 +431,62 @@ public virtual async Task CancelFineTuningJobAsync(string fineTuningJobI /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the fine-tuning job to cancel. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result CancelFineTuningJob(string fineTuningJobId, RequestOptions context) + public virtual ClientResult CancelFineTuningJob(string fineTuningJobId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); - - using var scope = ClientDiagnostics.CreateSpan("FineTuning.CancelFineTuningJob"); - scope.Start(); - try - { - using PipelineMessage message = CreateCancelFineTuningJobRequest(fineTuningJobId, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); + if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCancelFineTuningJobRequest(fineTuningJobId, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Get status updates for a fine-tuning job. /// The ID of the fine-tuning job to get events for. /// Identifier for the last event from the previous pagination request. /// Number of events to retrieve. - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual async Task> GetFineTuningEventsAsync(string fineTuningJobId, string after = null, int? limit = null, CancellationToken cancellationToken = default) + public virtual async Task> GetFineTuningEventsAsync(string fineTuningJobId, string after = null, int? limit = null) { - ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); + if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await GetFineTuningEventsAsync(fineTuningJobId, after, limit, context).ConfigureAwait(false); - return Result.FromValue(ListFineTuningJobEventsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = await GetFineTuningEventsAsync(fineTuningJobId, after, limit).ConfigureAwait(false); + return ClientResult.FromValue(ListFineTuningJobEventsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Get status updates for a fine-tuning job. /// The ID of the fine-tuning job to get events for. /// Identifier for the last event from the previous pagination request. /// Number of events to retrieve. - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual Result GetFineTuningEvents(string fineTuningJobId, string after = null, int? limit = null, CancellationToken cancellationToken = default) + public virtual ClientResult GetFineTuningEvents(string fineTuningJobId, string after = null, int? limit = null) { - ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); + if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); + if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = GetFineTuningEvents(fineTuningJobId, after, limit, context); - return Result.FromValue(ListFineTuningJobEventsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = GetFineTuningEvents(fineTuningJobId, after, limit); + return ClientResult.FromValue(ListFineTuningJobEventsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -531,7 +499,7 @@ public virtual Result GetFineTuningEvents(strin /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -539,27 +507,26 @@ public virtual Result GetFineTuningEvents(strin /// The ID of the fine-tuning job to get events for. /// Identifier for the last event from the previous pagination request. /// Number of events to retrieve. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task GetFineTuningEventsAsync(string fineTuningJobId, string after, int? limit, RequestOptions context) + public virtual async Task GetFineTuningEventsAsync(string fineTuningJobId, string after, int? limit, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); - - using var scope = ClientDiagnostics.CreateSpan("FineTuning.GetFineTuningEvents"); - scope.Start(); - try + if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); + if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetFineTuningEventsRequest(fineTuningJobId, after, limit, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateGetFineTuningEventsRequest(fineTuningJobId, after, limit, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -572,7 +539,7 @@ public virtual async Task GetFineTuningEventsAsync(string fineTuningJobI /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -580,129 +547,162 @@ public virtual async Task GetFineTuningEventsAsync(string fineTuningJobI /// The ID of the fine-tuning job to get events for. /// Identifier for the last event from the previous pagination request. /// Number of events to retrieve. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result GetFineTuningEvents(string fineTuningJobId, string after, int? limit, RequestOptions context) + public virtual ClientResult GetFineTuningEvents(string fineTuningJobId, string after, int? limit, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); - - using var scope = ClientDiagnostics.CreateSpan("FineTuning.GetFineTuningEvents"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetFineTuningEventsRequest(fineTuningJobId, after, limit, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); + if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetFineTuningEventsRequest(fineTuningJobId, after, limit, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } - internal PipelineMessage CreateCreateFineTuningJobRequest(RequestBody content, RequestOptions context) + internal PipelineMessage CreateCreateFineTuningJobRequest(BinaryContent content, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/fine_tuning/jobs", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - request.SetHeaderValue("Content-Type", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/fine_tuning/jobs"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); + request.Headers.Set("Content-Type", "application/json"); request.Content = content; + message.Apply(options); return message; } - internal PipelineMessage CreateGetPaginatedFineTuningJobsRequest(string after, long? limit, RequestOptions context) + internal PipelineMessage CreateGetPaginatedFineTuningJobsRequest(string after, long? limit, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("GET"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/fine_tuning/jobs", false); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "GET"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/fine_tuning/jobs"); + uriBuilder.Path += path.ToString(); if (after != null) { - uri.AppendQuery("after", after, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&after={after}"; + } + else + { + uriBuilder.Query = $"after={after}"; + } } if (limit != null) { - uri.AppendQuery("limit", limit.Value, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&limit={limit.Value}"; + } + else + { + uriBuilder.Query = $"limit={limit.Value}"; + } } - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); return message; } - internal PipelineMessage CreateRetrieveFineTuningJobRequest(string fineTuningJobId, RequestOptions context) + internal PipelineMessage CreateRetrieveFineTuningJobRequest(string fineTuningJobId, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("GET"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/fine_tuning/jobs/", false); - uri.AppendPath(fineTuningJobId, true); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "GET"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/fine_tuning/jobs/"); + uriBuilder.Path += path.ToString(); + path.Append(fineTuningJobId); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); return message; } - internal PipelineMessage CreateCancelFineTuningJobRequest(string fineTuningJobId, RequestOptions context) + internal PipelineMessage CreateCancelFineTuningJobRequest(string fineTuningJobId, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/fine_tuning/jobs/", false); - uri.AppendPath(fineTuningJobId, true); - uri.AppendPath("/cancel", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/fine_tuning/jobs/"); + uriBuilder.Path += path.ToString(); + path.Append(fineTuningJobId); + uriBuilder.Path += path.ToString(); + path.Append("/cancel"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); return message; } - internal PipelineMessage CreateGetFineTuningEventsRequest(string fineTuningJobId, string after, int? limit, RequestOptions context) + internal PipelineMessage CreateGetFineTuningEventsRequest(string fineTuningJobId, string after, int? limit, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("GET"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/fine_tuning/jobs/", false); - uri.AppendPath(fineTuningJobId, true); - uri.AppendPath("/events", false); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "GET"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/fine_tuning/jobs/"); + uriBuilder.Path += path.ToString(); + path.Append(fineTuningJobId); + uriBuilder.Path += path.ToString(); + path.Append("/events"); + uriBuilder.Path += path.ToString(); if (after != null) { - uri.AppendQuery("after", after, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&after={after}"; + } + else + { + uriBuilder.Query = $"after={after}"; + } } if (limit != null) { - uri.AppendQuery("limit", limit.Value, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&limit={limit.Value}"; + } + else + { + uriBuilder.Query = $"limit={limit.Value}"; + } } - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); return message; } - private static RequestOptions DefaultRequestContext = new RequestOptions(); - internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) - { - if (!cancellationToken.CanBeCanceled) - { - return DefaultRequestContext; - } - - return new RequestOptions() { CancellationToken = cancellationToken }; - } - - private static ResponseErrorClassifier _responseErrorClassifier200; - private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); + private static PipelineMessageClassifier _responseErrorClassifier200; + private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } } + diff --git a/.dotnet/src/Generated/Images.cs b/.dotnet/src/Generated/Images.cs index a3de80e0b..f2777b7ad 100644 --- a/.dotnet/src/Generated/Images.cs +++ b/.dotnet/src/Generated/Images.cs @@ -1,12 +1,9 @@ // -#nullable disable - using System; using System.ClientModel; -using System.ClientModel.Internal; using System.ClientModel.Primitives; -using System.ClientModel.Primitives.Pipeline; +using System.Text; using System.Threading; using System.Threading.Tasks; using OpenAI.Models; @@ -18,16 +15,13 @@ namespace OpenAI public partial class Images { private const string AuthorizationHeader = "Authorization"; - private readonly KeyCredential _keyCredential; + private readonly ApiKeyCredential _credential; private const string AuthorizationApiKeyPrefix = "Bearer"; - private readonly MessagePipeline _pipeline; + private readonly ClientPipeline _pipeline; private readonly Uri _endpoint; - /// The ClientDiagnostics is used to provide tracing support for the client library. - internal TelemetrySource ClientDiagnostics { get; } - /// The HTTP pipeline for sending and receiving REST requests and responses. - public virtual MessagePipeline Pipeline => _pipeline; + public virtual ClientPipeline Pipeline => _pipeline; /// Initializes a new instance of Images for mocking. protected Images() @@ -35,44 +29,38 @@ protected Images() } /// Initializes a new instance of Images. - /// The handler for diagnostic messaging in the client. /// The HTTP pipeline for sending and receiving REST requests and responses. - /// The key credential to copy. + /// The key credential to copy. /// OpenAI Endpoint. - internal Images(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + internal Images(ClientPipeline pipeline, ApiKeyCredential credential, Uri endpoint) { - ClientDiagnostics = clientDiagnostics; _pipeline = pipeline; - _keyCredential = keyCredential; + _credential = credential; _endpoint = endpoint; } /// Creates an image given a prompt. /// The to use. - /// The cancellation token to use. /// is null. - public virtual async Task> CreateImageAsync(CreateImageRequest image, CancellationToken cancellationToken = default) + public virtual async Task> CreateImageAsync(CreateImageRequest image) { - ClientUtilities.AssertNotNull(image, nameof(image)); + if (image is null) throw new ArgumentNullException(nameof(image)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = image.ToRequestBody(); - Result result = await CreateImageAsync(content, context).ConfigureAwait(false); - return Result.FromValue(ImagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(image); + ClientResult result = await CreateImageAsync(content).ConfigureAwait(false); + return ClientResult.FromValue(ImagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Creates an image given a prompt. /// The to use. - /// The cancellation token to use. /// is null. - public virtual Result CreateImage(CreateImageRequest image, CancellationToken cancellationToken = default) + public virtual ClientResult CreateImage(CreateImageRequest image) { - ClientUtilities.AssertNotNull(image, nameof(image)); + if (image is null) throw new ArgumentNullException(nameof(image)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = image.ToRequestBody(); - Result result = CreateImage(content, context); - return Result.FromValue(ImagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(image); + ClientResult result = CreateImage(content); + return ClientResult.FromValue(ImagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -85,32 +73,30 @@ public virtual Result CreateImage(CreateImageRequest image, Canc /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task CreateImageAsync(RequestBody content, RequestOptions context = null) + public virtual async Task CreateImageAsync(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateImageRequest(content, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Images.CreateImage"); - scope.Start(); - try - { - using PipelineMessage message = CreateCreateImageRequest(content, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -123,60 +109,54 @@ public virtual async Task CreateImageAsync(RequestBody content, RequestO /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result CreateImage(RequestBody content, RequestOptions context = null) + public virtual ClientResult CreateImage(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateImageRequest(content, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Images.CreateImage"); - scope.Start(); - try - { - using PipelineMessage message = CreateCreateImageRequest(content, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Creates an edited or extended image given an original image and a prompt. /// The to use. - /// The cancellation token to use. /// is null. - public virtual async Task> CreateImageEditAsync(CreateImageEditRequest image, CancellationToken cancellationToken = default) + public virtual async Task> CreateImageEditAsync(CreateImageEditRequest image) { - ClientUtilities.AssertNotNull(image, nameof(image)); + if (image is null) throw new ArgumentNullException(nameof(image)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = image.ToRequestBody(); - Result result = await CreateImageEditAsync(content, context).ConfigureAwait(false); - return Result.FromValue(ImagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(image); + ClientResult result = await CreateImageEditAsync(content).ConfigureAwait(false); + return ClientResult.FromValue(ImagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Creates an edited or extended image given an original image and a prompt. /// The to use. - /// The cancellation token to use. /// is null. - public virtual Result CreateImageEdit(CreateImageEditRequest image, CancellationToken cancellationToken = default) + public virtual ClientResult CreateImageEdit(CreateImageEditRequest image) { - ClientUtilities.AssertNotNull(image, nameof(image)); + if (image is null) throw new ArgumentNullException(nameof(image)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = image.ToRequestBody(); - Result result = CreateImageEdit(content, context); - return Result.FromValue(ImagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(image); + ClientResult result = CreateImageEdit(content); + return ClientResult.FromValue(ImagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -189,32 +169,30 @@ public virtual Result CreateImageEdit(CreateImageEditRequest ima /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task CreateImageEditAsync(RequestBody content, RequestOptions context = null) + public virtual async Task CreateImageEditAsync(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateImageEditRequest(content, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Images.CreateImageEdit"); - scope.Start(); - try - { - using PipelineMessage message = CreateCreateImageEditRequest(content, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -227,60 +205,54 @@ public virtual async Task CreateImageEditAsync(RequestBody content, Requ /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result CreateImageEdit(RequestBody content, RequestOptions context = null) + public virtual ClientResult CreateImageEdit(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateImageEditRequest(content, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Images.CreateImageEdit"); - scope.Start(); - try + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateCreateImageEditRequest(content, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Creates an edited or extended image given an original image and a prompt. /// The to use. - /// The cancellation token to use. /// is null. - public virtual async Task> CreateImageVariationAsync(CreateImageVariationRequest image, CancellationToken cancellationToken = default) + public virtual async Task> CreateImageVariationAsync(CreateImageVariationRequest image) { - ClientUtilities.AssertNotNull(image, nameof(image)); + if (image is null) throw new ArgumentNullException(nameof(image)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = image.ToRequestBody(); - Result result = await CreateImageVariationAsync(content, context).ConfigureAwait(false); - return Result.FromValue(ImagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(image); + ClientResult result = await CreateImageVariationAsync(content).ConfigureAwait(false); + return ClientResult.FromValue(ImagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Creates an edited or extended image given an original image and a prompt. /// The to use. - /// The cancellation token to use. /// is null. - public virtual Result CreateImageVariation(CreateImageVariationRequest image, CancellationToken cancellationToken = default) + public virtual ClientResult CreateImageVariation(CreateImageVariationRequest image) { - ClientUtilities.AssertNotNull(image, nameof(image)); + if (image is null) throw new ArgumentNullException(nameof(image)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = image.ToRequestBody(); - Result result = CreateImageVariation(content, context); - return Result.FromValue(ImagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(image); + ClientResult result = CreateImageVariation(content); + return ClientResult.FromValue(ImagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -293,32 +265,30 @@ public virtual Result CreateImageVariation(CreateImageVariationR /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task CreateImageVariationAsync(RequestBody content, RequestOptions context = null) + public virtual async Task CreateImageVariationAsync(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateImageVariationRequest(content, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Images.CreateImageVariation"); - scope.Start(); - try + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateCreateImageVariationRequest(content, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -331,91 +301,88 @@ public virtual async Task CreateImageVariationAsync(RequestBody content, /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result CreateImageVariation(RequestBody content, RequestOptions context = null) + public virtual ClientResult CreateImageVariation(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateImageVariationRequest(content, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Images.CreateImageVariation"); - scope.Start(); - try + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateCreateImageVariationRequest(content, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } - internal PipelineMessage CreateCreateImageRequest(RequestBody content, RequestOptions context) + internal PipelineMessage CreateCreateImageRequest(BinaryContent content, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/images/generations", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - request.SetHeaderValue("Content-Type", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/images/generations"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); + request.Headers.Set("Content-Type", "application/json"); request.Content = content; + message.Apply(options); return message; } - internal PipelineMessage CreateCreateImageEditRequest(RequestBody content, RequestOptions context) + internal PipelineMessage CreateCreateImageEditRequest(BinaryContent content, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/images/edits", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - request.SetHeaderValue("content-type", "multipart/form-data"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/images/edits"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); + request.Headers.Set("content-type", "multipart/form-data"); request.Content = content; + message.Apply(options); return message; } - internal PipelineMessage CreateCreateImageVariationRequest(RequestBody content, RequestOptions context) + internal PipelineMessage CreateCreateImageVariationRequest(BinaryContent content, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/images/variations", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - request.SetHeaderValue("content-type", "multipart/form-data"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/images/variations"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); + request.Headers.Set("content-type", "multipart/form-data"); request.Content = content; + message.Apply(options); return message; } - private static RequestOptions DefaultRequestContext = new RequestOptions(); - internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) - { - if (!cancellationToken.CanBeCanceled) - { - return DefaultRequestContext; - } - - return new RequestOptions() { CancellationToken = cancellationToken }; - } - - private static ResponseErrorClassifier _responseErrorClassifier200; - private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); + private static PipelineMessageClassifier _responseErrorClassifier200; + private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } } + diff --git a/.dotnet/src/Generated/Messages.cs b/.dotnet/src/Generated/Messages.cs index 1ca608801..28ac36351 100644 --- a/.dotnet/src/Generated/Messages.cs +++ b/.dotnet/src/Generated/Messages.cs @@ -1,12 +1,9 @@ // -#nullable disable - using System; using System.ClientModel; -using System.ClientModel.Internal; using System.ClientModel.Primitives; -using System.ClientModel.Primitives.Pipeline; +using System.Text; using System.Threading; using System.Threading.Tasks; using OpenAI.Models; @@ -18,16 +15,13 @@ namespace OpenAI public partial class Messages { private const string AuthorizationHeader = "Authorization"; - private readonly KeyCredential _keyCredential; + private readonly ApiKeyCredential _credential; private const string AuthorizationApiKeyPrefix = "Bearer"; - private readonly MessagePipeline _pipeline; + private readonly ClientPipeline _pipeline; private readonly Uri _endpoint; - /// The ClientDiagnostics is used to provide tracing support for the client library. - internal TelemetrySource ClientDiagnostics { get; } - /// The HTTP pipeline for sending and receiving REST requests and responses. - public virtual MessagePipeline Pipeline => _pipeline; + public virtual ClientPipeline Pipeline => _pipeline; /// Initializes a new instance of Messages for mocking. protected Messages() @@ -35,50 +29,46 @@ protected Messages() } /// Initializes a new instance of Messages. - /// The handler for diagnostic messaging in the client. /// The HTTP pipeline for sending and receiving REST requests and responses. - /// The key credential to copy. + /// The key credential to copy. /// OpenAI Endpoint. - internal Messages(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + internal Messages(ClientPipeline pipeline, ApiKeyCredential credential, Uri endpoint) { - ClientDiagnostics = clientDiagnostics; _pipeline = pipeline; - _keyCredential = keyCredential; + _credential = credential; _endpoint = endpoint; } /// Create a message. /// The ID of the [thread](/docs/api-reference/threads) to create a message for. /// The to use. - /// The cancellation token to use. /// or is null. /// is an empty string, and was expected to be non-empty. - public virtual async Task> CreateMessageAsync(string threadId, CreateMessageRequest message, CancellationToken cancellationToken = default) + public virtual async Task> CreateMessageAsync(string threadId, CreateMessageRequest message) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNull(message, nameof(message)); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (message is null) throw new ArgumentNullException(nameof(message)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = message.ToRequestBody(); - Result result = await CreateMessageAsync(threadId, content, context).ConfigureAwait(false); - return Result.FromValue(MessageObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(message); + ClientResult result = await CreateMessageAsync(threadId, content).ConfigureAwait(false); + return ClientResult.FromValue(MessageObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Create a message. /// The ID of the [thread](/docs/api-reference/threads) to create a message for. /// The to use. - /// The cancellation token to use. /// or is null. /// is an empty string, and was expected to be non-empty. - public virtual Result CreateMessage(string threadId, CreateMessageRequest message, CancellationToken cancellationToken = default) + public virtual ClientResult CreateMessage(string threadId, CreateMessageRequest message) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNull(message, nameof(message)); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (message is null) throw new ArgumentNullException(nameof(message)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = message.ToRequestBody(); - Result result = CreateMessage(threadId, content, context); - return Result.FromValue(MessageObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(message); + ClientResult result = CreateMessage(threadId, content); + return ClientResult.FromValue(MessageObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -91,35 +81,34 @@ public virtual Result CreateMessage(string threadId, CreateMessag /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the [thread](/docs/api-reference/threads) to create a message for. /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// or is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task CreateMessageAsync(string threadId, RequestBody content, RequestOptions context = null) + public virtual async Task CreateMessageAsync(string threadId, BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNull(content, nameof(content)); - - using var scope = ClientDiagnostics.CreateSpan("Messages.CreateMessage"); - scope.Start(); - try - { - using PipelineMessage message = CreateCreateMessageRequest(threadId, content, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateMessageRequest(threadId, content, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -132,35 +121,34 @@ public virtual async Task CreateMessageAsync(string threadId, RequestBod /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the [thread](/docs/api-reference/threads) to create a message for. /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// or is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result CreateMessage(string threadId, RequestBody content, RequestOptions context = null) + public virtual ClientResult CreateMessage(string threadId, BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNull(content, nameof(content)); - - using var scope = ClientDiagnostics.CreateSpan("Messages.CreateMessage"); - scope.Start(); - try + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateMessageRequest(threadId, content, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateCreateMessageRequest(threadId, content, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Returns a list of messages for a given thread. @@ -183,16 +171,15 @@ public virtual Result CreateMessage(string threadId, RequestBody content, Reques /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. /// - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual async Task> GetMessagesAsync(string threadId, int? limit = null, ListOrder? order = null, string after = null, string before = null, CancellationToken cancellationToken = default) + public virtual async Task> GetMessagesAsync(string threadId, int? limit = null, ListOrder? order = null, string after = null, string before = null) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await GetMessagesAsync(threadId, limit, order?.ToString(), after, before, context).ConfigureAwait(false); - return Result.FromValue(ListMessagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = await GetMessagesAsync(threadId, limit, order?.ToString(), after, before).ConfigureAwait(false); + return ClientResult.FromValue(ListMessagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Returns a list of messages for a given thread. @@ -215,16 +202,15 @@ public virtual async Task> GetMessagesAsync(string /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. /// - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual Result GetMessages(string threadId, int? limit = null, ListOrder? order = null, string after = null, string before = null, CancellationToken cancellationToken = default) + public virtual ClientResult GetMessages(string threadId, int? limit = null, ListOrder? order = null, string after = null, string before = null) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = GetMessages(threadId, limit, order?.ToString(), after, before, context); - return Result.FromValue(ListMessagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = GetMessages(threadId, limit, order?.ToString(), after, before); + return ClientResult.FromValue(ListMessagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -237,7 +223,7 @@ public virtual Result GetMessages(string threadId, int? li /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -261,27 +247,26 @@ public virtual Result GetMessages(string threadId, int? li /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. /// - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task GetMessagesAsync(string threadId, int? limit, string order, string after, string before, RequestOptions context) + public virtual async Task GetMessagesAsync(string threadId, int? limit, string order, string after, string before, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - - using var scope = ClientDiagnostics.CreateSpan("Messages.GetMessages"); - scope.Start(); - try + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetMessagesRequest(threadId, limit, order, after, before, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateGetMessagesRequest(threadId, limit, order, after, before, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -294,7 +279,7 @@ public virtual async Task GetMessagesAsync(string threadId, int? limit, /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -318,59 +303,58 @@ public virtual async Task GetMessagesAsync(string threadId, int? limit, /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. /// - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result GetMessages(string threadId, int? limit, string order, string after, string before, RequestOptions context) + public virtual ClientResult GetMessages(string threadId, int? limit, string order, string after, string before, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - - using var scope = ClientDiagnostics.CreateSpan("Messages.GetMessages"); - scope.Start(); - try + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetMessagesRequest(threadId, limit, order, after, before, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateGetMessagesRequest(threadId, limit, order, after, before, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Retrieve a message. /// The ID of the [thread](/docs/api-reference/threads) to which this message belongs. /// The ID of the message to retrieve. - /// The cancellation token to use. /// or is null. /// or is an empty string, and was expected to be non-empty. - public virtual async Task> GetMessageAsync(string threadId, string messageId, CancellationToken cancellationToken = default) + public virtual async Task> GetMessageAsync(string threadId, string messageId) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (messageId is null) throw new ArgumentNullException(nameof(messageId)); + if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await GetMessageAsync(threadId, messageId, context).ConfigureAwait(false); - return Result.FromValue(MessageObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = await GetMessageAsync(threadId, messageId).ConfigureAwait(false); + return ClientResult.FromValue(MessageObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Retrieve a message. /// The ID of the [thread](/docs/api-reference/threads) to which this message belongs. /// The ID of the message to retrieve. - /// The cancellation token to use. /// or is null. /// or is an empty string, and was expected to be non-empty. - public virtual Result GetMessage(string threadId, string messageId, CancellationToken cancellationToken = default) + public virtual ClientResult GetMessage(string threadId, string messageId) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (messageId is null) throw new ArgumentNullException(nameof(messageId)); + if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = GetMessage(threadId, messageId, context); - return Result.FromValue(MessageObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = GetMessage(threadId, messageId); + return ClientResult.FromValue(MessageObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -383,35 +367,35 @@ public virtual Result GetMessage(string threadId, string messageI /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the [thread](/docs/api-reference/threads) to which this message belongs. /// The ID of the message to retrieve. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// or is null. /// or is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task GetMessageAsync(string threadId, string messageId, RequestOptions context) + public virtual async Task GetMessageAsync(string threadId, string messageId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); - - using var scope = ClientDiagnostics.CreateSpan("Messages.GetMessage"); - scope.Start(); - try + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (messageId is null) throw new ArgumentNullException(nameof(messageId)); + if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetMessageRequest(threadId, messageId, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateGetMessageRequest(threadId, messageId, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -424,73 +408,73 @@ public virtual async Task GetMessageAsync(string threadId, string messag /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the [thread](/docs/api-reference/threads) to which this message belongs. /// The ID of the message to retrieve. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// or is null. /// or is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result GetMessage(string threadId, string messageId, RequestOptions context) + public virtual ClientResult GetMessage(string threadId, string messageId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); - - using var scope = ClientDiagnostics.CreateSpan("Messages.GetMessage"); - scope.Start(); - try + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (messageId is null) throw new ArgumentNullException(nameof(messageId)); + if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetMessageRequest(threadId, messageId, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateGetMessageRequest(threadId, messageId, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Modifies a message. /// The ID of the thread to which this message belongs. /// The ID of the message to modify. /// The to use. - /// The cancellation token to use. /// , or is null. /// or is an empty string, and was expected to be non-empty. - public virtual async Task> ModifyMessageAsync(string threadId, string messageId, ModifyMessageRequest message, CancellationToken cancellationToken = default) + public virtual async Task> ModifyMessageAsync(string threadId, string messageId, ModifyMessageRequest message) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); - ClientUtilities.AssertNotNull(message, nameof(message)); - - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = message.ToRequestBody(); - Result result = await ModifyMessageAsync(threadId, messageId, content, context).ConfigureAwait(false); - return Result.FromValue(MessageObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (messageId is null) throw new ArgumentNullException(nameof(messageId)); + if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); + if (message is null) throw new ArgumentNullException(nameof(message)); + + using BinaryContent content = BinaryContent.Create(message); + ClientResult result = await ModifyMessageAsync(threadId, messageId, content).ConfigureAwait(false); + return ClientResult.FromValue(MessageObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Modifies a message. /// The ID of the thread to which this message belongs. /// The ID of the message to modify. /// The to use. - /// The cancellation token to use. /// , or is null. /// or is an empty string, and was expected to be non-empty. - public virtual Result ModifyMessage(string threadId, string messageId, ModifyMessageRequest message, CancellationToken cancellationToken = default) + public virtual ClientResult ModifyMessage(string threadId, string messageId, ModifyMessageRequest message) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); - ClientUtilities.AssertNotNull(message, nameof(message)); - - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = message.ToRequestBody(); - Result result = ModifyMessage(threadId, messageId, content, context); - return Result.FromValue(MessageObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (messageId is null) throw new ArgumentNullException(nameof(messageId)); + if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); + if (message is null) throw new ArgumentNullException(nameof(message)); + + using BinaryContent content = BinaryContent.Create(message); + ClientResult result = ModifyMessage(threadId, messageId, content); + return ClientResult.FromValue(MessageObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -503,7 +487,7 @@ public virtual Result ModifyMessage(string threadId, string messa /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -511,29 +495,29 @@ public virtual Result ModifyMessage(string threadId, string messa /// The ID of the thread to which this message belongs. /// The ID of the message to modify. /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// , or is null. /// or is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task ModifyMessageAsync(string threadId, string messageId, RequestBody content, RequestOptions context = null) + public virtual async Task ModifyMessageAsync(string threadId, string messageId, BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); - ClientUtilities.AssertNotNull(content, nameof(content)); - - using var scope = ClientDiagnostics.CreateSpan("Messages.ModifyMessage"); - scope.Start(); - try + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (messageId is null) throw new ArgumentNullException(nameof(messageId)); + if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateModifyMessageRequest(threadId, messageId, content, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateModifyMessageRequest(threadId, messageId, content, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -546,7 +530,7 @@ public virtual async Task ModifyMessageAsync(string threadId, string mes /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -554,29 +538,29 @@ public virtual async Task ModifyMessageAsync(string threadId, string mes /// The ID of the thread to which this message belongs. /// The ID of the message to modify. /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// , or is null. /// or is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result ModifyMessage(string threadId, string messageId, RequestBody content, RequestOptions context = null) + public virtual ClientResult ModifyMessage(string threadId, string messageId, BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); - ClientUtilities.AssertNotNull(content, nameof(content)); - - using var scope = ClientDiagnostics.CreateSpan("Messages.ModifyMessage"); - scope.Start(); - try - { - using PipelineMessage message = CreateModifyMessageRequest(threadId, messageId, content, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (messageId is null) throw new ArgumentNullException(nameof(messageId)); + if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateModifyMessageRequest(threadId, messageId, content, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Returns a list of message files. @@ -600,17 +584,17 @@ public virtual Result ModifyMessage(string threadId, string messageId, RequestBo /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. /// - /// The cancellation token to use. /// or is null. /// or is an empty string, and was expected to be non-empty. - public virtual async Task> GetMessageFilesAsync(string threadId, string messageId, int? limit = null, ListOrder? order = null, string after = null, string before = null, CancellationToken cancellationToken = default) + public virtual async Task> GetMessageFilesAsync(string threadId, string messageId, int? limit = null, ListOrder? order = null, string after = null, string before = null) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (messageId is null) throw new ArgumentNullException(nameof(messageId)); + if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await GetMessageFilesAsync(threadId, messageId, limit, order?.ToString(), after, before, context).ConfigureAwait(false); - return Result.FromValue(ListMessageFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = await GetMessageFilesAsync(threadId, messageId, limit, order?.ToString(), after, before).ConfigureAwait(false); + return ClientResult.FromValue(ListMessageFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Returns a list of message files. @@ -634,17 +618,17 @@ public virtual async Task> GetMessageFilesAsync /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. /// - /// The cancellation token to use. /// or is null. /// or is an empty string, and was expected to be non-empty. - public virtual Result GetMessageFiles(string threadId, string messageId, int? limit = null, ListOrder? order = null, string after = null, string before = null, CancellationToken cancellationToken = default) + public virtual ClientResult GetMessageFiles(string threadId, string messageId, int? limit = null, ListOrder? order = null, string after = null, string before = null) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (messageId is null) throw new ArgumentNullException(nameof(messageId)); + if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = GetMessageFiles(threadId, messageId, limit, order?.ToString(), after, before, context); - return Result.FromValue(ListMessageFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = GetMessageFiles(threadId, messageId, limit, order?.ToString(), after, before); + return ClientResult.FromValue(ListMessageFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -657,7 +641,7 @@ public virtual Result GetMessageFiles(string threadId, /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -682,28 +666,28 @@ public virtual Result GetMessageFiles(string threadId, /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. /// - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// or is null. /// or is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task GetMessageFilesAsync(string threadId, string messageId, int? limit, string order, string after, string before, RequestOptions context) + public virtual async Task GetMessageFilesAsync(string threadId, string messageId, int? limit, string order, string after, string before, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); - - using var scope = ClientDiagnostics.CreateSpan("Messages.GetMessageFiles"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetMessageFilesRequest(threadId, messageId, limit, order, after, before, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (messageId is null) throw new ArgumentNullException(nameof(messageId)); + if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetMessageFilesRequest(threadId, messageId, limit, order, after, before, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -716,7 +700,7 @@ public virtual async Task GetMessageFilesAsync(string threadId, string m /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -741,64 +725,66 @@ public virtual async Task GetMessageFilesAsync(string threadId, string m /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. /// - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// or is null. /// or is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result GetMessageFiles(string threadId, string messageId, int? limit, string order, string after, string before, RequestOptions context) + public virtual ClientResult GetMessageFiles(string threadId, string messageId, int? limit, string order, string after, string before, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); - - using var scope = ClientDiagnostics.CreateSpan("Messages.GetMessageFiles"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetMessageFilesRequest(threadId, messageId, limit, order, after, before, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (messageId is null) throw new ArgumentNullException(nameof(messageId)); + if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetMessageFilesRequest(threadId, messageId, limit, order, after, before, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Retrieves a message file. /// The ID of the thread to which the message and File belong. /// The ID of the message the file belongs to. /// The ID of the file being retrieved. - /// The cancellation token to use. /// , or is null. /// , or is an empty string, and was expected to be non-empty. - public virtual async Task> GetMessageFileAsync(string threadId, string messageId, string fileId, CancellationToken cancellationToken = default) + public virtual async Task> GetMessageFileAsync(string threadId, string messageId, string fileId) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); - ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); - - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await GetMessageFileAsync(threadId, messageId, fileId, context).ConfigureAwait(false); - return Result.FromValue(MessageFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (messageId is null) throw new ArgumentNullException(nameof(messageId)); + if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); + if (fileId is null) throw new ArgumentNullException(nameof(fileId)); + if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); + + ClientResult result = await GetMessageFileAsync(threadId, messageId, fileId).ConfigureAwait(false); + return ClientResult.FromValue(MessageFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Retrieves a message file. /// The ID of the thread to which the message and File belong. /// The ID of the message the file belongs to. /// The ID of the file being retrieved. - /// The cancellation token to use. /// , or is null. /// , or is an empty string, and was expected to be non-empty. - public virtual Result GetMessageFile(string threadId, string messageId, string fileId, CancellationToken cancellationToken = default) + public virtual ClientResult GetMessageFile(string threadId, string messageId, string fileId) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); - ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); - - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = GetMessageFile(threadId, messageId, fileId, context); - return Result.FromValue(MessageFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (messageId is null) throw new ArgumentNullException(nameof(messageId)); + if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); + if (fileId is null) throw new ArgumentNullException(nameof(fileId)); + if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); + + ClientResult result = GetMessageFile(threadId, messageId, fileId); + return ClientResult.FromValue(MessageFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -811,7 +797,7 @@ public virtual Result GetMessageFile(string threadId, string /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -819,29 +805,30 @@ public virtual Result GetMessageFile(string threadId, string /// The ID of the thread to which the message and File belong. /// The ID of the message the file belongs to. /// The ID of the file being retrieved. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// , or is null. /// , or is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task GetMessageFileAsync(string threadId, string messageId, string fileId, RequestOptions context) + public virtual async Task GetMessageFileAsync(string threadId, string messageId, string fileId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); - ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); - - using var scope = ClientDiagnostics.CreateSpan("Messages.GetMessageFile"); - scope.Start(); - try + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (messageId is null) throw new ArgumentNullException(nameof(messageId)); + if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); + if (fileId is null) throw new ArgumentNullException(nameof(fileId)); + if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetMessageFileRequest(threadId, messageId, fileId, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateGetMessageFileRequest(threadId, messageId, fileId, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -854,7 +841,7 @@ public virtual async Task GetMessageFileAsync(string threadId, string me /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -862,176 +849,256 @@ public virtual async Task GetMessageFileAsync(string threadId, string me /// The ID of the thread to which the message and File belong. /// The ID of the message the file belongs to. /// The ID of the file being retrieved. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// , or is null. /// , or is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result GetMessageFile(string threadId, string messageId, string fileId, RequestOptions context) + public virtual ClientResult GetMessageFile(string threadId, string messageId, string fileId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(messageId, nameof(messageId)); - ClientUtilities.AssertNotNullOrEmpty(fileId, nameof(fileId)); - - using var scope = ClientDiagnostics.CreateSpan("Messages.GetMessageFile"); - scope.Start(); - try + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (messageId is null) throw new ArgumentNullException(nameof(messageId)); + if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); + if (fileId is null) throw new ArgumentNullException(nameof(fileId)); + if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetMessageFileRequest(threadId, messageId, fileId, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateGetMessageFileRequest(threadId, messageId, fileId, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } - internal PipelineMessage CreateCreateMessageRequest(string threadId, RequestBody content, RequestOptions context) + internal PipelineMessage CreateCreateMessageRequest(string threadId, BinaryContent content, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); - uri.AppendPath(threadId, true); - uri.AppendPath("/messages", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - request.SetHeaderValue("Content-Type", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/threads/"); + uriBuilder.Path += path.ToString(); + path.Append(threadId); + uriBuilder.Path += path.ToString(); + path.Append("/messages"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); + request.Headers.Set("Content-Type", "application/json"); request.Content = content; + message.Apply(options); return message; } - internal PipelineMessage CreateGetMessagesRequest(string threadId, int? limit, string order, string after, string before, RequestOptions context) + internal PipelineMessage CreateGetMessagesRequest(string threadId, int? limit, string order, string after, string before, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("GET"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); - uri.AppendPath(threadId, true); - uri.AppendPath("/messages", false); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "GET"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/threads/"); + uriBuilder.Path += path.ToString(); + path.Append(threadId); + uriBuilder.Path += path.ToString(); + path.Append("/messages"); + uriBuilder.Path += path.ToString(); if (limit != null) { - uri.AppendQuery("limit", limit.Value, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&limit={limit.Value}"; + } + else + { + uriBuilder.Query = $"limit={limit.Value}"; + } } if (order != null) { - uri.AppendQuery("order", order, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&order={order}"; + } + else + { + uriBuilder.Query = $"order={order}"; + } } if (after != null) { - uri.AppendQuery("after", after, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&after={after}"; + } + else + { + uriBuilder.Query = $"after={after}"; + } } if (before != null) { - uri.AppendQuery("before", before, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&before={before}"; + } + else + { + uriBuilder.Query = $"before={before}"; + } } - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); return message; } - internal PipelineMessage CreateGetMessageRequest(string threadId, string messageId, RequestOptions context) + internal PipelineMessage CreateGetMessageRequest(string threadId, string messageId, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("GET"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); - uri.AppendPath(threadId, true); - uri.AppendPath("/messages/", false); - uri.AppendPath(messageId, true); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "GET"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/threads/"); + uriBuilder.Path += path.ToString(); + path.Append(threadId); + uriBuilder.Path += path.ToString(); + path.Append("/messages/"); + uriBuilder.Path += path.ToString(); + path.Append(messageId); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); return message; } - internal PipelineMessage CreateModifyMessageRequest(string threadId, string messageId, RequestBody content, RequestOptions context) + internal PipelineMessage CreateModifyMessageRequest(string threadId, string messageId, BinaryContent content, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); - uri.AppendPath(threadId, true); - uri.AppendPath("/messages/", false); - uri.AppendPath(messageId, true); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - request.SetHeaderValue("Content-Type", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/threads/"); + uriBuilder.Path += path.ToString(); + path.Append(threadId); + uriBuilder.Path += path.ToString(); + path.Append("/messages/"); + uriBuilder.Path += path.ToString(); + path.Append(messageId); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); + request.Headers.Set("Content-Type", "application/json"); request.Content = content; + message.Apply(options); return message; } - internal PipelineMessage CreateGetMessageFilesRequest(string threadId, string messageId, int? limit, string order, string after, string before, RequestOptions context) + internal PipelineMessage CreateGetMessageFilesRequest(string threadId, string messageId, int? limit, string order, string after, string before, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("GET"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); - uri.AppendPath(threadId, true); - uri.AppendPath("/messages/", false); - uri.AppendPath(messageId, true); - uri.AppendPath("/files", false); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "GET"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/threads/"); + uriBuilder.Path += path.ToString(); + path.Append(threadId); + uriBuilder.Path += path.ToString(); + path.Append("/messages/"); + uriBuilder.Path += path.ToString(); + path.Append(messageId); + uriBuilder.Path += path.ToString(); + path.Append("/files"); + uriBuilder.Path += path.ToString(); if (limit != null) { - uri.AppendQuery("limit", limit.Value, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&limit={limit.Value}"; + } + else + { + uriBuilder.Query = $"limit={limit.Value}"; + } } if (order != null) { - uri.AppendQuery("order", order, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&order={order}"; + } + else + { + uriBuilder.Query = $"order={order}"; + } } if (after != null) { - uri.AppendQuery("after", after, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&after={after}"; + } + else + { + uriBuilder.Query = $"after={after}"; + } } if (before != null) { - uri.AppendQuery("before", before, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&before={before}"; + } + else + { + uriBuilder.Query = $"before={before}"; + } } - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); return message; } - internal PipelineMessage CreateGetMessageFileRequest(string threadId, string messageId, string fileId, RequestOptions context) + internal PipelineMessage CreateGetMessageFileRequest(string threadId, string messageId, string fileId, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("GET"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); - uri.AppendPath(threadId, true); - uri.AppendPath("/messages/", false); - uri.AppendPath(messageId, true); - uri.AppendPath("/files/", false); - uri.AppendPath(fileId, true); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "GET"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/threads/"); + uriBuilder.Path += path.ToString(); + path.Append(threadId); + uriBuilder.Path += path.ToString(); + path.Append("/messages/"); + uriBuilder.Path += path.ToString(); + path.Append(messageId); + uriBuilder.Path += path.ToString(); + path.Append("/files/"); + uriBuilder.Path += path.ToString(); + path.Append(fileId); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); return message; } - private static RequestOptions DefaultRequestContext = new RequestOptions(); - internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) - { - if (!cancellationToken.CanBeCanceled) - { - return DefaultRequestContext; - } - - return new RequestOptions() { CancellationToken = cancellationToken }; - } - - private static ResponseErrorClassifier _responseErrorClassifier200; - private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); + private static PipelineMessageClassifier _responseErrorClassifier200; + private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } } + diff --git a/.dotnet/src/Generated/Models/AssistantFileObject.Serialization.cs b/.dotnet/src/Generated/Models/AssistantFileObject.Serialization.cs index 74ad1f256..c2b95887f 100644 --- a/.dotnet/src/Generated/Models/AssistantFileObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/AssistantFileObject.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class AssistantFileObject : IUtf8JsonWriteable, IJsonModel + public partial class AssistantFileObject : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -144,13 +140,6 @@ internal static AssistantFileObject FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeAssistantFileObject(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/AssistantFileObject.cs b/.dotnet/src/Generated/Models/AssistantFileObject.cs index 21aef1f7b..ee5c47c27 100644 --- a/.dotnet/src/Generated/Models/AssistantFileObject.cs +++ b/.dotnet/src/Generated/Models/AssistantFileObject.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -50,8 +48,8 @@ public partial class AssistantFileObject /// or is null. internal AssistantFileObject(string id, DateTimeOffset createdAt, string assistantId) { - ClientUtilities.AssertNotNull(id, nameof(id)); - ClientUtilities.AssertNotNull(assistantId, nameof(assistantId)); + if (id is null) throw new ArgumentNullException(nameof(id)); + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); Id = id; CreatedAt = createdAt; @@ -89,3 +87,4 @@ internal AssistantFileObject() public string AssistantId { get; } } } + diff --git a/.dotnet/src/Generated/Models/AssistantFileObjectObject.cs b/.dotnet/src/Generated/Models/AssistantFileObjectObject.cs index d9b017682..7883e84f3 100644 --- a/.dotnet/src/Generated/Models/AssistantFileObjectObject.cs +++ b/.dotnet/src/Generated/Models/AssistantFileObjectObject.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public AssistantFileObjectObject(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/AssistantObject.Serialization.cs b/.dotnet/src/Generated/Models/AssistantObject.Serialization.cs index 3676fb26d..c4e51bcf9 100644 --- a/.dotnet/src/Generated/Models/AssistantObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/AssistantObject.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class AssistantObject : IUtf8JsonWriteable, IJsonModel + public partial class AssistantObject : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -290,13 +286,6 @@ internal static AssistantObject FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeAssistantObject(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/AssistantObject.cs b/.dotnet/src/Generated/Models/AssistantObject.cs index 4816bc339..3b6d4b131 100644 --- a/.dotnet/src/Generated/Models/AssistantObject.cs +++ b/.dotnet/src/Generated/Models/AssistantObject.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; @@ -72,10 +70,10 @@ public partial class AssistantObject /// , , or is null. internal AssistantObject(string id, DateTimeOffset createdAt, string name, string description, string model, string instructions, IEnumerable tools, IEnumerable fileIds, IReadOnlyDictionary metadata) { - ClientUtilities.AssertNotNull(id, nameof(id)); - ClientUtilities.AssertNotNull(model, nameof(model)); - ClientUtilities.AssertNotNull(tools, nameof(tools)); - ClientUtilities.AssertNotNull(fileIds, nameof(fileIds)); + if (id is null) throw new ArgumentNullException(nameof(id)); + if (model is null) throw new ArgumentNullException(nameof(model)); + if (tools is null) throw new ArgumentNullException(nameof(tools)); + if (fileIds is null) throw new ArgumentNullException(nameof(fileIds)); Id = id; CreatedAt = createdAt; @@ -200,3 +198,4 @@ internal AssistantObject() public IReadOnlyDictionary Metadata { get; } } } + diff --git a/.dotnet/src/Generated/Models/AssistantObjectObject.cs b/.dotnet/src/Generated/Models/AssistantObjectObject.cs index 9c8eb972f..f7a7cb21d 100644 --- a/.dotnet/src/Generated/Models/AssistantObjectObject.cs +++ b/.dotnet/src/Generated/Models/AssistantObjectObject.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public AssistantObjectObject(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/AudioSegment.Serialization.cs b/.dotnet/src/Generated/Models/AudioSegment.Serialization.cs index e114a09c0..5b4ef9b7a 100644 --- a/.dotnet/src/Generated/Models/AudioSegment.Serialization.cs +++ b/.dotnet/src/Generated/Models/AudioSegment.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class AudioSegment : IUtf8JsonWriteable, IJsonModel + public partial class AudioSegment : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -202,13 +198,6 @@ internal static AudioSegment FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeAudioSegment(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/AudioSegment.cs b/.dotnet/src/Generated/Models/AudioSegment.cs index d44bf8dc7..f25b206ff 100644 --- a/.dotnet/src/Generated/Models/AudioSegment.cs +++ b/.dotnet/src/Generated/Models/AudioSegment.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; @@ -64,8 +62,8 @@ public partial class AudioSegment /// or is null. internal AudioSegment(long id, long seek, TimeSpan start, TimeSpan end, string text, IEnumerable tokens, double temperature, double avgLogprob, double compressionRatio, double noSpeechProb) { - ClientUtilities.AssertNotNull(text, nameof(text)); - ClientUtilities.AssertNotNull(tokens, nameof(tokens)); + if (text is null) throw new ArgumentNullException(nameof(text)); + if (tokens is null) throw new ArgumentNullException(nameof(tokens)); Id = id; Seek = seek; @@ -145,3 +143,4 @@ internal AudioSegment() public double NoSpeechProb { get; } } } + diff --git a/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.Serialization.cs index c85718f98..d82b8d8e5 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - internal partial class ChatCompletionFunctionCallOption : IUtf8JsonWriteable, IJsonModel + internal partial class ChatCompletionFunctionCallOption : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -120,13 +116,6 @@ internal static ChatCompletionFunctionCallOption FromResponse(PipelineResponse r using var document = JsonDocument.Parse(response.Content); return DeserializeChatCompletionFunctionCallOption(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.cs b/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.cs index 268efaf1a..40c76aacd 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -51,7 +49,7 @@ internal partial class ChatCompletionFunctionCallOption /// is null. public ChatCompletionFunctionCallOption(string name) { - ClientUtilities.AssertNotNull(name, nameof(name)); + if (name is null) throw new ArgumentNullException(nameof(name)); Name = name; } @@ -74,3 +72,4 @@ internal ChatCompletionFunctionCallOption() public string Name { get; } } } + diff --git a/.dotnet/src/Generated/Models/ChatCompletionFunctions.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionFunctions.Serialization.cs index 119be9a51..5558f49c3 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionFunctions.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionFunctions.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class ChatCompletionFunctions : IUtf8JsonWriteable, IJsonModel + public partial class ChatCompletionFunctions : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -146,13 +142,6 @@ internal static ChatCompletionFunctions FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeChatCompletionFunctions(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/ChatCompletionFunctions.cs b/.dotnet/src/Generated/Models/ChatCompletionFunctions.cs index d1bbfa718..7055cc173 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionFunctions.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionFunctions.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -52,7 +50,7 @@ public partial class ChatCompletionFunctions /// is null. public ChatCompletionFunctions(string name) { - ClientUtilities.AssertNotNull(name, nameof(name)); + if (name is null) throw new ArgumentNullException(nameof(name)); Name = name; } @@ -95,3 +93,4 @@ internal ChatCompletionFunctions() public FunctionParameters Parameters { get; set; } } } + diff --git a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.Serialization.cs index e3d872da2..4806e429e 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class ChatCompletionMessageToolCall : IUtf8JsonWriteable, IJsonModel + public partial class ChatCompletionMessageToolCall : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -136,13 +132,6 @@ internal static ChatCompletionMessageToolCall FromResponse(PipelineResponse resp using var document = JsonDocument.Parse(response.Content); return DeserializeChatCompletionMessageToolCall(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.cs b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.cs index e5249dafc..1d5bbc882 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -49,8 +47,8 @@ public partial class ChatCompletionMessageToolCall /// or is null. public ChatCompletionMessageToolCall(string id, ChatCompletionMessageToolCallFunction function) { - ClientUtilities.AssertNotNull(id, nameof(id)); - ClientUtilities.AssertNotNull(function, nameof(function)); + if (id is null) throw new ArgumentNullException(nameof(id)); + if (function is null) throw new ArgumentNullException(nameof(function)); Id = id; Function = function; @@ -83,3 +81,4 @@ internal ChatCompletionMessageToolCall() public ChatCompletionMessageToolCallFunction Function { get; set; } } } + diff --git a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.Serialization.cs index ca4e609d1..57c8334c1 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class ChatCompletionMessageToolCallFunction : IUtf8JsonWriteable, IJsonModel + public partial class ChatCompletionMessageToolCallFunction : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -128,13 +124,6 @@ internal static ChatCompletionMessageToolCallFunction FromResponse(PipelineRespo using var document = JsonDocument.Parse(response.Content); return DeserializeChatCompletionMessageToolCallFunction(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.cs b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.cs index 92b945f4c..892e74010 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -53,8 +51,8 @@ public partial class ChatCompletionMessageToolCallFunction /// or is null. public ChatCompletionMessageToolCallFunction(string name, string arguments) { - ClientUtilities.AssertNotNull(name, nameof(name)); - ClientUtilities.AssertNotNull(arguments, nameof(arguments)); + if (name is null) throw new ArgumentNullException(nameof(name)); + if (arguments is null) throw new ArgumentNullException(nameof(arguments)); Name = name; Arguments = arguments; @@ -90,3 +88,4 @@ internal ChatCompletionMessageToolCallFunction() public string Arguments { get; set; } } } + diff --git a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallType.cs b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallType.cs index e6c9dff53..bdf80b599 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallType.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallType.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public ChatCompletionMessageToolCallType(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.Serialization.cs index 7ec5a3aeb..a5cb5af93 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - internal partial class ChatCompletionNamedToolChoice : IUtf8JsonWriteable, IJsonModel + internal partial class ChatCompletionNamedToolChoice : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -128,13 +124,6 @@ internal static ChatCompletionNamedToolChoice FromResponse(PipelineResponse resp using var document = JsonDocument.Parse(response.Content); return DeserializeChatCompletionNamedToolChoice(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.cs b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.cs index da8b10edb..63c912acc 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -48,7 +46,7 @@ internal partial class ChatCompletionNamedToolChoice /// is null. public ChatCompletionNamedToolChoice(ChatCompletionNamedToolChoiceFunction function) { - ClientUtilities.AssertNotNull(function, nameof(function)); + if (function is null) throw new ArgumentNullException(nameof(function)); Function = function; } @@ -76,3 +74,4 @@ internal ChatCompletionNamedToolChoice() public ChatCompletionNamedToolChoiceFunction Function { get; } } } + diff --git a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.Serialization.cs index 654aa4f90..cb372631e 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - internal partial class ChatCompletionNamedToolChoiceFunction : IUtf8JsonWriteable, IJsonModel + internal partial class ChatCompletionNamedToolChoiceFunction : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -120,13 +116,6 @@ internal static ChatCompletionNamedToolChoiceFunction FromResponse(PipelineRespo using var document = JsonDocument.Parse(response.Content); return DeserializeChatCompletionNamedToolChoiceFunction(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.cs b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.cs index 383fceef2..44be066fd 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -48,7 +46,7 @@ internal partial class ChatCompletionNamedToolChoiceFunction /// is null. public ChatCompletionNamedToolChoiceFunction(string name) { - ClientUtilities.AssertNotNull(name, nameof(name)); + if (name is null) throw new ArgumentNullException(nameof(name)); Name = name; } @@ -71,3 +69,4 @@ internal ChatCompletionNamedToolChoiceFunction() public string Name { get; } } } + diff --git a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceType.cs b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceType.cs index 8f94a2674..166411eac 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceType.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceType.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public ChatCompletionNamedToolChoiceType(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.Serialization.cs index b467eb421..b819876dc 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class ChatCompletionResponseMessage : IUtf8JsonWriteable, IJsonModel + public partial class ChatCompletionResponseMessage : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -180,13 +176,6 @@ internal static ChatCompletionResponseMessage FromResponse(PipelineResponse resp using var document = JsonDocument.Parse(response.Content); return DeserializeChatCompletionResponseMessage(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.cs b/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.cs index 709a705ff..a27e26e91 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -82,3 +80,4 @@ internal ChatCompletionResponseMessage() public ChatCompletionResponseMessageFunctionCall FunctionCall { get; } } } + diff --git a/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.Serialization.cs index 98aac4cd5..6fd3d045a 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class ChatCompletionResponseMessageFunctionCall : IUtf8JsonWriteable, IJsonModel + public partial class ChatCompletionResponseMessageFunctionCall : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -128,13 +124,6 @@ internal static ChatCompletionResponseMessageFunctionCall FromResponse(PipelineR using var document = JsonDocument.Parse(response.Content); return DeserializeChatCompletionResponseMessageFunctionCall(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.cs b/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.cs index 7f9e8549c..8016f2af6 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -53,8 +51,8 @@ public partial class ChatCompletionResponseMessageFunctionCall /// or is null. internal ChatCompletionResponseMessageFunctionCall(string arguments, string name) { - ClientUtilities.AssertNotNull(arguments, nameof(arguments)); - ClientUtilities.AssertNotNull(name, nameof(name)); + if (arguments is null) throw new ArgumentNullException(nameof(arguments)); + if (name is null) throw new ArgumentNullException(nameof(name)); Arguments = arguments; Name = name; @@ -90,3 +88,4 @@ internal ChatCompletionResponseMessageFunctionCall() public string Name { get; } } } + diff --git a/.dotnet/src/Generated/Models/ChatCompletionResponseMessageRole.cs b/.dotnet/src/Generated/Models/ChatCompletionResponseMessageRole.cs index ee43ccb40..08bcd42a2 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionResponseMessageRole.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionResponseMessageRole.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public ChatCompletionResponseMessageRole(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.Serialization.cs index b80e2c44a..b60cb9ec5 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class ChatCompletionTokenLogprob : IUtf8JsonWriteable, IJsonModel + public partial class ChatCompletionTokenLogprob : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -176,13 +172,6 @@ internal static ChatCompletionTokenLogprob FromResponse(PipelineResponse respons using var document = JsonDocument.Parse(response.Content); return DeserializeChatCompletionTokenLogprob(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.cs b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.cs index 6e487ac5c..bd303c7a2 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; @@ -60,8 +58,8 @@ public partial class ChatCompletionTokenLogprob /// or is null. internal ChatCompletionTokenLogprob(string token, double logprob, IEnumerable bytes, IEnumerable topLogprobs) { - ClientUtilities.AssertNotNull(token, nameof(token)); - ClientUtilities.AssertNotNull(topLogprobs, nameof(topLogprobs)); + if (token is null) throw new ArgumentNullException(nameof(token)); + if (topLogprobs is null) throw new ArgumentNullException(nameof(topLogprobs)); Token = token; Logprob = logprob; @@ -115,3 +113,4 @@ internal ChatCompletionTokenLogprob() public IReadOnlyList TopLogprobs { get; } } } + diff --git a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.Serialization.cs index ab6b52872..b71b5ace6 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class ChatCompletionTokenLogprobTopLogprob : IUtf8JsonWriteable, IJsonModel + public partial class ChatCompletionTokenLogprobTopLogprob : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -158,13 +154,6 @@ internal static ChatCompletionTokenLogprobTopLogprob FromResponse(PipelineRespon using var document = JsonDocument.Parse(response.Content); return DeserializeChatCompletionTokenLogprobTopLogprob(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.cs b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.cs index f0a7c191b..10e36b3a6 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; @@ -56,7 +54,7 @@ public partial class ChatCompletionTokenLogprobTopLogprob /// is null. internal ChatCompletionTokenLogprobTopLogprob(string token, double logprob, IEnumerable bytes) { - ClientUtilities.AssertNotNull(token, nameof(token)); + if (token is null) throw new ArgumentNullException(nameof(token)); Token = token; Logprob = logprob; @@ -99,3 +97,4 @@ internal ChatCompletionTokenLogprobTopLogprob() public IReadOnlyList Bytes { get; } } } + diff --git a/.dotnet/src/Generated/Models/ChatCompletionTool.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionTool.Serialization.cs index 4f0233034..b5913cfcd 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionTool.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionTool.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class ChatCompletionTool : IUtf8JsonWriteable, IJsonModel + public partial class ChatCompletionTool : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -128,13 +124,6 @@ internal static ChatCompletionTool FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeChatCompletionTool(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/ChatCompletionTool.cs b/.dotnet/src/Generated/Models/ChatCompletionTool.cs index c03dc4647..28feedefd 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionTool.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionTool.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -48,7 +46,7 @@ public partial class ChatCompletionTool /// is null. public ChatCompletionTool(FunctionObject function) { - ClientUtilities.AssertNotNull(function, nameof(function)); + if (function is null) throw new ArgumentNullException(nameof(function)); Function = function; } @@ -76,3 +74,4 @@ internal ChatCompletionTool() public FunctionObject Function { get; } } } + diff --git a/.dotnet/src/Generated/Models/ChatCompletionToolType.cs b/.dotnet/src/Generated/Models/ChatCompletionToolType.cs index f1a96376c..b1dae6880 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionToolType.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionToolType.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public ChatCompletionToolType(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CompletionUsage.Serialization.cs b/.dotnet/src/Generated/Models/CompletionUsage.Serialization.cs index ffaa5adcb..5f4745e70 100644 --- a/.dotnet/src/Generated/Models/CompletionUsage.Serialization.cs +++ b/.dotnet/src/Generated/Models/CompletionUsage.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CompletionUsage : IUtf8JsonWriteable, IJsonModel + public partial class CompletionUsage : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -136,13 +132,6 @@ internal static CompletionUsage FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCompletionUsage(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CompletionUsage.cs b/.dotnet/src/Generated/Models/CompletionUsage.cs index 07f38ee8b..440f8ef74 100644 --- a/.dotnet/src/Generated/Models/CompletionUsage.cs +++ b/.dotnet/src/Generated/Models/CompletionUsage.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.Collections.Generic; @@ -79,3 +77,4 @@ internal CompletionUsage() public long TotalTokens { get; } } } + diff --git a/.dotnet/src/Generated/Models/CreateAssistantFileRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateAssistantFileRequest.Serialization.cs index ae5a3b32e..e4d8ef38b 100644 --- a/.dotnet/src/Generated/Models/CreateAssistantFileRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateAssistantFileRequest.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateAssistantFileRequest : IUtf8JsonWriteable, IJsonModel + public partial class CreateAssistantFileRequest : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -120,13 +116,6 @@ internal static CreateAssistantFileRequest FromResponse(PipelineResponse respons using var document = JsonDocument.Parse(response.Content); return DeserializeCreateAssistantFileRequest(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateAssistantFileRequest.cs b/.dotnet/src/Generated/Models/CreateAssistantFileRequest.cs index 8c11246d1..7a7c067c9 100644 --- a/.dotnet/src/Generated/Models/CreateAssistantFileRequest.cs +++ b/.dotnet/src/Generated/Models/CreateAssistantFileRequest.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -51,7 +49,7 @@ public partial class CreateAssistantFileRequest /// is null. public CreateAssistantFileRequest(string fileId) { - ClientUtilities.AssertNotNull(fileId, nameof(fileId)); + if (fileId is null) throw new ArgumentNullException(nameof(fileId)); FileId = fileId; } @@ -80,3 +78,4 @@ internal CreateAssistantFileRequest() public string FileId { get; } } } + diff --git a/.dotnet/src/Generated/Models/CreateAssistantRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateAssistantRequest.Serialization.cs index 8aaa22372..6f034bc1e 100644 --- a/.dotnet/src/Generated/Models/CreateAssistantRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateAssistantRequest.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateAssistantRequest : IUtf8JsonWriteable, IJsonModel + public partial class CreateAssistantRequest : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -291,13 +287,6 @@ internal static CreateAssistantRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateAssistantRequest(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateAssistantRequest.cs b/.dotnet/src/Generated/Models/CreateAssistantRequest.cs index 115fbc0d9..f99c14f37 100644 --- a/.dotnet/src/Generated/Models/CreateAssistantRequest.cs +++ b/.dotnet/src/Generated/Models/CreateAssistantRequest.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -52,7 +50,7 @@ public partial class CreateAssistantRequest /// is null. public CreateAssistantRequest(string model) { - ClientUtilities.AssertNotNull(model, nameof(model)); + if (model is null) throw new ArgumentNullException(nameof(model)); Model = model; Tools = new OptionalList(); @@ -159,3 +157,4 @@ internal CreateAssistantRequest() public IDictionary Metadata { get; set; } } } + diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateChatCompletionRequest.Serialization.cs index 66c50785a..4310faf5b 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionRequest.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateChatCompletionRequest : IUtf8JsonWriteable, IJsonModel + public partial class CreateChatCompletionRequest : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -570,13 +566,6 @@ internal static CreateChatCompletionRequest FromResponse(PipelineResponse respon using var document = JsonDocument.Parse(response.Content); return DeserializeCreateChatCompletionRequest(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionRequest.cs b/.dotnet/src/Generated/Models/CreateChatCompletionRequest.cs index c773e9297..80c7d9be5 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionRequest.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionRequest.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; @@ -56,7 +54,7 @@ public partial class CreateChatCompletionRequest /// is null. public CreateChatCompletionRequest(IEnumerable messages, CreateChatCompletionRequestModel model) { - ClientUtilities.AssertNotNull(messages, nameof(messages)); + if (messages is null) throw new ArgumentNullException(nameof(messages)); Messages = messages.ToList(); Model = model; @@ -510,3 +508,4 @@ internal CreateChatCompletionRequest() public IList Functions { get; } } } + diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionRequestModel.cs b/.dotnet/src/Generated/Models/CreateChatCompletionRequestModel.cs index a0c497c47..5110350bd 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionRequestModel.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -88,3 +86,4 @@ public CreateChatCompletionRequestModel(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.Serialization.cs b/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.Serialization.cs index ecd0ac9b1..8a13529c4 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateChatCompletionRequestResponseFormat : IUtf8JsonWriteable, IJsonModel + public partial class CreateChatCompletionRequestResponseFormat : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -127,13 +123,6 @@ internal static CreateChatCompletionRequestResponseFormat FromResponse(PipelineR using var document = JsonDocument.Parse(response.Content); return DeserializeCreateChatCompletionRequestResponseFormat(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.cs b/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.cs index 5c8f4c2c0..a1dd64235 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.Collections.Generic; @@ -60,3 +58,4 @@ internal CreateChatCompletionRequestResponseFormat(CreateChatCompletionRequestRe public CreateChatCompletionRequestResponseFormatType? Type { get; set; } } } + diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormatType.cs b/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormatType.cs index d0332868f..894f322de 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormatType.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormatType.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -46,3 +44,4 @@ public CreateChatCompletionRequestResponseFormatType(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponse.Serialization.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponse.Serialization.cs index c560aa105..f9c94d1dc 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponse.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateChatCompletionResponse : IUtf8JsonWriteable, IJsonModel + public partial class CreateChatCompletionResponse : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -188,13 +184,6 @@ internal static CreateChatCompletionResponse FromResponse(PipelineResponse respo using var document = JsonDocument.Parse(response.Content); return DeserializeCreateChatCompletionResponse(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponse.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponse.cs index cc16880d8..6476530ae 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionResponse.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponse.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; @@ -52,9 +50,9 @@ public partial class CreateChatCompletionResponse /// , or is null. internal CreateChatCompletionResponse(string id, IEnumerable choices, DateTimeOffset created, string model) { - ClientUtilities.AssertNotNull(id, nameof(id)); - ClientUtilities.AssertNotNull(choices, nameof(choices)); - ClientUtilities.AssertNotNull(model, nameof(model)); + if (id is null) throw new ArgumentNullException(nameof(id)); + if (choices is null) throw new ArgumentNullException(nameof(choices)); + if (model is null) throw new ArgumentNullException(nameof(model)); Id = id; Choices = choices.ToList(); @@ -115,3 +113,4 @@ internal CreateChatCompletionResponse() public CompletionUsage Usage { get; } } } + diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.Serialization.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.Serialization.cs index 8663dced6..5cd85183e 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateChatCompletionResponseChoice : IUtf8JsonWriteable, IJsonModel + public partial class CreateChatCompletionResponseChoice : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -156,13 +152,6 @@ internal static CreateChatCompletionResponseChoice FromResponse(PipelineResponse using var document = JsonDocument.Parse(response.Content); return DeserializeCreateChatCompletionResponseChoice(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.cs index 7a5b8c5c9..17342fc9d 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -57,7 +55,7 @@ public partial class CreateChatCompletionResponseChoice /// is null. internal CreateChatCompletionResponseChoice(CreateChatCompletionResponseChoiceFinishReason finishReason, long index, ChatCompletionResponseMessage message, CreateChatCompletionResponseChoiceLogprobs logprobs) { - ClientUtilities.AssertNotNull(message, nameof(message)); + if (message is null) throw new ArgumentNullException(nameof(message)); FinishReason = finishReason; Index = index; @@ -107,3 +105,4 @@ internal CreateChatCompletionResponseChoice() public CreateChatCompletionResponseChoiceLogprobs Logprobs { get; } } } + diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceFinishReason.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceFinishReason.cs index 65e41895b..e1e180f28 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceFinishReason.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceFinishReason.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -55,3 +53,4 @@ public CreateChatCompletionResponseChoiceFinishReason(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.Serialization.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.Serialization.cs index 8893ed290..6e7b9371a 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateChatCompletionResponseChoiceLogprobs : IUtf8JsonWriteable, IJsonModel + public partial class CreateChatCompletionResponseChoiceLogprobs : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -142,13 +138,6 @@ internal static CreateChatCompletionResponseChoiceLogprobs FromResponse(Pipeline using var document = JsonDocument.Parse(response.Content); return DeserializeCreateChatCompletionResponseChoiceLogprobs(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.cs index 36cc66621..db7e2ef1d 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.Collections.Generic; using System.Linq; @@ -68,3 +66,4 @@ internal CreateChatCompletionResponseChoiceLogprobs() public IReadOnlyList Content { get; } } } + diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponseObject.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponseObject.cs index 3e2747865..e95f7fff6 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionResponseObject.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponseObject.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public CreateChatCompletionResponseObject(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateCompletionRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateCompletionRequest.Serialization.cs index 9d1be276a..e729592b7 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionRequest.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateCompletionRequest : IUtf8JsonWriteable, IJsonModel + public partial class CreateCompletionRequest : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -497,13 +493,6 @@ internal static CreateCompletionRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateCompletionRequest(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateCompletionRequest.cs b/.dotnet/src/Generated/Models/CreateCompletionRequest.cs index 7797fb2a3..65ce00804 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionRequest.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionRequest.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -399,3 +397,4 @@ internal CreateCompletionRequest() public string User { get; set; } } } + diff --git a/.dotnet/src/Generated/Models/CreateCompletionRequestModel.cs b/.dotnet/src/Generated/Models/CreateCompletionRequestModel.cs index 885dde0a4..f0afae0c4 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionRequestModel.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -49,3 +47,4 @@ public CreateCompletionRequestModel(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponse.Serialization.cs b/.dotnet/src/Generated/Models/CreateCompletionResponse.Serialization.cs index 3afa5cb8c..17ea98286 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionResponse.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateCompletionResponse : IUtf8JsonWriteable, IJsonModel + public partial class CreateCompletionResponse : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -188,13 +184,6 @@ internal static CreateCompletionResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateCompletionResponse(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponse.cs b/.dotnet/src/Generated/Models/CreateCompletionResponse.cs index 0d47cab50..944f32b56 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionResponse.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionResponse.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; @@ -55,9 +53,9 @@ public partial class CreateCompletionResponse /// , or is null. internal CreateCompletionResponse(string id, IEnumerable choices, DateTimeOffset created, string model) { - ClientUtilities.AssertNotNull(id, nameof(id)); - ClientUtilities.AssertNotNull(choices, nameof(choices)); - ClientUtilities.AssertNotNull(model, nameof(model)); + if (id is null) throw new ArgumentNullException(nameof(id)); + if (choices is null) throw new ArgumentNullException(nameof(choices)); + if (model is null) throw new ArgumentNullException(nameof(model)); Id = id; Choices = choices.ToList(); @@ -118,3 +116,4 @@ internal CreateCompletionResponse() public CompletionUsage Usage { get; } } } + diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.Serialization.cs b/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.Serialization.cs index d9f0caf93..0f9206ba2 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateCompletionResponseChoice : IUtf8JsonWriteable, IJsonModel + public partial class CreateCompletionResponseChoice : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -156,13 +152,6 @@ internal static CreateCompletionResponseChoice FromResponse(PipelineResponse res using var document = JsonDocument.Parse(response.Content); return DeserializeCreateCompletionResponseChoice(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.cs b/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.cs index b38455976..a0f883635 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -57,7 +55,7 @@ public partial class CreateCompletionResponseChoice /// is null. internal CreateCompletionResponseChoice(long index, string text, CreateCompletionResponseChoiceLogprobs logprobs, CreateCompletionResponseChoiceFinishReason finishReason) { - ClientUtilities.AssertNotNull(text, nameof(text)); + if (text is null) throw new ArgumentNullException(nameof(text)); Index = index; Text = text; @@ -107,3 +105,4 @@ internal CreateCompletionResponseChoice() public CreateCompletionResponseChoiceFinishReason FinishReason { get; } } } + diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceFinishReason.cs b/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceFinishReason.cs index 5071c4a7a..d4ee35578 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceFinishReason.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceFinishReason.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -49,3 +47,4 @@ public CreateCompletionResponseChoiceFinishReason(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.Serialization.cs b/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.Serialization.cs index 89dcafec8..b3ba1559f 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateCompletionResponseChoiceLogprobs : IUtf8JsonWriteable, IJsonModel + public partial class CreateCompletionResponseChoiceLogprobs : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -207,13 +203,6 @@ internal static CreateCompletionResponseChoiceLogprobs FromResponse(PipelineResp using var document = JsonDocument.Parse(response.Content); return DeserializeCreateCompletionResponseChoiceLogprobs(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.cs b/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.cs index 5b88d866b..598ec5916 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; @@ -52,10 +50,10 @@ public partial class CreateCompletionResponseChoiceLogprobs /// , , or is null. internal CreateCompletionResponseChoiceLogprobs(IEnumerable tokens, IEnumerable tokenLogprobs, IEnumerable> topLogprobs, IEnumerable textOffset) { - ClientUtilities.AssertNotNull(tokens, nameof(tokens)); - ClientUtilities.AssertNotNull(tokenLogprobs, nameof(tokenLogprobs)); - ClientUtilities.AssertNotNull(topLogprobs, nameof(topLogprobs)); - ClientUtilities.AssertNotNull(textOffset, nameof(textOffset)); + if (tokens is null) throw new ArgumentNullException(nameof(tokens)); + if (tokenLogprobs is null) throw new ArgumentNullException(nameof(tokenLogprobs)); + if (topLogprobs is null) throw new ArgumentNullException(nameof(topLogprobs)); + if (textOffset is null) throw new ArgumentNullException(nameof(textOffset)); Tokens = tokens.ToList(); TokenLogprobs = tokenLogprobs.ToList(); @@ -93,3 +91,4 @@ internal CreateCompletionResponseChoiceLogprobs() public IReadOnlyList TextOffset { get; } } } + diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponseObject.cs b/.dotnet/src/Generated/Models/CreateCompletionResponseObject.cs index 3185d279a..24c670201 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionResponseObject.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionResponseObject.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public CreateCompletionResponseObject(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateEmbeddingRequest.Serialization.cs index 4601bcc63..7a8ff235b 100644 --- a/.dotnet/src/Generated/Models/CreateEmbeddingRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateEmbeddingRequest.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateEmbeddingRequest : IUtf8JsonWriteable, IJsonModel + public partial class CreateEmbeddingRequest : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -176,13 +172,6 @@ internal static CreateEmbeddingRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateEmbeddingRequest(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingRequest.cs b/.dotnet/src/Generated/Models/CreateEmbeddingRequest.cs index 770cc70db..c2a286d4c 100644 --- a/.dotnet/src/Generated/Models/CreateEmbeddingRequest.cs +++ b/.dotnet/src/Generated/Models/CreateEmbeddingRequest.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -60,7 +58,7 @@ public partial class CreateEmbeddingRequest /// is null. public CreateEmbeddingRequest(BinaryData input, CreateEmbeddingRequestModel model) { - ClientUtilities.AssertNotNull(input, nameof(input)); + if (input is null) throw new ArgumentNullException(nameof(input)); Input = input; Model = model; @@ -184,3 +182,4 @@ internal CreateEmbeddingRequest() public string User { get; set; } } } + diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingRequestEncodingFormat.cs b/.dotnet/src/Generated/Models/CreateEmbeddingRequestEncodingFormat.cs index 23debf648..e252744e4 100644 --- a/.dotnet/src/Generated/Models/CreateEmbeddingRequestEncodingFormat.cs +++ b/.dotnet/src/Generated/Models/CreateEmbeddingRequestEncodingFormat.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -46,3 +44,4 @@ public CreateEmbeddingRequestEncodingFormat(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingRequestModel.cs b/.dotnet/src/Generated/Models/CreateEmbeddingRequestModel.cs index 1b65ef4e0..628de9b7b 100644 --- a/.dotnet/src/Generated/Models/CreateEmbeddingRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateEmbeddingRequestModel.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -49,3 +47,4 @@ public CreateEmbeddingRequestModel(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingResponse.Serialization.cs b/.dotnet/src/Generated/Models/CreateEmbeddingResponse.Serialization.cs index 78595eb7e..84e854405 100644 --- a/.dotnet/src/Generated/Models/CreateEmbeddingResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateEmbeddingResponse.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateEmbeddingResponse : IUtf8JsonWriteable, IJsonModel + public partial class CreateEmbeddingResponse : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -154,13 +150,6 @@ internal static CreateEmbeddingResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateEmbeddingResponse(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingResponse.cs b/.dotnet/src/Generated/Models/CreateEmbeddingResponse.cs index bf7e741ca..ce1b35c17 100644 --- a/.dotnet/src/Generated/Models/CreateEmbeddingResponse.cs +++ b/.dotnet/src/Generated/Models/CreateEmbeddingResponse.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; @@ -51,9 +49,9 @@ public partial class CreateEmbeddingResponse /// , or is null. internal CreateEmbeddingResponse(IEnumerable data, string model, CreateEmbeddingResponseUsage usage) { - ClientUtilities.AssertNotNull(data, nameof(data)); - ClientUtilities.AssertNotNull(model, nameof(model)); - ClientUtilities.AssertNotNull(usage, nameof(usage)); + if (data is null) throw new ArgumentNullException(nameof(data)); + if (model is null) throw new ArgumentNullException(nameof(model)); + if (usage is null) throw new ArgumentNullException(nameof(usage)); Data = data.ToList(); Model = model; @@ -91,3 +89,4 @@ internal CreateEmbeddingResponse() public CreateEmbeddingResponseUsage Usage { get; } } } + diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingResponseObject.cs b/.dotnet/src/Generated/Models/CreateEmbeddingResponseObject.cs index 82ba92eec..b98b10317 100644 --- a/.dotnet/src/Generated/Models/CreateEmbeddingResponseObject.cs +++ b/.dotnet/src/Generated/Models/CreateEmbeddingResponseObject.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public CreateEmbeddingResponseObject(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingResponseUsage.Serialization.cs b/.dotnet/src/Generated/Models/CreateEmbeddingResponseUsage.Serialization.cs index c662893ed..2b10317c0 100644 --- a/.dotnet/src/Generated/Models/CreateEmbeddingResponseUsage.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateEmbeddingResponseUsage.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateEmbeddingResponseUsage : IUtf8JsonWriteable, IJsonModel + public partial class CreateEmbeddingResponseUsage : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -128,13 +124,6 @@ internal static CreateEmbeddingResponseUsage FromResponse(PipelineResponse respo using var document = JsonDocument.Parse(response.Content); return DeserializeCreateEmbeddingResponseUsage(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingResponseUsage.cs b/.dotnet/src/Generated/Models/CreateEmbeddingResponseUsage.cs index d21b5b9e9..bafd0284c 100644 --- a/.dotnet/src/Generated/Models/CreateEmbeddingResponseUsage.cs +++ b/.dotnet/src/Generated/Models/CreateEmbeddingResponseUsage.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.Collections.Generic; @@ -73,3 +71,4 @@ internal CreateEmbeddingResponseUsage() public long TotalTokens { get; } } } + diff --git a/.dotnet/src/Generated/Models/CreateFileRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateFileRequest.Serialization.cs index 6f2012c20..f7d3ba503 100644 --- a/.dotnet/src/Generated/Models/CreateFileRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateFileRequest.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateFileRequest : IUtf8JsonWriteable, IJsonModel + public partial class CreateFileRequest : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -128,13 +124,6 @@ internal static CreateFileRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateFileRequest(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateFileRequest.cs b/.dotnet/src/Generated/Models/CreateFileRequest.cs index 9e10579a6..9475c30af 100644 --- a/.dotnet/src/Generated/Models/CreateFileRequest.cs +++ b/.dotnet/src/Generated/Models/CreateFileRequest.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -54,7 +52,7 @@ public partial class CreateFileRequest /// is null. public CreateFileRequest(BinaryData file, CreateFileRequestPurpose purpose) { - ClientUtilities.AssertNotNull(file, nameof(file)); + if (file is null) throw new ArgumentNullException(nameof(file)); File = file; Purpose = purpose; @@ -107,3 +105,4 @@ internal CreateFileRequest() public CreateFileRequestPurpose Purpose { get; } } } + diff --git a/.dotnet/src/Generated/Models/CreateFileRequestPurpose.cs b/.dotnet/src/Generated/Models/CreateFileRequestPurpose.cs index 866087c3b..51a939757 100644 --- a/.dotnet/src/Generated/Models/CreateFileRequestPurpose.cs +++ b/.dotnet/src/Generated/Models/CreateFileRequestPurpose.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -46,3 +44,4 @@ public CreateFileRequestPurpose(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.Serialization.cs index 6d26b67fc..08d63808e 100644 --- a/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateFineTuningJobRequest : IUtf8JsonWriteable, IJsonModel + public partial class CreateFineTuningJobRequest : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -189,13 +185,6 @@ internal static CreateFineTuningJobRequest FromResponse(PipelineResponse respons using var document = JsonDocument.Parse(response.Content); return DeserializeCreateFineTuningJobRequest(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.cs b/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.cs index 7157e813c..618e6069d 100644 --- a/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.cs +++ b/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -61,7 +59,7 @@ public partial class CreateFineTuningJobRequest /// is null. public CreateFineTuningJobRequest(string trainingFile, CreateFineTuningJobRequestModel model) { - ClientUtilities.AssertNotNull(trainingFile, nameof(trainingFile)); + if (trainingFile is null) throw new ArgumentNullException(nameof(trainingFile)); TrainingFile = trainingFile; Model = model; @@ -157,3 +155,4 @@ internal CreateFineTuningJobRequest() public string Suffix { get; set; } } } + diff --git a/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.Serialization.cs b/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.Serialization.cs index de057600c..98b42074d 100644 --- a/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateFineTuningJobRequestHyperparameters : IUtf8JsonWriteable, IJsonModel + public partial class CreateFineTuningJobRequestHyperparameters : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -134,13 +130,6 @@ internal static CreateFineTuningJobRequestHyperparameters FromResponse(PipelineR using var document = JsonDocument.Parse(response.Content); return DeserializeCreateFineTuningJobRequestHyperparameters(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.cs b/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.cs index 258881cb0..8094fc378 100644 --- a/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.cs +++ b/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.Collections.Generic; @@ -104,3 +102,4 @@ internal CreateFineTuningJobRequestHyperparameters(BinaryData nEpochs, IDictiona public BinaryData NEpochs { get; set; } } } + diff --git a/.dotnet/src/Generated/Models/CreateFineTuningJobRequestModel.cs b/.dotnet/src/Generated/Models/CreateFineTuningJobRequestModel.cs index ef3c6ec0c..e36868cc4 100644 --- a/.dotnet/src/Generated/Models/CreateFineTuningJobRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateFineTuningJobRequestModel.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -49,3 +47,4 @@ public CreateFineTuningJobRequestModel(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateImageEditRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateImageEditRequest.Serialization.cs index cc8938c1f..9de7cccac 100644 --- a/.dotnet/src/Generated/Models/CreateImageEditRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateImageEditRequest.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateImageEditRequest : IUtf8JsonWriteable, IJsonModel + public partial class CreateImageEditRequest : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -222,13 +218,6 @@ internal static CreateImageEditRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateImageEditRequest(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateImageEditRequest.cs b/.dotnet/src/Generated/Models/CreateImageEditRequest.cs index 12f245f91..5b78b294b 100644 --- a/.dotnet/src/Generated/Models/CreateImageEditRequest.cs +++ b/.dotnet/src/Generated/Models/CreateImageEditRequest.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -52,8 +50,8 @@ public partial class CreateImageEditRequest /// or is null. public CreateImageEditRequest(BinaryData image, string prompt) { - ClientUtilities.AssertNotNull(image, nameof(image)); - ClientUtilities.AssertNotNull(prompt, nameof(prompt)); + if (image is null) throw new ArgumentNullException(nameof(image)); + if (prompt is null) throw new ArgumentNullException(nameof(prompt)); Image = image; Prompt = prompt; @@ -151,3 +149,4 @@ internal CreateImageEditRequest() public string User { get; set; } } } + diff --git a/.dotnet/src/Generated/Models/CreateImageEditRequestModel.cs b/.dotnet/src/Generated/Models/CreateImageEditRequestModel.cs index 152466ce3..946936edb 100644 --- a/.dotnet/src/Generated/Models/CreateImageEditRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateImageEditRequestModel.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public CreateImageEditRequestModel(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateImageEditRequestResponseFormat.cs b/.dotnet/src/Generated/Models/CreateImageEditRequestResponseFormat.cs index 2dfc96644..b398ca63d 100644 --- a/.dotnet/src/Generated/Models/CreateImageEditRequestResponseFormat.cs +++ b/.dotnet/src/Generated/Models/CreateImageEditRequestResponseFormat.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -46,3 +44,4 @@ public CreateImageEditRequestResponseFormat(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateImageEditRequestSize.cs b/.dotnet/src/Generated/Models/CreateImageEditRequestSize.cs index 01c9a4c45..8e644e852 100644 --- a/.dotnet/src/Generated/Models/CreateImageEditRequestSize.cs +++ b/.dotnet/src/Generated/Models/CreateImageEditRequestSize.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -49,3 +47,4 @@ public CreateImageEditRequestSize(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateImageRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateImageRequest.Serialization.cs index f790166ff..74b4555fc 100644 --- a/.dotnet/src/Generated/Models/CreateImageRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateImageRequest.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateImageRequest : IUtf8JsonWriteable, IJsonModel + public partial class CreateImageRequest : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -229,13 +225,6 @@ internal static CreateImageRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateImageRequest(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateImageRequest.cs b/.dotnet/src/Generated/Models/CreateImageRequest.cs index bde1c78ba..0ddf94adb 100644 --- a/.dotnet/src/Generated/Models/CreateImageRequest.cs +++ b/.dotnet/src/Generated/Models/CreateImageRequest.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -51,7 +49,7 @@ public partial class CreateImageRequest /// is null. public CreateImageRequest(string prompt) { - ClientUtilities.AssertNotNull(prompt, nameof(prompt)); + if (prompt is null) throw new ArgumentNullException(nameof(prompt)); Prompt = prompt; } @@ -140,3 +138,4 @@ internal CreateImageRequest() public string User { get; set; } } } + diff --git a/.dotnet/src/Generated/Models/CreateImageRequestModel.cs b/.dotnet/src/Generated/Models/CreateImageRequestModel.cs index 46d224028..e6401986c 100644 --- a/.dotnet/src/Generated/Models/CreateImageRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateImageRequestModel.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -46,3 +44,4 @@ public CreateImageRequestModel(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateImageRequestQuality.cs b/.dotnet/src/Generated/Models/CreateImageRequestQuality.cs index e3a737c23..236be9ebf 100644 --- a/.dotnet/src/Generated/Models/CreateImageRequestQuality.cs +++ b/.dotnet/src/Generated/Models/CreateImageRequestQuality.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -46,3 +44,4 @@ public CreateImageRequestQuality(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateImageRequestResponseFormat.cs b/.dotnet/src/Generated/Models/CreateImageRequestResponseFormat.cs index 5990ab315..e7f95d5ee 100644 --- a/.dotnet/src/Generated/Models/CreateImageRequestResponseFormat.cs +++ b/.dotnet/src/Generated/Models/CreateImageRequestResponseFormat.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -46,3 +44,4 @@ public CreateImageRequestResponseFormat(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateImageRequestSize.cs b/.dotnet/src/Generated/Models/CreateImageRequestSize.cs index df73f6aac..091e4d3b0 100644 --- a/.dotnet/src/Generated/Models/CreateImageRequestSize.cs +++ b/.dotnet/src/Generated/Models/CreateImageRequestSize.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -55,3 +53,4 @@ public CreateImageRequestSize(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateImageRequestStyle.cs b/.dotnet/src/Generated/Models/CreateImageRequestStyle.cs index a711e0635..98f67425f 100644 --- a/.dotnet/src/Generated/Models/CreateImageRequestStyle.cs +++ b/.dotnet/src/Generated/Models/CreateImageRequestStyle.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -46,3 +44,4 @@ public CreateImageRequestStyle(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateImageVariationRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateImageVariationRequest.Serialization.cs index bd3a103fb..642a6c439 100644 --- a/.dotnet/src/Generated/Models/CreateImageVariationRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateImageVariationRequest.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateImageVariationRequest : IUtf8JsonWriteable, IJsonModel + public partial class CreateImageVariationRequest : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -199,13 +195,6 @@ internal static CreateImageVariationRequest FromResponse(PipelineResponse respon using var document = JsonDocument.Parse(response.Content); return DeserializeCreateImageVariationRequest(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateImageVariationRequest.cs b/.dotnet/src/Generated/Models/CreateImageVariationRequest.cs index f1c52762f..a034e2faa 100644 --- a/.dotnet/src/Generated/Models/CreateImageVariationRequest.cs +++ b/.dotnet/src/Generated/Models/CreateImageVariationRequest.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -51,7 +49,7 @@ public partial class CreateImageVariationRequest /// is null. public CreateImageVariationRequest(BinaryData image) { - ClientUtilities.AssertNotNull(image, nameof(image)); + if (image is null) throw new ArgumentNullException(nameof(image)); Image = image; } @@ -119,3 +117,4 @@ internal CreateImageVariationRequest() public string User { get; set; } } } + diff --git a/.dotnet/src/Generated/Models/CreateImageVariationRequestModel.cs b/.dotnet/src/Generated/Models/CreateImageVariationRequestModel.cs index e1fb70037..d40886648 100644 --- a/.dotnet/src/Generated/Models/CreateImageVariationRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateImageVariationRequestModel.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public CreateImageVariationRequestModel(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateImageVariationRequestResponseFormat.cs b/.dotnet/src/Generated/Models/CreateImageVariationRequestResponseFormat.cs index 2c384bb1f..94f353a25 100644 --- a/.dotnet/src/Generated/Models/CreateImageVariationRequestResponseFormat.cs +++ b/.dotnet/src/Generated/Models/CreateImageVariationRequestResponseFormat.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -46,3 +44,4 @@ public CreateImageVariationRequestResponseFormat(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateImageVariationRequestSize.cs b/.dotnet/src/Generated/Models/CreateImageVariationRequestSize.cs index 50f61d60c..0374c3214 100644 --- a/.dotnet/src/Generated/Models/CreateImageVariationRequestSize.cs +++ b/.dotnet/src/Generated/Models/CreateImageVariationRequestSize.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -49,3 +47,4 @@ public CreateImageVariationRequestSize(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateMessageRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateMessageRequest.Serialization.cs index f8cdabd45..3386db660 100644 --- a/.dotnet/src/Generated/Models/CreateMessageRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateMessageRequest.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateMessageRequest : IUtf8JsonWriteable, IJsonModel + public partial class CreateMessageRequest : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -186,13 +182,6 @@ internal static CreateMessageRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateMessageRequest(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateMessageRequest.cs b/.dotnet/src/Generated/Models/CreateMessageRequest.cs index 63200e048..7d2855a9f 100644 --- a/.dotnet/src/Generated/Models/CreateMessageRequest.cs +++ b/.dotnet/src/Generated/Models/CreateMessageRequest.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -48,7 +46,7 @@ public partial class CreateMessageRequest /// is null. public CreateMessageRequest(string content) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); Content = content; FileIds = new OptionalList(); @@ -102,3 +100,4 @@ internal CreateMessageRequest() public IDictionary Metadata { get; set; } } } + diff --git a/.dotnet/src/Generated/Models/CreateMessageRequestRole.cs b/.dotnet/src/Generated/Models/CreateMessageRequestRole.cs index 2f7ae075a..f5be49786 100644 --- a/.dotnet/src/Generated/Models/CreateMessageRequestRole.cs +++ b/.dotnet/src/Generated/Models/CreateMessageRequestRole.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public CreateMessageRequestRole(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateModerationRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateModerationRequest.Serialization.cs index d7d7cac14..50c0cf4f7 100644 --- a/.dotnet/src/Generated/Models/CreateModerationRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateModerationRequest.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateModerationRequest : IUtf8JsonWriteable, IJsonModel + public partial class CreateModerationRequest : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -142,13 +138,6 @@ internal static CreateModerationRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateModerationRequest(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateModerationRequest.cs b/.dotnet/src/Generated/Models/CreateModerationRequest.cs index 3192ceea7..b92114f96 100644 --- a/.dotnet/src/Generated/Models/CreateModerationRequest.cs +++ b/.dotnet/src/Generated/Models/CreateModerationRequest.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -48,7 +46,7 @@ public partial class CreateModerationRequest /// is null. public CreateModerationRequest(BinaryData input) { - ClientUtilities.AssertNotNull(input, nameof(input)); + if (input is null) throw new ArgumentNullException(nameof(input)); Input = input; } @@ -127,3 +125,4 @@ internal CreateModerationRequest() public CreateModerationRequestModel? Model { get; set; } } } + diff --git a/.dotnet/src/Generated/Models/CreateModerationRequestModel.cs b/.dotnet/src/Generated/Models/CreateModerationRequestModel.cs index fcc067e02..af410f3a0 100644 --- a/.dotnet/src/Generated/Models/CreateModerationRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateModerationRequestModel.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -46,3 +44,4 @@ public CreateModerationRequestModel(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateModerationResponse.Serialization.cs b/.dotnet/src/Generated/Models/CreateModerationResponse.Serialization.cs index 95902ce14..1d3fd1188 100644 --- a/.dotnet/src/Generated/Models/CreateModerationResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateModerationResponse.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateModerationResponse : IUtf8JsonWriteable, IJsonModel + public partial class CreateModerationResponse : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -146,13 +142,6 @@ internal static CreateModerationResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateModerationResponse(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateModerationResponse.cs b/.dotnet/src/Generated/Models/CreateModerationResponse.cs index 7fe06f011..caf0c4858 100644 --- a/.dotnet/src/Generated/Models/CreateModerationResponse.cs +++ b/.dotnet/src/Generated/Models/CreateModerationResponse.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; @@ -51,9 +49,9 @@ public partial class CreateModerationResponse /// , or is null. internal CreateModerationResponse(string id, string model, IEnumerable results) { - ClientUtilities.AssertNotNull(id, nameof(id)); - ClientUtilities.AssertNotNull(model, nameof(model)); - ClientUtilities.AssertNotNull(results, nameof(results)); + if (id is null) throw new ArgumentNullException(nameof(id)); + if (model is null) throw new ArgumentNullException(nameof(model)); + if (results is null) throw new ArgumentNullException(nameof(results)); Id = id; Model = model; @@ -86,3 +84,4 @@ internal CreateModerationResponse() public IReadOnlyList Results { get; } } } + diff --git a/.dotnet/src/Generated/Models/CreateModerationResponseResult.Serialization.cs b/.dotnet/src/Generated/Models/CreateModerationResponseResult.Serialization.cs index 6c56b94e2..edabb3d30 100644 --- a/.dotnet/src/Generated/Models/CreateModerationResponseResult.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateModerationResponseResult.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateModerationResponseResult : IUtf8JsonWriteable, IJsonModel + public partial class CreateModerationResponseResult : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -136,13 +132,6 @@ internal static CreateModerationResponseResult FromResponse(PipelineResponse res using var document = JsonDocument.Parse(response.Content); return DeserializeCreateModerationResponseResult(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateModerationResponseResult.cs b/.dotnet/src/Generated/Models/CreateModerationResponseResult.cs index 3842b8365..d3abebbc3 100644 --- a/.dotnet/src/Generated/Models/CreateModerationResponseResult.cs +++ b/.dotnet/src/Generated/Models/CreateModerationResponseResult.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -50,8 +48,8 @@ public partial class CreateModerationResponseResult /// or is null. internal CreateModerationResponseResult(bool flagged, CreateModerationResponseResultCategories categories, CreateModerationResponseResultCategoryScores categoryScores) { - ClientUtilities.AssertNotNull(categories, nameof(categories)); - ClientUtilities.AssertNotNull(categoryScores, nameof(categoryScores)); + if (categories is null) throw new ArgumentNullException(nameof(categories)); + if (categoryScores is null) throw new ArgumentNullException(nameof(categoryScores)); Flagged = flagged; Categories = categories; @@ -84,3 +82,4 @@ internal CreateModerationResponseResult() public CreateModerationResponseResultCategoryScores CategoryScores { get; } } } + diff --git a/.dotnet/src/Generated/Models/CreateModerationResponseResultCategories.Serialization.cs b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategories.Serialization.cs index 53595dc4a..5dce74b53 100644 --- a/.dotnet/src/Generated/Models/CreateModerationResponseResultCategories.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategories.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateModerationResponseResultCategories : IUtf8JsonWriteable, IJsonModel + public partial class CreateModerationResponseResultCategories : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -200,13 +196,6 @@ internal static CreateModerationResponseResultCategories FromResponse(PipelineRe using var document = JsonDocument.Parse(response.Content); return DeserializeCreateModerationResponseResultCategories(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateModerationResponseResultCategories.cs b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategories.cs index fdb93fb6c..8af6aa519 100644 --- a/.dotnet/src/Generated/Models/CreateModerationResponseResultCategories.cs +++ b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategories.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.Collections.Generic; @@ -187,3 +185,4 @@ internal CreateModerationResponseResultCategories() public bool ViolenceGraphic { get; } } } + diff --git a/.dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.Serialization.cs b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.Serialization.cs index 2c169bdec..50b22a9d6 100644 --- a/.dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateModerationResponseResultCategoryScores : IUtf8JsonWriteable, IJsonModel + public partial class CreateModerationResponseResultCategoryScores : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -200,13 +196,6 @@ internal static CreateModerationResponseResultCategoryScores FromResponse(Pipeli using var document = JsonDocument.Parse(response.Content); return DeserializeCreateModerationResponseResultCategoryScores(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.cs b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.cs index 2e5247ddb..0ee6e8d5a 100644 --- a/.dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.cs +++ b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.Collections.Generic; @@ -127,3 +125,4 @@ internal CreateModerationResponseResultCategoryScores() public double ViolenceGraphic { get; } } } + diff --git a/.dotnet/src/Generated/Models/CreateRunRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateRunRequest.Serialization.cs index 33e243bc6..4eda947a7 100644 --- a/.dotnet/src/Generated/Models/CreateRunRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateRunRequest.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateRunRequest : IUtf8JsonWriteable, IJsonModel + public partial class CreateRunRequest : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -273,13 +269,6 @@ internal static CreateRunRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateRunRequest(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateRunRequest.cs b/.dotnet/src/Generated/Models/CreateRunRequest.cs index 25e22310d..ea2ac5123 100644 --- a/.dotnet/src/Generated/Models/CreateRunRequest.cs +++ b/.dotnet/src/Generated/Models/CreateRunRequest.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -48,7 +46,7 @@ public partial class CreateRunRequest /// is null. public CreateRunRequest(string assistantId) { - ClientUtilities.AssertNotNull(assistantId, nameof(assistantId)); + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); AssistantId = assistantId; Tools = new OptionalList(); @@ -154,3 +152,4 @@ internal CreateRunRequest() public IDictionary Metadata { get; set; } } } + diff --git a/.dotnet/src/Generated/Models/CreateSpeechRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateSpeechRequest.Serialization.cs index 299ac0668..f2216a6e1 100644 --- a/.dotnet/src/Generated/Models/CreateSpeechRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateSpeechRequest.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateSpeechRequest : IUtf8JsonWriteable, IJsonModel + public partial class CreateSpeechRequest : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -166,13 +162,6 @@ internal static CreateSpeechRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateSpeechRequest(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateSpeechRequest.cs b/.dotnet/src/Generated/Models/CreateSpeechRequest.cs index ac765143c..eb2c71ae0 100644 --- a/.dotnet/src/Generated/Models/CreateSpeechRequest.cs +++ b/.dotnet/src/Generated/Models/CreateSpeechRequest.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -54,7 +52,7 @@ public partial class CreateSpeechRequest /// is null. public CreateSpeechRequest(CreateSpeechRequestModel model, string input, CreateSpeechRequestVoice voice) { - ClientUtilities.AssertNotNull(input, nameof(input)); + if (input is null) throw new ArgumentNullException(nameof(input)); Model = model; Input = input; @@ -103,3 +101,4 @@ internal CreateSpeechRequest() public double? Speed { get; set; } } } + diff --git a/.dotnet/src/Generated/Models/CreateSpeechRequestModel.cs b/.dotnet/src/Generated/Models/CreateSpeechRequestModel.cs index 0db564d08..590078a92 100644 --- a/.dotnet/src/Generated/Models/CreateSpeechRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateSpeechRequestModel.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -46,3 +44,4 @@ public CreateSpeechRequestModel(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateSpeechRequestResponseFormat.cs b/.dotnet/src/Generated/Models/CreateSpeechRequestResponseFormat.cs index ca5b8462f..4694fe9d7 100644 --- a/.dotnet/src/Generated/Models/CreateSpeechRequestResponseFormat.cs +++ b/.dotnet/src/Generated/Models/CreateSpeechRequestResponseFormat.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -52,3 +50,4 @@ public CreateSpeechRequestResponseFormat(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateSpeechRequestVoice.cs b/.dotnet/src/Generated/Models/CreateSpeechRequestVoice.cs index db9af9d9d..e764eed85 100644 --- a/.dotnet/src/Generated/Models/CreateSpeechRequestVoice.cs +++ b/.dotnet/src/Generated/Models/CreateSpeechRequestVoice.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -58,3 +56,4 @@ public CreateSpeechRequestVoice(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.Serialization.cs index 8710e7c9a..384147a67 100644 --- a/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateThreadAndRunRequest : IUtf8JsonWriteable, IJsonModel + public partial class CreateThreadAndRunRequest : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -265,13 +261,6 @@ internal static CreateThreadAndRunRequest FromResponse(PipelineResponse response using var document = JsonDocument.Parse(response.Content); return DeserializeCreateThreadAndRunRequest(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.cs b/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.cs index cffca99a7..b212c90c5 100644 --- a/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.cs +++ b/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -48,7 +46,7 @@ public partial class CreateThreadAndRunRequest /// is null. public CreateThreadAndRunRequest(string assistantId) { - ClientUtilities.AssertNotNull(assistantId, nameof(assistantId)); + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); AssistantId = assistantId; Tools = new OptionalList(); @@ -148,3 +146,4 @@ internal CreateThreadAndRunRequest() public IDictionary Metadata { get; set; } } } + diff --git a/.dotnet/src/Generated/Models/CreateThreadRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateThreadRequest.Serialization.cs index e321794d2..b899f1a9d 100644 --- a/.dotnet/src/Generated/Models/CreateThreadRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateThreadRequest.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateThreadRequest : IUtf8JsonWriteable, IJsonModel + public partial class CreateThreadRequest : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -170,13 +166,6 @@ internal static CreateThreadRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateThreadRequest(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateThreadRequest.cs b/.dotnet/src/Generated/Models/CreateThreadRequest.cs index b59545b62..a31999cb7 100644 --- a/.dotnet/src/Generated/Models/CreateThreadRequest.cs +++ b/.dotnet/src/Generated/Models/CreateThreadRequest.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -75,3 +73,4 @@ internal CreateThreadRequest(IList messages, IDictionary Metadata { get; set; } } } + diff --git a/.dotnet/src/Generated/Models/CreateTranscriptionRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateTranscriptionRequest.Serialization.cs index 8b89df137..8aa3b8a97 100644 --- a/.dotnet/src/Generated/Models/CreateTranscriptionRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateTranscriptionRequest.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateTranscriptionRequest : IUtf8JsonWriteable, IJsonModel + public partial class CreateTranscriptionRequest : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -180,13 +176,6 @@ internal static CreateTranscriptionRequest FromResponse(PipelineResponse respons using var document = JsonDocument.Parse(response.Content); return DeserializeCreateTranscriptionRequest(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateTranscriptionRequest.cs b/.dotnet/src/Generated/Models/CreateTranscriptionRequest.cs index 74d9d5ebd..7cccd2c15 100644 --- a/.dotnet/src/Generated/Models/CreateTranscriptionRequest.cs +++ b/.dotnet/src/Generated/Models/CreateTranscriptionRequest.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -52,7 +50,7 @@ public partial class CreateTranscriptionRequest /// is null. public CreateTranscriptionRequest(BinaryData file, CreateTranscriptionRequestModel model) { - ClientUtilities.AssertNotNull(file, nameof(file)); + if (file is null) throw new ArgumentNullException(nameof(file)); File = file; Model = model; @@ -145,3 +143,4 @@ internal CreateTranscriptionRequest() public double? Temperature { get; set; } } } + diff --git a/.dotnet/src/Generated/Models/CreateTranscriptionRequestModel.cs b/.dotnet/src/Generated/Models/CreateTranscriptionRequestModel.cs index d3c46e425..c4639fe72 100644 --- a/.dotnet/src/Generated/Models/CreateTranscriptionRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateTranscriptionRequestModel.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public CreateTranscriptionRequestModel(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateTranscriptionRequestResponseFormat.cs b/.dotnet/src/Generated/Models/CreateTranscriptionRequestResponseFormat.cs index 354321879..1eb2b8b48 100644 --- a/.dotnet/src/Generated/Models/CreateTranscriptionRequestResponseFormat.cs +++ b/.dotnet/src/Generated/Models/CreateTranscriptionRequestResponseFormat.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -55,3 +53,4 @@ public CreateTranscriptionRequestResponseFormat(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateTranscriptionResponse.Serialization.cs b/.dotnet/src/Generated/Models/CreateTranscriptionResponse.Serialization.cs index 7ebe36e6c..0052a0f0b 100644 --- a/.dotnet/src/Generated/Models/CreateTranscriptionResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateTranscriptionResponse.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateTranscriptionResponse : IUtf8JsonWriteable, IJsonModel + public partial class CreateTranscriptionResponse : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -186,13 +182,6 @@ internal static CreateTranscriptionResponse FromResponse(PipelineResponse respon using var document = JsonDocument.Parse(response.Content); return DeserializeCreateTranscriptionResponse(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateTranscriptionResponse.cs b/.dotnet/src/Generated/Models/CreateTranscriptionResponse.cs index c526f24a1..47f9428ca 100644 --- a/.dotnet/src/Generated/Models/CreateTranscriptionResponse.cs +++ b/.dotnet/src/Generated/Models/CreateTranscriptionResponse.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -48,7 +46,7 @@ public partial class CreateTranscriptionResponse /// is null. internal CreateTranscriptionResponse(string text) { - ClientUtilities.AssertNotNull(text, nameof(text)); + if (text is null) throw new ArgumentNullException(nameof(text)); Text = text; Segments = new OptionalList(); @@ -94,3 +92,4 @@ internal CreateTranscriptionResponse() public IReadOnlyList Segments { get; } } } + diff --git a/.dotnet/src/Generated/Models/CreateTranscriptionResponseTask.cs b/.dotnet/src/Generated/Models/CreateTranscriptionResponseTask.cs index 2cf79c9ae..45bb38166 100644 --- a/.dotnet/src/Generated/Models/CreateTranscriptionResponseTask.cs +++ b/.dotnet/src/Generated/Models/CreateTranscriptionResponseTask.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public CreateTranscriptionResponseTask(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateTranslationRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateTranslationRequest.Serialization.cs index 2e29df2c7..2b415a177 100644 --- a/.dotnet/src/Generated/Models/CreateTranslationRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateTranslationRequest.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateTranslationRequest : IUtf8JsonWriteable, IJsonModel + public partial class CreateTranslationRequest : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -169,13 +165,6 @@ internal static CreateTranslationRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateTranslationRequest(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateTranslationRequest.cs b/.dotnet/src/Generated/Models/CreateTranslationRequest.cs index 6ee7db49a..fa5224a3e 100644 --- a/.dotnet/src/Generated/Models/CreateTranslationRequest.cs +++ b/.dotnet/src/Generated/Models/CreateTranslationRequest.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -52,7 +50,7 @@ public partial class CreateTranslationRequest /// is null. public CreateTranslationRequest(BinaryData file, CreateTranslationRequestModel model) { - ClientUtilities.AssertNotNull(file, nameof(file)); + if (file is null) throw new ArgumentNullException(nameof(file)); File = file; Model = model; @@ -133,3 +131,4 @@ internal CreateTranslationRequest() public double? Temperature { get; set; } } } + diff --git a/.dotnet/src/Generated/Models/CreateTranslationRequestModel.cs b/.dotnet/src/Generated/Models/CreateTranslationRequestModel.cs index b9d4c7076..10536d253 100644 --- a/.dotnet/src/Generated/Models/CreateTranslationRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateTranslationRequestModel.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public CreateTranslationRequestModel(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateTranslationRequestResponseFormat.cs b/.dotnet/src/Generated/Models/CreateTranslationRequestResponseFormat.cs index b24279e3c..7c9a6ff50 100644 --- a/.dotnet/src/Generated/Models/CreateTranslationRequestResponseFormat.cs +++ b/.dotnet/src/Generated/Models/CreateTranslationRequestResponseFormat.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -55,3 +53,4 @@ public CreateTranslationRequestResponseFormat(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/CreateTranslationResponse.Serialization.cs b/.dotnet/src/Generated/Models/CreateTranslationResponse.Serialization.cs index 917fbfd99..10254dee9 100644 --- a/.dotnet/src/Generated/Models/CreateTranslationResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateTranslationResponse.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class CreateTranslationResponse : IUtf8JsonWriteable, IJsonModel + public partial class CreateTranslationResponse : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -186,13 +182,6 @@ internal static CreateTranslationResponse FromResponse(PipelineResponse response using var document = JsonDocument.Parse(response.Content); return DeserializeCreateTranslationResponse(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/CreateTranslationResponse.cs b/.dotnet/src/Generated/Models/CreateTranslationResponse.cs index c6c9ea458..bc4f03097 100644 --- a/.dotnet/src/Generated/Models/CreateTranslationResponse.cs +++ b/.dotnet/src/Generated/Models/CreateTranslationResponse.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -48,7 +46,7 @@ public partial class CreateTranslationResponse /// is null. internal CreateTranslationResponse(string text) { - ClientUtilities.AssertNotNull(text, nameof(text)); + if (text is null) throw new ArgumentNullException(nameof(text)); Text = text; Segments = new OptionalList(); @@ -94,3 +92,4 @@ internal CreateTranslationResponse() public IReadOnlyList Segments { get; } } } + diff --git a/.dotnet/src/Generated/Models/CreateTranslationResponseTask.cs b/.dotnet/src/Generated/Models/CreateTranslationResponseTask.cs index 4104c9b1c..fe24f6343 100644 --- a/.dotnet/src/Generated/Models/CreateTranslationResponseTask.cs +++ b/.dotnet/src/Generated/Models/CreateTranslationResponseTask.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public CreateTranslationResponseTask(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.Serialization.cs b/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.Serialization.cs index 2f92de865..997b39d80 100644 --- a/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class DeleteAssistantFileResponse : IUtf8JsonWriteable, IJsonModel + public partial class DeleteAssistantFileResponse : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -136,13 +132,6 @@ internal static DeleteAssistantFileResponse FromResponse(PipelineResponse respon using var document = JsonDocument.Parse(response.Content); return DeserializeDeleteAssistantFileResponse(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.cs b/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.cs index 478d175d2..2172613e2 100644 --- a/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.cs +++ b/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -52,7 +50,7 @@ public partial class DeleteAssistantFileResponse /// is null. internal DeleteAssistantFileResponse(string id, bool deleted) { - ClientUtilities.AssertNotNull(id, nameof(id)); + if (id is null) throw new ArgumentNullException(nameof(id)); Id = id; Deleted = deleted; @@ -84,3 +82,4 @@ internal DeleteAssistantFileResponse() public DeleteAssistantFileResponseObject Object { get; } = DeleteAssistantFileResponseObject.AssistantFileDeleted; } } + diff --git a/.dotnet/src/Generated/Models/DeleteAssistantFileResponseObject.cs b/.dotnet/src/Generated/Models/DeleteAssistantFileResponseObject.cs index 8f9d146db..df0a1e5a6 100644 --- a/.dotnet/src/Generated/Models/DeleteAssistantFileResponseObject.cs +++ b/.dotnet/src/Generated/Models/DeleteAssistantFileResponseObject.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public DeleteAssistantFileResponseObject(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/DeleteAssistantResponse.Serialization.cs b/.dotnet/src/Generated/Models/DeleteAssistantResponse.Serialization.cs index da95808b9..7b575f777 100644 --- a/.dotnet/src/Generated/Models/DeleteAssistantResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/DeleteAssistantResponse.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class DeleteAssistantResponse : IUtf8JsonWriteable, IJsonModel + public partial class DeleteAssistantResponse : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -136,13 +132,6 @@ internal static DeleteAssistantResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeDeleteAssistantResponse(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/DeleteAssistantResponse.cs b/.dotnet/src/Generated/Models/DeleteAssistantResponse.cs index 059769a28..4ce652ffd 100644 --- a/.dotnet/src/Generated/Models/DeleteAssistantResponse.cs +++ b/.dotnet/src/Generated/Models/DeleteAssistantResponse.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -49,7 +47,7 @@ public partial class DeleteAssistantResponse /// is null. internal DeleteAssistantResponse(string id, bool deleted) { - ClientUtilities.AssertNotNull(id, nameof(id)); + if (id is null) throw new ArgumentNullException(nameof(id)); Id = id; Deleted = deleted; @@ -81,3 +79,4 @@ internal DeleteAssistantResponse() public DeleteAssistantResponseObject Object { get; } = DeleteAssistantResponseObject.AssistantDeleted; } } + diff --git a/.dotnet/src/Generated/Models/DeleteAssistantResponseObject.cs b/.dotnet/src/Generated/Models/DeleteAssistantResponseObject.cs index 7c80077ca..4ce063190 100644 --- a/.dotnet/src/Generated/Models/DeleteAssistantResponseObject.cs +++ b/.dotnet/src/Generated/Models/DeleteAssistantResponseObject.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public DeleteAssistantResponseObject(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/DeleteFileResponse.Serialization.cs b/.dotnet/src/Generated/Models/DeleteFileResponse.Serialization.cs index 6ed78cf28..21416fc19 100644 --- a/.dotnet/src/Generated/Models/DeleteFileResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/DeleteFileResponse.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class DeleteFileResponse : IUtf8JsonWriteable, IJsonModel + public partial class DeleteFileResponse : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -136,13 +132,6 @@ internal static DeleteFileResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeDeleteFileResponse(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/DeleteFileResponse.cs b/.dotnet/src/Generated/Models/DeleteFileResponse.cs index 202cb2637..06777ae53 100644 --- a/.dotnet/src/Generated/Models/DeleteFileResponse.cs +++ b/.dotnet/src/Generated/Models/DeleteFileResponse.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -49,7 +47,7 @@ public partial class DeleteFileResponse /// is null. internal DeleteFileResponse(string id, bool deleted) { - ClientUtilities.AssertNotNull(id, nameof(id)); + if (id is null) throw new ArgumentNullException(nameof(id)); Id = id; Deleted = deleted; @@ -82,3 +80,4 @@ internal DeleteFileResponse() public bool Deleted { get; } } } + diff --git a/.dotnet/src/Generated/Models/DeleteFileResponseObject.cs b/.dotnet/src/Generated/Models/DeleteFileResponseObject.cs index 8b8080a6a..3f25d59f3 100644 --- a/.dotnet/src/Generated/Models/DeleteFileResponseObject.cs +++ b/.dotnet/src/Generated/Models/DeleteFileResponseObject.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public DeleteFileResponseObject(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/DeleteModelResponse.Serialization.cs b/.dotnet/src/Generated/Models/DeleteModelResponse.Serialization.cs index a16d26d8b..e1865ef13 100644 --- a/.dotnet/src/Generated/Models/DeleteModelResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/DeleteModelResponse.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class DeleteModelResponse : IUtf8JsonWriteable, IJsonModel + public partial class DeleteModelResponse : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -136,13 +132,6 @@ internal static DeleteModelResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeDeleteModelResponse(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/DeleteModelResponse.cs b/.dotnet/src/Generated/Models/DeleteModelResponse.cs index fc8a2790b..96f122d77 100644 --- a/.dotnet/src/Generated/Models/DeleteModelResponse.cs +++ b/.dotnet/src/Generated/Models/DeleteModelResponse.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -49,7 +47,7 @@ public partial class DeleteModelResponse /// is null. internal DeleteModelResponse(string id, bool deleted) { - ClientUtilities.AssertNotNull(id, nameof(id)); + if (id is null) throw new ArgumentNullException(nameof(id)); Id = id; Deleted = deleted; @@ -81,3 +79,4 @@ internal DeleteModelResponse() public DeleteModelResponseObject Object { get; } = DeleteModelResponseObject.Model; } } + diff --git a/.dotnet/src/Generated/Models/DeleteModelResponseObject.cs b/.dotnet/src/Generated/Models/DeleteModelResponseObject.cs index ec25f197b..25f957c69 100644 --- a/.dotnet/src/Generated/Models/DeleteModelResponseObject.cs +++ b/.dotnet/src/Generated/Models/DeleteModelResponseObject.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public DeleteModelResponseObject(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/DeleteThreadResponse.Serialization.cs b/.dotnet/src/Generated/Models/DeleteThreadResponse.Serialization.cs index f287add9c..b6c04e508 100644 --- a/.dotnet/src/Generated/Models/DeleteThreadResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/DeleteThreadResponse.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class DeleteThreadResponse : IUtf8JsonWriteable, IJsonModel + public partial class DeleteThreadResponse : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -136,13 +132,6 @@ internal static DeleteThreadResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeDeleteThreadResponse(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/DeleteThreadResponse.cs b/.dotnet/src/Generated/Models/DeleteThreadResponse.cs index 740de89a5..368b9ff80 100644 --- a/.dotnet/src/Generated/Models/DeleteThreadResponse.cs +++ b/.dotnet/src/Generated/Models/DeleteThreadResponse.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -49,7 +47,7 @@ public partial class DeleteThreadResponse /// is null. internal DeleteThreadResponse(string id, bool deleted) { - ClientUtilities.AssertNotNull(id, nameof(id)); + if (id is null) throw new ArgumentNullException(nameof(id)); Id = id; Deleted = deleted; @@ -81,3 +79,4 @@ internal DeleteThreadResponse() public DeleteThreadResponseObject Object { get; } = DeleteThreadResponseObject.ThreadDeleted; } } + diff --git a/.dotnet/src/Generated/Models/DeleteThreadResponseObject.cs b/.dotnet/src/Generated/Models/DeleteThreadResponseObject.cs index 87838dd02..7e4b34167 100644 --- a/.dotnet/src/Generated/Models/DeleteThreadResponseObject.cs +++ b/.dotnet/src/Generated/Models/DeleteThreadResponseObject.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public DeleteThreadResponseObject(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/Embedding.Serialization.cs b/.dotnet/src/Generated/Models/Embedding.Serialization.cs index cdb14b425..b3506e51c 100644 --- a/.dotnet/src/Generated/Models/Embedding.Serialization.cs +++ b/.dotnet/src/Generated/Models/Embedding.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class Embedding : IUtf8JsonWriteable, IJsonModel + public partial class Embedding : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -143,13 +139,6 @@ internal static Embedding FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeEmbedding(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/Embedding.cs b/.dotnet/src/Generated/Models/Embedding.cs index 40eba7486..ecabc7df9 100644 --- a/.dotnet/src/Generated/Models/Embedding.cs +++ b/.dotnet/src/Generated/Models/Embedding.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -52,7 +50,7 @@ public partial class Embedding /// is null. internal Embedding(long index, BinaryData embeddingProperty) { - ClientUtilities.AssertNotNull(embeddingProperty, nameof(embeddingProperty)); + if (embeddingProperty is null) throw new ArgumentNullException(nameof(embeddingProperty)); Index = index; EmbeddingProperty = embeddingProperty; @@ -128,3 +126,4 @@ internal Embedding() public EmbeddingObject Object { get; } = EmbeddingObject.Embedding; } } + diff --git a/.dotnet/src/Generated/Models/EmbeddingObject.cs b/.dotnet/src/Generated/Models/EmbeddingObject.cs index 1a6df67a6..2cc2f012c 100644 --- a/.dotnet/src/Generated/Models/EmbeddingObject.cs +++ b/.dotnet/src/Generated/Models/EmbeddingObject.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public EmbeddingObject(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/FineTuningJob.Serialization.cs b/.dotnet/src/Generated/Models/FineTuningJob.Serialization.cs index a7b9c02b7..930aa5fc5 100644 --- a/.dotnet/src/Generated/Models/FineTuningJob.Serialization.cs +++ b/.dotnet/src/Generated/Models/FineTuningJob.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class FineTuningJob : IUtf8JsonWriteable, IJsonModel + public partial class FineTuningJob : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -294,13 +290,6 @@ internal static FineTuningJob FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeFineTuningJob(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/FineTuningJob.cs b/.dotnet/src/Generated/Models/FineTuningJob.cs index 0203658aa..773d90651 100644 --- a/.dotnet/src/Generated/Models/FineTuningJob.cs +++ b/.dotnet/src/Generated/Models/FineTuningJob.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; @@ -88,12 +86,12 @@ public partial class FineTuningJob /// , , , , or is null. internal FineTuningJob(string id, DateTimeOffset createdAt, DateTimeOffset? finishedAt, string model, string fineTunedModel, string organizationId, FineTuningJobStatus status, FineTuningJobHyperparameters hyperparameters, string trainingFile, string validationFile, IEnumerable resultFiles, long? trainedTokens, FineTuningJobError error) { - ClientUtilities.AssertNotNull(id, nameof(id)); - ClientUtilities.AssertNotNull(model, nameof(model)); - ClientUtilities.AssertNotNull(organizationId, nameof(organizationId)); - ClientUtilities.AssertNotNull(hyperparameters, nameof(hyperparameters)); - ClientUtilities.AssertNotNull(trainingFile, nameof(trainingFile)); - ClientUtilities.AssertNotNull(resultFiles, nameof(resultFiles)); + if (id is null) throw new ArgumentNullException(nameof(id)); + if (model is null) throw new ArgumentNullException(nameof(model)); + if (organizationId is null) throw new ArgumentNullException(nameof(organizationId)); + if (hyperparameters is null) throw new ArgumentNullException(nameof(hyperparameters)); + if (trainingFile is null) throw new ArgumentNullException(nameof(trainingFile)); + if (resultFiles is null) throw new ArgumentNullException(nameof(resultFiles)); Id = id; CreatedAt = createdAt; @@ -235,3 +233,4 @@ internal FineTuningJob() public FineTuningJobError Error { get; } } } + diff --git a/.dotnet/src/Generated/Models/FineTuningJobError.Serialization.cs b/.dotnet/src/Generated/Models/FineTuningJobError.Serialization.cs index e586868e7..6bfe0c908 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobError.Serialization.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobError.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class FineTuningJobError : IUtf8JsonWriteable, IJsonModel + public partial class FineTuningJobError : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -157,13 +153,6 @@ internal static FineTuningJobError FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeFineTuningJobError(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/FineTuningJobError.cs b/.dotnet/src/Generated/Models/FineTuningJobError.cs index 9b5b27e34..98268009c 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobError.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobError.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.Collections.Generic; @@ -74,3 +72,4 @@ internal FineTuningJobError(string message, string code, string param, IDictiona public string Param { get; } } } + diff --git a/.dotnet/src/Generated/Models/FineTuningJobEvent.Serialization.cs b/.dotnet/src/Generated/Models/FineTuningJobEvent.Serialization.cs index 20bb7a0fa..f61e577d3 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobEvent.Serialization.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobEvent.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class FineTuningJobEvent : IUtf8JsonWriteable, IJsonModel + public partial class FineTuningJobEvent : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -152,13 +148,6 @@ internal static FineTuningJobEvent FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeFineTuningJobEvent(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/FineTuningJobEvent.cs b/.dotnet/src/Generated/Models/FineTuningJobEvent.cs index a65270a76..1ed3dacf3 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobEvent.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobEvent.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -52,9 +50,9 @@ public partial class FineTuningJobEvent /// , or is null. internal FineTuningJobEvent(string id, string @object, DateTimeOffset createdAt, FineTuningJobEventLevel level, string message) { - ClientUtilities.AssertNotNull(id, nameof(id)); - ClientUtilities.AssertNotNull(@object, nameof(@object)); - ClientUtilities.AssertNotNull(message, nameof(message)); + if (id is null) throw new ArgumentNullException(nameof(id)); + if (@object is null) throw new ArgumentNullException(nameof(@object)); + if (message is null) throw new ArgumentNullException(nameof(message)); Id = id; Object = @object; @@ -97,3 +95,4 @@ internal FineTuningJobEvent() public string Message { get; } } } + diff --git a/.dotnet/src/Generated/Models/FineTuningJobEventLevel.cs b/.dotnet/src/Generated/Models/FineTuningJobEventLevel.cs index 7ac7da4c5..1e0ae3a85 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobEventLevel.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobEventLevel.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -49,3 +47,4 @@ public FineTuningJobEventLevel(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.Serialization.cs b/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.Serialization.cs index 8e4802d8a..3b4a5c3aa 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.Serialization.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class FineTuningJobHyperparameters : IUtf8JsonWriteable, IJsonModel + public partial class FineTuningJobHyperparameters : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -134,13 +130,6 @@ internal static FineTuningJobHyperparameters FromResponse(PipelineResponse respo using var document = JsonDocument.Parse(response.Content); return DeserializeFineTuningJobHyperparameters(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.cs b/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.cs index efcb91d25..830aef443 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.Collections.Generic; @@ -110,3 +108,4 @@ internal FineTuningJobHyperparameters(BinaryData nEpochs, IDictionary -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public FineTuningJobObject(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/FineTuningJobStatus.cs b/.dotnet/src/Generated/Models/FineTuningJobStatus.cs index 23924df4f..f9715b5b6 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobStatus.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobStatus.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -58,3 +56,4 @@ public FineTuningJobStatus(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/FunctionObject.Serialization.cs b/.dotnet/src/Generated/Models/FunctionObject.Serialization.cs index 99d391fea..fec24f853 100644 --- a/.dotnet/src/Generated/Models/FunctionObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/FunctionObject.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class FunctionObject : IUtf8JsonWriteable, IJsonModel + public partial class FunctionObject : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -146,13 +142,6 @@ internal static FunctionObject FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeFunctionObject(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/FunctionObject.cs b/.dotnet/src/Generated/Models/FunctionObject.cs index 00e9c8cdb..ddd65ebfa 100644 --- a/.dotnet/src/Generated/Models/FunctionObject.cs +++ b/.dotnet/src/Generated/Models/FunctionObject.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -51,7 +49,7 @@ public partial class FunctionObject /// is null. public FunctionObject(string name) { - ClientUtilities.AssertNotNull(name, nameof(name)); + if (name is null) throw new ArgumentNullException(nameof(name)); Name = name; } @@ -94,3 +92,4 @@ internal FunctionObject() public FunctionParameters Parameters { get; set; } } } + diff --git a/.dotnet/src/Generated/Models/FunctionParameters.Serialization.cs b/.dotnet/src/Generated/Models/FunctionParameters.Serialization.cs index e6f167ed4..3d473765a 100644 --- a/.dotnet/src/Generated/Models/FunctionParameters.Serialization.cs +++ b/.dotnet/src/Generated/Models/FunctionParameters.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class FunctionParameters : IUtf8JsonWriteable, IJsonModel + public partial class FunctionParameters : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -106,13 +102,6 @@ internal static FunctionParameters FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeFunctionParameters(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/FunctionParameters.cs b/.dotnet/src/Generated/Models/FunctionParameters.cs index ae3100e0d..8490bdc5f 100644 --- a/.dotnet/src/Generated/Models/FunctionParameters.cs +++ b/.dotnet/src/Generated/Models/FunctionParameters.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -63,3 +61,4 @@ internal FunctionParameters(IDictionary additionalProperties public IDictionary AdditionalProperties { get; } } } + diff --git a/.dotnet/src/Generated/Models/Image.Serialization.cs b/.dotnet/src/Generated/Models/Image.Serialization.cs index 209416ec1..dc41f82a8 100644 --- a/.dotnet/src/Generated/Models/Image.Serialization.cs +++ b/.dotnet/src/Generated/Models/Image.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class Image : IUtf8JsonWriteable, IJsonModel + public partial class Image : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -153,13 +149,6 @@ internal static Image FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeImage(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/Image.cs b/.dotnet/src/Generated/Models/Image.cs index a813097a2..7d6c304f2 100644 --- a/.dotnet/src/Generated/Models/Image.cs +++ b/.dotnet/src/Generated/Models/Image.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.Collections.Generic; @@ -83,3 +81,4 @@ internal Image(BinaryData b64Json, Uri url, string revisedPrompt, IDictionary -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class ImagesResponse : IUtf8JsonWriteable, IJsonModel + public partial class ImagesResponse : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -138,13 +134,6 @@ internal static ImagesResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeImagesResponse(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/ImagesResponse.cs b/.dotnet/src/Generated/Models/ImagesResponse.cs index d3c377be9..44b649f3f 100644 --- a/.dotnet/src/Generated/Models/ImagesResponse.cs +++ b/.dotnet/src/Generated/Models/ImagesResponse.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; @@ -50,7 +48,7 @@ public partial class ImagesResponse /// is null. internal ImagesResponse(DateTimeOffset created, IEnumerable data) { - ClientUtilities.AssertNotNull(data, nameof(data)); + if (data is null) throw new ArgumentNullException(nameof(data)); Created = created; Data = data.ToList(); @@ -78,3 +76,4 @@ internal ImagesResponse() public IReadOnlyList Data { get; } } } + diff --git a/.dotnet/src/Generated/Models/ListAssistantFilesResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListAssistantFilesResponse.Serialization.cs index d1bb15a51..6e6f9758b 100644 --- a/.dotnet/src/Generated/Models/ListAssistantFilesResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListAssistantFilesResponse.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class ListAssistantFilesResponse : IUtf8JsonWriteable, IJsonModel + public partial class ListAssistantFilesResponse : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -162,13 +158,6 @@ internal static ListAssistantFilesResponse FromResponse(PipelineResponse respons using var document = JsonDocument.Parse(response.Content); return DeserializeListAssistantFilesResponse(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/ListAssistantFilesResponse.cs b/.dotnet/src/Generated/Models/ListAssistantFilesResponse.cs index d155bf3e6..4537942a4 100644 --- a/.dotnet/src/Generated/Models/ListAssistantFilesResponse.cs +++ b/.dotnet/src/Generated/Models/ListAssistantFilesResponse.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; @@ -52,9 +50,9 @@ public partial class ListAssistantFilesResponse /// , or is null. internal ListAssistantFilesResponse(IEnumerable data, string firstId, string lastId, bool hasMore) { - ClientUtilities.AssertNotNull(data, nameof(data)); - ClientUtilities.AssertNotNull(firstId, nameof(firstId)); - ClientUtilities.AssertNotNull(lastId, nameof(lastId)); + if (data is null) throw new ArgumentNullException(nameof(data)); + if (firstId is null) throw new ArgumentNullException(nameof(firstId)); + if (lastId is null) throw new ArgumentNullException(nameof(lastId)); Data = data.ToList(); FirstId = firstId; @@ -97,3 +95,4 @@ internal ListAssistantFilesResponse() public bool HasMore { get; } } } + diff --git a/.dotnet/src/Generated/Models/ListAssistantFilesResponseObject.cs b/.dotnet/src/Generated/Models/ListAssistantFilesResponseObject.cs index 5038ede26..4b8e72c7e 100644 --- a/.dotnet/src/Generated/Models/ListAssistantFilesResponseObject.cs +++ b/.dotnet/src/Generated/Models/ListAssistantFilesResponseObject.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public ListAssistantFilesResponseObject(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/ListAssistantsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListAssistantsResponse.Serialization.cs index f9c0b12b6..573a35240 100644 --- a/.dotnet/src/Generated/Models/ListAssistantsResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListAssistantsResponse.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class ListAssistantsResponse : IUtf8JsonWriteable, IJsonModel + public partial class ListAssistantsResponse : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -162,13 +158,6 @@ internal static ListAssistantsResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeListAssistantsResponse(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/ListAssistantsResponse.cs b/.dotnet/src/Generated/Models/ListAssistantsResponse.cs index 002b27f3f..bf553f319 100644 --- a/.dotnet/src/Generated/Models/ListAssistantsResponse.cs +++ b/.dotnet/src/Generated/Models/ListAssistantsResponse.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; @@ -52,9 +50,9 @@ public partial class ListAssistantsResponse /// , or is null. internal ListAssistantsResponse(IEnumerable data, string firstId, string lastId, bool hasMore) { - ClientUtilities.AssertNotNull(data, nameof(data)); - ClientUtilities.AssertNotNull(firstId, nameof(firstId)); - ClientUtilities.AssertNotNull(lastId, nameof(lastId)); + if (data is null) throw new ArgumentNullException(nameof(data)); + if (firstId is null) throw new ArgumentNullException(nameof(firstId)); + if (lastId is null) throw new ArgumentNullException(nameof(lastId)); Data = data.ToList(); FirstId = firstId; @@ -97,3 +95,4 @@ internal ListAssistantsResponse() public bool HasMore { get; } } } + diff --git a/.dotnet/src/Generated/Models/ListAssistantsResponseObject.cs b/.dotnet/src/Generated/Models/ListAssistantsResponseObject.cs index 5bbc18a2b..207fe09fa 100644 --- a/.dotnet/src/Generated/Models/ListAssistantsResponseObject.cs +++ b/.dotnet/src/Generated/Models/ListAssistantsResponseObject.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public ListAssistantsResponseObject(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/ListFilesResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListFilesResponse.Serialization.cs index a580904af..24134e771 100644 --- a/.dotnet/src/Generated/Models/ListFilesResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListFilesResponse.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class ListFilesResponse : IUtf8JsonWriteable, IJsonModel + public partial class ListFilesResponse : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -138,13 +134,6 @@ internal static ListFilesResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeListFilesResponse(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/ListFilesResponse.cs b/.dotnet/src/Generated/Models/ListFilesResponse.cs index 0738efe8d..7447294ac 100644 --- a/.dotnet/src/Generated/Models/ListFilesResponse.cs +++ b/.dotnet/src/Generated/Models/ListFilesResponse.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; @@ -49,7 +47,7 @@ public partial class ListFilesResponse /// is null. internal ListFilesResponse(IEnumerable data) { - ClientUtilities.AssertNotNull(data, nameof(data)); + if (data is null) throw new ArgumentNullException(nameof(data)); Data = data.ToList(); } @@ -76,3 +74,4 @@ internal ListFilesResponse() public ListFilesResponseObject Object { get; } = ListFilesResponseObject.List; } } + diff --git a/.dotnet/src/Generated/Models/ListFilesResponseObject.cs b/.dotnet/src/Generated/Models/ListFilesResponseObject.cs index ef68e3dda..1c8be15c3 100644 --- a/.dotnet/src/Generated/Models/ListFilesResponseObject.cs +++ b/.dotnet/src/Generated/Models/ListFilesResponseObject.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public ListFilesResponseObject(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.Serialization.cs index b141b423a..588d06c98 100644 --- a/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class ListFineTuningJobEventsResponse : IUtf8JsonWriteable, IJsonModel + public partial class ListFineTuningJobEventsResponse : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -138,13 +134,6 @@ internal static ListFineTuningJobEventsResponse FromResponse(PipelineResponse re using var document = JsonDocument.Parse(response.Content); return DeserializeListFineTuningJobEventsResponse(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.cs b/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.cs index 94573da09..b79f9a929 100644 --- a/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.cs +++ b/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; @@ -50,8 +48,8 @@ public partial class ListFineTuningJobEventsResponse /// or is null. internal ListFineTuningJobEventsResponse(string @object, IEnumerable data) { - ClientUtilities.AssertNotNull(@object, nameof(@object)); - ClientUtilities.AssertNotNull(data, nameof(data)); + if (@object is null) throw new ArgumentNullException(nameof(@object)); + if (data is null) throw new ArgumentNullException(nameof(data)); Object = @object; Data = data.ToList(); @@ -79,3 +77,4 @@ internal ListFineTuningJobEventsResponse() public IReadOnlyList Data { get; } } } + diff --git a/.dotnet/src/Generated/Models/ListMessageFilesResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListMessageFilesResponse.Serialization.cs index 516a772d1..c8585eaf5 100644 --- a/.dotnet/src/Generated/Models/ListMessageFilesResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListMessageFilesResponse.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class ListMessageFilesResponse : IUtf8JsonWriteable, IJsonModel + public partial class ListMessageFilesResponse : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -162,13 +158,6 @@ internal static ListMessageFilesResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeListMessageFilesResponse(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/ListMessageFilesResponse.cs b/.dotnet/src/Generated/Models/ListMessageFilesResponse.cs index e4476c13a..be35d9455 100644 --- a/.dotnet/src/Generated/Models/ListMessageFilesResponse.cs +++ b/.dotnet/src/Generated/Models/ListMessageFilesResponse.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; @@ -52,9 +50,9 @@ public partial class ListMessageFilesResponse /// , or is null. internal ListMessageFilesResponse(IEnumerable data, string firstId, string lastId, bool hasMore) { - ClientUtilities.AssertNotNull(data, nameof(data)); - ClientUtilities.AssertNotNull(firstId, nameof(firstId)); - ClientUtilities.AssertNotNull(lastId, nameof(lastId)); + if (data is null) throw new ArgumentNullException(nameof(data)); + if (firstId is null) throw new ArgumentNullException(nameof(firstId)); + if (lastId is null) throw new ArgumentNullException(nameof(lastId)); Data = data.ToList(); FirstId = firstId; @@ -97,3 +95,4 @@ internal ListMessageFilesResponse() public bool HasMore { get; } } } + diff --git a/.dotnet/src/Generated/Models/ListMessageFilesResponseObject.cs b/.dotnet/src/Generated/Models/ListMessageFilesResponseObject.cs index da8016c77..01cd0514a 100644 --- a/.dotnet/src/Generated/Models/ListMessageFilesResponseObject.cs +++ b/.dotnet/src/Generated/Models/ListMessageFilesResponseObject.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public ListMessageFilesResponseObject(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/ListMessagesResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListMessagesResponse.Serialization.cs index b68c46995..fd1dad634 100644 --- a/.dotnet/src/Generated/Models/ListMessagesResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListMessagesResponse.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class ListMessagesResponse : IUtf8JsonWriteable, IJsonModel + public partial class ListMessagesResponse : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -162,13 +158,6 @@ internal static ListMessagesResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeListMessagesResponse(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/ListMessagesResponse.cs b/.dotnet/src/Generated/Models/ListMessagesResponse.cs index 41193e112..56ef1f2ec 100644 --- a/.dotnet/src/Generated/Models/ListMessagesResponse.cs +++ b/.dotnet/src/Generated/Models/ListMessagesResponse.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; @@ -52,9 +50,9 @@ public partial class ListMessagesResponse /// , or is null. internal ListMessagesResponse(IEnumerable data, string firstId, string lastId, bool hasMore) { - ClientUtilities.AssertNotNull(data, nameof(data)); - ClientUtilities.AssertNotNull(firstId, nameof(firstId)); - ClientUtilities.AssertNotNull(lastId, nameof(lastId)); + if (data is null) throw new ArgumentNullException(nameof(data)); + if (firstId is null) throw new ArgumentNullException(nameof(firstId)); + if (lastId is null) throw new ArgumentNullException(nameof(lastId)); Data = data.ToList(); FirstId = firstId; @@ -97,3 +95,4 @@ internal ListMessagesResponse() public bool HasMore { get; } } } + diff --git a/.dotnet/src/Generated/Models/ListMessagesResponseObject.cs b/.dotnet/src/Generated/Models/ListMessagesResponseObject.cs index ff1303bf4..01ad83164 100644 --- a/.dotnet/src/Generated/Models/ListMessagesResponseObject.cs +++ b/.dotnet/src/Generated/Models/ListMessagesResponseObject.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public ListMessagesResponseObject(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/ListModelsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListModelsResponse.Serialization.cs index 8a6dbd3a7..36da18e24 100644 --- a/.dotnet/src/Generated/Models/ListModelsResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListModelsResponse.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class ListModelsResponse : IUtf8JsonWriteable, IJsonModel + public partial class ListModelsResponse : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -138,13 +134,6 @@ internal static ListModelsResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeListModelsResponse(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/ListModelsResponse.cs b/.dotnet/src/Generated/Models/ListModelsResponse.cs index bc2ddf1a7..ee8f8e350 100644 --- a/.dotnet/src/Generated/Models/ListModelsResponse.cs +++ b/.dotnet/src/Generated/Models/ListModelsResponse.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; @@ -49,7 +47,7 @@ public partial class ListModelsResponse /// is null. internal ListModelsResponse(IEnumerable data) { - ClientUtilities.AssertNotNull(data, nameof(data)); + if (data is null) throw new ArgumentNullException(nameof(data)); Data = data.ToList(); } @@ -77,3 +75,4 @@ internal ListModelsResponse() public IReadOnlyList Data { get; } } } + diff --git a/.dotnet/src/Generated/Models/ListModelsResponseObject.cs b/.dotnet/src/Generated/Models/ListModelsResponseObject.cs index bb0127059..081da58be 100644 --- a/.dotnet/src/Generated/Models/ListModelsResponseObject.cs +++ b/.dotnet/src/Generated/Models/ListModelsResponseObject.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public ListModelsResponseObject(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/ListOrder.cs b/.dotnet/src/Generated/Models/ListOrder.cs index 0343ac0f3..95b097763 100644 --- a/.dotnet/src/Generated/Models/ListOrder.cs +++ b/.dotnet/src/Generated/Models/ListOrder.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -45,3 +43,4 @@ public ListOrder(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.Serialization.cs index dd8425fb7..16a324034 100644 --- a/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class ListPaginatedFineTuningJobsResponse : IUtf8JsonWriteable, IJsonModel + public partial class ListPaginatedFineTuningJobsResponse : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -146,13 +142,6 @@ internal static ListPaginatedFineTuningJobsResponse FromResponse(PipelineRespons using var document = JsonDocument.Parse(response.Content); return DeserializeListPaginatedFineTuningJobsResponse(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.cs b/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.cs index db1bf28f5..3bb6a7d15 100644 --- a/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.cs +++ b/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; @@ -51,8 +49,8 @@ public partial class ListPaginatedFineTuningJobsResponse /// or is null. internal ListPaginatedFineTuningJobsResponse(string @object, IEnumerable data, bool hasMore) { - ClientUtilities.AssertNotNull(@object, nameof(@object)); - ClientUtilities.AssertNotNull(data, nameof(data)); + if (@object is null) throw new ArgumentNullException(nameof(@object)); + if (data is null) throw new ArgumentNullException(nameof(data)); Object = @object; Data = data.ToList(); @@ -85,3 +83,4 @@ internal ListPaginatedFineTuningJobsResponse() public bool HasMore { get; } } } + diff --git a/.dotnet/src/Generated/Models/ListRunStepsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListRunStepsResponse.Serialization.cs index 3aa87a8a1..a91044a98 100644 --- a/.dotnet/src/Generated/Models/ListRunStepsResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListRunStepsResponse.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class ListRunStepsResponse : IUtf8JsonWriteable, IJsonModel + public partial class ListRunStepsResponse : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -162,13 +158,6 @@ internal static ListRunStepsResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeListRunStepsResponse(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/ListRunStepsResponse.cs b/.dotnet/src/Generated/Models/ListRunStepsResponse.cs index 1df4309d3..641a91e04 100644 --- a/.dotnet/src/Generated/Models/ListRunStepsResponse.cs +++ b/.dotnet/src/Generated/Models/ListRunStepsResponse.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; @@ -52,9 +50,9 @@ public partial class ListRunStepsResponse /// , or is null. internal ListRunStepsResponse(IEnumerable data, string firstId, string lastId, bool hasMore) { - ClientUtilities.AssertNotNull(data, nameof(data)); - ClientUtilities.AssertNotNull(firstId, nameof(firstId)); - ClientUtilities.AssertNotNull(lastId, nameof(lastId)); + if (data is null) throw new ArgumentNullException(nameof(data)); + if (firstId is null) throw new ArgumentNullException(nameof(firstId)); + if (lastId is null) throw new ArgumentNullException(nameof(lastId)); Data = data.ToList(); FirstId = firstId; @@ -97,3 +95,4 @@ internal ListRunStepsResponse() public bool HasMore { get; } } } + diff --git a/.dotnet/src/Generated/Models/ListRunStepsResponseObject.cs b/.dotnet/src/Generated/Models/ListRunStepsResponseObject.cs index 043709495..2b613b3e4 100644 --- a/.dotnet/src/Generated/Models/ListRunStepsResponseObject.cs +++ b/.dotnet/src/Generated/Models/ListRunStepsResponseObject.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public ListRunStepsResponseObject(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/ListRunsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListRunsResponse.Serialization.cs index d0705cd68..a934e890e 100644 --- a/.dotnet/src/Generated/Models/ListRunsResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListRunsResponse.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class ListRunsResponse : IUtf8JsonWriteable, IJsonModel + public partial class ListRunsResponse : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -162,13 +158,6 @@ internal static ListRunsResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeListRunsResponse(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/ListRunsResponse.cs b/.dotnet/src/Generated/Models/ListRunsResponse.cs index efd6de920..f3fb538c7 100644 --- a/.dotnet/src/Generated/Models/ListRunsResponse.cs +++ b/.dotnet/src/Generated/Models/ListRunsResponse.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; @@ -52,9 +50,9 @@ public partial class ListRunsResponse /// , or is null. internal ListRunsResponse(IEnumerable data, string firstId, string lastId, bool hasMore) { - ClientUtilities.AssertNotNull(data, nameof(data)); - ClientUtilities.AssertNotNull(firstId, nameof(firstId)); - ClientUtilities.AssertNotNull(lastId, nameof(lastId)); + if (data is null) throw new ArgumentNullException(nameof(data)); + if (firstId is null) throw new ArgumentNullException(nameof(firstId)); + if (lastId is null) throw new ArgumentNullException(nameof(lastId)); Data = data.ToList(); FirstId = firstId; @@ -97,3 +95,4 @@ internal ListRunsResponse() public bool HasMore { get; } } } + diff --git a/.dotnet/src/Generated/Models/ListRunsResponseObject.cs b/.dotnet/src/Generated/Models/ListRunsResponseObject.cs index 548feb288..f8a80ed2d 100644 --- a/.dotnet/src/Generated/Models/ListRunsResponseObject.cs +++ b/.dotnet/src/Generated/Models/ListRunsResponseObject.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public ListRunsResponseObject(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/MessageFileObject.Serialization.cs b/.dotnet/src/Generated/Models/MessageFileObject.Serialization.cs index 01d813ec5..62d4e0d8e 100644 --- a/.dotnet/src/Generated/Models/MessageFileObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/MessageFileObject.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class MessageFileObject : IUtf8JsonWriteable, IJsonModel + public partial class MessageFileObject : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -144,13 +140,6 @@ internal static MessageFileObject FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeMessageFileObject(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/MessageFileObject.cs b/.dotnet/src/Generated/Models/MessageFileObject.cs index 0afed8c95..1f4f67e75 100644 --- a/.dotnet/src/Generated/Models/MessageFileObject.cs +++ b/.dotnet/src/Generated/Models/MessageFileObject.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -50,8 +48,8 @@ public partial class MessageFileObject /// or is null. internal MessageFileObject(string id, DateTimeOffset createdAt, string messageId) { - ClientUtilities.AssertNotNull(id, nameof(id)); - ClientUtilities.AssertNotNull(messageId, nameof(messageId)); + if (id is null) throw new ArgumentNullException(nameof(id)); + if (messageId is null) throw new ArgumentNullException(nameof(messageId)); Id = id; CreatedAt = createdAt; @@ -89,3 +87,4 @@ internal MessageFileObject() public string MessageId { get; } } } + diff --git a/.dotnet/src/Generated/Models/MessageFileObjectObject.cs b/.dotnet/src/Generated/Models/MessageFileObjectObject.cs index 55f4cc6f8..f1185adf5 100644 --- a/.dotnet/src/Generated/Models/MessageFileObjectObject.cs +++ b/.dotnet/src/Generated/Models/MessageFileObjectObject.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public MessageFileObjectObject(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/MessageObject.Serialization.cs b/.dotnet/src/Generated/Models/MessageObject.Serialization.cs index 5f9db4673..bc6f566b7 100644 --- a/.dotnet/src/Generated/Models/MessageObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/MessageObject.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class MessageObject : IUtf8JsonWriteable, IJsonModel + public partial class MessageObject : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -278,13 +274,6 @@ internal static MessageObject FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeMessageObject(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/MessageObject.cs b/.dotnet/src/Generated/Models/MessageObject.cs index 54ea98399..0ed781f8d 100644 --- a/.dotnet/src/Generated/Models/MessageObject.cs +++ b/.dotnet/src/Generated/Models/MessageObject.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; @@ -71,10 +69,10 @@ public partial class MessageObject /// , , or is null. internal MessageObject(string id, DateTimeOffset createdAt, string threadId, MessageObjectRole role, IEnumerable content, string assistantId, string runId, IEnumerable fileIds, IReadOnlyDictionary metadata) { - ClientUtilities.AssertNotNull(id, nameof(id)); - ClientUtilities.AssertNotNull(threadId, nameof(threadId)); - ClientUtilities.AssertNotNull(content, nameof(content)); - ClientUtilities.AssertNotNull(fileIds, nameof(fileIds)); + if (id is null) throw new ArgumentNullException(nameof(id)); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (content is null) throw new ArgumentNullException(nameof(content)); + if (fileIds is null) throw new ArgumentNullException(nameof(fileIds)); Id = id; CreatedAt = createdAt; @@ -199,3 +197,4 @@ internal MessageObject() public IReadOnlyDictionary Metadata { get; } } } + diff --git a/.dotnet/src/Generated/Models/MessageObjectObject.cs b/.dotnet/src/Generated/Models/MessageObjectObject.cs index 5f835f436..978ab0a6a 100644 --- a/.dotnet/src/Generated/Models/MessageObjectObject.cs +++ b/.dotnet/src/Generated/Models/MessageObjectObject.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public MessageObjectObject(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/MessageObjectRole.cs b/.dotnet/src/Generated/Models/MessageObjectRole.cs index a62512cd2..53ee3cafe 100644 --- a/.dotnet/src/Generated/Models/MessageObjectRole.cs +++ b/.dotnet/src/Generated/Models/MessageObjectRole.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -46,3 +44,4 @@ public MessageObjectRole(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/Model.Serialization.cs b/.dotnet/src/Generated/Models/Model.Serialization.cs index b3a797b7b..4b0cb8d8a 100644 --- a/.dotnet/src/Generated/Models/Model.Serialization.cs +++ b/.dotnet/src/Generated/Models/Model.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class Model : IUtf8JsonWriteable, IJsonModel + public partial class Model : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -144,13 +140,6 @@ internal static Model FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeModel(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/Model.cs b/.dotnet/src/Generated/Models/Model.cs index 70edf9a14..66fe38632 100644 --- a/.dotnet/src/Generated/Models/Model.cs +++ b/.dotnet/src/Generated/Models/Model.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -50,8 +48,8 @@ public partial class Model /// or is null. internal Model(string id, DateTimeOffset created, string ownedBy) { - ClientUtilities.AssertNotNull(id, nameof(id)); - ClientUtilities.AssertNotNull(ownedBy, nameof(ownedBy)); + if (id is null) throw new ArgumentNullException(nameof(id)); + if (ownedBy is null) throw new ArgumentNullException(nameof(ownedBy)); Id = id; Created = created; @@ -89,3 +87,4 @@ internal Model() public string OwnedBy { get; } } } + diff --git a/.dotnet/src/Generated/Models/ModelObject.cs b/.dotnet/src/Generated/Models/ModelObject.cs index 063012b5a..70fd47f04 100644 --- a/.dotnet/src/Generated/Models/ModelObject.cs +++ b/.dotnet/src/Generated/Models/ModelObject.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public ModelObject(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/ModifyAssistantRequest.Serialization.cs b/.dotnet/src/Generated/Models/ModifyAssistantRequest.Serialization.cs index 7e9027ef1..7635f00f3 100644 --- a/.dotnet/src/Generated/Models/ModifyAssistantRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/ModifyAssistantRequest.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class ModifyAssistantRequest : IUtf8JsonWriteable, IJsonModel + public partial class ModifyAssistantRequest : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -294,13 +290,6 @@ internal static ModifyAssistantRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeModifyAssistantRequest(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/ModifyAssistantRequest.cs b/.dotnet/src/Generated/Models/ModifyAssistantRequest.cs index abc79d17a..9882b6462 100644 --- a/.dotnet/src/Generated/Models/ModifyAssistantRequest.cs +++ b/.dotnet/src/Generated/Models/ModifyAssistantRequest.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -145,3 +143,4 @@ internal ModifyAssistantRequest(string model, string name, string description, s public IDictionary Metadata { get; set; } } } + diff --git a/.dotnet/src/Generated/Models/ModifyMessageRequest.Serialization.cs b/.dotnet/src/Generated/Models/ModifyMessageRequest.Serialization.cs index 35ee9a46e..2c5c37dec 100644 --- a/.dotnet/src/Generated/Models/ModifyMessageRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/ModifyMessageRequest.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class ModifyMessageRequest : IUtf8JsonWriteable, IJsonModel + public partial class ModifyMessageRequest : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -145,13 +141,6 @@ internal static ModifyMessageRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeModifyMessageRequest(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/ModifyMessageRequest.cs b/.dotnet/src/Generated/Models/ModifyMessageRequest.cs index 3a200b238..a087c656d 100644 --- a/.dotnet/src/Generated/Models/ModifyMessageRequest.cs +++ b/.dotnet/src/Generated/Models/ModifyMessageRequest.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -70,3 +68,4 @@ internal ModifyMessageRequest(IDictionary metadata, IDictionary< public IDictionary Metadata { get; set; } } } + diff --git a/.dotnet/src/Generated/Models/ModifyRunRequest.Serialization.cs b/.dotnet/src/Generated/Models/ModifyRunRequest.Serialization.cs index 75c891191..1976fd93e 100644 --- a/.dotnet/src/Generated/Models/ModifyRunRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/ModifyRunRequest.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class ModifyRunRequest : IUtf8JsonWriteable, IJsonModel + public partial class ModifyRunRequest : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -145,13 +141,6 @@ internal static ModifyRunRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeModifyRunRequest(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/ModifyRunRequest.cs b/.dotnet/src/Generated/Models/ModifyRunRequest.cs index 8a8a14588..1be502ea5 100644 --- a/.dotnet/src/Generated/Models/ModifyRunRequest.cs +++ b/.dotnet/src/Generated/Models/ModifyRunRequest.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -70,3 +68,4 @@ internal ModifyRunRequest(IDictionary metadata, IDictionary Metadata { get; set; } } } + diff --git a/.dotnet/src/Generated/Models/ModifyThreadRequest.Serialization.cs b/.dotnet/src/Generated/Models/ModifyThreadRequest.Serialization.cs index 2e8149f8e..e5bc72917 100644 --- a/.dotnet/src/Generated/Models/ModifyThreadRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/ModifyThreadRequest.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class ModifyThreadRequest : IUtf8JsonWriteable, IJsonModel + public partial class ModifyThreadRequest : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -145,13 +141,6 @@ internal static ModifyThreadRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeModifyThreadRequest(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/ModifyThreadRequest.cs b/.dotnet/src/Generated/Models/ModifyThreadRequest.cs index 635172be4..084d68686 100644 --- a/.dotnet/src/Generated/Models/ModifyThreadRequest.cs +++ b/.dotnet/src/Generated/Models/ModifyThreadRequest.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -70,3 +68,4 @@ internal ModifyThreadRequest(IDictionary metadata, IDictionary Metadata { get; set; } } } + diff --git a/.dotnet/src/Generated/Models/OpenAIFile.Serialization.cs b/.dotnet/src/Generated/Models/OpenAIFile.Serialization.cs index 53c7116dd..fe73a6958 100644 --- a/.dotnet/src/Generated/Models/OpenAIFile.Serialization.cs +++ b/.dotnet/src/Generated/Models/OpenAIFile.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class OpenAIFile : IUtf8JsonWriteable, IJsonModel + public partial class OpenAIFile : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -179,13 +175,6 @@ internal static OpenAIFile FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeOpenAIFile(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/OpenAIFile.cs b/.dotnet/src/Generated/Models/OpenAIFile.cs index 7d3adf563..05b42f6de 100644 --- a/.dotnet/src/Generated/Models/OpenAIFile.cs +++ b/.dotnet/src/Generated/Models/OpenAIFile.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -59,8 +57,8 @@ public partial class OpenAIFile /// or is null. internal OpenAIFile(string id, long bytes, DateTimeOffset createdAt, string filename, OpenAIFilePurpose purpose, OpenAIFileStatus status) { - ClientUtilities.AssertNotNull(id, nameof(id)); - ClientUtilities.AssertNotNull(filename, nameof(filename)); + if (id is null) throw new ArgumentNullException(nameof(id)); + if (filename is null) throw new ArgumentNullException(nameof(filename)); Id = id; Bytes = bytes; @@ -135,3 +133,4 @@ internal OpenAIFile() public string StatusDetails { get; } } } + diff --git a/.dotnet/src/Generated/Models/OpenAIFileObject.cs b/.dotnet/src/Generated/Models/OpenAIFileObject.cs index 79e03b84c..268a0888e 100644 --- a/.dotnet/src/Generated/Models/OpenAIFileObject.cs +++ b/.dotnet/src/Generated/Models/OpenAIFileObject.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public OpenAIFileObject(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/OpenAIFilePurpose.cs b/.dotnet/src/Generated/Models/OpenAIFilePurpose.cs index 0f3c83bc5..98a369e91 100644 --- a/.dotnet/src/Generated/Models/OpenAIFilePurpose.cs +++ b/.dotnet/src/Generated/Models/OpenAIFilePurpose.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -52,3 +50,4 @@ public OpenAIFilePurpose(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/OpenAIFileStatus.cs b/.dotnet/src/Generated/Models/OpenAIFileStatus.cs index c35731688..cddc7cf60 100644 --- a/.dotnet/src/Generated/Models/OpenAIFileStatus.cs +++ b/.dotnet/src/Generated/Models/OpenAIFileStatus.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -49,3 +47,4 @@ public OpenAIFileStatus(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/RunCompletionUsage.Serialization.cs b/.dotnet/src/Generated/Models/RunCompletionUsage.Serialization.cs index e857ef3b6..b730fa9c8 100644 --- a/.dotnet/src/Generated/Models/RunCompletionUsage.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunCompletionUsage.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class RunCompletionUsage : IUtf8JsonWriteable, IJsonModel + public partial class RunCompletionUsage : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -136,13 +132,6 @@ internal static RunCompletionUsage FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeRunCompletionUsage(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/RunCompletionUsage.cs b/.dotnet/src/Generated/Models/RunCompletionUsage.cs index be9401604..a1bd07938 100644 --- a/.dotnet/src/Generated/Models/RunCompletionUsage.cs +++ b/.dotnet/src/Generated/Models/RunCompletionUsage.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.Collections.Generic; @@ -82,3 +80,4 @@ internal RunCompletionUsage() public long TotalTokens { get; } } } + diff --git a/.dotnet/src/Generated/Models/RunObject.Serialization.cs b/.dotnet/src/Generated/Models/RunObject.Serialization.cs index 7128918dc..1c7779a88 100644 --- a/.dotnet/src/Generated/Models/RunObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunObject.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class RunObject : IUtf8JsonWriteable, IJsonModel + public partial class RunObject : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -410,13 +406,6 @@ internal static RunObject FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeRunObject(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/RunObject.cs b/.dotnet/src/Generated/Models/RunObject.cs index 8222d1eec..a1baf8de2 100644 --- a/.dotnet/src/Generated/Models/RunObject.cs +++ b/.dotnet/src/Generated/Models/RunObject.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; @@ -82,13 +80,13 @@ public partial class RunObject /// , , , , , or is null. internal RunObject(string id, DateTimeOffset createdAt, string threadId, string assistantId, RunObjectStatus status, RunObjectRequiredAction requiredAction, RunObjectLastError lastError, DateTimeOffset expiresAt, DateTimeOffset? startedAt, DateTimeOffset? cancelledAt, DateTimeOffset? failedAt, DateTimeOffset? completedAt, string model, string instructions, IEnumerable tools, IEnumerable fileIds, IReadOnlyDictionary metadata, RunCompletionUsage usage) { - ClientUtilities.AssertNotNull(id, nameof(id)); - ClientUtilities.AssertNotNull(threadId, nameof(threadId)); - ClientUtilities.AssertNotNull(assistantId, nameof(assistantId)); - ClientUtilities.AssertNotNull(model, nameof(model)); - ClientUtilities.AssertNotNull(instructions, nameof(instructions)); - ClientUtilities.AssertNotNull(tools, nameof(tools)); - ClientUtilities.AssertNotNull(fileIds, nameof(fileIds)); + if (id is null) throw new ArgumentNullException(nameof(id)); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (model is null) throw new ArgumentNullException(nameof(model)); + if (instructions is null) throw new ArgumentNullException(nameof(instructions)); + if (tools is null) throw new ArgumentNullException(nameof(tools)); + if (fileIds is null) throw new ArgumentNullException(nameof(fileIds)); Id = id; CreatedAt = createdAt; @@ -262,3 +260,4 @@ internal RunObject() public RunCompletionUsage Usage { get; } } } + diff --git a/.dotnet/src/Generated/Models/RunObjectLastError.Serialization.cs b/.dotnet/src/Generated/Models/RunObjectLastError.Serialization.cs index f40c2aa0a..f3486aafe 100644 --- a/.dotnet/src/Generated/Models/RunObjectLastError.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunObjectLastError.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class RunObjectLastError : IUtf8JsonWriteable, IJsonModel + public partial class RunObjectLastError : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -128,13 +124,6 @@ internal static RunObjectLastError FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeRunObjectLastError(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/RunObjectLastError.cs b/.dotnet/src/Generated/Models/RunObjectLastError.cs index f2e26a107..b46274c65 100644 --- a/.dotnet/src/Generated/Models/RunObjectLastError.cs +++ b/.dotnet/src/Generated/Models/RunObjectLastError.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -49,7 +47,7 @@ public partial class RunObjectLastError /// is null. internal RunObjectLastError(RunObjectLastErrorCode code, string message) { - ClientUtilities.AssertNotNull(message, nameof(message)); + if (message is null) throw new ArgumentNullException(nameof(message)); Code = code; Message = message; @@ -77,3 +75,4 @@ internal RunObjectLastError() public string Message { get; } } } + diff --git a/.dotnet/src/Generated/Models/RunObjectLastErrorCode.cs b/.dotnet/src/Generated/Models/RunObjectLastErrorCode.cs index abcb19758..d851f2397 100644 --- a/.dotnet/src/Generated/Models/RunObjectLastErrorCode.cs +++ b/.dotnet/src/Generated/Models/RunObjectLastErrorCode.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -46,3 +44,4 @@ public RunObjectLastErrorCode(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/RunObjectObject.cs b/.dotnet/src/Generated/Models/RunObjectObject.cs index c9b970b98..19925055a 100644 --- a/.dotnet/src/Generated/Models/RunObjectObject.cs +++ b/.dotnet/src/Generated/Models/RunObjectObject.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public RunObjectObject(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/RunObjectRequiredAction.Serialization.cs b/.dotnet/src/Generated/Models/RunObjectRequiredAction.Serialization.cs index 8b354c03e..98fb7bbc1 100644 --- a/.dotnet/src/Generated/Models/RunObjectRequiredAction.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunObjectRequiredAction.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class RunObjectRequiredAction : IUtf8JsonWriteable, IJsonModel + public partial class RunObjectRequiredAction : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -128,13 +124,6 @@ internal static RunObjectRequiredAction FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeRunObjectRequiredAction(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/RunObjectRequiredAction.cs b/.dotnet/src/Generated/Models/RunObjectRequiredAction.cs index fa11171c8..034fedcca 100644 --- a/.dotnet/src/Generated/Models/RunObjectRequiredAction.cs +++ b/.dotnet/src/Generated/Models/RunObjectRequiredAction.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -48,7 +46,7 @@ public partial class RunObjectRequiredAction /// is null. internal RunObjectRequiredAction(RunObjectRequiredActionSubmitToolOutputs submitToolOutputs) { - ClientUtilities.AssertNotNull(submitToolOutputs, nameof(submitToolOutputs)); + if (submitToolOutputs is null) throw new ArgumentNullException(nameof(submitToolOutputs)); SubmitToolOutputs = submitToolOutputs; } @@ -76,3 +74,4 @@ internal RunObjectRequiredAction() public RunObjectRequiredActionSubmitToolOutputs SubmitToolOutputs { get; } } } + diff --git a/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.Serialization.cs b/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.Serialization.cs index 6f7c1b4e5..0f374b56a 100644 --- a/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class RunObjectRequiredActionSubmitToolOutputs : IUtf8JsonWriteable, IJsonModel + public partial class RunObjectRequiredActionSubmitToolOutputs : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -130,13 +126,6 @@ internal static RunObjectRequiredActionSubmitToolOutputs FromResponse(PipelineRe using var document = JsonDocument.Parse(response.Content); return DeserializeRunObjectRequiredActionSubmitToolOutputs(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.cs b/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.cs index e9f7b6a58..ffdc5ff0f 100644 --- a/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.cs +++ b/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; @@ -49,7 +47,7 @@ public partial class RunObjectRequiredActionSubmitToolOutputs /// is null. internal RunObjectRequiredActionSubmitToolOutputs(IEnumerable toolCalls) { - ClientUtilities.AssertNotNull(toolCalls, nameof(toolCalls)); + if (toolCalls is null) throw new ArgumentNullException(nameof(toolCalls)); ToolCalls = toolCalls.ToList(); } @@ -72,3 +70,4 @@ internal RunObjectRequiredActionSubmitToolOutputs() public IReadOnlyList ToolCalls { get; } } } + diff --git a/.dotnet/src/Generated/Models/RunObjectRequiredActionType.cs b/.dotnet/src/Generated/Models/RunObjectRequiredActionType.cs index eb11f17ac..d8d1c8f07 100644 --- a/.dotnet/src/Generated/Models/RunObjectRequiredActionType.cs +++ b/.dotnet/src/Generated/Models/RunObjectRequiredActionType.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public RunObjectRequiredActionType(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/RunObjectStatus.cs b/.dotnet/src/Generated/Models/RunObjectStatus.cs index 52f7c1603..cd13d9b49 100644 --- a/.dotnet/src/Generated/Models/RunObjectStatus.cs +++ b/.dotnet/src/Generated/Models/RunObjectStatus.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -64,3 +62,4 @@ public RunObjectStatus(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.Serialization.cs b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.Serialization.cs index 9bfd95a67..38408c8d1 100644 --- a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - internal partial class RunStepDetailsMessageCreationObject : IUtf8JsonWriteable, IJsonModel + internal partial class RunStepDetailsMessageCreationObject : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -128,13 +124,6 @@ internal static RunStepDetailsMessageCreationObject FromResponse(PipelineRespons using var document = JsonDocument.Parse(response.Content); return DeserializeRunStepDetailsMessageCreationObject(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.cs b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.cs index d0db44dad..ffac3bdb1 100644 --- a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.cs +++ b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -48,7 +46,7 @@ internal partial class RunStepDetailsMessageCreationObject /// is null. internal RunStepDetailsMessageCreationObject(RunStepDetailsMessageCreationObjectMessageCreation messageCreation) { - ClientUtilities.AssertNotNull(messageCreation, nameof(messageCreation)); + if (messageCreation is null) throw new ArgumentNullException(nameof(messageCreation)); MessageCreation = messageCreation; } @@ -76,3 +74,4 @@ internal RunStepDetailsMessageCreationObject() public RunStepDetailsMessageCreationObjectMessageCreation MessageCreation { get; } } } + diff --git a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.Serialization.cs b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.Serialization.cs index aadaece5e..1d02bc66a 100644 --- a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - internal partial class RunStepDetailsMessageCreationObjectMessageCreation : IUtf8JsonWriteable, IJsonModel + internal partial class RunStepDetailsMessageCreationObjectMessageCreation : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -120,13 +116,6 @@ internal static RunStepDetailsMessageCreationObjectMessageCreation FromResponse( using var document = JsonDocument.Parse(response.Content); return DeserializeRunStepDetailsMessageCreationObjectMessageCreation(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.cs b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.cs index 3163ffe5c..447962ae3 100644 --- a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.cs +++ b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -48,7 +46,7 @@ internal partial class RunStepDetailsMessageCreationObjectMessageCreation /// is null. internal RunStepDetailsMessageCreationObjectMessageCreation(string messageId) { - ClientUtilities.AssertNotNull(messageId, nameof(messageId)); + if (messageId is null) throw new ArgumentNullException(nameof(messageId)); MessageId = messageId; } @@ -71,3 +69,4 @@ internal RunStepDetailsMessageCreationObjectMessageCreation() public string MessageId { get; } } } + diff --git a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectType.cs b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectType.cs index 007fd9eed..bf0a1f637 100644 --- a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectType.cs +++ b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectType.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public RunStepDetailsMessageCreationObjectType(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.Serialization.cs b/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.Serialization.cs index 5fa47d28b..ebf127b7d 100644 --- a/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - internal partial class RunStepDetailsToolCallsObject : IUtf8JsonWriteable, IJsonModel + internal partial class RunStepDetailsToolCallsObject : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -157,13 +153,6 @@ internal static RunStepDetailsToolCallsObject FromResponse(PipelineResponse resp using var document = JsonDocument.Parse(response.Content); return DeserializeRunStepDetailsToolCallsObject(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.cs b/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.cs index 76cdc1d4c..f290db55e 100644 --- a/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.cs +++ b/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; @@ -52,7 +50,7 @@ internal partial class RunStepDetailsToolCallsObject /// is null. internal RunStepDetailsToolCallsObject(IEnumerable toolCalls) { - ClientUtilities.AssertNotNull(toolCalls, nameof(toolCalls)); + if (toolCalls is null) throw new ArgumentNullException(nameof(toolCalls)); ToolCalls = toolCalls.ToList(); } @@ -113,3 +111,4 @@ internal RunStepDetailsToolCallsObject() public IReadOnlyList ToolCalls { get; } } } + diff --git a/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObjectType.cs b/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObjectType.cs index 56b168ac3..a307fc4c4 100644 --- a/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObjectType.cs +++ b/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObjectType.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public RunStepDetailsToolCallsObjectType(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/RunStepObject.Serialization.cs b/.dotnet/src/Generated/Models/RunStepObject.Serialization.cs index 74f027391..a73966402 100644 --- a/.dotnet/src/Generated/Models/RunStepObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunStepObject.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class RunStepObject : IUtf8JsonWriteable, IJsonModel + public partial class RunStepObject : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -342,13 +338,6 @@ internal static RunStepObject FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeRunStepObject(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/RunStepObject.cs b/.dotnet/src/Generated/Models/RunStepObject.cs index 801dc2367..24cbfec6e 100644 --- a/.dotnet/src/Generated/Models/RunStepObject.cs +++ b/.dotnet/src/Generated/Models/RunStepObject.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -72,11 +70,11 @@ public partial class RunStepObject /// , , , or is null. internal RunStepObject(string id, DateTimeOffset createdAt, string assistantId, string threadId, string runId, RunStepObjectType type, RunStepObjectStatus status, BinaryData stepDetails, RunStepObjectLastError lastError, DateTimeOffset? expiresAt, DateTimeOffset? cancelledAt, DateTimeOffset? failedAt, DateTimeOffset? completedAt, IReadOnlyDictionary metadata, RunCompletionUsage usage) { - ClientUtilities.AssertNotNull(id, nameof(id)); - ClientUtilities.AssertNotNull(assistantId, nameof(assistantId)); - ClientUtilities.AssertNotNull(threadId, nameof(threadId)); - ClientUtilities.AssertNotNull(runId, nameof(runId)); - ClientUtilities.AssertNotNull(stepDetails, nameof(stepDetails)); + if (id is null) throw new ArgumentNullException(nameof(id)); + if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (runId is null) throw new ArgumentNullException(nameof(runId)); + if (stepDetails is null) throw new ArgumentNullException(nameof(stepDetails)); Id = id; CreatedAt = createdAt; @@ -234,3 +232,4 @@ internal RunStepObject() public RunCompletionUsage Usage { get; } } } + diff --git a/.dotnet/src/Generated/Models/RunStepObjectLastError.Serialization.cs b/.dotnet/src/Generated/Models/RunStepObjectLastError.Serialization.cs index 368f9006e..71a0e8a2f 100644 --- a/.dotnet/src/Generated/Models/RunStepObjectLastError.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunStepObjectLastError.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class RunStepObjectLastError : IUtf8JsonWriteable, IJsonModel + public partial class RunStepObjectLastError : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -128,13 +124,6 @@ internal static RunStepObjectLastError FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeRunStepObjectLastError(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/RunStepObjectLastError.cs b/.dotnet/src/Generated/Models/RunStepObjectLastError.cs index 8742db0c0..2bf3b1db8 100644 --- a/.dotnet/src/Generated/Models/RunStepObjectLastError.cs +++ b/.dotnet/src/Generated/Models/RunStepObjectLastError.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -49,7 +47,7 @@ public partial class RunStepObjectLastError /// is null. internal RunStepObjectLastError(RunStepObjectLastErrorCode code, string message) { - ClientUtilities.AssertNotNull(message, nameof(message)); + if (message is null) throw new ArgumentNullException(nameof(message)); Code = code; Message = message; @@ -77,3 +75,4 @@ internal RunStepObjectLastError() public string Message { get; } } } + diff --git a/.dotnet/src/Generated/Models/RunStepObjectLastErrorCode.cs b/.dotnet/src/Generated/Models/RunStepObjectLastErrorCode.cs index e3b156259..9bf035ea1 100644 --- a/.dotnet/src/Generated/Models/RunStepObjectLastErrorCode.cs +++ b/.dotnet/src/Generated/Models/RunStepObjectLastErrorCode.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -46,3 +44,4 @@ public RunStepObjectLastErrorCode(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/RunStepObjectObject.cs b/.dotnet/src/Generated/Models/RunStepObjectObject.cs index 3c774719f..21477c60d 100644 --- a/.dotnet/src/Generated/Models/RunStepObjectObject.cs +++ b/.dotnet/src/Generated/Models/RunStepObjectObject.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public RunStepObjectObject(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/RunStepObjectStatus.cs b/.dotnet/src/Generated/Models/RunStepObjectStatus.cs index 4b11e62a4..21abb0c10 100644 --- a/.dotnet/src/Generated/Models/RunStepObjectStatus.cs +++ b/.dotnet/src/Generated/Models/RunStepObjectStatus.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -55,3 +53,4 @@ public RunStepObjectStatus(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/RunStepObjectType.cs b/.dotnet/src/Generated/Models/RunStepObjectType.cs index 49adee903..432a90099 100644 --- a/.dotnet/src/Generated/Models/RunStepObjectType.cs +++ b/.dotnet/src/Generated/Models/RunStepObjectType.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -46,3 +44,4 @@ public RunStepObjectType(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/RunToolCallObject.Serialization.cs b/.dotnet/src/Generated/Models/RunToolCallObject.Serialization.cs index 421bb3a02..47b58bfd9 100644 --- a/.dotnet/src/Generated/Models/RunToolCallObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunToolCallObject.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class RunToolCallObject : IUtf8JsonWriteable, IJsonModel + public partial class RunToolCallObject : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -136,13 +132,6 @@ internal static RunToolCallObject FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeRunToolCallObject(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/RunToolCallObject.cs b/.dotnet/src/Generated/Models/RunToolCallObject.cs index b6f3694a3..d70655724 100644 --- a/.dotnet/src/Generated/Models/RunToolCallObject.cs +++ b/.dotnet/src/Generated/Models/RunToolCallObject.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -52,8 +50,8 @@ public partial class RunToolCallObject /// or is null. internal RunToolCallObject(string id, RunToolCallObjectFunction function) { - ClientUtilities.AssertNotNull(id, nameof(id)); - ClientUtilities.AssertNotNull(function, nameof(function)); + if (id is null) throw new ArgumentNullException(nameof(id)); + if (function is null) throw new ArgumentNullException(nameof(function)); Id = id; Function = function; @@ -92,3 +90,4 @@ internal RunToolCallObject() public RunToolCallObjectFunction Function { get; } } } + diff --git a/.dotnet/src/Generated/Models/RunToolCallObjectFunction.Serialization.cs b/.dotnet/src/Generated/Models/RunToolCallObjectFunction.Serialization.cs index ecef680d8..a62970151 100644 --- a/.dotnet/src/Generated/Models/RunToolCallObjectFunction.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunToolCallObjectFunction.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class RunToolCallObjectFunction : IUtf8JsonWriteable, IJsonModel + public partial class RunToolCallObjectFunction : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -128,13 +124,6 @@ internal static RunToolCallObjectFunction FromResponse(PipelineResponse response using var document = JsonDocument.Parse(response.Content); return DeserializeRunToolCallObjectFunction(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/RunToolCallObjectFunction.cs b/.dotnet/src/Generated/Models/RunToolCallObjectFunction.cs index c94197dac..1fab15eac 100644 --- a/.dotnet/src/Generated/Models/RunToolCallObjectFunction.cs +++ b/.dotnet/src/Generated/Models/RunToolCallObjectFunction.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -49,8 +47,8 @@ public partial class RunToolCallObjectFunction /// or is null. internal RunToolCallObjectFunction(string name, string arguments) { - ClientUtilities.AssertNotNull(name, nameof(name)); - ClientUtilities.AssertNotNull(arguments, nameof(arguments)); + if (name is null) throw new ArgumentNullException(nameof(name)); + if (arguments is null) throw new ArgumentNullException(nameof(arguments)); Name = name; Arguments = arguments; @@ -78,3 +76,4 @@ internal RunToolCallObjectFunction() public string Arguments { get; } } } + diff --git a/.dotnet/src/Generated/Models/RunToolCallObjectType.cs b/.dotnet/src/Generated/Models/RunToolCallObjectType.cs index fb277c525..d882bc7f3 100644 --- a/.dotnet/src/Generated/Models/RunToolCallObjectType.cs +++ b/.dotnet/src/Generated/Models/RunToolCallObjectType.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public RunToolCallObjectType(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.Serialization.cs b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.Serialization.cs index b1c71aec2..a5bf6fda2 100644 --- a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class SubmitToolOutputsRunRequest : IUtf8JsonWriteable, IJsonModel + public partial class SubmitToolOutputsRunRequest : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -120,13 +116,6 @@ internal static SubmitToolOutputsRunRequest FromResponse(PipelineResponse respon using var document = JsonDocument.Parse(response.Content); return DeserializeSubmitToolOutputsRunRequest(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.cs b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.cs index 47d39c5d4..abdcfb9e3 100644 --- a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.cs +++ b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -48,7 +46,7 @@ public partial class SubmitToolOutputsRunRequest /// is null. public SubmitToolOutputsRunRequest(SubmitToolOutputsRunRequestToolOutputs toolOutputs) { - ClientUtilities.AssertNotNull(toolOutputs, nameof(toolOutputs)); + if (toolOutputs is null) throw new ArgumentNullException(nameof(toolOutputs)); ToolOutputs = toolOutputs; } @@ -71,3 +69,4 @@ internal SubmitToolOutputsRunRequest() public SubmitToolOutputsRunRequestToolOutputs ToolOutputs { get; } } } + diff --git a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutputs.Serialization.cs b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutputs.Serialization.cs index dc7e3a12d..f7c09dcf1 100644 --- a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutputs.Serialization.cs +++ b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutputs.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class SubmitToolOutputsRunRequestToolOutputs : IUtf8JsonWriteable, IJsonModel + public partial class SubmitToolOutputsRunRequestToolOutputs : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -134,13 +130,6 @@ internal static SubmitToolOutputsRunRequestToolOutputs FromResponse(PipelineResp using var document = JsonDocument.Parse(response.Content); return DeserializeSubmitToolOutputsRunRequestToolOutputs(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutputs.cs b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutputs.cs index 45de2cc25..8d8a8109c 100644 --- a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutputs.cs +++ b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutputs.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.Collections.Generic; @@ -70,3 +68,4 @@ internal SubmitToolOutputsRunRequestToolOutputs(string toolCallId, string output public string Output { get; set; } } } + diff --git a/.dotnet/src/Generated/Models/ThreadObject.Serialization.cs b/.dotnet/src/Generated/Models/ThreadObject.Serialization.cs index 1d3b80be1..4644d1aa9 100644 --- a/.dotnet/src/Generated/Models/ThreadObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/ThreadObject.Serialization.cs @@ -1,19 +1,15 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models { - public partial class ThreadObject : IUtf8JsonWriteable, IJsonModel + public partial class ThreadObject : IJsonModel { - void IUtf8JsonWriteable.Write(Utf8JsonWriter writer) => ((IJsonModel)this).Write(writer, new ModelReaderWriterOptions("W")); - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; @@ -167,13 +163,6 @@ internal static ThreadObject FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeThreadObject(document.RootElement); } - - /// Convert into a Utf8JsonRequestBody. - internal virtual RequestBody ToRequestBody() - { - var content = new Utf8JsonRequestBody(); - content.JsonWriter.WriteObjectValue(this); - return content; - } } } + diff --git a/.dotnet/src/Generated/Models/ThreadObject.cs b/.dotnet/src/Generated/Models/ThreadObject.cs index 600c5b250..22d754976 100644 --- a/.dotnet/src/Generated/Models/ThreadObject.cs +++ b/.dotnet/src/Generated/Models/ThreadObject.cs @@ -1,9 +1,7 @@ // -#nullable disable - using System; -using System.ClientModel.Internal; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Models @@ -54,7 +52,7 @@ public partial class ThreadObject /// is null. internal ThreadObject(string id, DateTimeOffset createdAt, IReadOnlyDictionary metadata) { - ClientUtilities.AssertNotNull(id, nameof(id)); + if (id is null) throw new ArgumentNullException(nameof(id)); Id = id; CreatedAt = createdAt; @@ -100,3 +98,4 @@ internal ThreadObject() public IReadOnlyDictionary Metadata { get; } } } + diff --git a/.dotnet/src/Generated/Models/ThreadObjectObject.cs b/.dotnet/src/Generated/Models/ThreadObjectObject.cs index 4fd5f5e05..8eb382a0b 100644 --- a/.dotnet/src/Generated/Models/ThreadObjectObject.cs +++ b/.dotnet/src/Generated/Models/ThreadObjectObject.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.ComponentModel; @@ -43,3 +41,4 @@ public ThreadObjectObject(string value) public override string ToString() => _value; } } + diff --git a/.dotnet/src/Generated/ModelsOps.cs b/.dotnet/src/Generated/ModelsOps.cs index 5b9442920..e806f3cef 100644 --- a/.dotnet/src/Generated/ModelsOps.cs +++ b/.dotnet/src/Generated/ModelsOps.cs @@ -1,12 +1,9 @@ // -#nullable disable - using System; using System.ClientModel; -using System.ClientModel.Internal; using System.ClientModel.Primitives; -using System.ClientModel.Primitives.Pipeline; +using System.Text; using System.Threading; using System.Threading.Tasks; using OpenAI.Models; @@ -18,16 +15,13 @@ namespace OpenAI public partial class ModelsOps { private const string AuthorizationHeader = "Authorization"; - private readonly KeyCredential _keyCredential; + private readonly ApiKeyCredential _credential; private const string AuthorizationApiKeyPrefix = "Bearer"; - private readonly MessagePipeline _pipeline; + private readonly ClientPipeline _pipeline; private readonly Uri _endpoint; - /// The ClientDiagnostics is used to provide tracing support for the client library. - internal TelemetrySource ClientDiagnostics { get; } - /// The HTTP pipeline for sending and receiving REST requests and responses. - public virtual MessagePipeline Pipeline => _pipeline; + public virtual ClientPipeline Pipeline => _pipeline; /// Initializes a new instance of ModelsOps for mocking. protected ModelsOps() @@ -35,15 +29,13 @@ protected ModelsOps() } /// Initializes a new instance of ModelsOps. - /// The handler for diagnostic messaging in the client. /// The HTTP pipeline for sending and receiving REST requests and responses. - /// The key credential to copy. + /// The key credential to copy. /// OpenAI Endpoint. - internal ModelsOps(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + internal ModelsOps(ClientPipeline pipeline, ApiKeyCredential credential, Uri endpoint) { - ClientDiagnostics = clientDiagnostics; _pipeline = pipeline; - _keyCredential = keyCredential; + _credential = credential; _endpoint = endpoint; } @@ -51,24 +43,20 @@ internal ModelsOps(TelemetrySource clientDiagnostics, MessagePipeline pipeline, /// Lists the currently available models, and provides basic information about each one such as the /// owner and availability. /// - /// The cancellation token to use. - public virtual async Task> GetModelsAsync(CancellationToken cancellationToken = default) + public virtual async Task> GetModelsAsync(CancellationToken cancellationToken = default) { - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await GetModelsAsync(context).ConfigureAwait(false); - return Result.FromValue(ListModelsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = await GetModelsAsync().ConfigureAwait(false); + return ClientResult.FromValue(ListModelsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// /// Lists the currently available models, and provides basic information about each one such as the /// owner and availability. /// - /// The cancellation token to use. - public virtual Result GetModels(CancellationToken cancellationToken = default) + public virtual ClientResult GetModels(CancellationToken cancellationToken = default) { - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = GetModels(context); - return Result.FromValue(ListModelsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = GetModels(); + return ClientResult.FromValue(ListModelsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -87,23 +75,22 @@ public virtual Result GetModels(CancellationToken cancellati /// /// /// - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// Service returned a non-success status code. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task GetModelsAsync(RequestOptions context) + public virtual async Task GetModelsAsync(RequestOptions options) { - using var scope = ClientDiagnostics.CreateSpan("ModelsOps.GetModels"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetModelsRequest(context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetModelsRequest(options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -122,23 +109,22 @@ public virtual async Task GetModelsAsync(RequestOptions context) /// /// /// - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. - /// Service returned a non-success status code. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result GetModels(RequestOptions context) + public virtual ClientResult GetModels(RequestOptions options) { - using var scope = ClientDiagnostics.CreateSpan("ModelsOps.GetModels"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetModelsRequest(context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetModelsRequest(options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// @@ -146,16 +132,15 @@ public virtual Result GetModels(RequestOptions context) /// permissioning. /// /// The ID of the model to use for this request. - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual async Task> RetrieveAsync(string model, CancellationToken cancellationToken = default) + public virtual async Task> RetrieveAsync(string model) { - ClientUtilities.AssertNotNullOrEmpty(model, nameof(model)); + if (model is null) throw new ArgumentNullException(nameof(model)); + if (string.IsNullOrEmpty(model)) throw new ArgumentException(nameof(model)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await RetrieveAsync(model, context).ConfigureAwait(false); - return Result.FromValue(Model.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = await RetrieveAsync(model).ConfigureAwait(false); + return ClientResult.FromValue(Model.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -163,16 +148,15 @@ public virtual async Task> RetrieveAsync(string model, Cancellatio /// permissioning. /// /// The ID of the model to use for this request. - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual Result Retrieve(string model, CancellationToken cancellationToken = default) + public virtual ClientResult Retrieve(string model) { - ClientUtilities.AssertNotNullOrEmpty(model, nameof(model)); + if (model is null) throw new ArgumentNullException(nameof(model)); + if (string.IsNullOrEmpty(model)) throw new ArgumentException(nameof(model)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = Retrieve(model, context); - return Result.FromValue(Model.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = Retrieve(model); + return ClientResult.FromValue(Model.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -186,33 +170,32 @@ public virtual Result Retrieve(string model, CancellationToken cancellati /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the model to use for this request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task RetrieveAsync(string model, RequestOptions context) + public virtual async Task RetrieveAsync(string model, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(model, nameof(model)); - - using var scope = ClientDiagnostics.CreateSpan("ModelsOps.Retrieve"); - scope.Start(); - try - { - using PipelineMessage message = CreateRetrieveRequest(model, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (model is null) throw new ArgumentNullException(nameof(model)); + if (string.IsNullOrEmpty(model)) throw new ArgumentException(nameof(model)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateRetrieveRequest(model, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -226,61 +209,58 @@ public virtual async Task RetrieveAsync(string model, RequestOptions con /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the model to use for this request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result Retrieve(string model, RequestOptions context) + public virtual ClientResult Retrieve(string model, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(model, nameof(model)); - - using var scope = ClientDiagnostics.CreateSpan("ModelsOps.Retrieve"); - scope.Start(); - try - { - using PipelineMessage message = CreateRetrieveRequest(model, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + if (model is null) throw new ArgumentNullException(nameof(model)); + if (string.IsNullOrEmpty(model)) throw new ArgumentException(nameof(model)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateRetrieveRequest(model, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Delete a fine-tuned model. You must have the Owner role in your organization to delete a model. /// The model to delete. - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual async Task> DeleteAsync(string model, CancellationToken cancellationToken = default) + public virtual async Task> DeleteAsync(string model) { - ClientUtilities.AssertNotNullOrEmpty(model, nameof(model)); + if (model is null) throw new ArgumentNullException(nameof(model)); + if (string.IsNullOrEmpty(model)) throw new ArgumentException(nameof(model)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await DeleteAsync(model, context).ConfigureAwait(false); - return Result.FromValue(DeleteModelResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = await DeleteAsync(model).ConfigureAwait(false); + return ClientResult.FromValue(DeleteModelResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Delete a fine-tuned model. You must have the Owner role in your organization to delete a model. /// The model to delete. - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual Result Delete(string model, CancellationToken cancellationToken = default) + public virtual ClientResult Delete(string model) { - ClientUtilities.AssertNotNullOrEmpty(model, nameof(model)); + if (model is null) throw new ArgumentNullException(nameof(model)); + if (string.IsNullOrEmpty(model)) throw new ArgumentException(nameof(model)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = Delete(model, context); - return Result.FromValue(DeleteModelResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = Delete(model); + return ClientResult.FromValue(DeleteModelResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -293,33 +273,32 @@ public virtual Result Delete(string model, CancellationToke /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The model to delete. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task DeleteAsync(string model, RequestOptions context) + public virtual async Task DeleteAsync(string model, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(model, nameof(model)); - - using var scope = ClientDiagnostics.CreateSpan("ModelsOps.Delete"); - scope.Start(); - try - { - using PipelineMessage message = CreateDeleteRequest(model, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (model is null) throw new ArgumentNullException(nameof(model)); + if (string.IsNullOrEmpty(model)) throw new ArgumentException(nameof(model)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateDeleteRequest(model, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -332,88 +311,85 @@ public virtual async Task DeleteAsync(string model, RequestOptions conte /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The model to delete. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result Delete(string model, RequestOptions context) + public virtual ClientResult Delete(string model, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(model, nameof(model)); - - using var scope = ClientDiagnostics.CreateSpan("ModelsOps.Delete"); - scope.Start(); - try - { - using PipelineMessage message = CreateDeleteRequest(model, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + if (model is null) throw new ArgumentNullException(nameof(model)); + if (string.IsNullOrEmpty(model)) throw new ArgumentException(nameof(model)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateDeleteRequest(model, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } - } - internal PipelineMessage CreateGetModelsRequest(RequestOptions context) - { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("GET"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/models", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - return message; + return ClientResult.FromResponse(response); } - internal PipelineMessage CreateRetrieveRequest(string model, RequestOptions context) + internal PipelineMessage CreateGetModelsRequest(RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("GET"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/models/", false); - uri.AppendPath(model, true); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "GET"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/models"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); return message; } - internal PipelineMessage CreateDeleteRequest(string model, RequestOptions context) + internal PipelineMessage CreateRetrieveRequest(string model, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("DELETE"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/models/", false); - uri.AppendPath(model, true); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "GET"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/models/"); + uriBuilder.Path += path.ToString(); + path.Append(model); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); return message; } - private static RequestOptions DefaultRequestContext = new RequestOptions(); - internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) + internal PipelineMessage CreateDeleteRequest(string model, RequestOptions options) { - if (!cancellationToken.CanBeCanceled) - { - return DefaultRequestContext; - } - - return new RequestOptions() { CancellationToken = cancellationToken }; + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "DELETE"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/models/"); + uriBuilder.Path += path.ToString(); + path.Append(model); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); + return message; } - private static ResponseErrorClassifier _responseErrorClassifier200; - private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); + private static PipelineMessageClassifier _responseErrorClassifier200; + private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } } + diff --git a/.dotnet/src/Generated/Moderations.cs b/.dotnet/src/Generated/Moderations.cs index 7c4520943..e0127be76 100644 --- a/.dotnet/src/Generated/Moderations.cs +++ b/.dotnet/src/Generated/Moderations.cs @@ -1,12 +1,9 @@ // -#nullable disable - using System; using System.ClientModel; -using System.ClientModel.Internal; using System.ClientModel.Primitives; -using System.ClientModel.Primitives.Pipeline; +using System.Text; using System.Threading; using System.Threading.Tasks; using OpenAI.Models; @@ -18,16 +15,13 @@ namespace OpenAI public partial class Moderations { private const string AuthorizationHeader = "Authorization"; - private readonly KeyCredential _keyCredential; + private readonly ApiKeyCredential _credential; private const string AuthorizationApiKeyPrefix = "Bearer"; - private readonly MessagePipeline _pipeline; + private readonly ClientPipeline _pipeline; private readonly Uri _endpoint; - /// The ClientDiagnostics is used to provide tracing support for the client library. - internal TelemetrySource ClientDiagnostics { get; } - /// The HTTP pipeline for sending and receiving REST requests and responses. - public virtual MessagePipeline Pipeline => _pipeline; + public virtual ClientPipeline Pipeline => _pipeline; /// Initializes a new instance of Moderations for mocking. protected Moderations() @@ -35,44 +29,38 @@ protected Moderations() } /// Initializes a new instance of Moderations. - /// The handler for diagnostic messaging in the client. /// The HTTP pipeline for sending and receiving REST requests and responses. - /// The key credential to copy. + /// The key credential to copy. /// OpenAI Endpoint. - internal Moderations(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + internal Moderations(ClientPipeline pipeline, ApiKeyCredential credential, Uri endpoint) { - ClientDiagnostics = clientDiagnostics; _pipeline = pipeline; - _keyCredential = keyCredential; + _credential = credential; _endpoint = endpoint; } /// Classifies if text violates OpenAI's Content Policy. /// The to use. - /// The cancellation token to use. /// is null. - public virtual async Task> CreateModerationAsync(CreateModerationRequest content, CancellationToken cancellationToken = default) + public virtual async Task> CreateModerationAsync(CreateModerationRequest content) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content0 = content.ToRequestBody(); - Result result = await CreateModerationAsync(content0, context).ConfigureAwait(false); - return Result.FromValue(CreateModerationResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content0 = BinaryContent.Create(content); + ClientResult result = await CreateModerationAsync(content0).ConfigureAwait(false); + return ClientResult.FromValue(CreateModerationResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Classifies if text violates OpenAI's Content Policy. /// The to use. - /// The cancellation token to use. /// is null. - public virtual Result CreateModeration(CreateModerationRequest content, CancellationToken cancellationToken = default) + public virtual ClientResult CreateModeration(CreateModerationRequest content) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content0 = content.ToRequestBody(); - Result result = CreateModeration(content0, context); - return Result.FromValue(CreateModerationResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content0 = BinaryContent.Create(content); + ClientResult result = CreateModeration(content0); + return ClientResult.FromValue(CreateModerationResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -85,32 +73,30 @@ public virtual Result CreateModeration(CreateModeratio /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task CreateModerationAsync(RequestBody content, RequestOptions context = null) + public virtual async Task CreateModerationAsync(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateModerationRequest(content, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Moderations.CreateModeration"); - scope.Start(); - try - { - using PipelineMessage message = CreateCreateModerationRequest(content, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -123,61 +109,52 @@ public virtual async Task CreateModerationAsync(RequestBody content, Req /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result CreateModeration(RequestBody content, RequestOptions context = null) + public virtual ClientResult CreateModeration(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateModerationRequest(content, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Moderations.CreateModeration"); - scope.Start(); - try - { - using PipelineMessage message = CreateCreateModerationRequest(content, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } - internal PipelineMessage CreateCreateModerationRequest(RequestBody content, RequestOptions context) + internal PipelineMessage CreateCreateModerationRequest(BinaryContent content, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/moderations", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - request.SetHeaderValue("Content-Type", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/moderations"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); + request.Headers.Set("Content-Type", "application/json"); request.Content = content; + message.Apply(options); return message; } - private static RequestOptions DefaultRequestContext = new RequestOptions(); - internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) - { - if (!cancellationToken.CanBeCanceled) - { - return DefaultRequestContext; - } - - return new RequestOptions() { CancellationToken = cancellationToken }; - } - - private static ResponseErrorClassifier _responseErrorClassifier200; - private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); + private static PipelineMessageClassifier _responseErrorClassifier200; + private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } } + diff --git a/.dotnet/src/Generated/OpenAIClient.cs b/.dotnet/src/Generated/OpenAIClient.cs index 67ceeca49..29785453c 100644 --- a/.dotnet/src/Generated/OpenAIClient.cs +++ b/.dotnet/src/Generated/OpenAIClient.cs @@ -1,12 +1,8 @@ // -#nullable disable - using System; using System.ClientModel; -using System.ClientModel.Internal; using System.ClientModel.Primitives; -using System.ClientModel.Primitives.Pipeline; using System.Threading; namespace OpenAI @@ -16,16 +12,13 @@ namespace OpenAI public partial class OpenAIClient { private const string AuthorizationHeader = "Authorization"; - private readonly KeyCredential _keyCredential; + private readonly ApiKeyCredential _credential; private const string AuthorizationApiKeyPrefix = "Bearer"; - private readonly MessagePipeline _pipeline; + private readonly ClientPipeline _pipeline; private readonly Uri _endpoint; - /// The ClientDiagnostics is used to provide tracing support for the client library. - internal TelemetrySource ClientDiagnostics { get; } - /// The HTTP pipeline for sending and receiving REST requests and responses. - public virtual MessagePipeline Pipeline => _pipeline; + public virtual ClientPipeline Pipeline => _pipeline; /// Initializes a new instance of OpenAIClient for mocking. protected OpenAIClient() @@ -35,7 +28,7 @@ protected OpenAIClient() /// Initializes a new instance of OpenAIClient. /// A credential used to authenticate to an Azure Service. /// is null. - public OpenAIClient(KeyCredential credential) : this(new Uri("https://api.openai.com/v1"), credential, new OpenAIClientOptions()) + public OpenAIClient(ApiKeyCredential credential) : this(new Uri("https://api.openai.com/v1"), credential, new OpenAIClientOptions()) { } @@ -44,15 +37,17 @@ protected OpenAIClient() /// A credential used to authenticate to an Azure Service. /// The options for configuring the client. /// or is null. - public OpenAIClient(Uri endpoint, KeyCredential credential, OpenAIClientOptions options) + public OpenAIClient(Uri endpoint, ApiKeyCredential credential, OpenAIClientOptions options) { - ClientUtilities.AssertNotNull(endpoint, nameof(endpoint)); - ClientUtilities.AssertNotNull(credential, nameof(credential)); + if (endpoint is null) throw new ArgumentNullException(nameof(endpoint)); + if (credential is null) throw new ArgumentNullException(nameof(credential)); options ??= new OpenAIClientOptions(); - - ClientDiagnostics = new TelemetrySource(options, true); - _keyCredential = credential; - _pipeline = MessagePipeline.Create(options, new IPipelinePolicy[] { new KeyCredentialPolicy(_keyCredential, AuthorizationHeader, AuthorizationApiKeyPrefix) }, Array.Empty>()); + _credential = credential; + var authenticationPolicy = ApiKeyAuthenticationPolicy.CreateBearerAuthorizationPolicy(_credential); + _pipeline = ClientPipeline.Create(options, + perCallPolicies: ReadOnlySpan.Empty, + perTryPolicies: new PipelinePolicy[] { authenticationPolicy }, + beforeTransportPolicies: ReadOnlySpan.Empty); _endpoint = endpoint; } @@ -73,79 +68,80 @@ public OpenAIClient(Uri endpoint, KeyCredential credential, OpenAIClientOptions /// Initializes a new instance of Audio. public virtual Audio GetAudioClient() { - return Volatile.Read(ref _cachedAudio) ?? Interlocked.CompareExchange(ref _cachedAudio, new Audio(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedAudio; + return Volatile.Read(ref _cachedAudio) ?? Interlocked.CompareExchange(ref _cachedAudio, new Audio(_pipeline, _credential, _endpoint), null) ?? _cachedAudio; } /// Initializes a new instance of Assistants. public virtual Assistants GetAssistantsClient() { - return Volatile.Read(ref _cachedAssistants) ?? Interlocked.CompareExchange(ref _cachedAssistants, new Assistants(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedAssistants; + return Volatile.Read(ref _cachedAssistants) ?? Interlocked.CompareExchange(ref _cachedAssistants, new Assistants(_pipeline, _credential, _endpoint), null) ?? _cachedAssistants; } /// Initializes a new instance of Chat. public virtual Chat GetChatClient() { - return Volatile.Read(ref _cachedChat) ?? Interlocked.CompareExchange(ref _cachedChat, new Chat(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedChat; + return Volatile.Read(ref _cachedChat) ?? Interlocked.CompareExchange(ref _cachedChat, new Chat(_pipeline, _credential, _endpoint), null) ?? _cachedChat; } /// Initializes a new instance of Completions. public virtual Completions GetCompletionsClient() { - return Volatile.Read(ref _cachedCompletions) ?? Interlocked.CompareExchange(ref _cachedCompletions, new Completions(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedCompletions; + return Volatile.Read(ref _cachedCompletions) ?? Interlocked.CompareExchange(ref _cachedCompletions, new Completions(_pipeline, _credential, _endpoint), null) ?? _cachedCompletions; } /// Initializes a new instance of Embeddings. public virtual Embeddings GetEmbeddingsClient() { - return Volatile.Read(ref _cachedEmbeddings) ?? Interlocked.CompareExchange(ref _cachedEmbeddings, new Embeddings(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedEmbeddings; + return Volatile.Read(ref _cachedEmbeddings) ?? Interlocked.CompareExchange(ref _cachedEmbeddings, new Embeddings(_pipeline, _credential, _endpoint), null) ?? _cachedEmbeddings; } /// Initializes a new instance of Files. public virtual Files GetFilesClient() { - return Volatile.Read(ref _cachedFiles) ?? Interlocked.CompareExchange(ref _cachedFiles, new Files(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedFiles; + return Volatile.Read(ref _cachedFiles) ?? Interlocked.CompareExchange(ref _cachedFiles, new Files(_pipeline, _credential, _endpoint), null) ?? _cachedFiles; } /// Initializes a new instance of FineTuning. public virtual FineTuning GetFineTuningClient() { - return Volatile.Read(ref _cachedFineTuning) ?? Interlocked.CompareExchange(ref _cachedFineTuning, new FineTuning(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedFineTuning; + return Volatile.Read(ref _cachedFineTuning) ?? Interlocked.CompareExchange(ref _cachedFineTuning, new FineTuning(_pipeline, _credential, _endpoint), null) ?? _cachedFineTuning; } /// Initializes a new instance of Images. public virtual Images GetImagesClient() { - return Volatile.Read(ref _cachedImages) ?? Interlocked.CompareExchange(ref _cachedImages, new Images(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedImages; + return Volatile.Read(ref _cachedImages) ?? Interlocked.CompareExchange(ref _cachedImages, new Images(_pipeline, _credential, _endpoint), null) ?? _cachedImages; } /// Initializes a new instance of Messages. public virtual Messages GetMessagesClient() { - return Volatile.Read(ref _cachedMessages) ?? Interlocked.CompareExchange(ref _cachedMessages, new Messages(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedMessages; + return Volatile.Read(ref _cachedMessages) ?? Interlocked.CompareExchange(ref _cachedMessages, new Messages(_pipeline, _credential, _endpoint), null) ?? _cachedMessages; } /// Initializes a new instance of ModelsOps. public virtual ModelsOps GetModelsOpsClient() { - return Volatile.Read(ref _cachedModelsOps) ?? Interlocked.CompareExchange(ref _cachedModelsOps, new ModelsOps(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedModelsOps; + return Volatile.Read(ref _cachedModelsOps) ?? Interlocked.CompareExchange(ref _cachedModelsOps, new ModelsOps(_pipeline, _credential, _endpoint), null) ?? _cachedModelsOps; } /// Initializes a new instance of Moderations. public virtual Moderations GetModerationsClient() { - return Volatile.Read(ref _cachedModerations) ?? Interlocked.CompareExchange(ref _cachedModerations, new Moderations(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedModerations; + return Volatile.Read(ref _cachedModerations) ?? Interlocked.CompareExchange(ref _cachedModerations, new Moderations(_pipeline, _credential, _endpoint), null) ?? _cachedModerations; } /// Initializes a new instance of Runs. public virtual Runs GetRunsClient() { - return Volatile.Read(ref _cachedRuns) ?? Interlocked.CompareExchange(ref _cachedRuns, new Runs(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedRuns; + return Volatile.Read(ref _cachedRuns) ?? Interlocked.CompareExchange(ref _cachedRuns, new Runs(_pipeline, _credential, _endpoint), null) ?? _cachedRuns; } /// Initializes a new instance of Threads. public virtual Threads GetThreadsClient() { - return Volatile.Read(ref _cachedThreads) ?? Interlocked.CompareExchange(ref _cachedThreads, new Threads(ClientDiagnostics, _pipeline, _keyCredential, _endpoint), null) ?? _cachedThreads; + return Volatile.Read(ref _cachedThreads) ?? Interlocked.CompareExchange(ref _cachedThreads, new Threads(_pipeline, _credential, _endpoint), null) ?? _cachedThreads; } } } + diff --git a/.dotnet/src/Generated/OpenAIClientOptions.cs b/.dotnet/src/Generated/OpenAIClientOptions.cs index 5b661878a..31df0818d 100644 --- a/.dotnet/src/Generated/OpenAIClientOptions.cs +++ b/.dotnet/src/Generated/OpenAIClientOptions.cs @@ -1,13 +1,12 @@ // -#nullable disable - -using System.ClientModel; +using System.ClientModel.Primitives; namespace OpenAI { /// Client options for OpenAIClient. - public partial class OpenAIClientOptions : RequestOptions + public partial class OpenAIClientOptions : ClientPipelineOptions { } } + diff --git a/.dotnet/src/Generated/OpenAIModelFactory.cs b/.dotnet/src/Generated/OpenAIModelFactory.cs index 494ab0f0a..c8de3f61a 100644 --- a/.dotnet/src/Generated/OpenAIModelFactory.cs +++ b/.dotnet/src/Generated/OpenAIModelFactory.cs @@ -1,7 +1,5 @@ // -#nullable disable - using System; using System.Collections.Generic; using System.Linq; @@ -576,7 +574,7 @@ public static CompletionUsage CompletionUsage(long promptTokens = default, long /// /// /// Generates `best_of` completions server-side and returns the "best" (the one with the highest - /// log probability per token). Results cannot be streamed. + /// log probability per token). ClientResults cannot be streamed. /// /// When used with `n`, `best_of` controls the number of candidate completions and `n` specifies /// how many to return – `best_of` must be greater than `n`. @@ -1579,3 +1577,4 @@ public static DeleteThreadResponse DeleteThreadResponse(string id = null, bool d } } } + diff --git a/.dotnet/src/Generated/Runs.cs b/.dotnet/src/Generated/Runs.cs index fbe954204..05661caa5 100644 --- a/.dotnet/src/Generated/Runs.cs +++ b/.dotnet/src/Generated/Runs.cs @@ -1,12 +1,9 @@ // -#nullable disable - using System; using System.ClientModel; -using System.ClientModel.Internal; using System.ClientModel.Primitives; -using System.ClientModel.Primitives.Pipeline; +using System.Text; using System.Threading; using System.Threading.Tasks; using OpenAI.Models; @@ -18,16 +15,13 @@ namespace OpenAI public partial class Runs { private const string AuthorizationHeader = "Authorization"; - private readonly KeyCredential _keyCredential; + private readonly ApiKeyCredential _credential; private const string AuthorizationApiKeyPrefix = "Bearer"; - private readonly MessagePipeline _pipeline; + private readonly ClientPipeline _pipeline; private readonly Uri _endpoint; - /// The ClientDiagnostics is used to provide tracing support for the client library. - internal TelemetrySource ClientDiagnostics { get; } - /// The HTTP pipeline for sending and receiving REST requests and responses. - public virtual MessagePipeline Pipeline => _pipeline; + public virtual ClientPipeline Pipeline => _pipeline; /// Initializes a new instance of Runs for mocking. protected Runs() @@ -35,44 +29,38 @@ protected Runs() } /// Initializes a new instance of Runs. - /// The handler for diagnostic messaging in the client. /// The HTTP pipeline for sending and receiving REST requests and responses. - /// The key credential to copy. + /// The key credential to copy. /// OpenAI Endpoint. - internal Runs(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + internal Runs(ClientPipeline pipeline, ApiKeyCredential credential, Uri endpoint) { - ClientDiagnostics = clientDiagnostics; _pipeline = pipeline; - _keyCredential = keyCredential; + _credential = credential; _endpoint = endpoint; } /// Create a thread and run it in one request. /// The to use. - /// The cancellation token to use. /// is null. - public virtual async Task> CreateThreadAndRunAsync(CreateThreadAndRunRequest threadAndRun, CancellationToken cancellationToken = default) + public virtual async Task> CreateThreadAndRunAsync(CreateThreadAndRunRequest threadAndRun) { - ClientUtilities.AssertNotNull(threadAndRun, nameof(threadAndRun)); + if (threadAndRun is null) throw new ArgumentNullException(nameof(threadAndRun)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = threadAndRun.ToRequestBody(); - Result result = await CreateThreadAndRunAsync(content, context).ConfigureAwait(false); - return Result.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(threadAndRun); + ClientResult result = await CreateThreadAndRunAsync(content).ConfigureAwait(false); + return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Create a thread and run it in one request. /// The to use. - /// The cancellation token to use. /// is null. - public virtual Result CreateThreadAndRun(CreateThreadAndRunRequest threadAndRun, CancellationToken cancellationToken = default) + public virtual ClientResult CreateThreadAndRun(CreateThreadAndRunRequest threadAndRun) { - ClientUtilities.AssertNotNull(threadAndRun, nameof(threadAndRun)); + if (threadAndRun is null) throw new ArgumentNullException(nameof(threadAndRun)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = threadAndRun.ToRequestBody(); - Result result = CreateThreadAndRun(content, context); - return Result.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(threadAndRun); + ClientResult result = CreateThreadAndRun(content); + return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -85,32 +73,30 @@ public virtual Result CreateThreadAndRun(CreateThreadAndRunRequest th /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task CreateThreadAndRunAsync(RequestBody content, RequestOptions context = null) + public virtual async Task CreateThreadAndRunAsync(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateThreadAndRunRequest(content, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Runs.CreateThreadAndRun"); - scope.Start(); - try - { - using PipelineMessage message = CreateCreateThreadAndRunRequest(content, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -123,66 +109,62 @@ public virtual async Task CreateThreadAndRunAsync(RequestBody content, R /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result CreateThreadAndRun(RequestBody content, RequestOptions context = null) + public virtual ClientResult CreateThreadAndRun(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateThreadAndRunRequest(content, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Runs.CreateThreadAndRun"); - scope.Start(); - try + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateCreateThreadAndRunRequest(content, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Create a run. /// The ID of the thread to run. /// The to use. - /// The cancellation token to use. /// or is null. /// is an empty string, and was expected to be non-empty. - public virtual async Task> CreateRunAsync(string threadId, CreateRunRequest run, CancellationToken cancellationToken = default) + public virtual async Task> CreateRunAsync(string threadId, CreateRunRequest run) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNull(run, nameof(run)); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (run is null) throw new ArgumentNullException(nameof(run)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = run.ToRequestBody(); - Result result = await CreateRunAsync(threadId, content, context).ConfigureAwait(false); - return Result.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(run); + ClientResult result = await CreateRunAsync(threadId, content).ConfigureAwait(false); + return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Create a run. /// The ID of the thread to run. /// The to use. - /// The cancellation token to use. /// or is null. /// is an empty string, and was expected to be non-empty. - public virtual Result CreateRun(string threadId, CreateRunRequest run, CancellationToken cancellationToken = default) + public virtual ClientResult CreateRun(string threadId, CreateRunRequest run) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNull(run, nameof(run)); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (run is null) throw new ArgumentNullException(nameof(run)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = run.ToRequestBody(); - Result result = CreateRun(threadId, content, context); - return Result.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(run); + ClientResult result = CreateRun(threadId, content); + return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -195,35 +177,34 @@ public virtual Result CreateRun(string threadId, CreateRunRequest run /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the thread to run. /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// or is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task CreateRunAsync(string threadId, RequestBody content, RequestOptions context = null) + public virtual async Task CreateRunAsync(string threadId, BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNull(content, nameof(content)); - - using var scope = ClientDiagnostics.CreateSpan("Runs.CreateRun"); - scope.Start(); - try - { - using PipelineMessage message = CreateCreateRunRequest(threadId, content, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateRunRequest(threadId, content, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -236,35 +217,34 @@ public virtual async Task CreateRunAsync(string threadId, RequestBody co /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the thread to run. /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// or is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result CreateRun(string threadId, RequestBody content, RequestOptions context = null) + public virtual ClientResult CreateRun(string threadId, BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNull(content, nameof(content)); - - using var scope = ClientDiagnostics.CreateSpan("Runs.CreateRun"); - scope.Start(); - try + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateRunRequest(threadId, content, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateCreateRunRequest(threadId, content, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Returns a list of runs belonging to a thread. @@ -287,16 +267,15 @@ public virtual Result CreateRun(string threadId, RequestBody content, RequestOpt /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. /// - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual async Task> GetRunsAsync(string threadId, int? limit = null, ListOrder? order = null, string after = null, string before = null, CancellationToken cancellationToken = default) + public virtual async Task> GetRunsAsync(string threadId, int? limit = null, ListOrder? order = null, string after = null, string before = null) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await GetRunsAsync(threadId, limit, order?.ToString(), after, before, context).ConfigureAwait(false); - return Result.FromValue(ListRunsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = await GetRunsAsync(threadId, limit, order?.ToString(), after, before).ConfigureAwait(false); + return ClientResult.FromValue(ListRunsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Returns a list of runs belonging to a thread. @@ -319,16 +298,15 @@ public virtual async Task> GetRunsAsync(string threadId /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. /// - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual Result GetRuns(string threadId, int? limit = null, ListOrder? order = null, string after = null, string before = null, CancellationToken cancellationToken = default) + public virtual ClientResult GetRuns(string threadId, int? limit = null, ListOrder? order = null, string after = null, string before = null) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = GetRuns(threadId, limit, order?.ToString(), after, before, context); - return Result.FromValue(ListRunsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = GetRuns(threadId, limit, order?.ToString(), after, before); + return ClientResult.FromValue(ListRunsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -341,7 +319,7 @@ public virtual Result GetRuns(string threadId, int? limit = nu /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -365,27 +343,26 @@ public virtual Result GetRuns(string threadId, int? limit = nu /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. /// - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task GetRunsAsync(string threadId, int? limit, string order, string after, string before, RequestOptions context) + public virtual async Task GetRunsAsync(string threadId, int? limit, string order, string after, string before, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - - using var scope = ClientDiagnostics.CreateSpan("Runs.GetRuns"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetRunsRequest(threadId, limit, order, after, before, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetRunsRequest(threadId, limit, order, after, before, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -398,7 +375,7 @@ public virtual async Task GetRunsAsync(string threadId, int? limit, stri /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -422,59 +399,58 @@ public virtual async Task GetRunsAsync(string threadId, int? limit, stri /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. /// - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result GetRuns(string threadId, int? limit, string order, string after, string before, RequestOptions context) + public virtual ClientResult GetRuns(string threadId, int? limit, string order, string after, string before, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - - using var scope = ClientDiagnostics.CreateSpan("Runs.GetRuns"); - scope.Start(); - try + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetRunsRequest(threadId, limit, order, after, before, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateGetRunsRequest(threadId, limit, order, after, before, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Retrieves a run. /// The ID of the [thread](/docs/api-reference/threads) that was run. /// The ID of the run to retrieve. - /// The cancellation token to use. /// or is null. /// or is an empty string, and was expected to be non-empty. - public virtual async Task> GetRunAsync(string threadId, string runId, CancellationToken cancellationToken = default) + public virtual async Task> GetRunAsync(string threadId, string runId) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (runId is null) throw new ArgumentNullException(nameof(runId)); + if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await GetRunAsync(threadId, runId, context).ConfigureAwait(false); - return Result.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = await GetRunAsync(threadId, runId).ConfigureAwait(false); + return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Retrieves a run. /// The ID of the [thread](/docs/api-reference/threads) that was run. /// The ID of the run to retrieve. - /// The cancellation token to use. /// or is null. /// or is an empty string, and was expected to be non-empty. - public virtual Result GetRun(string threadId, string runId, CancellationToken cancellationToken = default) + public virtual ClientResult GetRun(string threadId, string runId) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (runId is null) throw new ArgumentNullException(nameof(runId)); + if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = GetRun(threadId, runId, context); - return Result.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = GetRun(threadId, runId); + return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -487,35 +463,35 @@ public virtual Result GetRun(string threadId, string runId, Cancellat /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the [thread](/docs/api-reference/threads) that was run. /// The ID of the run to retrieve. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// or is null. /// or is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task GetRunAsync(string threadId, string runId, RequestOptions context) + public virtual async Task GetRunAsync(string threadId, string runId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); - - using var scope = ClientDiagnostics.CreateSpan("Runs.GetRun"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetRunRequest(threadId, runId, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (runId is null) throw new ArgumentNullException(nameof(runId)); + if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetRunRequest(threadId, runId, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -528,73 +504,73 @@ public virtual async Task GetRunAsync(string threadId, string runId, Req /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the [thread](/docs/api-reference/threads) that was run. /// The ID of the run to retrieve. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// or is null. /// or is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result GetRun(string threadId, string runId, RequestOptions context) + public virtual ClientResult GetRun(string threadId, string runId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); - - using var scope = ClientDiagnostics.CreateSpan("Runs.GetRun"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetRunRequest(threadId, runId, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (runId is null) throw new ArgumentNullException(nameof(runId)); + if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetRunRequest(threadId, runId, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Modifies a run. /// The ID of the [thread](/docs/api-reference/threads) that was run. /// The ID of the run to modify. /// The to use. - /// The cancellation token to use. /// , or is null. /// or is an empty string, and was expected to be non-empty. - public virtual async Task> ModifyRunAsync(string threadId, string runId, ModifyRunRequest run, CancellationToken cancellationToken = default) + public virtual async Task> ModifyRunAsync(string threadId, string runId, ModifyRunRequest run) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); - ClientUtilities.AssertNotNull(run, nameof(run)); - - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = run.ToRequestBody(); - Result result = await ModifyRunAsync(threadId, runId, content, context).ConfigureAwait(false); - return Result.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (runId is null) throw new ArgumentNullException(nameof(runId)); + if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); + if (run is null) throw new ArgumentNullException(nameof(run)); + + using BinaryContent content = BinaryContent.Create(run); + ClientResult result = await ModifyRunAsync(threadId, runId, content).ConfigureAwait(false); + return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Modifies a run. /// The ID of the [thread](/docs/api-reference/threads) that was run. /// The ID of the run to modify. /// The to use. - /// The cancellation token to use. /// , or is null. /// or is an empty string, and was expected to be non-empty. - public virtual Result ModifyRun(string threadId, string runId, ModifyRunRequest run, CancellationToken cancellationToken = default) + public virtual ClientResult ModifyRun(string threadId, string runId, ModifyRunRequest run) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); - ClientUtilities.AssertNotNull(run, nameof(run)); - - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = run.ToRequestBody(); - Result result = ModifyRun(threadId, runId, content, context); - return Result.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (runId is null) throw new ArgumentNullException(nameof(runId)); + if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); + if (run is null) throw new ArgumentNullException(nameof(run)); + + using BinaryContent content = BinaryContent.Create(run); + ClientResult result = ModifyRun(threadId, runId, content); + return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -607,7 +583,7 @@ public virtual Result ModifyRun(string threadId, string runId, Modify /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -615,29 +591,29 @@ public virtual Result ModifyRun(string threadId, string runId, Modify /// The ID of the [thread](/docs/api-reference/threads) that was run. /// The ID of the run to modify. /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// , or is null. /// or is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task ModifyRunAsync(string threadId, string runId, RequestBody content, RequestOptions context = null) + public virtual async Task ModifyRunAsync(string threadId, string runId, BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); - ClientUtilities.AssertNotNull(content, nameof(content)); - - using var scope = ClientDiagnostics.CreateSpan("Runs.ModifyRun"); - scope.Start(); - try + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (runId is null) throw new ArgumentNullException(nameof(runId)); + if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateModifyRunRequest(threadId, runId, content, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateModifyRunRequest(threadId, runId, content, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -650,7 +626,7 @@ public virtual async Task ModifyRunAsync(string threadId, string runId, /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -658,61 +634,61 @@ public virtual async Task ModifyRunAsync(string threadId, string runId, /// The ID of the [thread](/docs/api-reference/threads) that was run. /// The ID of the run to modify. /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// , or is null. /// or is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result ModifyRun(string threadId, string runId, RequestBody content, RequestOptions context = null) + public virtual ClientResult ModifyRun(string threadId, string runId, BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); - ClientUtilities.AssertNotNull(content, nameof(content)); - - using var scope = ClientDiagnostics.CreateSpan("Runs.ModifyRun"); - scope.Start(); - try - { - using PipelineMessage message = CreateModifyRunRequest(threadId, runId, content, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (runId is null) throw new ArgumentNullException(nameof(runId)); + if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateModifyRunRequest(threadId, runId, content, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Cancels a run that is `in_progress`. /// The ID of the thread to which this run belongs. /// The ID of the run to cancel. - /// The cancellation token to use. /// or is null. /// or is an empty string, and was expected to be non-empty. - public virtual async Task> CancelRunAsync(string threadId, string runId, CancellationToken cancellationToken = default) + public virtual async Task> CancelRunAsync(string threadId, string runId) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (runId is null) throw new ArgumentNullException(nameof(runId)); + if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await CancelRunAsync(threadId, runId, context).ConfigureAwait(false); - return Result.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = await CancelRunAsync(threadId, runId).ConfigureAwait(false); + return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Cancels a run that is `in_progress`. /// The ID of the thread to which this run belongs. /// The ID of the run to cancel. - /// The cancellation token to use. /// or is null. /// or is an empty string, and was expected to be non-empty. - public virtual Result CancelRun(string threadId, string runId, CancellationToken cancellationToken = default) + public virtual ClientResult CancelRun(string threadId, string runId) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (runId is null) throw new ArgumentNullException(nameof(runId)); + if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = CancelRun(threadId, runId, context); - return Result.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = CancelRun(threadId, runId); + return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -725,35 +701,35 @@ public virtual Result CancelRun(string threadId, string runId, Cancel /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the thread to which this run belongs. /// The ID of the run to cancel. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// or is null. /// or is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task CancelRunAsync(string threadId, string runId, RequestOptions context) + public virtual async Task CancelRunAsync(string threadId, string runId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); - - using var scope = ClientDiagnostics.CreateSpan("Runs.CancelRun"); - scope.Start(); - try + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (runId is null) throw new ArgumentNullException(nameof(runId)); + if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCancelRunRequest(threadId, runId, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateCancelRunRequest(threadId, runId, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -766,35 +742,35 @@ public virtual async Task CancelRunAsync(string threadId, string runId, /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the thread to which this run belongs. /// The ID of the run to cancel. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// or is null. /// or is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result CancelRun(string threadId, string runId, RequestOptions context) + public virtual ClientResult CancelRun(string threadId, string runId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); - - using var scope = ClientDiagnostics.CreateSpan("Runs.CancelRun"); - scope.Start(); - try - { - using PipelineMessage message = CreateCancelRunRequest(threadId, runId, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (runId is null) throw new ArgumentNullException(nameof(runId)); + if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCancelRunRequest(threadId, runId, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// @@ -805,19 +781,19 @@ public virtual Result CancelRun(string threadId, string runId, RequestOptions co /// The ID of the [thread](/docs/api-reference/threads) to which this run belongs. /// The ID of the run that requires the tool output submission. /// The to use. - /// The cancellation token to use. /// , or is null. /// or is an empty string, and was expected to be non-empty. - public virtual async Task> SubmitToolOuputsToRunAsync(string threadId, string runId, SubmitToolOutputsRunRequest submitToolOutputsRun, CancellationToken cancellationToken = default) + public virtual async Task> SubmitToolOuputsToRunAsync(string threadId, string runId, SubmitToolOutputsRunRequest submitToolOutputsRun) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); - ClientUtilities.AssertNotNull(submitToolOutputsRun, nameof(submitToolOutputsRun)); - - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = submitToolOutputsRun.ToRequestBody(); - Result result = await SubmitToolOuputsToRunAsync(threadId, runId, content, context).ConfigureAwait(false); - return Result.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (runId is null) throw new ArgumentNullException(nameof(runId)); + if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); + if (submitToolOutputsRun is null) throw new ArgumentNullException(nameof(submitToolOutputsRun)); + + using BinaryContent content = BinaryContent.Create(submitToolOutputsRun); + ClientResult result = await SubmitToolOuputsToRunAsync(threadId, runId, content).ConfigureAwait(false); + return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -828,19 +804,19 @@ public virtual async Task> SubmitToolOuputsToRunAsync(string t /// The ID of the [thread](/docs/api-reference/threads) to which this run belongs. /// The ID of the run that requires the tool output submission. /// The to use. - /// The cancellation token to use. /// , or is null. /// or is an empty string, and was expected to be non-empty. - public virtual Result SubmitToolOuputsToRun(string threadId, string runId, SubmitToolOutputsRunRequest submitToolOutputsRun, CancellationToken cancellationToken = default) + public virtual ClientResult SubmitToolOuputsToRun(string threadId, string runId, SubmitToolOutputsRunRequest submitToolOutputsRun) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); - ClientUtilities.AssertNotNull(submitToolOutputsRun, nameof(submitToolOutputsRun)); - - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = submitToolOutputsRun.ToRequestBody(); - Result result = SubmitToolOuputsToRun(threadId, runId, content, context); - return Result.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (runId is null) throw new ArgumentNullException(nameof(runId)); + if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); + if (submitToolOutputsRun is null) throw new ArgumentNullException(nameof(submitToolOutputsRun)); + + using BinaryContent content = BinaryContent.Create(submitToolOutputsRun); + ClientResult result = SubmitToolOuputsToRun(threadId, runId, content); + return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -855,7 +831,7 @@ public virtual Result SubmitToolOuputsToRun(string threadId, string r /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -863,29 +839,29 @@ public virtual Result SubmitToolOuputsToRun(string threadId, string r /// The ID of the [thread](/docs/api-reference/threads) to which this run belongs. /// The ID of the run that requires the tool output submission. /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// , or is null. /// or is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task SubmitToolOuputsToRunAsync(string threadId, string runId, RequestBody content, RequestOptions context = null) + public virtual async Task SubmitToolOuputsToRunAsync(string threadId, string runId, BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); - ClientUtilities.AssertNotNull(content, nameof(content)); - - using var scope = ClientDiagnostics.CreateSpan("Runs.SubmitToolOuputsToRun"); - scope.Start(); - try - { - using PipelineMessage message = CreateSubmitToolOuputsToRunRequest(threadId, runId, content, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (runId is null) throw new ArgumentNullException(nameof(runId)); + if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateSubmitToolOuputsToRunRequest(threadId, runId, content, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -900,7 +876,7 @@ public virtual async Task SubmitToolOuputsToRunAsync(string threadId, st /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -908,29 +884,29 @@ public virtual async Task SubmitToolOuputsToRunAsync(string threadId, st /// The ID of the [thread](/docs/api-reference/threads) to which this run belongs. /// The ID of the run that requires the tool output submission. /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// , or is null. /// or is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result SubmitToolOuputsToRun(string threadId, string runId, RequestBody content, RequestOptions context = null) + public virtual ClientResult SubmitToolOuputsToRun(string threadId, string runId, BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); - ClientUtilities.AssertNotNull(content, nameof(content)); - - using var scope = ClientDiagnostics.CreateSpan("Runs.SubmitToolOuputsToRun"); - scope.Start(); - try + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (runId is null) throw new ArgumentNullException(nameof(runId)); + if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateSubmitToolOuputsToRunRequest(threadId, runId, content, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateSubmitToolOuputsToRunRequest(threadId, runId, content, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Returns a list of run steps belonging to a run. @@ -954,17 +930,17 @@ public virtual Result SubmitToolOuputsToRun(string threadId, string runId, Reque /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. /// - /// The cancellation token to use. /// or is null. /// or is an empty string, and was expected to be non-empty. - public virtual async Task> GetRunStepsAsync(string threadId, string runId, int? limit = null, ListOrder? order = null, string after = null, string before = null, CancellationToken cancellationToken = default) + public virtual async Task> GetRunStepsAsync(string threadId, string runId, int? limit = null, ListOrder? order = null, string after = null, string before = null) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (runId is null) throw new ArgumentNullException(nameof(runId)); + if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await GetRunStepsAsync(threadId, runId, limit, order?.ToString(), after, before, context).ConfigureAwait(false); - return Result.FromValue(ListRunStepsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = await GetRunStepsAsync(threadId, runId, limit, order?.ToString(), after, before).ConfigureAwait(false); + return ClientResult.FromValue(ListRunStepsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Returns a list of run steps belonging to a run. @@ -988,17 +964,17 @@ public virtual async Task> GetRunStepsAsync(string /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. /// - /// The cancellation token to use. /// or is null. /// or is an empty string, and was expected to be non-empty. - public virtual Result GetRunSteps(string threadId, string runId, int? limit = null, ListOrder? order = null, string after = null, string before = null, CancellationToken cancellationToken = default) + public virtual ClientResult GetRunSteps(string threadId, string runId, int? limit = null, ListOrder? order = null, string after = null, string before = null) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (runId is null) throw new ArgumentNullException(nameof(runId)); + if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = GetRunSteps(threadId, runId, limit, order?.ToString(), after, before, context); - return Result.FromValue(ListRunStepsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = GetRunSteps(threadId, runId, limit, order?.ToString(), after, before); + return ClientResult.FromValue(ListRunStepsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -1011,7 +987,7 @@ public virtual Result GetRunSteps(string threadId, string /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -1036,28 +1012,28 @@ public virtual Result GetRunSteps(string threadId, string /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. /// - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// or is null. /// or is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task GetRunStepsAsync(string threadId, string runId, int? limit, string order, string after, string before, RequestOptions context) + public virtual async Task GetRunStepsAsync(string threadId, string runId, int? limit, string order, string after, string before, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); - - using var scope = ClientDiagnostics.CreateSpan("Runs.GetRunSteps"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetRunStepsRequest(threadId, runId, limit, order, after, before, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (runId is null) throw new ArgumentNullException(nameof(runId)); + if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetRunStepsRequest(threadId, runId, limit, order, after, before, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -1070,7 +1046,7 @@ public virtual async Task GetRunStepsAsync(string threadId, string runId /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -1095,64 +1071,66 @@ public virtual async Task GetRunStepsAsync(string threadId, string runId /// For instance, if you make a list request and receive 100 objects, ending with obj_foo, your /// subsequent call can include before=obj_foo in order to fetch the previous page of the list. /// - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// or is null. /// or is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result GetRunSteps(string threadId, string runId, int? limit, string order, string after, string before, RequestOptions context) + public virtual ClientResult GetRunSteps(string threadId, string runId, int? limit, string order, string after, string before, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); - - using var scope = ClientDiagnostics.CreateSpan("Runs.GetRunSteps"); - scope.Start(); - try + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (runId is null) throw new ArgumentNullException(nameof(runId)); + if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetRunStepsRequest(threadId, runId, limit, order, after, before, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateGetRunStepsRequest(threadId, runId, limit, order, after, before, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Retrieves a run step. /// The ID of the thread to which the run and run step belongs. /// The ID of the run to which the run step belongs. /// The ID of the run step to retrieve. - /// The cancellation token to use. /// , or is null. /// , or is an empty string, and was expected to be non-empty. - public virtual async Task> GetRunStepAsync(string threadId, string runId, string stepId, CancellationToken cancellationToken = default) + public virtual async Task> GetRunStepAsync(string threadId, string runId, string stepId) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); - ClientUtilities.AssertNotNullOrEmpty(stepId, nameof(stepId)); - - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await GetRunStepAsync(threadId, runId, stepId, context).ConfigureAwait(false); - return Result.FromValue(RunStepObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (runId is null) throw new ArgumentNullException(nameof(runId)); + if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); + if (stepId is null) throw new ArgumentNullException(nameof(stepId)); + if (string.IsNullOrEmpty(stepId)) throw new ArgumentException(nameof(stepId)); + + ClientResult result = await GetRunStepAsync(threadId, runId, stepId).ConfigureAwait(false); + return ClientResult.FromValue(RunStepObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Retrieves a run step. /// The ID of the thread to which the run and run step belongs. /// The ID of the run to which the run step belongs. /// The ID of the run step to retrieve. - /// The cancellation token to use. /// , or is null. /// , or is an empty string, and was expected to be non-empty. - public virtual Result GetRunStep(string threadId, string runId, string stepId, CancellationToken cancellationToken = default) + public virtual ClientResult GetRunStep(string threadId, string runId, string stepId) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); - ClientUtilities.AssertNotNullOrEmpty(stepId, nameof(stepId)); - - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = GetRunStep(threadId, runId, stepId, context); - return Result.FromValue(RunStepObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (runId is null) throw new ArgumentNullException(nameof(runId)); + if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); + if (stepId is null) throw new ArgumentNullException(nameof(stepId)); + if (string.IsNullOrEmpty(stepId)) throw new ArgumentException(nameof(stepId)); + + ClientResult result = GetRunStep(threadId, runId, stepId); + return ClientResult.FromValue(RunStepObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -1165,7 +1143,7 @@ public virtual Result GetRunStep(string threadId, string runId, s /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -1173,29 +1151,30 @@ public virtual Result GetRunStep(string threadId, string runId, s /// The ID of the thread to which the run and run step belongs. /// The ID of the run to which the run step belongs. /// The ID of the run step to retrieve. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// , or is null. /// , or is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task GetRunStepAsync(string threadId, string runId, string stepId, RequestOptions context) + public virtual async Task GetRunStepAsync(string threadId, string runId, string stepId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); - ClientUtilities.AssertNotNullOrEmpty(stepId, nameof(stepId)); - - using var scope = ClientDiagnostics.CreateSpan("Runs.GetRunStep"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetRunStepRequest(threadId, runId, stepId, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (runId is null) throw new ArgumentNullException(nameof(runId)); + if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); + if (stepId is null) throw new ArgumentNullException(nameof(stepId)); + if (string.IsNullOrEmpty(stepId)) throw new ArgumentException(nameof(stepId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetRunStepRequest(threadId, runId, stepId, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -1208,7 +1187,7 @@ public virtual async Task GetRunStepAsync(string threadId, string runId, /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -1216,227 +1195,323 @@ public virtual async Task GetRunStepAsync(string threadId, string runId, /// The ID of the thread to which the run and run step belongs. /// The ID of the run to which the run step belongs. /// The ID of the run step to retrieve. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// , or is null. /// , or is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result GetRunStep(string threadId, string runId, string stepId, RequestOptions context) + public virtual ClientResult GetRunStep(string threadId, string runId, string stepId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNullOrEmpty(runId, nameof(runId)); - ClientUtilities.AssertNotNullOrEmpty(stepId, nameof(stepId)); - - using var scope = ClientDiagnostics.CreateSpan("Runs.GetRunStep"); - scope.Start(); - try + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (runId is null) throw new ArgumentNullException(nameof(runId)); + if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); + if (stepId is null) throw new ArgumentNullException(nameof(stepId)); + if (string.IsNullOrEmpty(stepId)) throw new ArgumentException(nameof(stepId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetRunStepRequest(threadId, runId, stepId, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateGetRunStepRequest(threadId, runId, stepId, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } - internal PipelineMessage CreateCreateThreadAndRunRequest(RequestBody content, RequestOptions context) + internal PipelineMessage CreateCreateThreadAndRunRequest(BinaryContent content, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/threads/runs", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - request.SetHeaderValue("Content-Type", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/threads/runs"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); + request.Headers.Set("Content-Type", "application/json"); request.Content = content; + message.Apply(options); return message; } - internal PipelineMessage CreateCreateRunRequest(string threadId, RequestBody content, RequestOptions context) + internal PipelineMessage CreateCreateRunRequest(string threadId, BinaryContent content, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); - uri.AppendPath(threadId, true); - uri.AppendPath("/runs", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - request.SetHeaderValue("Content-Type", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/threads/"); + uriBuilder.Path += path.ToString(); + path.Append(threadId); + uriBuilder.Path += path.ToString(); + path.Append("/runs"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); + request.Headers.Set("Content-Type", "application/json"); request.Content = content; + message.Apply(options); return message; } - internal PipelineMessage CreateGetRunsRequest(string threadId, int? limit, string order, string after, string before, RequestOptions context) + internal PipelineMessage CreateGetRunsRequest(string threadId, int? limit, string order, string after, string before, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("GET"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); - uri.AppendPath(threadId, true); - uri.AppendPath("/runs", false); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "GET"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/threads/"); + uriBuilder.Path += path.ToString(); + path.Append(threadId); + uriBuilder.Path += path.ToString(); + path.Append("/runs"); + uriBuilder.Path += path.ToString(); if (limit != null) { - uri.AppendQuery("limit", limit.Value, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&limit={limit.Value}"; + } + else + { + uriBuilder.Query = $"limit={limit.Value}"; + } } if (order != null) { - uri.AppendQuery("order", order, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&order={order}"; + } + else + { + uriBuilder.Query = $"order={order}"; + } } if (after != null) { - uri.AppendQuery("after", after, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&after={after}"; + } + else + { + uriBuilder.Query = $"after={after}"; + } } if (before != null) { - uri.AppendQuery("before", before, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&before={before}"; + } + else + { + uriBuilder.Query = $"before={before}"; + } } - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); return message; } - internal PipelineMessage CreateGetRunRequest(string threadId, string runId, RequestOptions context) + internal PipelineMessage CreateGetRunRequest(string threadId, string runId, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("GET"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); - uri.AppendPath(threadId, true); - uri.AppendPath("/runs/", false); - uri.AppendPath(runId, true); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "GET"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/threads/"); + uriBuilder.Path += path.ToString(); + path.Append(threadId); + uriBuilder.Path += path.ToString(); + path.Append("/runs/"); + uriBuilder.Path += path.ToString(); + path.Append(runId); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); return message; } - internal PipelineMessage CreateModifyRunRequest(string threadId, string runId, RequestBody content, RequestOptions context) + internal PipelineMessage CreateModifyRunRequest(string threadId, string runId, BinaryContent content, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); - uri.AppendPath(threadId, true); - uri.AppendPath("/runs/", false); - uri.AppendPath(runId, true); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - request.SetHeaderValue("Content-Type", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/threads/"); + uriBuilder.Path += path.ToString(); + path.Append(threadId); + uriBuilder.Path += path.ToString(); + path.Append("/runs/"); + uriBuilder.Path += path.ToString(); + path.Append(runId); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); + request.Headers.Set("Content-Type", "application/json"); request.Content = content; + message.Apply(options); return message; } - internal PipelineMessage CreateCancelRunRequest(string threadId, string runId, RequestOptions context) + internal PipelineMessage CreateCancelRunRequest(string threadId, string runId, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); - uri.AppendPath(threadId, true); - uri.AppendPath("/runs/", false); - uri.AppendPath(runId, true); - uri.AppendPath("/cancel", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/threads/"); + uriBuilder.Path += path.ToString(); + path.Append(threadId); + uriBuilder.Path += path.ToString(); + path.Append("/runs/"); + uriBuilder.Path += path.ToString(); + path.Append(runId); + uriBuilder.Path += path.ToString(); + path.Append("/cancel"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); return message; } - internal PipelineMessage CreateSubmitToolOuputsToRunRequest(string threadId, string runId, RequestBody content, RequestOptions context) + internal PipelineMessage CreateSubmitToolOuputsToRunRequest(string threadId, string runId, BinaryContent content, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); - uri.AppendPath(threadId, true); - uri.AppendPath("/runs/", false); - uri.AppendPath(runId, true); - uri.AppendPath("/submit_tool_outputs", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - request.SetHeaderValue("Content-Type", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/threads/"); + uriBuilder.Path += path.ToString(); + path.Append(threadId); + uriBuilder.Path += path.ToString(); + path.Append("/runs/"); + uriBuilder.Path += path.ToString(); + path.Append(runId); + uriBuilder.Path += path.ToString(); + path.Append("/submit_tool_outputs"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); + request.Headers.Set("Content-Type", "application/json"); request.Content = content; + message.Apply(options); return message; } - internal PipelineMessage CreateGetRunStepsRequest(string threadId, string runId, int? limit, string order, string after, string before, RequestOptions context) + internal PipelineMessage CreateGetRunStepsRequest(string threadId, string runId, int? limit, string order, string after, string before, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("GET"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); - uri.AppendPath(threadId, true); - uri.AppendPath("/runs/", false); - uri.AppendPath(runId, true); - uri.AppendPath("/steps", false); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "GET"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/threads/"); + uriBuilder.Path += path.ToString(); + path.Append(threadId); + uriBuilder.Path += path.ToString(); + path.Append("/runs/"); + uriBuilder.Path += path.ToString(); + path.Append(runId); + uriBuilder.Path += path.ToString(); + path.Append("/steps"); + uriBuilder.Path += path.ToString(); if (limit != null) { - uri.AppendQuery("limit", limit.Value, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&limit={limit.Value}"; + } + else + { + uriBuilder.Query = $"limit={limit.Value}"; + } } if (order != null) { - uri.AppendQuery("order", order, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&order={order}"; + } + else + { + uriBuilder.Query = $"order={order}"; + } } if (after != null) { - uri.AppendQuery("after", after, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&after={after}"; + } + else + { + uriBuilder.Query = $"after={after}"; + } } if (before != null) { - uri.AppendQuery("before", before, true); + if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) + { + uriBuilder.Query += $"&before={before}"; + } + else + { + uriBuilder.Query = $"before={before}"; + } } - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); return message; } - internal PipelineMessage CreateGetRunStepRequest(string threadId, string runId, string stepId, RequestOptions context) + internal PipelineMessage CreateGetRunStepRequest(string threadId, string runId, string stepId, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("GET"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); - uri.AppendPath(threadId, true); - uri.AppendPath("/runs/", false); - uri.AppendPath(runId, true); - uri.AppendPath("/steps/", false); - uri.AppendPath(stepId, true); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "GET"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/threads/"); + uriBuilder.Path += path.ToString(); + path.Append(threadId); + uriBuilder.Path += path.ToString(); + path.Append("/runs/"); + uriBuilder.Path += path.ToString(); + path.Append(runId); + uriBuilder.Path += path.ToString(); + path.Append("/steps/"); + uriBuilder.Path += path.ToString(); + path.Append(stepId); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); return message; } - private static RequestOptions DefaultRequestContext = new RequestOptions(); - internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) - { - if (!cancellationToken.CanBeCanceled) - { - return DefaultRequestContext; - } - - return new RequestOptions() { CancellationToken = cancellationToken }; - } - - private static ResponseErrorClassifier _responseErrorClassifier200; - private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); + private static PipelineMessageClassifier _responseErrorClassifier200; + private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } } + diff --git a/.dotnet/src/Generated/Threads.cs b/.dotnet/src/Generated/Threads.cs index b7ef0388d..462f88718 100644 --- a/.dotnet/src/Generated/Threads.cs +++ b/.dotnet/src/Generated/Threads.cs @@ -1,12 +1,9 @@ // -#nullable disable - using System; using System.ClientModel; -using System.ClientModel.Internal; using System.ClientModel.Primitives; -using System.ClientModel.Primitives.Pipeline; +using System.Text; using System.Threading; using System.Threading.Tasks; using OpenAI.Models; @@ -18,16 +15,13 @@ namespace OpenAI public partial class Threads { private const string AuthorizationHeader = "Authorization"; - private readonly KeyCredential _keyCredential; + private readonly ApiKeyCredential _credential; private const string AuthorizationApiKeyPrefix = "Bearer"; - private readonly MessagePipeline _pipeline; + private readonly ClientPipeline _pipeline; private readonly Uri _endpoint; - /// The ClientDiagnostics is used to provide tracing support for the client library. - internal TelemetrySource ClientDiagnostics { get; } - /// The HTTP pipeline for sending and receiving REST requests and responses. - public virtual MessagePipeline Pipeline => _pipeline; + public virtual ClientPipeline Pipeline => _pipeline; /// Initializes a new instance of Threads for mocking. protected Threads() @@ -35,44 +29,38 @@ protected Threads() } /// Initializes a new instance of Threads. - /// The handler for diagnostic messaging in the client. /// The HTTP pipeline for sending and receiving REST requests and responses. - /// The key credential to copy. + /// The key credential to copy. /// OpenAI Endpoint. - internal Threads(TelemetrySource clientDiagnostics, MessagePipeline pipeline, KeyCredential keyCredential, Uri endpoint) + internal Threads(ClientPipeline pipeline, ApiKeyCredential credential, Uri endpoint) { - ClientDiagnostics = clientDiagnostics; _pipeline = pipeline; - _keyCredential = keyCredential; + _credential = credential; _endpoint = endpoint; } /// Create a thread. /// The to use. - /// The cancellation token to use. /// is null. - public virtual async Task> CreateThreadAsync(CreateThreadRequest thread, CancellationToken cancellationToken = default) + public virtual async Task> CreateThreadAsync(CreateThreadRequest thread) { - ClientUtilities.AssertNotNull(thread, nameof(thread)); + if (thread is null) throw new ArgumentNullException(nameof(thread)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = thread.ToRequestBody(); - Result result = await CreateThreadAsync(content, context).ConfigureAwait(false); - return Result.FromValue(ThreadObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(thread); + ClientResult result = await CreateThreadAsync(content).ConfigureAwait(false); + return ClientResult.FromValue(ThreadObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Create a thread. /// The to use. - /// The cancellation token to use. /// is null. - public virtual Result CreateThread(CreateThreadRequest thread, CancellationToken cancellationToken = default) + public virtual ClientResult CreateThread(CreateThreadRequest thread) { - ClientUtilities.AssertNotNull(thread, nameof(thread)); + if (thread is null) throw new ArgumentNullException(nameof(thread)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = thread.ToRequestBody(); - Result result = CreateThread(content, context); - return Result.FromValue(ThreadObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(thread); + ClientResult result = CreateThread(content); + return ClientResult.FromValue(ThreadObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -85,32 +73,30 @@ public virtual Result CreateThread(CreateThreadRequest thread, Can /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task CreateThreadAsync(RequestBody content, RequestOptions context = null) + public virtual async Task CreateThreadAsync(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateThreadRequest(content, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Threads.CreateThread"); - scope.Start(); - try + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateCreateThreadRequest(content, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -123,60 +109,56 @@ public virtual async Task CreateThreadAsync(RequestBody content, Request /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result CreateThread(RequestBody content, RequestOptions context = null) + public virtual ClientResult CreateThread(BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNull(content, nameof(content)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateCreateThreadRequest(content, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; - using var scope = ClientDiagnostics.CreateSpan("Threads.CreateThread"); - scope.Start(); - try + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateCreateThreadRequest(content, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Retrieves a thread. /// The ID of the thread to retrieve. - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual async Task> GetThreadAsync(string threadId, CancellationToken cancellationToken = default) + public virtual async Task> GetThreadAsync(string threadId) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await GetThreadAsync(threadId, context).ConfigureAwait(false); - return Result.FromValue(ThreadObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = await GetThreadAsync(threadId).ConfigureAwait(false); + return ClientResult.FromValue(ThreadObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Retrieves a thread. /// The ID of the thread to retrieve. - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual Result GetThread(string threadId, CancellationToken cancellationToken = default) + public virtual ClientResult GetThread(string threadId) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = GetThread(threadId, context); - return Result.FromValue(ThreadObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = GetThread(threadId); + return ClientResult.FromValue(ThreadObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -189,33 +171,32 @@ public virtual Result GetThread(string threadId, CancellationToken /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the thread to retrieve. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task GetThreadAsync(string threadId, RequestOptions context) + public virtual async Task GetThreadAsync(string threadId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - - using var scope = ClientDiagnostics.CreateSpan("Threads.GetThread"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetThreadRequest(threadId, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetThreadRequest(threadId, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -228,67 +209,64 @@ public virtual async Task GetThreadAsync(string threadId, RequestOptions /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the thread to retrieve. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result GetThread(string threadId, RequestOptions context) + public virtual ClientResult GetThread(string threadId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - - using var scope = ClientDiagnostics.CreateSpan("Threads.GetThread"); - scope.Start(); - try - { - using PipelineMessage message = CreateGetThreadRequest(threadId, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateGetThreadRequest(threadId, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Modifies a thread. /// The ID of the thread to modify. Only the `metadata` can be modified. /// The to use. - /// The cancellation token to use. /// or is null. /// is an empty string, and was expected to be non-empty. - public virtual async Task> ModifyThreadAsync(string threadId, ModifyThreadRequest thread, CancellationToken cancellationToken = default) + public virtual async Task> ModifyThreadAsync(string threadId, ModifyThreadRequest thread) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNull(thread, nameof(thread)); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (thread is null) throw new ArgumentNullException(nameof(thread)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = thread.ToRequestBody(); - Result result = await ModifyThreadAsync(threadId, content, context).ConfigureAwait(false); - return Result.FromValue(ThreadObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(thread); + ClientResult result = await ModifyThreadAsync(threadId, content).ConfigureAwait(false); + return ClientResult.FromValue(ThreadObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Modifies a thread. /// The ID of the thread to modify. Only the `metadata` can be modified. /// The to use. - /// The cancellation token to use. /// or is null. /// is an empty string, and was expected to be non-empty. - public virtual Result ModifyThread(string threadId, ModifyThreadRequest thread, CancellationToken cancellationToken = default) + public virtual ClientResult ModifyThread(string threadId, ModifyThreadRequest thread) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNull(thread, nameof(thread)); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (thread is null) throw new ArgumentNullException(nameof(thread)); - RequestOptions context = FromCancellationToken(cancellationToken); - using RequestBody content = thread.ToRequestBody(); - Result result = ModifyThread(threadId, content, context); - return Result.FromValue(ThreadObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + using BinaryContent content = BinaryContent.Create(thread); + ClientResult result = ModifyThread(threadId, content); + return ClientResult.FromValue(ThreadObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -301,35 +279,34 @@ public virtual Result ModifyThread(string threadId, ModifyThreadRe /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the thread to modify. Only the `metadata` can be modified. /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// or is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task ModifyThreadAsync(string threadId, RequestBody content, RequestOptions context = null) + public virtual async Task ModifyThreadAsync(string threadId, BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNull(content, nameof(content)); - - using var scope = ClientDiagnostics.CreateSpan("Threads.ModifyThread"); - scope.Start(); - try + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateModifyThreadRequest(threadId, content, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateModifyThreadRequest(threadId, content, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -342,63 +319,60 @@ public virtual async Task ModifyThreadAsync(string threadId, RequestBody /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the thread to modify. Only the `metadata` can be modified. /// The content to send as the body of the request. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// or is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result ModifyThread(string threadId, RequestBody content, RequestOptions context = null) + public virtual ClientResult ModifyThread(string threadId, BinaryContent content, RequestOptions options = null) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - ClientUtilities.AssertNotNull(content, nameof(content)); - - using var scope = ClientDiagnostics.CreateSpan("Threads.ModifyThread"); - scope.Start(); - try - { - using PipelineMessage message = CreateModifyThreadRequest(threadId, content, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + if (content is null) throw new ArgumentNullException(nameof(content)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateModifyThreadRequest(threadId, content, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } /// Delete a thread. /// The ID of the thread to delete. - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual async Task> DeleteThreadAsync(string threadId, CancellationToken cancellationToken = default) + public virtual async Task> DeleteThreadAsync(string threadId) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = await DeleteThreadAsync(threadId, context).ConfigureAwait(false); - return Result.FromValue(DeleteThreadResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = await DeleteThreadAsync(threadId).ConfigureAwait(false); + return ClientResult.FromValue(DeleteThreadResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Delete a thread. /// The ID of the thread to delete. - /// The cancellation token to use. /// is null. /// is an empty string, and was expected to be non-empty. - public virtual Result DeleteThread(string threadId, CancellationToken cancellationToken = default) + public virtual ClientResult DeleteThread(string threadId) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - RequestOptions context = FromCancellationToken(cancellationToken); - Result result = DeleteThread(threadId, context); - return Result.FromValue(DeleteThreadResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + ClientResult result = DeleteThread(threadId); + return ClientResult.FromValue(DeleteThreadResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -411,33 +385,32 @@ public virtual Result DeleteThread(string threadId, Cancel /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the thread to delete. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task DeleteThreadAsync(string threadId, RequestOptions context) + public virtual async Task DeleteThreadAsync(string threadId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - - using var scope = ClientDiagnostics.CreateSpan("Threads.DeleteThread"); - scope.Start(); - try + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateDeleteThreadRequest(threadId, options); + await _pipeline.SendAsync(message).ConfigureAwait(false); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateDeleteThreadRequest(threadId, context); - return Result.FromResponse(await _pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } + + return ClientResult.FromResponse(response); } /// @@ -450,106 +423,108 @@ public virtual async Task DeleteThreadAsync(string threadId, RequestOpti /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// /// /// The ID of the thread to delete. - /// The request context, which can override default behaviors of the client pipeline on a per-call basis. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. - /// Service returned a non-success status code. + /// Service returned a non-success status code. /// The response returned from the service. - public virtual Result DeleteThread(string threadId, RequestOptions context) + public virtual ClientResult DeleteThread(string threadId, RequestOptions options) { - ClientUtilities.AssertNotNullOrEmpty(threadId, nameof(threadId)); - - using var scope = ClientDiagnostics.CreateSpan("Threads.DeleteThread"); - scope.Start(); - try + if (threadId is null) throw new ArgumentNullException(nameof(threadId)); + if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + options ??= new RequestOptions(); + using PipelineMessage message = CreateDeleteThreadRequest(threadId, options); + _pipeline.Send(message); + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - using PipelineMessage message = CreateDeleteThreadRequest(threadId, context); - return Result.FromResponse(_pipeline.ProcessMessage(message, context)); - } - catch (Exception e) - { - scope.Failed(e); - throw; + throw new ClientResultException(response); } + + return ClientResult.FromResponse(response); } - internal PipelineMessage CreateCreateThreadRequest(RequestBody content, RequestOptions context) + internal PipelineMessage CreateCreateThreadRequest(BinaryContent content, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/threads", false); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - request.SetHeaderValue("Content-Type", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/threads"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); + request.Headers.Set("Content-Type", "application/json"); request.Content = content; + message.Apply(options); return message; } - internal PipelineMessage CreateGetThreadRequest(string threadId, RequestOptions context) + internal PipelineMessage CreateGetThreadRequest(string threadId, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("GET"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); - uri.AppendPath(threadId, true); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "GET"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/threads/"); + uriBuilder.Path += path.ToString(); + path.Append(threadId); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); return message; } - internal PipelineMessage CreateModifyThreadRequest(string threadId, RequestBody content, RequestOptions context) + internal PipelineMessage CreateModifyThreadRequest(string threadId, BinaryContent content, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("POST"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); - uri.AppendPath(threadId, true); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); - request.SetHeaderValue("Content-Type", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/threads/"); + uriBuilder.Path += path.ToString(); + path.Append(threadId); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); + request.Headers.Set("Content-Type", "application/json"); request.Content = content; + message.Apply(options); return message; } - internal PipelineMessage CreateDeleteThreadRequest(string threadId, RequestOptions context) + internal PipelineMessage CreateDeleteThreadRequest(string threadId, RequestOptions options) { - var message = _pipeline.CreateMessage(context, ResponseErrorClassifier200); - var request = message.Request; - request.SetMethod("DELETE"); - var uri = new RequestUri(); - uri.Reset(_endpoint); - uri.AppendPath("/threads/", false); - uri.AppendPath(threadId, true); - request.Uri = uri.ToUri(); - request.SetHeaderValue("Accept", "application/json"); + PipelineMessage message = _pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "DELETE"; + UriBuilder uriBuilder = new(_endpoint.ToString()); + StringBuilder path = new(); + path.Append("/threads/"); + uriBuilder.Path += path.ToString(); + path.Append(threadId); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); return message; } - private static RequestOptions DefaultRequestContext = new RequestOptions(); - internal static RequestOptions FromCancellationToken(CancellationToken cancellationToken = default) - { - if (!cancellationToken.CanBeCanceled) - { - return DefaultRequestContext; - } - - return new RequestOptions() { CancellationToken = cancellationToken }; - } - - private static ResponseErrorClassifier _responseErrorClassifier200; - private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= new StatusResponseClassifier(stackalloc ushort[] { 200 }); + private static PipelineMessageClassifier _responseErrorClassifier200; + private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } } + diff --git a/.dotnet/src/OpenAI.csproj b/.dotnet/src/OpenAI.csproj index c07146eaf..c53137241 100644 --- a/.dotnet/src/OpenAI.csproj +++ b/.dotnet/src/OpenAI.csproj @@ -10,7 +10,7 @@ - + diff --git a/.dotnet/tests/Generated/Tests/AssistantsTests.cs b/.dotnet/tests/Generated/Tests/AssistantsTests.cs index ea014b7fb..6c1ba99d2 100644 --- a/.dotnet/tests/Generated/Tests/AssistantsTests.cs +++ b/.dotnet/tests/Generated/Tests/AssistantsTests.cs @@ -14,9 +14,10 @@ public partial class AssistantsTests [Test] public void SmokeTest() { - KeyCredential credential = new KeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); Assistants client = new OpenAIClient(credential).GetAssistantsClient(); Assert.IsNotNull(client); } } } + diff --git a/.dotnet/tests/Generated/Tests/AudioTests.cs b/.dotnet/tests/Generated/Tests/AudioTests.cs index 8fe314b48..6ff9cd6f5 100644 --- a/.dotnet/tests/Generated/Tests/AudioTests.cs +++ b/.dotnet/tests/Generated/Tests/AudioTests.cs @@ -14,9 +14,10 @@ public partial class AudioTests [Test] public void SmokeTest() { - KeyCredential credential = new KeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); Audio client = new OpenAIClient(credential).GetAudioClient(); Assert.IsNotNull(client); } } } + diff --git a/.dotnet/tests/Generated/Tests/ChatTests.cs b/.dotnet/tests/Generated/Tests/ChatTests.cs index eb5b40763..17a9746da 100644 --- a/.dotnet/tests/Generated/Tests/ChatTests.cs +++ b/.dotnet/tests/Generated/Tests/ChatTests.cs @@ -14,9 +14,10 @@ public partial class ChatTests [Test] public void SmokeTest() { - KeyCredential credential = new KeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); Chat client = new OpenAIClient(credential).GetChatClient(); Assert.IsNotNull(client); } } } + diff --git a/.dotnet/tests/Generated/Tests/CompletionsTests.cs b/.dotnet/tests/Generated/Tests/CompletionsTests.cs index 3a0695403..159a4444d 100644 --- a/.dotnet/tests/Generated/Tests/CompletionsTests.cs +++ b/.dotnet/tests/Generated/Tests/CompletionsTests.cs @@ -14,9 +14,10 @@ public partial class CompletionsTests [Test] public void SmokeTest() { - KeyCredential credential = new KeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); Completions client = new OpenAIClient(credential).GetCompletionsClient(); Assert.IsNotNull(client); } } } + diff --git a/.dotnet/tests/Generated/Tests/EmbeddingsTests.cs b/.dotnet/tests/Generated/Tests/EmbeddingsTests.cs index 8a6052960..b4deac0fc 100644 --- a/.dotnet/tests/Generated/Tests/EmbeddingsTests.cs +++ b/.dotnet/tests/Generated/Tests/EmbeddingsTests.cs @@ -14,9 +14,10 @@ public partial class EmbeddingsTests [Test] public void SmokeTest() { - KeyCredential credential = new KeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); Embeddings client = new OpenAIClient(credential).GetEmbeddingsClient(); Assert.IsNotNull(client); } } } + diff --git a/.dotnet/tests/Generated/Tests/FilesTests.cs b/.dotnet/tests/Generated/Tests/FilesTests.cs index 9372d75f4..c08f7aee8 100644 --- a/.dotnet/tests/Generated/Tests/FilesTests.cs +++ b/.dotnet/tests/Generated/Tests/FilesTests.cs @@ -14,9 +14,10 @@ public partial class FilesTests [Test] public void SmokeTest() { - KeyCredential credential = new KeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); Files client = new OpenAIClient(credential).GetFilesClient(); Assert.IsNotNull(client); } } } + diff --git a/.dotnet/tests/Generated/Tests/FineTuningTests.cs b/.dotnet/tests/Generated/Tests/FineTuningTests.cs index 40abbe22d..7504035a2 100644 --- a/.dotnet/tests/Generated/Tests/FineTuningTests.cs +++ b/.dotnet/tests/Generated/Tests/FineTuningTests.cs @@ -14,9 +14,10 @@ public partial class FineTuningTests [Test] public void SmokeTest() { - KeyCredential credential = new KeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); FineTuning client = new OpenAIClient(credential).GetFineTuningClient(); Assert.IsNotNull(client); } } } + diff --git a/.dotnet/tests/Generated/Tests/ImagesTests.cs b/.dotnet/tests/Generated/Tests/ImagesTests.cs index a48795229..097054471 100644 --- a/.dotnet/tests/Generated/Tests/ImagesTests.cs +++ b/.dotnet/tests/Generated/Tests/ImagesTests.cs @@ -14,9 +14,10 @@ public partial class ImagesTests [Test] public void SmokeTest() { - KeyCredential credential = new KeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); Images client = new OpenAIClient(credential).GetImagesClient(); Assert.IsNotNull(client); } } } + diff --git a/.dotnet/tests/Generated/Tests/MessagesTests.cs b/.dotnet/tests/Generated/Tests/MessagesTests.cs index 4b62bbf50..ab0223685 100644 --- a/.dotnet/tests/Generated/Tests/MessagesTests.cs +++ b/.dotnet/tests/Generated/Tests/MessagesTests.cs @@ -14,9 +14,10 @@ public partial class MessagesTests [Test] public void SmokeTest() { - KeyCredential credential = new KeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); Messages client = new OpenAIClient(credential).GetMessagesClient(); Assert.IsNotNull(client); } } } + diff --git a/.dotnet/tests/Generated/Tests/ModelsOpsTests.cs b/.dotnet/tests/Generated/Tests/ModelsOpsTests.cs index 24c9896c0..0560956dc 100644 --- a/.dotnet/tests/Generated/Tests/ModelsOpsTests.cs +++ b/.dotnet/tests/Generated/Tests/ModelsOpsTests.cs @@ -14,9 +14,10 @@ public partial class ModelsOpsTests [Test] public void SmokeTest() { - KeyCredential credential = new KeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); ModelsOps client = new OpenAIClient(credential).GetModelsOpsClient(); Assert.IsNotNull(client); } } } + diff --git a/.dotnet/tests/Generated/Tests/ModerationsTests.cs b/.dotnet/tests/Generated/Tests/ModerationsTests.cs index 138b487d3..7fc5a1d0b 100644 --- a/.dotnet/tests/Generated/Tests/ModerationsTests.cs +++ b/.dotnet/tests/Generated/Tests/ModerationsTests.cs @@ -14,9 +14,10 @@ public partial class ModerationsTests [Test] public void SmokeTest() { - KeyCredential credential = new KeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); Moderations client = new OpenAIClient(credential).GetModerationsClient(); Assert.IsNotNull(client); } } } + diff --git a/.dotnet/tests/Generated/Tests/RunsTests.cs b/.dotnet/tests/Generated/Tests/RunsTests.cs index e3b8ee12b..bd4de7947 100644 --- a/.dotnet/tests/Generated/Tests/RunsTests.cs +++ b/.dotnet/tests/Generated/Tests/RunsTests.cs @@ -14,9 +14,10 @@ public partial class RunsTests [Test] public void SmokeTest() { - KeyCredential credential = new KeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); Runs client = new OpenAIClient(credential).GetRunsClient(); Assert.IsNotNull(client); } } } + diff --git a/.dotnet/tests/Generated/Tests/ThreadsTests.cs b/.dotnet/tests/Generated/Tests/ThreadsTests.cs index 9b7ef6f78..b5ea58e10 100644 --- a/.dotnet/tests/Generated/Tests/ThreadsTests.cs +++ b/.dotnet/tests/Generated/Tests/ThreadsTests.cs @@ -14,9 +14,10 @@ public partial class ThreadsTests [Test] public void SmokeTest() { - KeyCredential credential = new KeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); Threads client = new OpenAIClient(credential).GetThreadsClient(); Assert.IsNotNull(client); } } } + From a1ba42ca112a4e482a1ccfbf8f98d83f85dee582 Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado Date: Tue, 20 Feb 2024 11:52:21 -0800 Subject: [PATCH 12/50] Fix Update-ClientModel.ps1 script --- .dotnet/scripts/Update-ClientModel.ps1 | 1 - 1 file changed, 1 deletion(-) diff --git a/.dotnet/scripts/Update-ClientModel.ps1 b/.dotnet/scripts/Update-ClientModel.ps1 index b8a9a590f..1e533dde4 100644 --- a/.dotnet/scripts/Update-ClientModel.ps1 +++ b/.dotnet/scripts/Update-ClientModel.ps1 @@ -5,7 +5,6 @@ function Update-ClientModelPackage { $current = Get-Location Set-Location -Path $directory - dotnet build dotnet remove "OpenAI.csproj" package "System.ClientModel" dotnet add "OpenAI.csproj" package "System.ClientModel" --version "1.1.0-alpha.20240215.1" --source "https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-net/nuget/v3/index.json" From 54851e2b0617f56ed59ebbde546f6e8aad2ba3bd Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado Date: Tue, 20 Feb 2024 12:50:02 -0800 Subject: [PATCH 13/50] Add embeddings example --- .dotnet/src/Custom/Embeddings/Embeddings.cs | 93 ++++++++++++++++ .../Models/Embedding.Serialization.cs | 67 ++++++++++++ .../src/Custom/Embeddings/Models/Embedding.cs | 68 ++++++++++++ .../Embeddings/Models/EmbeddingObject.cs | 10 ++ .../Models/GenerateEmbeddingsOptions.cs | 13 +++ .dotnet/src/Custom/OpenAIClient.cs | 22 ++++ .dotnet/src/Custom/OpenAIModelFactory.cs | 36 +++++++ .dotnet/src/Generated/Embeddings.cs | 20 ++-- .../CreateEmbeddingRequestEncodingFormat.cs | 47 -------- .../Models/CreateEmbeddingRequestModel.cs | 50 --------- .../Models/CreateEmbeddingResponseObject.cs | 44 -------- .../Models/Embedding.Serialization.cs | 40 ------- .dotnet/src/Generated/Models/Embedding.cs | 45 -------- ...s => EmbeddingCollection.Serialization.cs} | 48 ++++----- ...dingResponse.cs => EmbeddingCollection.cs} | 20 ++-- .../Models/EmbeddingCollectionObject.cs | 44 ++++++++ .../src/Generated/Models/EmbeddingObject.cs | 2 +- ...s => EmbeddingTokenUsage.Serialization.cs} | 40 +++---- ...esponseUsage.cs => EmbeddingTokenUsage.cs} | 16 +-- ...enerateEmbeddingsOptions.Serialization.cs} | 48 ++++----- ...equest.cs => GenerateEmbeddingsOptions.cs} | 78 ++------------ ...GenerateEmbeddingsOptionsEncodingFormat.cs | 47 ++++++++ .../Models/GenerateEmbeddingsOptionsModel.cs | 50 +++++++++ .dotnet/src/Generated/OpenAIClient.cs | 6 -- .dotnet/src/Generated/OpenAIModelFactory.cs | 61 ++--------- .dotnet/tests/EmbeddingsTests.cs | 101 ++++++++++++++++++ .../tests/Generated/Tests/EmbeddingsTests.cs | 23 ---- embeddings/models.tsp | 19 ++-- main.tsp | 11 ++ tsp-output/@typespec/openapi3/openapi.yaml | 29 ++--- 30 files changed, 702 insertions(+), 496 deletions(-) create mode 100644 .dotnet/src/Custom/Embeddings/Embeddings.cs create mode 100644 .dotnet/src/Custom/Embeddings/Models/Embedding.Serialization.cs create mode 100644 .dotnet/src/Custom/Embeddings/Models/Embedding.cs create mode 100644 .dotnet/src/Custom/Embeddings/Models/EmbeddingObject.cs create mode 100644 .dotnet/src/Custom/Embeddings/Models/GenerateEmbeddingsOptions.cs create mode 100644 .dotnet/src/Custom/OpenAIClient.cs create mode 100644 .dotnet/src/Custom/OpenAIModelFactory.cs delete mode 100644 .dotnet/src/Generated/Models/CreateEmbeddingRequestEncodingFormat.cs delete mode 100644 .dotnet/src/Generated/Models/CreateEmbeddingRequestModel.cs delete mode 100644 .dotnet/src/Generated/Models/CreateEmbeddingResponseObject.cs rename .dotnet/src/Generated/Models/{CreateEmbeddingResponse.Serialization.cs => EmbeddingCollection.Serialization.cs} (64%) rename .dotnet/src/Generated/Models/{CreateEmbeddingResponse.cs => EmbeddingCollection.cs} (77%) create mode 100644 .dotnet/src/Generated/Models/EmbeddingCollectionObject.cs rename .dotnet/src/Generated/Models/{CreateEmbeddingResponseUsage.Serialization.cs => EmbeddingTokenUsage.Serialization.cs} (62%) rename .dotnet/src/Generated/Models/{CreateEmbeddingResponseUsage.cs => EmbeddingTokenUsage.cs} (77%) rename .dotnet/src/Generated/Models/{CreateEmbeddingRequest.Serialization.cs => GenerateEmbeddingsOptions.Serialization.cs} (67%) rename .dotnet/src/Generated/Models/{CreateEmbeddingRequest.cs => GenerateEmbeddingsOptions.cs} (58%) create mode 100644 .dotnet/src/Generated/Models/GenerateEmbeddingsOptionsEncodingFormat.cs create mode 100644 .dotnet/src/Generated/Models/GenerateEmbeddingsOptionsModel.cs create mode 100644 .dotnet/tests/EmbeddingsTests.cs delete mode 100644 .dotnet/tests/Generated/Tests/EmbeddingsTests.cs diff --git a/.dotnet/src/Custom/Embeddings/Embeddings.cs b/.dotnet/src/Custom/Embeddings/Embeddings.cs new file mode 100644 index 000000000..1dad5bf62 --- /dev/null +++ b/.dotnet/src/Custom/Embeddings/Embeddings.cs @@ -0,0 +1,93 @@ +using OpenAI.Models; +using System; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenAI +{ + public partial class Embeddings + { + private readonly string _model; + + /// Initializes a new instance of Embeddings. + /// The HTTP pipeline for sending and receiving REST requests and responses. + /// The key credential to copy. + /// OpenAI Endpoint. + internal Embeddings(string model, ClientPipeline pipeline, ApiKeyCredential credential, Uri endpoint) + : this(pipeline, credential, endpoint) + { + _model = model; + } + + public virtual async Task> GenerateEmbeddingAsync(string input, GenerateEmbeddingsOptions options = null) + { + options ??= new GenerateEmbeddingsOptions(); + options.Model = new GenerateEmbeddingsOptionsModel(_model); + options.Input = BinaryData.FromString(input); + ClientResult result = await CreateEmbeddingAsync(options).ConfigureAwait(false); + return ClientResult.FromValue(result.Value.Data[0], result.GetRawResponse()); + } + + public virtual ClientResult GenerateEmbedding(string input, GenerateEmbeddingsOptions options = null) + { + options ??= new GenerateEmbeddingsOptions(); + options.Model = new GenerateEmbeddingsOptionsModel(_model); + options.Input = BinaryData.FromObjectAsJson(input); + ClientResult result = CreateEmbedding(options); + return ClientResult.FromValue(result.Value.Data[0], result.GetRawResponse()); + } + + public virtual async Task> GenerateEmbeddingAsync(IEnumerable input, GenerateEmbeddingsOptions options = null) + { + options ??= new GenerateEmbeddingsOptions(); + options.Model = new GenerateEmbeddingsOptionsModel(_model); + options.Input = BinaryData.FromObjectAsJson(input.ToArray()); + ClientResult result = await CreateEmbeddingAsync(options).ConfigureAwait(false); + return ClientResult.FromValue(result.Value.Data[0], result.GetRawResponse()); + } + + public virtual ClientResult GenerateEmbedding(IEnumerable input, GenerateEmbeddingsOptions options = null) + { + options ??= new GenerateEmbeddingsOptions(); + options.Model = new GenerateEmbeddingsOptionsModel(_model); + options.Input = BinaryData.FromObjectAsJson(input.ToArray()); + ClientResult result = CreateEmbedding(options); + return ClientResult.FromValue(result.Value.Data[0], result.GetRawResponse()); + } + + public virtual async Task> GenerateEmbeddingsAsync(IEnumerable inputs, GenerateEmbeddingsOptions options = null) + { + options ??= new GenerateEmbeddingsOptions(); + options.Model = new GenerateEmbeddingsOptionsModel(_model); + options.Input = BinaryData.FromObjectAsJson(inputs.ToArray()); + return await CreateEmbeddingAsync(options).ConfigureAwait(false); + } + + public virtual ClientResult GenerateEmbeddings(IEnumerable inputs, GenerateEmbeddingsOptions options = null) + { + options ??= new GenerateEmbeddingsOptions(); + options.Model = new GenerateEmbeddingsOptionsModel(_model); + options.Input = BinaryData.FromObjectAsJson(inputs.ToArray()); + return CreateEmbedding(options); + } + + public virtual async Task> GenerateEmbeddingsAsync(IEnumerable> inputs, GenerateEmbeddingsOptions options = null) + { + options ??= new GenerateEmbeddingsOptions(); + options.Model = new GenerateEmbeddingsOptionsModel(_model); + options.Input = BinaryData.FromObjectAsJson(inputs.ToArray()); + return await CreateEmbeddingAsync(options).ConfigureAwait(false); + } + + public virtual ClientResult GenerateEmbeddings(IEnumerable> inputs, GenerateEmbeddingsOptions options = null) + { + options ??= new GenerateEmbeddingsOptions(); + options.Model = new GenerateEmbeddingsOptionsModel(_model); + options.Input = BinaryData.FromObjectAsJson(inputs.ToArray()); + return CreateEmbedding(options); + } + } +} diff --git a/.dotnet/src/Custom/Embeddings/Models/Embedding.Serialization.cs b/.dotnet/src/Custom/Embeddings/Models/Embedding.Serialization.cs new file mode 100644 index 000000000..602547f22 --- /dev/null +++ b/.dotnet/src/Custom/Embeddings/Models/Embedding.Serialization.cs @@ -0,0 +1,67 @@ +using System; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Models +{ + public partial class Embedding + { + internal static Embedding DeserializeEmbedding(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + long index = default; + BinaryData embedding = default; + EmbeddingObject @object = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("index"u8)) + { + index = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("embedding"u8)) + { + embedding = BinaryData.FromString(property.Value.GetRawText()); + continue; + } + if (property.NameEquals("object"u8)) + { + @object = new EmbeddingObject(property.Value.GetString()); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + + ReadOnlyMemory? embeddingAsFloats = default; + BinaryData embeddingAsBase64Data = default; + JsonDocument doc = JsonDocument.Parse(embedding); + + if (doc.RootElement.ValueKind == JsonValueKind.Array) + { + List floats = new(); + foreach (var item in doc.RootElement.EnumerateArray()) + { + floats.Add(item.GetSingle()); + } + embeddingAsFloats = new ReadOnlyMemory(floats.ToArray()); + } + else if (doc.RootElement.ValueKind == JsonValueKind.String) + { + embeddingAsBase64Data = embedding; + } + + return new(index, embedding, @object, serializedAdditionalRawData, embeddingAsFloats, embeddingAsBase64Data); + } + } +} diff --git a/.dotnet/src/Custom/Embeddings/Models/Embedding.cs b/.dotnet/src/Custom/Embeddings/Models/Embedding.cs new file mode 100644 index 000000000..0cf994146 --- /dev/null +++ b/.dotnet/src/Custom/Embeddings/Models/Embedding.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; + +#nullable disable + +namespace OpenAI.Models +{ + public partial class Embedding + { + /// + /// The embedding vector, which is a list of floats. The length of vector depends on the model as + /// listed in the [embedding guide](/docs/guides/embeddings). + /// + /// To assign an object to this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// + /// Supported types: + /// + /// + /// where T is of type + /// + /// + /// + /// + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + internal BinaryData EmbeddingProperty { get; } + /// The object type, which is always "embedding". + internal EmbeddingObject Object { get; } = EmbeddingObject.Embedding; + + internal Embedding(long index, BinaryData embeddingProperty, EmbeddingObject @object, IDictionary serializedAdditionalRawData, ReadOnlyMemory? embeddingAsFloats, BinaryData embeddingAsBase64Data) + : this(index, embeddingProperty, @object, serializedAdditionalRawData) + { + EmbeddingAsFloats = embeddingAsFloats; + EmbeddingAsBase64Data = embeddingAsBase64Data; + } + + /// The embedding represented as a vector of floats. + public ReadOnlyMemory? EmbeddingAsFloats { get; } + /// The embedding represented as a Base64-encoded string. + public BinaryData EmbeddingAsBase64Data { get; } + } +} diff --git a/.dotnet/src/Custom/Embeddings/Models/EmbeddingObject.cs b/.dotnet/src/Custom/Embeddings/Models/EmbeddingObject.cs new file mode 100644 index 000000000..a2bd2f70e --- /dev/null +++ b/.dotnet/src/Custom/Embeddings/Models/EmbeddingObject.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenAI.Models +{ + internal readonly partial struct EmbeddingObject + { + } +} diff --git a/.dotnet/src/Custom/Embeddings/Models/GenerateEmbeddingsOptions.cs b/.dotnet/src/Custom/Embeddings/Models/GenerateEmbeddingsOptions.cs new file mode 100644 index 000000000..64500d31a --- /dev/null +++ b/.dotnet/src/Custom/Embeddings/Models/GenerateEmbeddingsOptions.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenAI.Models +{ + public partial class GenerateEmbeddingsOptions + { + internal BinaryData Input { get; set; } + + internal GenerateEmbeddingsOptionsModel Model { get; set; } + } +} diff --git a/.dotnet/src/Custom/OpenAIClient.cs b/.dotnet/src/Custom/OpenAIClient.cs new file mode 100644 index 000000000..2c7ed2700 --- /dev/null +++ b/.dotnet/src/Custom/OpenAIClient.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; + +namespace OpenAI +{ + public partial class OpenAIClient + { + // TODO: This needs to be suppressed. + internal virtual Embeddings GetEmbeddingsClient() + { + return Volatile.Read(ref _cachedEmbeddings) ?? Interlocked.CompareExchange(ref _cachedEmbeddings, new Embeddings(_pipeline, _credential, _endpoint), null) ?? _cachedEmbeddings; + } + + /// Initializes a new instance of Embeddings. + public virtual Embeddings GetEmbeddingsClient(string model) + { + return Volatile.Read(ref _cachedEmbeddings) ?? Interlocked.CompareExchange(ref _cachedEmbeddings, new Embeddings(model, _pipeline, _credential, _endpoint), null) ?? _cachedEmbeddings; + } + } +} diff --git a/.dotnet/src/Custom/OpenAIModelFactory.cs b/.dotnet/src/Custom/OpenAIModelFactory.cs new file mode 100644 index 000000000..895344070 --- /dev/null +++ b/.dotnet/src/Custom/OpenAIModelFactory.cs @@ -0,0 +1,36 @@ +using OpenAI.Models; +using System; + +namespace OpenAI +{ + /// Model factory for models. + public static partial class OpenAIModelFactory + { + /// Initializes a new instance of . + /// The index of the embedding in the list of embeddings. + /// + /// The embedding vector, which is a list of floats. The length of vector depends on the model as + /// listed in the [embedding guide](/docs/guides/embeddings). + /// + /// The object type, which is always "embedding". + /// A new instance for mocking. + public static Embedding Embedding(long index = default, ReadOnlyMemory? embeddingAsFloats = null) + { + // TODO: We need to populate the embedding property from the embeddingAsFloats parameter. + return new Embedding(index, embeddingProperty: null, EmbeddingObject.Embedding, serializedAdditionalRawData: null, embeddingAsFloats, embeddingAsBase64Data: null); + } + + /// Initializes a new instance of . + /// The index of the embedding in the list of embeddings. + /// + /// The embedding vector, which is a list of floats. The length of vector depends on the model as + /// listed in the [embedding guide](/docs/guides/embeddings). + /// + /// The object type, which is always "embedding". + /// A new instance for mocking. + public static Embedding Embedding(long index = default, BinaryData embeddingAsBase64Data = default) + { + return new Embedding(index, embeddingAsBase64Data, EmbeddingObject.Embedding, serializedAdditionalRawData: null, embeddingAsFloats: null, embeddingAsBase64Data); + } + } +} diff --git a/.dotnet/src/Generated/Embeddings.cs b/.dotnet/src/Generated/Embeddings.cs index f935d7640..d6b7802a6 100644 --- a/.dotnet/src/Generated/Embeddings.cs +++ b/.dotnet/src/Generated/Embeddings.cs @@ -40,27 +40,27 @@ internal Embeddings(ClientPipeline pipeline, ApiKeyCredential credential, Uri en } /// Creates an embedding vector representing the input text. - /// The to use. + /// The to use. /// is null. - public virtual async Task> CreateEmbeddingAsync(CreateEmbeddingRequest embedding) + internal virtual async Task> CreateEmbeddingAsync(GenerateEmbeddingsOptions embedding) { if (embedding is null) throw new ArgumentNullException(nameof(embedding)); using BinaryContent content = BinaryContent.Create(embedding); ClientResult result = await CreateEmbeddingAsync(content).ConfigureAwait(false); - return ClientResult.FromValue(CreateEmbeddingResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + return ClientResult.FromValue(EmbeddingCollection.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Creates an embedding vector representing the input text. - /// The to use. + /// The to use. /// is null. - public virtual ClientResult CreateEmbedding(CreateEmbeddingRequest embedding) + internal virtual ClientResult CreateEmbedding(GenerateEmbeddingsOptions embedding) { if (embedding is null) throw new ArgumentNullException(nameof(embedding)); using BinaryContent content = BinaryContent.Create(embedding); ClientResult result = CreateEmbedding(content); - return ClientResult.FromValue(CreateEmbeddingResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + return ClientResult.FromValue(EmbeddingCollection.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -73,7 +73,7 @@ public virtual ClientResult CreateEmbedding(CreateEmbed /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -83,7 +83,7 @@ public virtual ClientResult CreateEmbedding(CreateEmbed /// is null. /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task CreateEmbeddingAsync(BinaryContent content, RequestOptions options = null) + internal virtual async Task CreateEmbeddingAsync(BinaryContent content, RequestOptions options = null) { if (content is null) throw new ArgumentNullException(nameof(content)); options ??= new RequestOptions(); @@ -109,7 +109,7 @@ public virtual async Task CreateEmbeddingAsync(BinaryContent conte /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -119,7 +119,7 @@ public virtual async Task CreateEmbeddingAsync(BinaryContent conte /// is null. /// Service returned a non-success status code. /// The response returned from the service. - public virtual ClientResult CreateEmbedding(BinaryContent content, RequestOptions options = null) + internal virtual ClientResult CreateEmbedding(BinaryContent content, RequestOptions options = null) { if (content is null) throw new ArgumentNullException(nameof(content)); options ??= new RequestOptions(); diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingRequestEncodingFormat.cs b/.dotnet/src/Generated/Models/CreateEmbeddingRequestEncodingFormat.cs deleted file mode 100644 index e252744e4..000000000 --- a/.dotnet/src/Generated/Models/CreateEmbeddingRequestEncodingFormat.cs +++ /dev/null @@ -1,47 +0,0 @@ -// - -using System; -using System.ComponentModel; - -namespace OpenAI.Models -{ - /// Enum for encoding_format in CreateEmbeddingRequest. - public readonly partial struct CreateEmbeddingRequestEncodingFormat : IEquatable - { - private readonly string _value; - - /// Initializes a new instance of . - /// is null. - public CreateEmbeddingRequestEncodingFormat(string value) - { - _value = value ?? throw new ArgumentNullException(nameof(value)); - } - - private const string FloatValue = "float"; - private const string Base64Value = "base64"; - - /// float. - public static CreateEmbeddingRequestEncodingFormat Float { get; } = new CreateEmbeddingRequestEncodingFormat(FloatValue); - /// base64. - public static CreateEmbeddingRequestEncodingFormat Base64 { get; } = new CreateEmbeddingRequestEncodingFormat(Base64Value); - /// Determines if two values are the same. - public static bool operator ==(CreateEmbeddingRequestEncodingFormat left, CreateEmbeddingRequestEncodingFormat right) => left.Equals(right); - /// Determines if two values are not the same. - public static bool operator !=(CreateEmbeddingRequestEncodingFormat left, CreateEmbeddingRequestEncodingFormat right) => !left.Equals(right); - /// Converts a string to a . - public static implicit operator CreateEmbeddingRequestEncodingFormat(string value) => new CreateEmbeddingRequestEncodingFormat(value); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public override bool Equals(object obj) => obj is CreateEmbeddingRequestEncodingFormat other && Equals(other); - /// - public bool Equals(CreateEmbeddingRequestEncodingFormat other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public override int GetHashCode() => _value?.GetHashCode() ?? 0; - /// - public override string ToString() => _value; - } -} - diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingRequestModel.cs b/.dotnet/src/Generated/Models/CreateEmbeddingRequestModel.cs deleted file mode 100644 index 628de9b7b..000000000 --- a/.dotnet/src/Generated/Models/CreateEmbeddingRequestModel.cs +++ /dev/null @@ -1,50 +0,0 @@ -// - -using System; -using System.ComponentModel; - -namespace OpenAI.Models -{ - /// Enum for model in CreateEmbeddingRequest. - public readonly partial struct CreateEmbeddingRequestModel : IEquatable - { - private readonly string _value; - - /// Initializes a new instance of . - /// is null. - public CreateEmbeddingRequestModel(string value) - { - _value = value ?? throw new ArgumentNullException(nameof(value)); - } - - private const string TextEmbeddingAda002Value = "text-embedding-ada-002"; - private const string TextEmbedding3SmallValue = "text-embedding-3-small"; - private const string TextEmbedding3LargeValue = "text-embedding-3-large"; - - /// text-embedding-ada-002. - public static CreateEmbeddingRequestModel TextEmbeddingAda002 { get; } = new CreateEmbeddingRequestModel(TextEmbeddingAda002Value); - /// text-embedding-3-small. - public static CreateEmbeddingRequestModel TextEmbedding3Small { get; } = new CreateEmbeddingRequestModel(TextEmbedding3SmallValue); - /// text-embedding-3-large. - public static CreateEmbeddingRequestModel TextEmbedding3Large { get; } = new CreateEmbeddingRequestModel(TextEmbedding3LargeValue); - /// Determines if two values are the same. - public static bool operator ==(CreateEmbeddingRequestModel left, CreateEmbeddingRequestModel right) => left.Equals(right); - /// Determines if two values are not the same. - public static bool operator !=(CreateEmbeddingRequestModel left, CreateEmbeddingRequestModel right) => !left.Equals(right); - /// Converts a string to a . - public static implicit operator CreateEmbeddingRequestModel(string value) => new CreateEmbeddingRequestModel(value); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public override bool Equals(object obj) => obj is CreateEmbeddingRequestModel other && Equals(other); - /// - public bool Equals(CreateEmbeddingRequestModel other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public override int GetHashCode() => _value?.GetHashCode() ?? 0; - /// - public override string ToString() => _value; - } -} - diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingResponseObject.cs b/.dotnet/src/Generated/Models/CreateEmbeddingResponseObject.cs deleted file mode 100644 index b98b10317..000000000 --- a/.dotnet/src/Generated/Models/CreateEmbeddingResponseObject.cs +++ /dev/null @@ -1,44 +0,0 @@ -// - -using System; -using System.ComponentModel; - -namespace OpenAI.Models -{ - /// The CreateEmbeddingResponse_object. - public readonly partial struct CreateEmbeddingResponseObject : IEquatable - { - private readonly string _value; - - /// Initializes a new instance of . - /// is null. - public CreateEmbeddingResponseObject(string value) - { - _value = value ?? throw new ArgumentNullException(nameof(value)); - } - - private const string ListValue = "list"; - - /// list. - public static CreateEmbeddingResponseObject List { get; } = new CreateEmbeddingResponseObject(ListValue); - /// Determines if two values are the same. - public static bool operator ==(CreateEmbeddingResponseObject left, CreateEmbeddingResponseObject right) => left.Equals(right); - /// Determines if two values are not the same. - public static bool operator !=(CreateEmbeddingResponseObject left, CreateEmbeddingResponseObject right) => !left.Equals(right); - /// Converts a string to a . - public static implicit operator CreateEmbeddingResponseObject(string value) => new CreateEmbeddingResponseObject(value); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public override bool Equals(object obj) => obj is CreateEmbeddingResponseObject other && Equals(other); - /// - public bool Equals(CreateEmbeddingResponseObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public override int GetHashCode() => _value?.GetHashCode() ?? 0; - /// - public override string ToString() => _value; - } -} - diff --git a/.dotnet/src/Generated/Models/Embedding.Serialization.cs b/.dotnet/src/Generated/Models/Embedding.Serialization.cs index b3506e51c..0f9790a19 100644 --- a/.dotnet/src/Generated/Models/Embedding.Serialization.cs +++ b/.dotnet/src/Generated/Models/Embedding.Serialization.cs @@ -3,7 +3,6 @@ using System; using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; -using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models @@ -62,45 +61,6 @@ Embedding IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWri return DeserializeEmbedding(document.RootElement, options); } - internal static Embedding DeserializeEmbedding(JsonElement element, ModelReaderWriterOptions options = null) - { - options ??= new ModelReaderWriterOptions("W"); - - if (element.ValueKind == JsonValueKind.Null) - { - return null; - } - long index = default; - BinaryData embedding = default; - EmbeddingObject @object = default; - IDictionary serializedAdditionalRawData = default; - Dictionary additionalPropertiesDictionary = new Dictionary(); - foreach (var property in element.EnumerateObject()) - { - if (property.NameEquals("index"u8)) - { - index = property.Value.GetInt64(); - continue; - } - if (property.NameEquals("embedding"u8)) - { - embedding = BinaryData.FromString(property.Value.GetRawText()); - continue; - } - if (property.NameEquals("object"u8)) - { - @object = new EmbeddingObject(property.Value.GetString()); - continue; - } - if (options.Format != "W") - { - additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); - } - } - serializedAdditionalRawData = additionalPropertiesDictionary; - return new Embedding(index, embedding, @object, serializedAdditionalRawData); - } - BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; diff --git a/.dotnet/src/Generated/Models/Embedding.cs b/.dotnet/src/Generated/Models/Embedding.cs index ecabc7df9..9a3e895f8 100644 --- a/.dotnet/src/Generated/Models/Embedding.cs +++ b/.dotnet/src/Generated/Models/Embedding.cs @@ -79,51 +79,6 @@ internal Embedding() /// The index of the embedding in the list of embeddings. public long Index { get; } - /// - /// The embedding vector, which is a list of floats. The length of vector depends on the model as - /// listed in the [embedding guide](/docs/guides/embeddings). - /// - /// To assign an object to this property use . - /// - /// - /// To assign an already formatted json string to this property use . - /// - /// - /// - /// Supported types: - /// - /// - /// where T is of type - /// - /// - /// - /// - /// - /// - /// Examples: - /// - /// - /// BinaryData.FromObjectAsJson("foo") - /// Creates a payload of "foo". - /// - /// - /// BinaryData.FromString("\"foo\"") - /// Creates a payload of "foo". - /// - /// - /// BinaryData.FromObjectAsJson(new { key = "value" }) - /// Creates a payload of { "key": "value" }. - /// - /// - /// BinaryData.FromString("{\"key\": \"value\"}") - /// Creates a payload of { "key": "value" }. - /// - /// - /// - /// - public BinaryData EmbeddingProperty { get; } - /// The object type, which is always "embedding". - public EmbeddingObject Object { get; } = EmbeddingObject.Embedding; } } diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingResponse.Serialization.cs b/.dotnet/src/Generated/Models/EmbeddingCollection.Serialization.cs similarity index 64% rename from .dotnet/src/Generated/Models/CreateEmbeddingResponse.Serialization.cs rename to .dotnet/src/Generated/Models/EmbeddingCollection.Serialization.cs index 84e854405..c4a8aa240 100644 --- a/.dotnet/src/Generated/Models/CreateEmbeddingResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/EmbeddingCollection.Serialization.cs @@ -8,14 +8,14 @@ namespace OpenAI.Models { - public partial class CreateEmbeddingResponse : IJsonModel + public partial class EmbeddingCollection : IJsonModel { - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; if (format != "J") { - throw new FormatException($"The model {nameof(CreateEmbeddingResponse)} does not support '{format}' format."); + throw new FormatException($"The model {nameof(EmbeddingCollection)} does not support '{format}' format."); } writer.WriteStartObject(); @@ -50,19 +50,19 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReade writer.WriteEndObject(); } - CreateEmbeddingResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + EmbeddingCollection IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; if (format != "J") { - throw new FormatException($"The model {nameof(CreateEmbeddingResponse)} does not support '{format}' format."); + throw new FormatException($"The model {nameof(EmbeddingCollection)} does not support '{format}' format."); } using JsonDocument document = JsonDocument.ParseValue(ref reader); - return DeserializeCreateEmbeddingResponse(document.RootElement, options); + return DeserializeEmbeddingCollection(document.RootElement, options); } - internal static CreateEmbeddingResponse DeserializeCreateEmbeddingResponse(JsonElement element, ModelReaderWriterOptions options = null) + internal static EmbeddingCollection DeserializeEmbeddingCollection(JsonElement element, ModelReaderWriterOptions options = null) { options ??= new ModelReaderWriterOptions("W"); @@ -72,8 +72,8 @@ internal static CreateEmbeddingResponse DeserializeCreateEmbeddingResponse(JsonE } IReadOnlyList data = default; string model = default; - CreateEmbeddingResponseObject @object = default; - CreateEmbeddingResponseUsage usage = default; + EmbeddingCollectionObject @object = default; + EmbeddingTokenUsage usage = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -95,12 +95,12 @@ internal static CreateEmbeddingResponse DeserializeCreateEmbeddingResponse(JsonE } if (property.NameEquals("object"u8)) { - @object = new CreateEmbeddingResponseObject(property.Value.GetString()); + @object = new EmbeddingCollectionObject(property.Value.GetString()); continue; } if (property.NameEquals("usage"u8)) { - usage = CreateEmbeddingResponseUsage.DeserializeCreateEmbeddingResponseUsage(property.Value); + usage = EmbeddingTokenUsage.DeserializeEmbeddingTokenUsage(property.Value); continue; } if (options.Format != "W") @@ -109,46 +109,46 @@ internal static CreateEmbeddingResponse DeserializeCreateEmbeddingResponse(JsonE } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateEmbeddingResponse(data, model, @object, usage, serializedAdditionalRawData); + return new EmbeddingCollection(data, model, @object, usage, serializedAdditionalRawData); } - BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; switch (format) { case "J": return ModelReaderWriter.Write(this, options); default: - throw new FormatException($"The model {nameof(CreateEmbeddingResponse)} does not support '{options.Format}' format."); + throw new FormatException($"The model {nameof(EmbeddingCollection)} does not support '{options.Format}' format."); } } - CreateEmbeddingResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + EmbeddingCollection IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; switch (format) { case "J": { using JsonDocument document = JsonDocument.Parse(data); - return DeserializeCreateEmbeddingResponse(document.RootElement, options); + return DeserializeEmbeddingCollection(document.RootElement, options); } default: - throw new FormatException($"The model {nameof(CreateEmbeddingResponse)} does not support '{options.Format}' format."); + throw new FormatException($"The model {nameof(EmbeddingCollection)} does not support '{options.Format}' format."); } } - string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; /// Deserializes the model from a raw response. /// The result to deserialize the model from. - internal static CreateEmbeddingResponse FromResponse(PipelineResponse response) + internal static EmbeddingCollection FromResponse(PipelineResponse response) { using var document = JsonDocument.Parse(response.Content); - return DeserializeCreateEmbeddingResponse(document.RootElement); + return DeserializeEmbeddingCollection(document.RootElement); } } } diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingResponse.cs b/.dotnet/src/Generated/Models/EmbeddingCollection.cs similarity index 77% rename from .dotnet/src/Generated/Models/CreateEmbeddingResponse.cs rename to .dotnet/src/Generated/Models/EmbeddingCollection.cs index ce1b35c17..d7dd3ec73 100644 --- a/.dotnet/src/Generated/Models/CreateEmbeddingResponse.cs +++ b/.dotnet/src/Generated/Models/EmbeddingCollection.cs @@ -7,8 +7,8 @@ namespace OpenAI.Models { - /// The CreateEmbeddingResponse. - public partial class CreateEmbeddingResponse + /// The EmbeddingCollection. + public partial class EmbeddingCollection { /// /// Keeps track of any properties unknown to the library. @@ -42,12 +42,12 @@ public partial class CreateEmbeddingResponse /// private IDictionary _serializedAdditionalRawData; - /// Initializes a new instance of . + /// Initializes a new instance of . /// The list of embeddings generated by the model. /// The name of the model used to generate the embedding. /// The usage information for the request. /// , or is null. - internal CreateEmbeddingResponse(IEnumerable data, string model, CreateEmbeddingResponseUsage usage) + internal EmbeddingCollection(IEnumerable data, string model, EmbeddingTokenUsage usage) { if (data is null) throw new ArgumentNullException(nameof(data)); if (model is null) throw new ArgumentNullException(nameof(model)); @@ -58,13 +58,13 @@ internal CreateEmbeddingResponse(IEnumerable data, string model, Crea Usage = usage; } - /// Initializes a new instance of . + /// Initializes a new instance of . /// The list of embeddings generated by the model. /// The name of the model used to generate the embedding. /// The object type, which is always "list". /// The usage information for the request. /// Keeps track of any properties unknown to the library. - internal CreateEmbeddingResponse(IReadOnlyList data, string model, CreateEmbeddingResponseObject @object, CreateEmbeddingResponseUsage usage, IDictionary serializedAdditionalRawData) + internal EmbeddingCollection(IReadOnlyList data, string model, EmbeddingCollectionObject @object, EmbeddingTokenUsage usage, IDictionary serializedAdditionalRawData) { Data = data; Model = model; @@ -73,8 +73,8 @@ internal CreateEmbeddingResponse(IReadOnlyList data, string model, Cr _serializedAdditionalRawData = serializedAdditionalRawData; } - /// Initializes a new instance of for deserialization. - internal CreateEmbeddingResponse() + /// Initializes a new instance of for deserialization. + internal EmbeddingCollection() { } @@ -83,10 +83,10 @@ internal CreateEmbeddingResponse() /// The name of the model used to generate the embedding. public string Model { get; } /// The object type, which is always "list". - public CreateEmbeddingResponseObject Object { get; } = CreateEmbeddingResponseObject.List; + public EmbeddingCollectionObject Object { get; } = EmbeddingCollectionObject.List; /// The usage information for the request. - public CreateEmbeddingResponseUsage Usage { get; } + public EmbeddingTokenUsage Usage { get; } } } diff --git a/.dotnet/src/Generated/Models/EmbeddingCollectionObject.cs b/.dotnet/src/Generated/Models/EmbeddingCollectionObject.cs new file mode 100644 index 000000000..b045cf349 --- /dev/null +++ b/.dotnet/src/Generated/Models/EmbeddingCollectionObject.cs @@ -0,0 +1,44 @@ +// + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The EmbeddingCollection_object. + public readonly partial struct EmbeddingCollectionObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public EmbeddingCollectionObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string ListValue = "list"; + + /// list. + public static EmbeddingCollectionObject List { get; } = new EmbeddingCollectionObject(ListValue); + /// Determines if two values are the same. + public static bool operator ==(EmbeddingCollectionObject left, EmbeddingCollectionObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(EmbeddingCollectionObject left, EmbeddingCollectionObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator EmbeddingCollectionObject(string value) => new EmbeddingCollectionObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is EmbeddingCollectionObject other && Equals(other); + /// + public bool Equals(EmbeddingCollectionObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} + diff --git a/.dotnet/src/Generated/Models/EmbeddingObject.cs b/.dotnet/src/Generated/Models/EmbeddingObject.cs index 2cc2f012c..c6088b162 100644 --- a/.dotnet/src/Generated/Models/EmbeddingObject.cs +++ b/.dotnet/src/Generated/Models/EmbeddingObject.cs @@ -6,7 +6,7 @@ namespace OpenAI.Models { /// The Embedding_object. - public readonly partial struct EmbeddingObject : IEquatable + internal readonly partial struct EmbeddingObject : IEquatable { private readonly string _value; diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingResponseUsage.Serialization.cs b/.dotnet/src/Generated/Models/EmbeddingTokenUsage.Serialization.cs similarity index 62% rename from .dotnet/src/Generated/Models/CreateEmbeddingResponseUsage.Serialization.cs rename to .dotnet/src/Generated/Models/EmbeddingTokenUsage.Serialization.cs index 2b10317c0..8026af740 100644 --- a/.dotnet/src/Generated/Models/CreateEmbeddingResponseUsage.Serialization.cs +++ b/.dotnet/src/Generated/Models/EmbeddingTokenUsage.Serialization.cs @@ -8,14 +8,14 @@ namespace OpenAI.Models { - public partial class CreateEmbeddingResponseUsage : IJsonModel + public partial class EmbeddingTokenUsage : IJsonModel { - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; if (format != "J") { - throw new FormatException($"The model {nameof(CreateEmbeddingResponseUsage)} does not support '{format}' format."); + throw new FormatException($"The model {nameof(EmbeddingTokenUsage)} does not support '{format}' format."); } writer.WriteStartObject(); @@ -41,19 +41,19 @@ void IJsonModel.Write(Utf8JsonWriter writer, Model writer.WriteEndObject(); } - CreateEmbeddingResponseUsage IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + EmbeddingTokenUsage IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; if (format != "J") { - throw new FormatException($"The model {nameof(CreateEmbeddingResponseUsage)} does not support '{format}' format."); + throw new FormatException($"The model {nameof(EmbeddingTokenUsage)} does not support '{format}' format."); } using JsonDocument document = JsonDocument.ParseValue(ref reader); - return DeserializeCreateEmbeddingResponseUsage(document.RootElement, options); + return DeserializeEmbeddingTokenUsage(document.RootElement, options); } - internal static CreateEmbeddingResponseUsage DeserializeCreateEmbeddingResponseUsage(JsonElement element, ModelReaderWriterOptions options = null) + internal static EmbeddingTokenUsage DeserializeEmbeddingTokenUsage(JsonElement element, ModelReaderWriterOptions options = null) { options ??= new ModelReaderWriterOptions("W"); @@ -83,46 +83,46 @@ internal static CreateEmbeddingResponseUsage DeserializeCreateEmbeddingResponseU } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateEmbeddingResponseUsage(promptTokens, totalTokens, serializedAdditionalRawData); + return new EmbeddingTokenUsage(promptTokens, totalTokens, serializedAdditionalRawData); } - BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; switch (format) { case "J": return ModelReaderWriter.Write(this, options); default: - throw new FormatException($"The model {nameof(CreateEmbeddingResponseUsage)} does not support '{options.Format}' format."); + throw new FormatException($"The model {nameof(EmbeddingTokenUsage)} does not support '{options.Format}' format."); } } - CreateEmbeddingResponseUsage IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + EmbeddingTokenUsage IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; switch (format) { case "J": { using JsonDocument document = JsonDocument.Parse(data); - return DeserializeCreateEmbeddingResponseUsage(document.RootElement, options); + return DeserializeEmbeddingTokenUsage(document.RootElement, options); } default: - throw new FormatException($"The model {nameof(CreateEmbeddingResponseUsage)} does not support '{options.Format}' format."); + throw new FormatException($"The model {nameof(EmbeddingTokenUsage)} does not support '{options.Format}' format."); } } - string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; /// Deserializes the model from a raw response. /// The result to deserialize the model from. - internal static CreateEmbeddingResponseUsage FromResponse(PipelineResponse response) + internal static EmbeddingTokenUsage FromResponse(PipelineResponse response) { using var document = JsonDocument.Parse(response.Content); - return DeserializeCreateEmbeddingResponseUsage(document.RootElement); + return DeserializeEmbeddingTokenUsage(document.RootElement); } } } diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingResponseUsage.cs b/.dotnet/src/Generated/Models/EmbeddingTokenUsage.cs similarity index 77% rename from .dotnet/src/Generated/Models/CreateEmbeddingResponseUsage.cs rename to .dotnet/src/Generated/Models/EmbeddingTokenUsage.cs index bafd0284c..e235e4d4b 100644 --- a/.dotnet/src/Generated/Models/CreateEmbeddingResponseUsage.cs +++ b/.dotnet/src/Generated/Models/EmbeddingTokenUsage.cs @@ -5,8 +5,8 @@ namespace OpenAI.Models { - /// The CreateEmbeddingResponseUsage. - public partial class CreateEmbeddingResponseUsage + /// The EmbeddingTokenUsage. + public partial class EmbeddingTokenUsage { /// /// Keeps track of any properties unknown to the library. @@ -40,28 +40,28 @@ public partial class CreateEmbeddingResponseUsage /// private IDictionary _serializedAdditionalRawData; - /// Initializes a new instance of . + /// Initializes a new instance of . /// The number of tokens used by the prompt. /// The total number of tokens used by the request. - internal CreateEmbeddingResponseUsage(long promptTokens, long totalTokens) + internal EmbeddingTokenUsage(long promptTokens, long totalTokens) { PromptTokens = promptTokens; TotalTokens = totalTokens; } - /// Initializes a new instance of . + /// Initializes a new instance of . /// The number of tokens used by the prompt. /// The total number of tokens used by the request. /// Keeps track of any properties unknown to the library. - internal CreateEmbeddingResponseUsage(long promptTokens, long totalTokens, IDictionary serializedAdditionalRawData) + internal EmbeddingTokenUsage(long promptTokens, long totalTokens, IDictionary serializedAdditionalRawData) { PromptTokens = promptTokens; TotalTokens = totalTokens; _serializedAdditionalRawData = serializedAdditionalRawData; } - /// Initializes a new instance of for deserialization. - internal CreateEmbeddingResponseUsage() + /// Initializes a new instance of for deserialization. + internal EmbeddingTokenUsage() { } diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingRequest.Serialization.cs b/.dotnet/src/Generated/Models/GenerateEmbeddingsOptions.Serialization.cs similarity index 67% rename from .dotnet/src/Generated/Models/CreateEmbeddingRequest.Serialization.cs rename to .dotnet/src/Generated/Models/GenerateEmbeddingsOptions.Serialization.cs index 7a8ff235b..5d6ec0838 100644 --- a/.dotnet/src/Generated/Models/CreateEmbeddingRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/GenerateEmbeddingsOptions.Serialization.cs @@ -8,14 +8,14 @@ namespace OpenAI.Models { - public partial class CreateEmbeddingRequest : IJsonModel + public partial class GenerateEmbeddingsOptions : IJsonModel { - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; if (format != "J") { - throw new FormatException($"The model {nameof(CreateEmbeddingRequest)} does not support '{format}' format."); + throw new FormatException($"The model {nameof(GenerateEmbeddingsOptions)} does not support '{format}' format."); } writer.WriteStartObject(); @@ -63,19 +63,19 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReader writer.WriteEndObject(); } - CreateEmbeddingRequest IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + GenerateEmbeddingsOptions IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; if (format != "J") { - throw new FormatException($"The model {nameof(CreateEmbeddingRequest)} does not support '{format}' format."); + throw new FormatException($"The model {nameof(GenerateEmbeddingsOptions)} does not support '{format}' format."); } using JsonDocument document = JsonDocument.ParseValue(ref reader); - return DeserializeCreateEmbeddingRequest(document.RootElement, options); + return DeserializeGenerateEmbeddingsOptions(document.RootElement, options); } - internal static CreateEmbeddingRequest DeserializeCreateEmbeddingRequest(JsonElement element, ModelReaderWriterOptions options = null) + internal static GenerateEmbeddingsOptions DeserializeGenerateEmbeddingsOptions(JsonElement element, ModelReaderWriterOptions options = null) { options ??= new ModelReaderWriterOptions("W"); @@ -84,8 +84,8 @@ internal static CreateEmbeddingRequest DeserializeCreateEmbeddingRequest(JsonEle return null; } BinaryData input = default; - CreateEmbeddingRequestModel model = default; - OptionalProperty encodingFormat = default; + GenerateEmbeddingsOptionsModel model = default; + OptionalProperty encodingFormat = default; OptionalProperty dimensions = default; OptionalProperty user = default; IDictionary serializedAdditionalRawData = default; @@ -99,7 +99,7 @@ internal static CreateEmbeddingRequest DeserializeCreateEmbeddingRequest(JsonEle } if (property.NameEquals("model"u8)) { - model = new CreateEmbeddingRequestModel(property.Value.GetString()); + model = new GenerateEmbeddingsOptionsModel(property.Value.GetString()); continue; } if (property.NameEquals("encoding_format"u8)) @@ -108,7 +108,7 @@ internal static CreateEmbeddingRequest DeserializeCreateEmbeddingRequest(JsonEle { continue; } - encodingFormat = new CreateEmbeddingRequestEncodingFormat(property.Value.GetString()); + encodingFormat = new GenerateEmbeddingsOptionsEncodingFormat(property.Value.GetString()); continue; } if (property.NameEquals("dimensions"u8)) @@ -131,46 +131,46 @@ internal static CreateEmbeddingRequest DeserializeCreateEmbeddingRequest(JsonEle } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateEmbeddingRequest(input, model, OptionalProperty.ToNullable(encodingFormat), OptionalProperty.ToNullable(dimensions), user.Value, serializedAdditionalRawData); + return new GenerateEmbeddingsOptions(input, model, OptionalProperty.ToNullable(encodingFormat), OptionalProperty.ToNullable(dimensions), user.Value, serializedAdditionalRawData); } - BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; switch (format) { case "J": return ModelReaderWriter.Write(this, options); default: - throw new FormatException($"The model {nameof(CreateEmbeddingRequest)} does not support '{options.Format}' format."); + throw new FormatException($"The model {nameof(GenerateEmbeddingsOptions)} does not support '{options.Format}' format."); } } - CreateEmbeddingRequest IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + GenerateEmbeddingsOptions IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; switch (format) { case "J": { using JsonDocument document = JsonDocument.Parse(data); - return DeserializeCreateEmbeddingRequest(document.RootElement, options); + return DeserializeGenerateEmbeddingsOptions(document.RootElement, options); } default: - throw new FormatException($"The model {nameof(CreateEmbeddingRequest)} does not support '{options.Format}' format."); + throw new FormatException($"The model {nameof(GenerateEmbeddingsOptions)} does not support '{options.Format}' format."); } } - string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; /// Deserializes the model from a raw response. /// The result to deserialize the model from. - internal static CreateEmbeddingRequest FromResponse(PipelineResponse response) + internal static GenerateEmbeddingsOptions FromResponse(PipelineResponse response) { using var document = JsonDocument.Parse(response.Content); - return DeserializeCreateEmbeddingRequest(document.RootElement); + return DeserializeGenerateEmbeddingsOptions(document.RootElement); } } } diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingRequest.cs b/.dotnet/src/Generated/Models/GenerateEmbeddingsOptions.cs similarity index 58% rename from .dotnet/src/Generated/Models/CreateEmbeddingRequest.cs rename to .dotnet/src/Generated/Models/GenerateEmbeddingsOptions.cs index c2a286d4c..d8a90823c 100644 --- a/.dotnet/src/Generated/Models/CreateEmbeddingRequest.cs +++ b/.dotnet/src/Generated/Models/GenerateEmbeddingsOptions.cs @@ -6,8 +6,8 @@ namespace OpenAI.Models { - /// The CreateEmbeddingRequest. - public partial class CreateEmbeddingRequest + /// The GenerateEmbeddingsOptions. + public partial class GenerateEmbeddingsOptions { /// /// Keeps track of any properties unknown to the library. @@ -41,7 +41,7 @@ public partial class CreateEmbeddingRequest /// private IDictionary _serializedAdditionalRawData; - /// Initializes a new instance of . + /// Initializes a new instance of . /// /// Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a /// single request, pass an array of strings or array of token arrays. Each input must not exceed @@ -56,7 +56,7 @@ public partial class CreateEmbeddingRequest /// descriptions of them. /// /// is null. - public CreateEmbeddingRequest(BinaryData input, CreateEmbeddingRequestModel model) + public GenerateEmbeddingsOptions(BinaryData input, GenerateEmbeddingsOptionsModel model) { if (input is null) throw new ArgumentNullException(nameof(input)); @@ -64,7 +64,7 @@ public CreateEmbeddingRequest(BinaryData input, CreateEmbeddingRequestModel mode Model = model; } - /// Initializes a new instance of . + /// Initializes a new instance of . /// /// Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a /// single request, pass an array of strings or array of token arrays. Each input must not exceed @@ -91,7 +91,7 @@ public CreateEmbeddingRequest(BinaryData input, CreateEmbeddingRequestModel mode /// abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). /// /// Keeps track of any properties unknown to the library. - internal CreateEmbeddingRequest(BinaryData input, CreateEmbeddingRequestModel model, CreateEmbeddingRequestEncodingFormat? encodingFormat, long? dimensions, string user, IDictionary serializedAdditionalRawData) + internal GenerateEmbeddingsOptions(BinaryData input, GenerateEmbeddingsOptionsModel model, GenerateEmbeddingsOptionsEncodingFormat? encodingFormat, long? dimensions, string user, IDictionary serializedAdditionalRawData) { Input = input; Model = model; @@ -101,75 +101,15 @@ internal CreateEmbeddingRequest(BinaryData input, CreateEmbeddingRequestModel mo _serializedAdditionalRawData = serializedAdditionalRawData; } - /// Initializes a new instance of for deserialization. - internal CreateEmbeddingRequest() + /// Initializes a new instance of for deserialization. + internal GenerateEmbeddingsOptions() { } - - /// - /// Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a - /// single request, pass an array of strings or array of token arrays. Each input must not exceed - /// the max input tokens for the model (8191 tokens for `text-embedding-ada-002`) and cannot be an - /// empty string. - /// [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) - /// for counting tokens. - /// - /// To assign an object to this property use . - /// - /// - /// To assign an already formatted json string to this property use . - /// - /// - /// - /// Supported types: - /// - /// - /// - /// - /// - /// where T is of type - /// - /// - /// where T is of type - /// - /// - /// where T is of type IList{long} - /// - /// - /// - /// Examples: - /// - /// - /// BinaryData.FromObjectAsJson("foo") - /// Creates a payload of "foo". - /// - /// - /// BinaryData.FromString("\"foo\"") - /// Creates a payload of "foo". - /// - /// - /// BinaryData.FromObjectAsJson(new { key = "value" }) - /// Creates a payload of { "key": "value" }. - /// - /// - /// BinaryData.FromString("{\"key\": \"value\"}") - /// Creates a payload of { "key": "value" }. - /// - /// - /// - /// - public BinaryData Input { get; } - /// - /// ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to - /// see all of your available models, or see our [Model overview](/docs/models/overview) for - /// descriptions of them. - /// - public CreateEmbeddingRequestModel Model { get; } /// /// The format to return the embeddings in. Can be either `float` or /// [`base64`](https://pypi.org/project/pybase64/). /// - public CreateEmbeddingRequestEncodingFormat? EncodingFormat { get; set; } + public GenerateEmbeddingsOptionsEncodingFormat? EncodingFormat { get; set; } /// /// The number of dimensions the resulting output embeddings should have. Only supported in /// `text-embedding-3` and later models. diff --git a/.dotnet/src/Generated/Models/GenerateEmbeddingsOptionsEncodingFormat.cs b/.dotnet/src/Generated/Models/GenerateEmbeddingsOptionsEncodingFormat.cs new file mode 100644 index 000000000..805a38b93 --- /dev/null +++ b/.dotnet/src/Generated/Models/GenerateEmbeddingsOptionsEncodingFormat.cs @@ -0,0 +1,47 @@ +// + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for encoding_format in GenerateEmbeddingsOptions. + public readonly partial struct GenerateEmbeddingsOptionsEncodingFormat : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public GenerateEmbeddingsOptionsEncodingFormat(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string FloatValue = "float"; + private const string Base64Value = "base64"; + + /// float. + public static GenerateEmbeddingsOptionsEncodingFormat Float { get; } = new GenerateEmbeddingsOptionsEncodingFormat(FloatValue); + /// base64. + public static GenerateEmbeddingsOptionsEncodingFormat Base64 { get; } = new GenerateEmbeddingsOptionsEncodingFormat(Base64Value); + /// Determines if two values are the same. + public static bool operator ==(GenerateEmbeddingsOptionsEncodingFormat left, GenerateEmbeddingsOptionsEncodingFormat right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(GenerateEmbeddingsOptionsEncodingFormat left, GenerateEmbeddingsOptionsEncodingFormat right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator GenerateEmbeddingsOptionsEncodingFormat(string value) => new GenerateEmbeddingsOptionsEncodingFormat(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is GenerateEmbeddingsOptionsEncodingFormat other && Equals(other); + /// + public bool Equals(GenerateEmbeddingsOptionsEncodingFormat other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} + diff --git a/.dotnet/src/Generated/Models/GenerateEmbeddingsOptionsModel.cs b/.dotnet/src/Generated/Models/GenerateEmbeddingsOptionsModel.cs new file mode 100644 index 000000000..e1a9c9135 --- /dev/null +++ b/.dotnet/src/Generated/Models/GenerateEmbeddingsOptionsModel.cs @@ -0,0 +1,50 @@ +// + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for model in GenerateEmbeddingsOptions. + public readonly partial struct GenerateEmbeddingsOptionsModel : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public GenerateEmbeddingsOptionsModel(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string TextEmbeddingAda002Value = "text-embedding-ada-002"; + private const string TextEmbedding3SmallValue = "text-embedding-3-small"; + private const string TextEmbedding3LargeValue = "text-embedding-3-large"; + + /// text-embedding-ada-002. + public static GenerateEmbeddingsOptionsModel TextEmbeddingAda002 { get; } = new GenerateEmbeddingsOptionsModel(TextEmbeddingAda002Value); + /// text-embedding-3-small. + public static GenerateEmbeddingsOptionsModel TextEmbedding3Small { get; } = new GenerateEmbeddingsOptionsModel(TextEmbedding3SmallValue); + /// text-embedding-3-large. + public static GenerateEmbeddingsOptionsModel TextEmbedding3Large { get; } = new GenerateEmbeddingsOptionsModel(TextEmbedding3LargeValue); + /// Determines if two values are the same. + public static bool operator ==(GenerateEmbeddingsOptionsModel left, GenerateEmbeddingsOptionsModel right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(GenerateEmbeddingsOptionsModel left, GenerateEmbeddingsOptionsModel right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator GenerateEmbeddingsOptionsModel(string value) => new GenerateEmbeddingsOptionsModel(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is GenerateEmbeddingsOptionsModel other && Equals(other); + /// + public bool Equals(GenerateEmbeddingsOptionsModel other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} + diff --git a/.dotnet/src/Generated/OpenAIClient.cs b/.dotnet/src/Generated/OpenAIClient.cs index 29785453c..7565c4dd1 100644 --- a/.dotnet/src/Generated/OpenAIClient.cs +++ b/.dotnet/src/Generated/OpenAIClient.cs @@ -89,12 +89,6 @@ public virtual Completions GetCompletionsClient() return Volatile.Read(ref _cachedCompletions) ?? Interlocked.CompareExchange(ref _cachedCompletions, new Completions(_pipeline, _credential, _endpoint), null) ?? _cachedCompletions; } - /// Initializes a new instance of Embeddings. - public virtual Embeddings GetEmbeddingsClient() - { - return Volatile.Read(ref _cachedEmbeddings) ?? Interlocked.CompareExchange(ref _cachedEmbeddings, new Embeddings(_pipeline, _credential, _endpoint), null) ?? _cachedEmbeddings; - } - /// Initializes a new instance of Files. public virtual Files GetFilesClient() { diff --git a/.dotnet/src/Generated/OpenAIModelFactory.cs b/.dotnet/src/Generated/OpenAIModelFactory.cs index c8de3f61a..dd7118fc0 100644 --- a/.dotnet/src/Generated/OpenAIModelFactory.cs +++ b/.dotnet/src/Generated/OpenAIModelFactory.cs @@ -724,71 +724,26 @@ public static CreateCompletionResponseChoiceLogprobs CreateCompletionResponseCho return new CreateCompletionResponseChoiceLogprobs(tokens?.ToList(), tokenLogprobs?.ToList(), topLogprobs?.ToList(), textOffset?.ToList(), serializedAdditionalRawData: null); } - /// Initializes a new instance of . - /// - /// Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a - /// single request, pass an array of strings or array of token arrays. Each input must not exceed - /// the max input tokens for the model (8191 tokens for `text-embedding-ada-002`) and cannot be an - /// empty string. - /// [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) - /// for counting tokens. - /// - /// - /// ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to - /// see all of your available models, or see our [Model overview](/docs/models/overview) for - /// descriptions of them. - /// - /// - /// The format to return the embeddings in. Can be either `float` or - /// [`base64`](https://pypi.org/project/pybase64/). - /// - /// - /// The number of dimensions the resulting output embeddings should have. Only supported in - /// `text-embedding-3` and later models. - /// - /// - /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect - /// abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). - /// - /// A new instance for mocking. - public static CreateEmbeddingRequest CreateEmbeddingRequest(BinaryData input = null, CreateEmbeddingRequestModel model = default, CreateEmbeddingRequestEncodingFormat? encodingFormat = null, long? dimensions = null, string user = null) - { - return new CreateEmbeddingRequest(input, model, encodingFormat, dimensions, user, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . + /// Initializes a new instance of . /// The list of embeddings generated by the model. /// The name of the model used to generate the embedding. /// The object type, which is always "list". /// The usage information for the request. - /// A new instance for mocking. - public static CreateEmbeddingResponse CreateEmbeddingResponse(IEnumerable data = null, string model = null, CreateEmbeddingResponseObject @object = default, CreateEmbeddingResponseUsage usage = null) + /// A new instance for mocking. + public static EmbeddingCollection EmbeddingCollection(IEnumerable data = null, string model = null, EmbeddingCollectionObject @object = default, EmbeddingTokenUsage usage = null) { data ??= new List(); - return new CreateEmbeddingResponse(data?.ToList(), model, @object, usage, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// The index of the embedding in the list of embeddings. - /// - /// The embedding vector, which is a list of floats. The length of vector depends on the model as - /// listed in the [embedding guide](/docs/guides/embeddings). - /// - /// The object type, which is always "embedding". - /// A new instance for mocking. - public static Embedding Embedding(long index = default, BinaryData embeddingProperty = null, EmbeddingObject @object = default) - { - return new Embedding(index, embeddingProperty, @object, serializedAdditionalRawData: null); + return new EmbeddingCollection(data?.ToList(), model, @object, usage, serializedAdditionalRawData: null); } - /// Initializes a new instance of . + /// Initializes a new instance of . /// The number of tokens used by the prompt. /// The total number of tokens used by the request. - /// A new instance for mocking. - public static CreateEmbeddingResponseUsage CreateEmbeddingResponseUsage(long promptTokens = default, long totalTokens = default) + /// A new instance for mocking. + public static EmbeddingTokenUsage EmbeddingTokenUsage(long promptTokens = default, long totalTokens = default) { - return new CreateEmbeddingResponseUsage(promptTokens, totalTokens, serializedAdditionalRawData: null); + return new EmbeddingTokenUsage(promptTokens, totalTokens, serializedAdditionalRawData: null); } /// Initializes a new instance of . diff --git a/.dotnet/tests/EmbeddingsTests.cs b/.dotnet/tests/EmbeddingsTests.cs new file mode 100644 index 000000000..ecf35be7d --- /dev/null +++ b/.dotnet/tests/EmbeddingsTests.cs @@ -0,0 +1,101 @@ +using NUnit.Framework; +using OpenAI.Models; +using System; +using System.ClientModel; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using System.Text; +using System.Threading.Tasks; + +namespace OpenAI.Tests +{ + public partial class EmbeddingsTests + { + [Test] + public static void GetEmbeddingFromString() + { + ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + OpenAIClient client = new(credential); + Embeddings embeddingsClient = client.GetEmbeddingsClient("text-embedding-3-small"); + + string input = "Best hotel in town if you like luxury hotels. They have an amazing infinity pool, a spa," + + " and a really helpful concierge. The location is perfect -- right downtown, close to all " + + " the tourist attractions. We highly recommend this hotel."; + + ClientResult result = embeddingsClient.GenerateEmbedding(input); + Embedding embedding = result.Value; + + ReadOnlyMemory vector = embedding.EmbeddingAsFloats.Value; + Assert.IsTrue(vector.Length == 1536); + } + + [Test] + public static void GetEmbeddingFromArrayOfTokens() + { + ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + OpenAIClient client = new(credential); + Embeddings embeddingsClient = client.GetEmbeddingsClient("text-embedding-3-small"); + + List input = new() { 14809, 9689, 304, 6424, 422, 499, 1093, 19913, 25325, 13, 2435, 617, 459, 8056, + 56010, 7463, 11, 264, 31493, 11, 323, 264, 2216, 11190, 3613, 87103, 13, 578, 3813, 374, 4832, 1198, + 1314, 19441, 11, 3345, 311, 682, 279, 31070, 39591, 13, 1226, 7701, 7079, 420, 9689, 13 }; + + ClientResult result = embeddingsClient.GenerateEmbedding(input); + Embedding embedding = result.Value; + + ReadOnlyMemory vector = embedding.EmbeddingAsFloats.Value; + Assert.IsTrue(vector.Length == 1536); + } + + [Test] + public static void GetEmbeddingsFromArrayOfStrings() + { + ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + OpenAIClient client = new(credential); + Embeddings embeddingsClient = client.GetEmbeddingsClient("text-embedding-3-small"); + + List inputs = new() { + "Luxury", + "Best hotel in town if you like luxury hotels. They have an amazing infinity pool, a spa," + + " and a really helpful concierge. The location is perfect -- right downtown, close to all " + + " the tourist attractions. We highly recommend this hotel." + }; + + ClientResult result = embeddingsClient.GenerateEmbeddings(inputs); + EmbeddingCollection collection = result.Value; // TODO: Make EmbeddingCollection inherit from ReadOnlyCollection. + IReadOnlyList data = collection.Data; + + ReadOnlyMemory vector0 = data[0].EmbeddingAsFloats.Value; + Assert.IsTrue(vector0.Length == 1536); + + ReadOnlyMemory vector1 = data[1].EmbeddingAsFloats.Value; + Assert.IsTrue(vector1.Length == 1536); + } + + [Test] + public static void GetEmbeddingsFromArrayOfArraysOfTokens() + { + ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + OpenAIClient client = new(credential); + Embeddings embeddingsClient = client.GetEmbeddingsClient("text-embedding-3-small"); + + List> inputs = new() { + new List { 78379, 3431 }, + new List { 14809, 9689, 304, 6424, 422, 499, 1093, 19913, 25325, 13, 2435, 617, 459, 8056, + 56010, 7463, 11, 264, 31493, 11, 323, 264, 2216, 11190, 3613, 87103, 13, 578, 3813, 374, 4832, 1198, + 1314, 19441, 11, 3345, 311, 682, 279, 31070, 39591, 13, 1226, 7701, 7079, 420, 9689, 13 } + }; + + ClientResult result = embeddingsClient.GenerateEmbeddings(inputs); + EmbeddingCollection collection = result.Value; // TODO: Make EmbeddingCollection inherit from ReadOnlyCollection. + IReadOnlyList data = collection.Data; + + ReadOnlyMemory vector0 = data[0].EmbeddingAsFloats.Value; + Assert.IsTrue(vector0.Length == 1536); + + ReadOnlyMemory vector1 = data[1].EmbeddingAsFloats.Value; + Assert.IsTrue(vector1.Length == 1536); + } + } +} diff --git a/.dotnet/tests/Generated/Tests/EmbeddingsTests.cs b/.dotnet/tests/Generated/Tests/EmbeddingsTests.cs deleted file mode 100644 index b4deac0fc..000000000 --- a/.dotnet/tests/Generated/Tests/EmbeddingsTests.cs +++ /dev/null @@ -1,23 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel; -using NUnit.Framework; -using OpenAI; - -namespace OpenAI.Tests -{ - public partial class EmbeddingsTests - { - [Test] - public void SmokeTest() - { - ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - Embeddings client = new OpenAIClient(credential).GetEmbeddingsClient(); - Assert.IsNotNull(client); - } - } -} - diff --git a/embeddings/models.tsp b/embeddings/models.tsp index fd9c13fde..fb6ab394a 100644 --- a/embeddings/models.tsp +++ b/embeddings/models.tsp @@ -55,13 +55,7 @@ model CreateEmbeddingResponse { object: "list"; /** The usage information for the request. */ - usage: { - /** The number of tokens used by the prompt. */ - prompt_tokens: safeint; - - /** The total number of tokens used by the request. */ - total_tokens: safeint; - }; + usage: EmbeddingUsage; } alias EMBEDDINGS_MODELS = @@ -70,8 +64,7 @@ alias EMBEDDINGS_MODELS = | "text-embedding-3-large"; @oneOf -union CreateEmbeddingRequestInput -{ +union CreateEmbeddingRequestInput { /** The string that will be turned into an embedding. */ string, @@ -99,3 +92,11 @@ model Embedding { /** The object type, which is always "embedding". */ object: "embedding"; } + +model EmbeddingUsage { + /** The number of tokens used by the prompt. */ + prompt_tokens: safeint; + + /** The total number of tokens used by the request. */ + total_tokens: safeint; +}; \ No newline at end of file diff --git a/main.tsp b/main.tsp index 604a75f8c..e46a4467c 100644 --- a/main.tsp +++ b/main.tsp @@ -1,6 +1,7 @@ import "@typespec/http"; import "@typespec/openapi3"; import "@typespec/openapi"; +import "@azure-tools/typespec-client-generator-core"; import "./audio"; import "./assistants"; @@ -17,6 +18,7 @@ import "./runs"; import "./threads"; using TypeSpec.Http; +using Azure.ClientGenerator.Core; /** The OpenAI REST API. Please see https://platform.openai.com/docs/api-reference for more details. */ @service({ @@ -35,3 +37,12 @@ using TypeSpec.Http; @server("https://api.openai.com/v1", "OpenAI Endpoint") @useAuth(BearerAuth) namespace OpenAI; + +@@projectedName(OpenAI.CreateEmbeddingRequest, "csharp", "GenerateEmbeddingsOptions"); +@@projectedName(OpenAI.CreateEmbeddingResponse, "csharp", "EmbeddingCollection"); +@@projectedName(OpenAI.EmbeddingUsage, "csharp", "EmbeddingTokenUsage"); + +@@access(OpenAI.Embeddings.createEmbedding, Access.internal, "csharp"); +@@access(OpenAI.CreateEmbeddingRequest, Access.public, "csharp"); +@@access(OpenAI.CreateEmbeddingResponse, Access.public, "csharp"); +@@access(OpenAI.EmbeddingUsage, Access.public, "csharp"); \ No newline at end of file diff --git a/tsp-output/@typespec/openapi3/openapi.yaml b/tsp-output/@typespec/openapi3/openapi.yaml index c96cc33ed..e27e57ba4 100644 --- a/tsp-output/@typespec/openapi3/openapi.yaml +++ b/tsp-output/@typespec/openapi3/openapi.yaml @@ -3112,19 +3112,8 @@ components: - list description: The object type, which is always "list". usage: - type: object - properties: - prompt_tokens: - type: integer - format: int64 - description: The number of tokens used by the prompt. - total_tokens: - type: integer - format: int64 - description: The total number of tokens used by the request. - required: - - prompt_tokens - - total_tokens + allOf: + - $ref: '#/components/schemas/EmbeddingUsage' description: The usage information for the request. CreateFileRequestMultiPart: type: object @@ -4210,6 +4199,20 @@ components: - embedding description: The object type, which is always "embedding". description: Represents an embedding vector returned by embedding endpoint. + EmbeddingUsage: + type: object + required: + - prompt_tokens + - total_tokens + properties: + prompt_tokens: + type: integer + format: int64 + description: The number of tokens used by the prompt. + total_tokens: + type: integer + format: int64 + description: The total number of tokens used by the request. Error: type: object required: From 03664d5818b57ac6fd4a751913c900b3d02dde2c Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado Date: Tue, 20 Feb 2024 17:15:32 -0800 Subject: [PATCH 14/50] Fix Update-ClientModel.ps1 script: DefaultRequestContext and URI path fixes --- .dotnet/scripts/Update-ClientModel.ps1 | 14 +++--- .dotnet/src/Generated/Assistants.cs | 55 ++++++++------------ .dotnet/src/Generated/Audio.cs | 14 +++--- .dotnet/src/Generated/Chat.cs | 6 ++- .dotnet/src/Generated/Completions.cs | 6 ++- .dotnet/src/Generated/Embeddings.cs | 6 ++- .dotnet/src/Generated/Files.cs | 28 +++++------ .dotnet/src/Generated/FineTuning.cs | 31 ++++++------ .dotnet/src/Generated/Images.cs | 14 +++--- .dotnet/src/Generated/Messages.cs | 49 ++++++------------ .dotnet/src/Generated/ModelsOps.cs | 16 +++--- .dotnet/src/Generated/Moderations.cs | 6 ++- .dotnet/src/Generated/Runs.cs | 69 ++++++++------------------ .dotnet/src/Generated/Threads.cs | 21 ++++---- 14 files changed, 144 insertions(+), 191 deletions(-) diff --git a/.dotnet/scripts/Update-ClientModel.ps1 b/.dotnet/scripts/Update-ClientModel.ps1 index 1e533dde4..203cdd80c 100644 --- a/.dotnet/scripts/Update-ClientModel.ps1 +++ b/.dotnet/scripts/Update-ClientModel.ps1 @@ -89,10 +89,10 @@ function Update-Subclients { $content = $content -creplace "RequestOptions context = FromCancellationToken\(cancellationToken\);\s+", "" $content = $content -creplace "using RequestBody content = (?\w+)\.ToRequestBody\(\);", "using BinaryContent content = BinaryContent.Create(`${var});" $content = $content -creplace "using RequestBody content0 = (?\w+)\.ToRequestBody\(\);", "using BinaryContent content0 = BinaryContent.Create(`${var});" - $content = $content -creplace "Result result = await (?\w+)\(context\)\.ConfigureAwait\(false\);", "ClientResult result = await `${method}().ConfigureAwait(false);" - $content = $content -creplace "Result result = (?\w+)\(context\);", "ClientResult result = `${method}();" - $content = $content -creplace "Result result = await (?\w+)\((?[(\w+)(\?.ToString\(\)*)(,\s\w+)]*), context\)\.ConfigureAwait\(false\);", "ClientResult result = await `${method}(`${params}).ConfigureAwait(false);" - $content = $content -creplace "Result result = (?\w+)\((?[(\w+)(\?.ToString\(\)*)(,\s\w+)]*), context\);", "ClientResult result = `${method}(`${params});" + $content = $content -creplace "Result result = await (?\w+)\(context\)\.ConfigureAwait\(false\);", "ClientResult result = await `${method}(DefaultRequestContext).ConfigureAwait(false);" + $content = $content -creplace "Result result = (?\w+)\(context\);", "ClientResult result = `${method}(DefaultRequestContext);" + $content = $content -creplace "Result result = await (?\w+)\((?[(\w+)(\?.ToString\(\)*)(,\s\w+)]*), context\)\.ConfigureAwait\(false\);", "ClientResult result = await `${method}(`${params}, DefaultRequestContext).ConfigureAwait(false);" + $content = $content -creplace "Result result = (?\w+)\((?[(\w+)(\?.ToString\(\)*)(,\s\w+)]*), context\);", "ClientResult result = `${method}(`${params}, DefaultRequestContext);" # Modify protocol methods $content = $content -creplace "\/\/\/ Please try the simpler \w+)\((?[(\w+)(\?*)(,\s\w+)]*),CancellationToken\)`"/> convenience overload with strongly typed models first.", "/// Please try the simpler convenience overload with strongly typed models first." @@ -119,14 +119,14 @@ function Update-Subclients { $content = $content -creplace "request\.SetMethod\(`"(?[\w\/]+)`"\);", "request.Method = `"`${name}`";" $content = $content -creplace "var uri = new RequestUri\(\);", "UriBuilder uriBuilder = new(_endpoint.ToString());" $content = $content -creplace "uri\.Reset\(_endpoint\);", "StringBuilder path = new();" - $content = $content -creplace "uri\.AppendPath\((?`"?[\w\/]+`"?), (\w+)\);", "path.Append(`${path});`r`n uriBuilder.Path += path.ToString();" + $content = $content -creplace "uri\.AppendPath\((?`"?[\w\/]+`"?), (\w+)\);", "path.Append(`${path});" $content = $content -creplace "uri\.AppendQuery\(`"(?\w+)`", (?\w+(\.Value)?), (\w+)\);", "if (uriBuilder.Query != null && uriBuilder.Query.Length > 1)`r`n {`r`n uriBuilder.Query += $`"&`${key}={`${value}}`";`r`n }`r`n else`r`n {`r`n uriBuilder.Query = $`"`${key}={`${value}}`";`r`n }" - $content = $content -creplace "request\.Uri = uri\.ToUri\(\);", "request.Uri = uriBuilder.Uri;" + $content = $content -creplace "request\.Uri = uri\.ToUri\(\);", "uriBuilder.Path += path.ToString();`r`n request.Uri = uriBuilder.Uri;" $content = $content -creplace "request\.SetHeaderValue", "request.Headers.Set" $content = $content -creplace "request\.Content = content;", "request.Content = content;`r`n message.Apply(options);" # Delete DefaultRequestContext - $content = $content -creplace "\s+private static RequestOptions DefaultRequestContext = new RequestOptions\(\);", "" + # $content = $content -creplace "\s+private static RequestOptions DefaultRequestContext = new RequestOptions\(\);", "" # Delete FromCancellationToken $content = $content -creplace "(?s)\s+internal static RequestOptions FromCancellationToken\(CancellationToken cancellationToken = default\).*?return new RequestOptions\(\) \{ CancellationToken = cancellationToken \};.*?\}", "" diff --git a/.dotnet/src/Generated/Assistants.cs b/.dotnet/src/Generated/Assistants.cs index afaac60ee..e725cfe7e 100644 --- a/.dotnet/src/Generated/Assistants.cs +++ b/.dotnet/src/Generated/Assistants.cs @@ -47,7 +47,7 @@ public virtual async Task> CreateAssistantAsync(Cr if (assistant is null) throw new ArgumentNullException(nameof(assistant)); using BinaryContent content = BinaryContent.Create(assistant); - ClientResult result = await CreateAssistantAsync(content).ConfigureAwait(false); + ClientResult result = await CreateAssistantAsync(content, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(AssistantObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -59,7 +59,7 @@ public virtual ClientResult CreateAssistant(CreateAssistantRequ if (assistant is null) throw new ArgumentNullException(nameof(assistant)); using BinaryContent content = BinaryContent.Create(assistant); - ClientResult result = CreateAssistant(content); + ClientResult result = CreateAssistant(content, DefaultRequestContext); return ClientResult.FromValue(AssistantObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -156,7 +156,7 @@ public virtual ClientResult CreateAssistant(BinaryContent content, RequestOption /// public virtual async Task> GetAssistantsAsync(int? limit = null, ListOrder? order = null, string after = null, string before = null) { - ClientResult result = await GetAssistantsAsync(limit, order?.ToString(), after, before).ConfigureAwait(false); + ClientResult result = await GetAssistantsAsync(limit, order?.ToString(), after, before, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(ListAssistantsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -181,7 +181,7 @@ public virtual async Task> GetAssistantsAsy /// public virtual ClientResult GetAssistants(int? limit = null, ListOrder? order = null, string after = null, string before = null) { - ClientResult result = GetAssistants(limit, order?.ToString(), after, before); + ClientResult result = GetAssistants(limit, order?.ToString(), after, before, DefaultRequestContext); return ClientResult.FromValue(ListAssistantsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -296,7 +296,7 @@ public virtual async Task> GetAssistantAsync(strin if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - ClientResult result = await GetAssistantAsync(assistantId).ConfigureAwait(false); + ClientResult result = await GetAssistantAsync(assistantId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(AssistantObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -309,7 +309,7 @@ public virtual ClientResult GetAssistant(string assistantId) if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - ClientResult result = GetAssistant(assistantId); + ClientResult result = GetAssistant(assistantId, DefaultRequestContext); return ClientResult.FromValue(AssistantObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -401,7 +401,7 @@ public virtual async Task> ModifyAssistantAsync(st if (assistant is null) throw new ArgumentNullException(nameof(assistant)); using BinaryContent content = BinaryContent.Create(assistant); - ClientResult result = await ModifyAssistantAsync(assistantId, content).ConfigureAwait(false); + ClientResult result = await ModifyAssistantAsync(assistantId, content, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(AssistantObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -417,7 +417,7 @@ public virtual ClientResult ModifyAssistant(string assistantId, if (assistant is null) throw new ArgumentNullException(nameof(assistant)); using BinaryContent content = BinaryContent.Create(assistant); - ClientResult result = ModifyAssistant(assistantId, content); + ClientResult result = ModifyAssistant(assistantId, content, DefaultRequestContext); return ClientResult.FromValue(AssistantObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -510,7 +510,7 @@ public virtual async Task> DeleteAssistant if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - ClientResult result = await DeleteAssistantAsync(assistantId).ConfigureAwait(false); + ClientResult result = await DeleteAssistantAsync(assistantId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(DeleteAssistantResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -523,7 +523,7 @@ public virtual ClientResult DeleteAssistant(string assi if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - ClientResult result = DeleteAssistant(assistantId); + ClientResult result = DeleteAssistant(assistantId, DefaultRequestContext); return ClientResult.FromValue(DeleteAssistantResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -618,7 +618,7 @@ public virtual async Task> CreateAssistantFile if (file is null) throw new ArgumentNullException(nameof(file)); using BinaryContent content = BinaryContent.Create(file); - ClientResult result = await CreateAssistantFileAsync(assistantId, content).ConfigureAwait(false); + ClientResult result = await CreateAssistantFileAsync(assistantId, content, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(AssistantFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -637,7 +637,7 @@ public virtual ClientResult CreateAssistantFile(string assi if (file is null) throw new ArgumentNullException(nameof(file)); using BinaryContent content = BinaryContent.Create(file); - ClientResult result = CreateAssistantFile(assistantId, content); + ClientResult result = CreateAssistantFile(assistantId, content, DefaultRequestContext); return ClientResult.FromValue(AssistantFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -750,7 +750,7 @@ public virtual async Task> GetAssistant if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - ClientResult result = await GetAssistantFilesAsync(assistantId, limit, order?.ToString(), after, before).ConfigureAwait(false); + ClientResult result = await GetAssistantFilesAsync(assistantId, limit, order?.ToString(), after, before, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(ListAssistantFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -781,7 +781,7 @@ public virtual ClientResult GetAssistantFiles(string if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - ClientResult result = GetAssistantFiles(assistantId, limit, order?.ToString(), after, before); + ClientResult result = GetAssistantFiles(assistantId, limit, order?.ToString(), after, before, DefaultRequestContext); return ClientResult.FromValue(ListAssistantFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -909,7 +909,7 @@ public virtual async Task> GetAssistantFileAsy if (fileId is null) throw new ArgumentNullException(nameof(fileId)); if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - ClientResult result = await GetAssistantFileAsync(assistantId, fileId).ConfigureAwait(false); + ClientResult result = await GetAssistantFileAsync(assistantId, fileId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(AssistantFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -925,7 +925,7 @@ public virtual ClientResult GetAssistantFile(string assista if (fileId is null) throw new ArgumentNullException(nameof(fileId)); if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - ClientResult result = GetAssistantFile(assistantId, fileId); + ClientResult result = GetAssistantFile(assistantId, fileId, DefaultRequestContext); return ClientResult.FromValue(AssistantFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -1023,7 +1023,7 @@ public virtual async Task> DeleteAssis if (fileId is null) throw new ArgumentNullException(nameof(fileId)); if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - ClientResult result = await DeleteAssistantFileAsync(assistantId, fileId).ConfigureAwait(false); + ClientResult result = await DeleteAssistantFileAsync(assistantId, fileId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(DeleteAssistantFileResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -1039,7 +1039,7 @@ public virtual ClientResult DeleteAssistantFile(str if (fileId is null) throw new ArgumentNullException(nameof(fileId)); if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - ClientResult result = DeleteAssistantFile(assistantId, fileId); + ClientResult result = DeleteAssistantFile(assistantId, fileId, DefaultRequestContext); return ClientResult.FromValue(DeleteAssistantFileResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -1152,7 +1152,6 @@ internal PipelineMessage CreateGetAssistantsRequest(int? limit, string order, st UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/assistants"); - uriBuilder.Path += path.ToString(); if (limit != null) { if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) @@ -1197,6 +1196,7 @@ internal PipelineMessage CreateGetAssistantsRequest(int? limit, string order, st uriBuilder.Query = $"before={before}"; } } + uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; request.Headers.Set("Accept", "application/json"); return message; @@ -1211,7 +1211,6 @@ internal PipelineMessage CreateGetAssistantRequest(string assistantId, RequestOp UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/assistants/"); - uriBuilder.Path += path.ToString(); path.Append(assistantId); uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; @@ -1228,7 +1227,6 @@ internal PipelineMessage CreateModifyAssistantRequest(string assistantId, Binary UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/assistants/"); - uriBuilder.Path += path.ToString(); path.Append(assistantId); uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; @@ -1248,7 +1246,6 @@ internal PipelineMessage CreateDeleteAssistantRequest(string assistantId, Reques UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/assistants/"); - uriBuilder.Path += path.ToString(); path.Append(assistantId); uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; @@ -1265,9 +1262,7 @@ internal PipelineMessage CreateCreateAssistantFileRequest(string assistantId, Bi UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/assistants/"); - uriBuilder.Path += path.ToString(); path.Append(assistantId); - uriBuilder.Path += path.ToString(); path.Append("/files"); uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; @@ -1287,11 +1282,8 @@ internal PipelineMessage CreateGetAssistantFilesRequest(string assistantId, int? UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/assistants/"); - uriBuilder.Path += path.ToString(); path.Append(assistantId); - uriBuilder.Path += path.ToString(); path.Append("/files"); - uriBuilder.Path += path.ToString(); if (limit != null) { if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) @@ -1336,6 +1328,7 @@ internal PipelineMessage CreateGetAssistantFilesRequest(string assistantId, int? uriBuilder.Query = $"before={before}"; } } + uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; request.Headers.Set("Accept", "application/json"); return message; @@ -1350,11 +1343,8 @@ internal PipelineMessage CreateGetAssistantFileRequest(string assistantId, strin UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/assistants/"); - uriBuilder.Path += path.ToString(); path.Append(assistantId); - uriBuilder.Path += path.ToString(); path.Append("/files/"); - uriBuilder.Path += path.ToString(); path.Append(fileId); uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; @@ -1371,11 +1361,8 @@ internal PipelineMessage CreateDeleteAssistantFileRequest(string assistantId, st UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/assistants/"); - uriBuilder.Path += path.ToString(); path.Append(assistantId); - uriBuilder.Path += path.ToString(); path.Append("/files/"); - uriBuilder.Path += path.ToString(); path.Append(fileId); uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; @@ -1383,6 +1370,8 @@ internal PipelineMessage CreateDeleteAssistantFileRequest(string assistantId, st return message; } + private static RequestOptions DefaultRequestContext = new RequestOptions(); + private static PipelineMessageClassifier _responseErrorClassifier200; private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } diff --git a/.dotnet/src/Generated/Audio.cs b/.dotnet/src/Generated/Audio.cs index d2bd5db96..963cfc0f2 100644 --- a/.dotnet/src/Generated/Audio.cs +++ b/.dotnet/src/Generated/Audio.cs @@ -47,7 +47,7 @@ public virtual async Task> CreateSpeechAsync(CreateSpee if (speech is null) throw new ArgumentNullException(nameof(speech)); using BinaryContent content = BinaryContent.Create(speech); - ClientResult result = await CreateSpeechAsync(content).ConfigureAwait(false); + ClientResult result = await CreateSpeechAsync(content, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(result.GetRawResponse().Content, result.GetRawResponse()); } @@ -59,7 +59,7 @@ public virtual ClientResult CreateSpeech(CreateSpeechRequest speech) if (speech is null) throw new ArgumentNullException(nameof(speech)); using BinaryContent content = BinaryContent.Create(speech); - ClientResult result = CreateSpeech(content); + ClientResult result = CreateSpeech(content, DefaultRequestContext); return ClientResult.FromValue(result.GetRawResponse().Content, result.GetRawResponse()); } @@ -143,7 +143,7 @@ public virtual async Task> CreateTrans if (audio is null) throw new ArgumentNullException(nameof(audio)); using BinaryContent content = BinaryContent.Create(audio); - ClientResult result = await CreateTranscriptionAsync(content).ConfigureAwait(false); + ClientResult result = await CreateTranscriptionAsync(content, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(CreateTranscriptionResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -155,7 +155,7 @@ public virtual ClientResult CreateTranscription(Cre if (audio is null) throw new ArgumentNullException(nameof(audio)); using BinaryContent content = BinaryContent.Create(audio); - ClientResult result = CreateTranscription(content); + ClientResult result = CreateTranscription(content, DefaultRequestContext); return ClientResult.FromValue(CreateTranscriptionResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -239,7 +239,7 @@ public virtual async Task> CreateTransla if (audio is null) throw new ArgumentNullException(nameof(audio)); using BinaryContent content = BinaryContent.Create(audio); - ClientResult result = await CreateTranslationAsync(content).ConfigureAwait(false); + ClientResult result = await CreateTranslationAsync(content, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(CreateTranslationResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -251,7 +251,7 @@ public virtual ClientResult CreateTranslation(CreateT if (audio is null) throw new ArgumentNullException(nameof(audio)); using BinaryContent content = BinaryContent.Create(audio); - ClientResult result = CreateTranslation(content); + ClientResult result = CreateTranslation(content, DefaultRequestContext); return ClientResult.FromValue(CreateTranslationResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -381,6 +381,8 @@ internal PipelineMessage CreateCreateTranslationRequest(BinaryContent content, R return message; } + private static RequestOptions DefaultRequestContext = new RequestOptions(); + private static PipelineMessageClassifier _responseErrorClassifier200; private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } diff --git a/.dotnet/src/Generated/Chat.cs b/.dotnet/src/Generated/Chat.cs index 3fa357d90..bb3bb2cc3 100644 --- a/.dotnet/src/Generated/Chat.cs +++ b/.dotnet/src/Generated/Chat.cs @@ -47,7 +47,7 @@ public virtual async Task> CreateChat if (createChatCompletionRequest is null) throw new ArgumentNullException(nameof(createChatCompletionRequest)); using BinaryContent content = BinaryContent.Create(createChatCompletionRequest); - ClientResult result = await CreateChatCompletionAsync(content).ConfigureAwait(false); + ClientResult result = await CreateChatCompletionAsync(content, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(CreateChatCompletionResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -59,7 +59,7 @@ public virtual ClientResult CreateChatCompletion(C if (createChatCompletionRequest is null) throw new ArgumentNullException(nameof(createChatCompletionRequest)); using BinaryContent content = BinaryContent.Create(createChatCompletionRequest); - ClientResult result = CreateChatCompletion(content); + ClientResult result = CreateChatCompletion(content, DefaultRequestContext); return ClientResult.FromValue(CreateChatCompletionResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -153,6 +153,8 @@ internal PipelineMessage CreateCreateChatCompletionRequest(BinaryContent content return message; } + private static RequestOptions DefaultRequestContext = new RequestOptions(); + private static PipelineMessageClassifier _responseErrorClassifier200; private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } diff --git a/.dotnet/src/Generated/Completions.cs b/.dotnet/src/Generated/Completions.cs index 779fa66c0..f55f7c729 100644 --- a/.dotnet/src/Generated/Completions.cs +++ b/.dotnet/src/Generated/Completions.cs @@ -47,7 +47,7 @@ public virtual async Task> CreateCompleti if (createCompletionRequest is null) throw new ArgumentNullException(nameof(createCompletionRequest)); using BinaryContent content = BinaryContent.Create(createCompletionRequest); - ClientResult result = await CreateCompletionAsync(content).ConfigureAwait(false); + ClientResult result = await CreateCompletionAsync(content, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(CreateCompletionResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -59,7 +59,7 @@ public virtual ClientResult CreateCompletion(CreateCom if (createCompletionRequest is null) throw new ArgumentNullException(nameof(createCompletionRequest)); using BinaryContent content = BinaryContent.Create(createCompletionRequest); - ClientResult result = CreateCompletion(content); + ClientResult result = CreateCompletion(content, DefaultRequestContext); return ClientResult.FromValue(CreateCompletionResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -153,6 +153,8 @@ internal PipelineMessage CreateCreateCompletionRequest(BinaryContent content, Re return message; } + private static RequestOptions DefaultRequestContext = new RequestOptions(); + private static PipelineMessageClassifier _responseErrorClassifier200; private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } diff --git a/.dotnet/src/Generated/Embeddings.cs b/.dotnet/src/Generated/Embeddings.cs index d6b7802a6..0788abad9 100644 --- a/.dotnet/src/Generated/Embeddings.cs +++ b/.dotnet/src/Generated/Embeddings.cs @@ -47,7 +47,7 @@ internal virtual async Task> CreateEmbeddingAs if (embedding is null) throw new ArgumentNullException(nameof(embedding)); using BinaryContent content = BinaryContent.Create(embedding); - ClientResult result = await CreateEmbeddingAsync(content).ConfigureAwait(false); + ClientResult result = await CreateEmbeddingAsync(content, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(EmbeddingCollection.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -59,7 +59,7 @@ internal virtual ClientResult CreateEmbedding(GenerateEmbed if (embedding is null) throw new ArgumentNullException(nameof(embedding)); using BinaryContent content = BinaryContent.Create(embedding); - ClientResult result = CreateEmbedding(content); + ClientResult result = CreateEmbedding(content, DefaultRequestContext); return ClientResult.FromValue(EmbeddingCollection.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -153,6 +153,8 @@ internal PipelineMessage CreateCreateEmbeddingRequest(BinaryContent content, Req return message; } + private static RequestOptions DefaultRequestContext = new RequestOptions(); + private static PipelineMessageClassifier _responseErrorClassifier200; private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } diff --git a/.dotnet/src/Generated/Files.cs b/.dotnet/src/Generated/Files.cs index 10258b608..815ae85ce 100644 --- a/.dotnet/src/Generated/Files.cs +++ b/.dotnet/src/Generated/Files.cs @@ -56,7 +56,7 @@ public virtual async Task> CreateFileAsync(CreateFileRe if (file is null) throw new ArgumentNullException(nameof(file)); using BinaryContent content = BinaryContent.Create(file); - ClientResult result = await CreateFileAsync(content).ConfigureAwait(false); + ClientResult result = await CreateFileAsync(content, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(OpenAIFile.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -77,7 +77,7 @@ public virtual ClientResult CreateFile(CreateFileRequest file) if (file is null) throw new ArgumentNullException(nameof(file)); using BinaryContent content = BinaryContent.Create(file); - ClientResult result = CreateFile(content); + ClientResult result = CreateFile(content, DefaultRequestContext); return ClientResult.FromValue(OpenAIFile.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -171,7 +171,7 @@ public virtual ClientResult CreateFile(BinaryContent content, RequestOptions opt /// Only return files with the given purpose. public virtual async Task> GetFilesAsync(string purpose = null) { - ClientResult result = await GetFilesAsync(purpose).ConfigureAwait(false); + ClientResult result = await GetFilesAsync(purpose, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(ListFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -179,7 +179,7 @@ public virtual async Task> GetFilesAsync(string /// Only return files with the given purpose. public virtual ClientResult GetFiles(string purpose = null) { - ClientResult result = GetFiles(purpose); + ClientResult result = GetFiles(purpose, DefaultRequestContext); return ClientResult.FromValue(ListFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -260,7 +260,7 @@ public virtual async Task> RetrieveFileAsync(string fil if (fileId is null) throw new ArgumentNullException(nameof(fileId)); if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - ClientResult result = await RetrieveFileAsync(fileId).ConfigureAwait(false); + ClientResult result = await RetrieveFileAsync(fileId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(OpenAIFile.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -273,7 +273,7 @@ public virtual ClientResult RetrieveFile(string fileId) if (fileId is null) throw new ArgumentNullException(nameof(fileId)); if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - ClientResult result = RetrieveFile(fileId); + ClientResult result = RetrieveFile(fileId, DefaultRequestContext); return ClientResult.FromValue(OpenAIFile.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -362,7 +362,7 @@ public virtual async Task> DeleteFileAsync(stri if (fileId is null) throw new ArgumentNullException(nameof(fileId)); if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - ClientResult result = await DeleteFileAsync(fileId).ConfigureAwait(false); + ClientResult result = await DeleteFileAsync(fileId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(DeleteFileResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -375,7 +375,7 @@ public virtual ClientResult DeleteFile(string fileId) if (fileId is null) throw new ArgumentNullException(nameof(fileId)); if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - ClientResult result = DeleteFile(fileId); + ClientResult result = DeleteFile(fileId, DefaultRequestContext); return ClientResult.FromValue(DeleteFileResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -464,7 +464,7 @@ public virtual async Task> DownloadFileAsync(string fileId) if (fileId is null) throw new ArgumentNullException(nameof(fileId)); if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - ClientResult result = await DownloadFileAsync(fileId).ConfigureAwait(false); + ClientResult result = await DownloadFileAsync(fileId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(result.GetRawResponse().Content.ToObjectFromJson(), result.GetRawResponse()); } @@ -477,7 +477,7 @@ public virtual ClientResult DownloadFile(string fileId) if (fileId is null) throw new ArgumentNullException(nameof(fileId)); if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - ClientResult result = DownloadFile(fileId); + ClientResult result = DownloadFile(fileId, DefaultRequestContext); return ClientResult.FromValue(result.GetRawResponse().Content.ToObjectFromJson(), result.GetRawResponse()); } @@ -584,7 +584,6 @@ internal PipelineMessage CreateGetFilesRequest(string purpose, RequestOptions op UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/files"); - uriBuilder.Path += path.ToString(); if (purpose != null) { if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) @@ -596,6 +595,7 @@ internal PipelineMessage CreateGetFilesRequest(string purpose, RequestOptions op uriBuilder.Query = $"purpose={purpose}"; } } + uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; request.Headers.Set("Accept", "application/json"); return message; @@ -610,7 +610,6 @@ internal PipelineMessage CreateRetrieveFileRequest(string fileId, RequestOptions UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/files/"); - uriBuilder.Path += path.ToString(); path.Append(fileId); uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; @@ -627,7 +626,6 @@ internal PipelineMessage CreateDeleteFileRequest(string fileId, RequestOptions o UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/files/"); - uriBuilder.Path += path.ToString(); path.Append(fileId); uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; @@ -644,9 +642,7 @@ internal PipelineMessage CreateDownloadFileRequest(string fileId, RequestOptions UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/files/"); - uriBuilder.Path += path.ToString(); path.Append(fileId); - uriBuilder.Path += path.ToString(); path.Append("/content"); uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; @@ -654,6 +650,8 @@ internal PipelineMessage CreateDownloadFileRequest(string fileId, RequestOptions return message; } + private static RequestOptions DefaultRequestContext = new RequestOptions(); + private static PipelineMessageClassifier _responseErrorClassifier200; private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } diff --git a/.dotnet/src/Generated/FineTuning.cs b/.dotnet/src/Generated/FineTuning.cs index 63c8b2f63..827f7f18f 100644 --- a/.dotnet/src/Generated/FineTuning.cs +++ b/.dotnet/src/Generated/FineTuning.cs @@ -53,7 +53,7 @@ public virtual async Task> CreateFineTuningJobAsync( if (job is null) throw new ArgumentNullException(nameof(job)); using BinaryContent content = BinaryContent.Create(job); - ClientResult result = await CreateFineTuningJobAsync(content).ConfigureAwait(false); + ClientResult result = await CreateFineTuningJobAsync(content, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -71,7 +71,7 @@ public virtual ClientResult CreateFineTuningJob(CreateFineTuningJ if (job is null) throw new ArgumentNullException(nameof(job)); using BinaryContent content = BinaryContent.Create(job); - ClientResult result = CreateFineTuningJob(content); + ClientResult result = CreateFineTuningJob(content, DefaultRequestContext); return ClientResult.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -160,7 +160,7 @@ public virtual ClientResult CreateFineTuningJob(BinaryContent content, RequestOp /// Number of fine-tuning jobs to retrieve. public virtual async Task> GetPaginatedFineTuningJobsAsync(string after = null, long? limit = null) { - ClientResult result = await GetPaginatedFineTuningJobsAsync(after, limit).ConfigureAwait(false); + ClientResult result = await GetPaginatedFineTuningJobsAsync(after, limit, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(ListPaginatedFineTuningJobsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -169,7 +169,7 @@ public virtual async Task> Get /// Number of fine-tuning jobs to retrieve. public virtual ClientResult GetPaginatedFineTuningJobs(string after = null, long? limit = null) { - ClientResult result = GetPaginatedFineTuningJobs(after, limit); + ClientResult result = GetPaginatedFineTuningJobs(after, limit, DefaultRequestContext); return ClientResult.FromValue(ListPaginatedFineTuningJobsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -256,7 +256,7 @@ public virtual async Task> RetrieveFineTuningJobAsyn if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); - ClientResult result = await RetrieveFineTuningJobAsync(fineTuningJobId).ConfigureAwait(false); + ClientResult result = await RetrieveFineTuningJobAsync(fineTuningJobId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -273,7 +273,7 @@ public virtual ClientResult RetrieveFineTuningJob(string fineTuni if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); - ClientResult result = RetrieveFineTuningJob(fineTuningJobId); + ClientResult result = RetrieveFineTuningJob(fineTuningJobId, DefaultRequestContext); return ClientResult.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -366,7 +366,7 @@ public virtual async Task> CancelFineTuningJobAsync( if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); - ClientResult result = await CancelFineTuningJobAsync(fineTuningJobId).ConfigureAwait(false); + ClientResult result = await CancelFineTuningJobAsync(fineTuningJobId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -379,7 +379,7 @@ public virtual ClientResult CancelFineTuningJob(string fineTuning if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); - ClientResult result = CancelFineTuningJob(fineTuningJobId); + ClientResult result = CancelFineTuningJob(fineTuningJobId, DefaultRequestContext); return ClientResult.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -470,7 +470,7 @@ public virtual async Task> GetFine if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); - ClientResult result = await GetFineTuningEventsAsync(fineTuningJobId, after, limit).ConfigureAwait(false); + ClientResult result = await GetFineTuningEventsAsync(fineTuningJobId, after, limit, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(ListFineTuningJobEventsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -485,7 +485,7 @@ public virtual ClientResult GetFineTuningEvents if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); - ClientResult result = GetFineTuningEvents(fineTuningJobId, after, limit); + ClientResult result = GetFineTuningEvents(fineTuningJobId, after, limit, DefaultRequestContext); return ClientResult.FromValue(ListFineTuningJobEventsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -596,7 +596,6 @@ internal PipelineMessage CreateGetPaginatedFineTuningJobsRequest(string after, l UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/fine_tuning/jobs"); - uriBuilder.Path += path.ToString(); if (after != null) { if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) @@ -619,6 +618,7 @@ internal PipelineMessage CreateGetPaginatedFineTuningJobsRequest(string after, l uriBuilder.Query = $"limit={limit.Value}"; } } + uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; request.Headers.Set("Accept", "application/json"); return message; @@ -633,7 +633,6 @@ internal PipelineMessage CreateRetrieveFineTuningJobRequest(string fineTuningJob UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/fine_tuning/jobs/"); - uriBuilder.Path += path.ToString(); path.Append(fineTuningJobId); uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; @@ -650,9 +649,7 @@ internal PipelineMessage CreateCancelFineTuningJobRequest(string fineTuningJobId UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/fine_tuning/jobs/"); - uriBuilder.Path += path.ToString(); path.Append(fineTuningJobId); - uriBuilder.Path += path.ToString(); path.Append("/cancel"); uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; @@ -669,11 +666,8 @@ internal PipelineMessage CreateGetFineTuningEventsRequest(string fineTuningJobId UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/fine_tuning/jobs/"); - uriBuilder.Path += path.ToString(); path.Append(fineTuningJobId); - uriBuilder.Path += path.ToString(); path.Append("/events"); - uriBuilder.Path += path.ToString(); if (after != null) { if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) @@ -696,11 +690,14 @@ internal PipelineMessage CreateGetFineTuningEventsRequest(string fineTuningJobId uriBuilder.Query = $"limit={limit.Value}"; } } + uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; request.Headers.Set("Accept", "application/json"); return message; } + private static RequestOptions DefaultRequestContext = new RequestOptions(); + private static PipelineMessageClassifier _responseErrorClassifier200; private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } diff --git a/.dotnet/src/Generated/Images.cs b/.dotnet/src/Generated/Images.cs index f2777b7ad..fb99a3319 100644 --- a/.dotnet/src/Generated/Images.cs +++ b/.dotnet/src/Generated/Images.cs @@ -47,7 +47,7 @@ public virtual async Task> CreateImageAsync(CreateI if (image is null) throw new ArgumentNullException(nameof(image)); using BinaryContent content = BinaryContent.Create(image); - ClientResult result = await CreateImageAsync(content).ConfigureAwait(false); + ClientResult result = await CreateImageAsync(content, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(ImagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -59,7 +59,7 @@ public virtual ClientResult CreateImage(CreateImageRequest image if (image is null) throw new ArgumentNullException(nameof(image)); using BinaryContent content = BinaryContent.Create(image); - ClientResult result = CreateImage(content); + ClientResult result = CreateImage(content, DefaultRequestContext); return ClientResult.FromValue(ImagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -143,7 +143,7 @@ public virtual async Task> CreateImageEditAsync(Cre if (image is null) throw new ArgumentNullException(nameof(image)); using BinaryContent content = BinaryContent.Create(image); - ClientResult result = await CreateImageEditAsync(content).ConfigureAwait(false); + ClientResult result = await CreateImageEditAsync(content, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(ImagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -155,7 +155,7 @@ public virtual ClientResult CreateImageEdit(CreateImageEditReque if (image is null) throw new ArgumentNullException(nameof(image)); using BinaryContent content = BinaryContent.Create(image); - ClientResult result = CreateImageEdit(content); + ClientResult result = CreateImageEdit(content, DefaultRequestContext); return ClientResult.FromValue(ImagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -239,7 +239,7 @@ public virtual async Task> CreateImageVariationAsyn if (image is null) throw new ArgumentNullException(nameof(image)); using BinaryContent content = BinaryContent.Create(image); - ClientResult result = await CreateImageVariationAsync(content).ConfigureAwait(false); + ClientResult result = await CreateImageVariationAsync(content, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(ImagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -251,7 +251,7 @@ public virtual ClientResult CreateImageVariation(CreateImageVari if (image is null) throw new ArgumentNullException(nameof(image)); using BinaryContent content = BinaryContent.Create(image); - ClientResult result = CreateImageVariation(content); + ClientResult result = CreateImageVariation(content, DefaultRequestContext); return ClientResult.FromValue(ImagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -381,6 +381,8 @@ internal PipelineMessage CreateCreateImageVariationRequest(BinaryContent content return message; } + private static RequestOptions DefaultRequestContext = new RequestOptions(); + private static PipelineMessageClassifier _responseErrorClassifier200; private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } diff --git a/.dotnet/src/Generated/Messages.cs b/.dotnet/src/Generated/Messages.cs index 28ac36351..f3abd4bad 100644 --- a/.dotnet/src/Generated/Messages.cs +++ b/.dotnet/src/Generated/Messages.cs @@ -51,7 +51,7 @@ public virtual async Task> CreateMessageAsync(string if (message is null) throw new ArgumentNullException(nameof(message)); using BinaryContent content = BinaryContent.Create(message); - ClientResult result = await CreateMessageAsync(threadId, content).ConfigureAwait(false); + ClientResult result = await CreateMessageAsync(threadId, content, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(MessageObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -67,7 +67,7 @@ public virtual ClientResult CreateMessage(string threadId, Create if (message is null) throw new ArgumentNullException(nameof(message)); using BinaryContent content = BinaryContent.Create(message); - ClientResult result = CreateMessage(threadId, content); + ClientResult result = CreateMessage(threadId, content, DefaultRequestContext); return ClientResult.FromValue(MessageObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -178,7 +178,7 @@ public virtual async Task> GetMessagesAsync(s if (threadId is null) throw new ArgumentNullException(nameof(threadId)); if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - ClientResult result = await GetMessagesAsync(threadId, limit, order?.ToString(), after, before).ConfigureAwait(false); + ClientResult result = await GetMessagesAsync(threadId, limit, order?.ToString(), after, before, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(ListMessagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -209,7 +209,7 @@ public virtual ClientResult GetMessages(string threadId, i if (threadId is null) throw new ArgumentNullException(nameof(threadId)); if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - ClientResult result = GetMessages(threadId, limit, order?.ToString(), after, before); + ClientResult result = GetMessages(threadId, limit, order?.ToString(), after, before, DefaultRequestContext); return ClientResult.FromValue(ListMessagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -337,7 +337,7 @@ public virtual async Task> GetMessageAsync(string th if (messageId is null) throw new ArgumentNullException(nameof(messageId)); if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); - ClientResult result = await GetMessageAsync(threadId, messageId).ConfigureAwait(false); + ClientResult result = await GetMessageAsync(threadId, messageId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(MessageObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -353,7 +353,7 @@ public virtual ClientResult GetMessage(string threadId, string me if (messageId is null) throw new ArgumentNullException(nameof(messageId)); if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); - ClientResult result = GetMessage(threadId, messageId); + ClientResult result = GetMessage(threadId, messageId, DefaultRequestContext); return ClientResult.FromValue(MessageObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -454,7 +454,7 @@ public virtual async Task> ModifyMessageAsync(string if (message is null) throw new ArgumentNullException(nameof(message)); using BinaryContent content = BinaryContent.Create(message); - ClientResult result = await ModifyMessageAsync(threadId, messageId, content).ConfigureAwait(false); + ClientResult result = await ModifyMessageAsync(threadId, messageId, content, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(MessageObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -473,7 +473,7 @@ public virtual ClientResult ModifyMessage(string threadId, string if (message is null) throw new ArgumentNullException(nameof(message)); using BinaryContent content = BinaryContent.Create(message); - ClientResult result = ModifyMessage(threadId, messageId, content); + ClientResult result = ModifyMessage(threadId, messageId, content, DefaultRequestContext); return ClientResult.FromValue(MessageObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -593,7 +593,7 @@ public virtual async Task> GetMessageFile if (messageId is null) throw new ArgumentNullException(nameof(messageId)); if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); - ClientResult result = await GetMessageFilesAsync(threadId, messageId, limit, order?.ToString(), after, before).ConfigureAwait(false); + ClientResult result = await GetMessageFilesAsync(threadId, messageId, limit, order?.ToString(), after, before, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(ListMessageFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -627,7 +627,7 @@ public virtual ClientResult GetMessageFiles(string thr if (messageId is null) throw new ArgumentNullException(nameof(messageId)); if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); - ClientResult result = GetMessageFiles(threadId, messageId, limit, order?.ToString(), after, before); + ClientResult result = GetMessageFiles(threadId, messageId, limit, order?.ToString(), after, before, DefaultRequestContext); return ClientResult.FromValue(ListMessageFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -764,7 +764,7 @@ public virtual async Task> GetMessageFileAsync(s if (fileId is null) throw new ArgumentNullException(nameof(fileId)); if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - ClientResult result = await GetMessageFileAsync(threadId, messageId, fileId).ConfigureAwait(false); + ClientResult result = await GetMessageFileAsync(threadId, messageId, fileId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(MessageFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -783,7 +783,7 @@ public virtual ClientResult GetMessageFile(string threadId, s if (fileId is null) throw new ArgumentNullException(nameof(fileId)); if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - ClientResult result = GetMessageFile(threadId, messageId, fileId); + ClientResult result = GetMessageFile(threadId, messageId, fileId, DefaultRequestContext); return ClientResult.FromValue(MessageFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -884,9 +884,7 @@ internal PipelineMessage CreateCreateMessageRequest(string threadId, BinaryConte UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/threads/"); - uriBuilder.Path += path.ToString(); path.Append(threadId); - uriBuilder.Path += path.ToString(); path.Append("/messages"); uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; @@ -906,11 +904,8 @@ internal PipelineMessage CreateGetMessagesRequest(string threadId, int? limit, s UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/threads/"); - uriBuilder.Path += path.ToString(); path.Append(threadId); - uriBuilder.Path += path.ToString(); path.Append("/messages"); - uriBuilder.Path += path.ToString(); if (limit != null) { if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) @@ -955,6 +950,7 @@ internal PipelineMessage CreateGetMessagesRequest(string threadId, int? limit, s uriBuilder.Query = $"before={before}"; } } + uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; request.Headers.Set("Accept", "application/json"); return message; @@ -969,11 +965,8 @@ internal PipelineMessage CreateGetMessageRequest(string threadId, string message UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/threads/"); - uriBuilder.Path += path.ToString(); path.Append(threadId); - uriBuilder.Path += path.ToString(); path.Append("/messages/"); - uriBuilder.Path += path.ToString(); path.Append(messageId); uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; @@ -990,11 +983,8 @@ internal PipelineMessage CreateModifyMessageRequest(string threadId, string mess UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/threads/"); - uriBuilder.Path += path.ToString(); path.Append(threadId); - uriBuilder.Path += path.ToString(); path.Append("/messages/"); - uriBuilder.Path += path.ToString(); path.Append(messageId); uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; @@ -1014,15 +1004,10 @@ internal PipelineMessage CreateGetMessageFilesRequest(string threadId, string me UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/threads/"); - uriBuilder.Path += path.ToString(); path.Append(threadId); - uriBuilder.Path += path.ToString(); path.Append("/messages/"); - uriBuilder.Path += path.ToString(); path.Append(messageId); - uriBuilder.Path += path.ToString(); path.Append("/files"); - uriBuilder.Path += path.ToString(); if (limit != null) { if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) @@ -1067,6 +1052,7 @@ internal PipelineMessage CreateGetMessageFilesRequest(string threadId, string me uriBuilder.Query = $"before={before}"; } } + uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; request.Headers.Set("Accept", "application/json"); return message; @@ -1081,15 +1067,10 @@ internal PipelineMessage CreateGetMessageFileRequest(string threadId, string mes UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/threads/"); - uriBuilder.Path += path.ToString(); path.Append(threadId); - uriBuilder.Path += path.ToString(); path.Append("/messages/"); - uriBuilder.Path += path.ToString(); path.Append(messageId); - uriBuilder.Path += path.ToString(); path.Append("/files/"); - uriBuilder.Path += path.ToString(); path.Append(fileId); uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; @@ -1097,6 +1078,8 @@ internal PipelineMessage CreateGetMessageFileRequest(string threadId, string mes return message; } + private static RequestOptions DefaultRequestContext = new RequestOptions(); + private static PipelineMessageClassifier _responseErrorClassifier200; private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } diff --git a/.dotnet/src/Generated/ModelsOps.cs b/.dotnet/src/Generated/ModelsOps.cs index e806f3cef..528bd4d2f 100644 --- a/.dotnet/src/Generated/ModelsOps.cs +++ b/.dotnet/src/Generated/ModelsOps.cs @@ -45,7 +45,7 @@ internal ModelsOps(ClientPipeline pipeline, ApiKeyCredential credential, Uri end /// public virtual async Task> GetModelsAsync(CancellationToken cancellationToken = default) { - ClientResult result = await GetModelsAsync().ConfigureAwait(false); + ClientResult result = await GetModelsAsync(DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(ListModelsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -55,7 +55,7 @@ public virtual async Task> GetModelsAsync(Cance /// public virtual ClientResult GetModels(CancellationToken cancellationToken = default) { - ClientResult result = GetModels(); + ClientResult result = GetModels(DefaultRequestContext); return ClientResult.FromValue(ListModelsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -139,7 +139,7 @@ public virtual async Task> RetrieveAsync(string model) if (model is null) throw new ArgumentNullException(nameof(model)); if (string.IsNullOrEmpty(model)) throw new ArgumentException(nameof(model)); - ClientResult result = await RetrieveAsync(model).ConfigureAwait(false); + ClientResult result = await RetrieveAsync(model, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(Model.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -155,7 +155,7 @@ public virtual ClientResult Retrieve(string model) if (model is null) throw new ArgumentNullException(nameof(model)); if (string.IsNullOrEmpty(model)) throw new ArgumentException(nameof(model)); - ClientResult result = Retrieve(model); + ClientResult result = Retrieve(model, DefaultRequestContext); return ClientResult.FromValue(Model.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -246,7 +246,7 @@ public virtual async Task> DeleteAsync(string if (model is null) throw new ArgumentNullException(nameof(model)); if (string.IsNullOrEmpty(model)) throw new ArgumentException(nameof(model)); - ClientResult result = await DeleteAsync(model).ConfigureAwait(false); + ClientResult result = await DeleteAsync(model, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(DeleteModelResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -259,7 +259,7 @@ public virtual ClientResult Delete(string model) if (model is null) throw new ArgumentNullException(nameof(model)); if (string.IsNullOrEmpty(model)) throw new ArgumentException(nameof(model)); - ClientResult result = Delete(model); + ClientResult result = Delete(model, DefaultRequestContext); return ClientResult.FromValue(DeleteModelResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -363,7 +363,6 @@ internal PipelineMessage CreateRetrieveRequest(string model, RequestOptions opti UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/models/"); - uriBuilder.Path += path.ToString(); path.Append(model); uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; @@ -380,7 +379,6 @@ internal PipelineMessage CreateDeleteRequest(string model, RequestOptions option UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/models/"); - uriBuilder.Path += path.ToString(); path.Append(model); uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; @@ -388,6 +386,8 @@ internal PipelineMessage CreateDeleteRequest(string model, RequestOptions option return message; } + private static RequestOptions DefaultRequestContext = new RequestOptions(); + private static PipelineMessageClassifier _responseErrorClassifier200; private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } diff --git a/.dotnet/src/Generated/Moderations.cs b/.dotnet/src/Generated/Moderations.cs index e0127be76..3c728d50a 100644 --- a/.dotnet/src/Generated/Moderations.cs +++ b/.dotnet/src/Generated/Moderations.cs @@ -47,7 +47,7 @@ public virtual async Task> CreateModerati if (content is null) throw new ArgumentNullException(nameof(content)); using BinaryContent content0 = BinaryContent.Create(content); - ClientResult result = await CreateModerationAsync(content0).ConfigureAwait(false); + ClientResult result = await CreateModerationAsync(content0, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(CreateModerationResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -59,7 +59,7 @@ public virtual ClientResult CreateModeration(CreateMod if (content is null) throw new ArgumentNullException(nameof(content)); using BinaryContent content0 = BinaryContent.Create(content); - ClientResult result = CreateModeration(content0); + ClientResult result = CreateModeration(content0, DefaultRequestContext); return ClientResult.FromValue(CreateModerationResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -153,6 +153,8 @@ internal PipelineMessage CreateCreateModerationRequest(BinaryContent content, Re return message; } + private static RequestOptions DefaultRequestContext = new RequestOptions(); + private static PipelineMessageClassifier _responseErrorClassifier200; private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } diff --git a/.dotnet/src/Generated/Runs.cs b/.dotnet/src/Generated/Runs.cs index 05661caa5..5d79922ec 100644 --- a/.dotnet/src/Generated/Runs.cs +++ b/.dotnet/src/Generated/Runs.cs @@ -47,7 +47,7 @@ public virtual async Task> CreateThreadAndRunAsync(Creat if (threadAndRun is null) throw new ArgumentNullException(nameof(threadAndRun)); using BinaryContent content = BinaryContent.Create(threadAndRun); - ClientResult result = await CreateThreadAndRunAsync(content).ConfigureAwait(false); + ClientResult result = await CreateThreadAndRunAsync(content, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -59,7 +59,7 @@ public virtual ClientResult CreateThreadAndRun(CreateThreadAndRunRequ if (threadAndRun is null) throw new ArgumentNullException(nameof(threadAndRun)); using BinaryContent content = BinaryContent.Create(threadAndRun); - ClientResult result = CreateThreadAndRun(content); + ClientResult result = CreateThreadAndRun(content, DefaultRequestContext); return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -147,7 +147,7 @@ public virtual async Task> CreateRunAsync(string threadI if (run is null) throw new ArgumentNullException(nameof(run)); using BinaryContent content = BinaryContent.Create(run); - ClientResult result = await CreateRunAsync(threadId, content).ConfigureAwait(false); + ClientResult result = await CreateRunAsync(threadId, content, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -163,7 +163,7 @@ public virtual ClientResult CreateRun(string threadId, CreateRunReque if (run is null) throw new ArgumentNullException(nameof(run)); using BinaryContent content = BinaryContent.Create(run); - ClientResult result = CreateRun(threadId, content); + ClientResult result = CreateRun(threadId, content, DefaultRequestContext); return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -274,7 +274,7 @@ public virtual async Task> GetRunsAsync(string th if (threadId is null) throw new ArgumentNullException(nameof(threadId)); if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - ClientResult result = await GetRunsAsync(threadId, limit, order?.ToString(), after, before).ConfigureAwait(false); + ClientResult result = await GetRunsAsync(threadId, limit, order?.ToString(), after, before, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(ListRunsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -305,7 +305,7 @@ public virtual ClientResult GetRuns(string threadId, int? limi if (threadId is null) throw new ArgumentNullException(nameof(threadId)); if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - ClientResult result = GetRuns(threadId, limit, order?.ToString(), after, before); + ClientResult result = GetRuns(threadId, limit, order?.ToString(), after, before, DefaultRequestContext); return ClientResult.FromValue(ListRunsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -433,7 +433,7 @@ public virtual async Task> GetRunAsync(string threadId, if (runId is null) throw new ArgumentNullException(nameof(runId)); if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - ClientResult result = await GetRunAsync(threadId, runId).ConfigureAwait(false); + ClientResult result = await GetRunAsync(threadId, runId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -449,7 +449,7 @@ public virtual ClientResult GetRun(string threadId, string runId) if (runId is null) throw new ArgumentNullException(nameof(runId)); if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - ClientResult result = GetRun(threadId, runId); + ClientResult result = GetRun(threadId, runId, DefaultRequestContext); return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -550,7 +550,7 @@ public virtual async Task> ModifyRunAsync(string threadI if (run is null) throw new ArgumentNullException(nameof(run)); using BinaryContent content = BinaryContent.Create(run); - ClientResult result = await ModifyRunAsync(threadId, runId, content).ConfigureAwait(false); + ClientResult result = await ModifyRunAsync(threadId, runId, content, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -569,7 +569,7 @@ public virtual ClientResult ModifyRun(string threadId, string runId, if (run is null) throw new ArgumentNullException(nameof(run)); using BinaryContent content = BinaryContent.Create(run); - ClientResult result = ModifyRun(threadId, runId, content); + ClientResult result = ModifyRun(threadId, runId, content, DefaultRequestContext); return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -671,7 +671,7 @@ public virtual async Task> CancelRunAsync(string threadI if (runId is null) throw new ArgumentNullException(nameof(runId)); if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - ClientResult result = await CancelRunAsync(threadId, runId).ConfigureAwait(false); + ClientResult result = await CancelRunAsync(threadId, runId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -687,7 +687,7 @@ public virtual ClientResult CancelRun(string threadId, string runId) if (runId is null) throw new ArgumentNullException(nameof(runId)); if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - ClientResult result = CancelRun(threadId, runId); + ClientResult result = CancelRun(threadId, runId, DefaultRequestContext); return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -792,7 +792,7 @@ public virtual async Task> SubmitToolOuputsToRunAsync(st if (submitToolOutputsRun is null) throw new ArgumentNullException(nameof(submitToolOutputsRun)); using BinaryContent content = BinaryContent.Create(submitToolOutputsRun); - ClientResult result = await SubmitToolOuputsToRunAsync(threadId, runId, content).ConfigureAwait(false); + ClientResult result = await SubmitToolOuputsToRunAsync(threadId, runId, content, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -815,7 +815,7 @@ public virtual ClientResult SubmitToolOuputsToRun(string threadId, st if (submitToolOutputsRun is null) throw new ArgumentNullException(nameof(submitToolOutputsRun)); using BinaryContent content = BinaryContent.Create(submitToolOutputsRun); - ClientResult result = SubmitToolOuputsToRun(threadId, runId, content); + ClientResult result = SubmitToolOuputsToRun(threadId, runId, content, DefaultRequestContext); return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -939,7 +939,7 @@ public virtual async Task> GetRunStepsAsync(s if (runId is null) throw new ArgumentNullException(nameof(runId)); if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - ClientResult result = await GetRunStepsAsync(threadId, runId, limit, order?.ToString(), after, before).ConfigureAwait(false); + ClientResult result = await GetRunStepsAsync(threadId, runId, limit, order?.ToString(), after, before, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(ListRunStepsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -973,7 +973,7 @@ public virtual ClientResult GetRunSteps(string threadId, s if (runId is null) throw new ArgumentNullException(nameof(runId)); if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - ClientResult result = GetRunSteps(threadId, runId, limit, order?.ToString(), after, before); + ClientResult result = GetRunSteps(threadId, runId, limit, order?.ToString(), after, before, DefaultRequestContext); return ClientResult.FromValue(ListRunStepsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -1110,7 +1110,7 @@ public virtual async Task> GetRunStepAsync(string th if (stepId is null) throw new ArgumentNullException(nameof(stepId)); if (string.IsNullOrEmpty(stepId)) throw new ArgumentException(nameof(stepId)); - ClientResult result = await GetRunStepAsync(threadId, runId, stepId).ConfigureAwait(false); + ClientResult result = await GetRunStepAsync(threadId, runId, stepId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(RunStepObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -1129,7 +1129,7 @@ public virtual ClientResult GetRunStep(string threadId, string ru if (stepId is null) throw new ArgumentNullException(nameof(stepId)); if (string.IsNullOrEmpty(stepId)) throw new ArgumentException(nameof(stepId)); - ClientResult result = GetRunStep(threadId, runId, stepId); + ClientResult result = GetRunStep(threadId, runId, stepId, DefaultRequestContext); return ClientResult.FromValue(RunStepObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -1248,9 +1248,7 @@ internal PipelineMessage CreateCreateRunRequest(string threadId, BinaryContent c UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/threads/"); - uriBuilder.Path += path.ToString(); path.Append(threadId); - uriBuilder.Path += path.ToString(); path.Append("/runs"); uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; @@ -1270,11 +1268,8 @@ internal PipelineMessage CreateGetRunsRequest(string threadId, int? limit, strin UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/threads/"); - uriBuilder.Path += path.ToString(); path.Append(threadId); - uriBuilder.Path += path.ToString(); path.Append("/runs"); - uriBuilder.Path += path.ToString(); if (limit != null) { if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) @@ -1319,6 +1314,7 @@ internal PipelineMessage CreateGetRunsRequest(string threadId, int? limit, strin uriBuilder.Query = $"before={before}"; } } + uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; request.Headers.Set("Accept", "application/json"); return message; @@ -1333,11 +1329,8 @@ internal PipelineMessage CreateGetRunRequest(string threadId, string runId, Requ UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/threads/"); - uriBuilder.Path += path.ToString(); path.Append(threadId); - uriBuilder.Path += path.ToString(); path.Append("/runs/"); - uriBuilder.Path += path.ToString(); path.Append(runId); uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; @@ -1354,11 +1347,8 @@ internal PipelineMessage CreateModifyRunRequest(string threadId, string runId, B UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/threads/"); - uriBuilder.Path += path.ToString(); path.Append(threadId); - uriBuilder.Path += path.ToString(); path.Append("/runs/"); - uriBuilder.Path += path.ToString(); path.Append(runId); uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; @@ -1378,13 +1368,9 @@ internal PipelineMessage CreateCancelRunRequest(string threadId, string runId, R UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/threads/"); - uriBuilder.Path += path.ToString(); path.Append(threadId); - uriBuilder.Path += path.ToString(); path.Append("/runs/"); - uriBuilder.Path += path.ToString(); path.Append(runId); - uriBuilder.Path += path.ToString(); path.Append("/cancel"); uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; @@ -1401,13 +1387,9 @@ internal PipelineMessage CreateSubmitToolOuputsToRunRequest(string threadId, str UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/threads/"); - uriBuilder.Path += path.ToString(); path.Append(threadId); - uriBuilder.Path += path.ToString(); path.Append("/runs/"); - uriBuilder.Path += path.ToString(); path.Append(runId); - uriBuilder.Path += path.ToString(); path.Append("/submit_tool_outputs"); uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; @@ -1427,15 +1409,10 @@ internal PipelineMessage CreateGetRunStepsRequest(string threadId, string runId, UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/threads/"); - uriBuilder.Path += path.ToString(); path.Append(threadId); - uriBuilder.Path += path.ToString(); path.Append("/runs/"); - uriBuilder.Path += path.ToString(); path.Append(runId); - uriBuilder.Path += path.ToString(); path.Append("/steps"); - uriBuilder.Path += path.ToString(); if (limit != null) { if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) @@ -1480,6 +1457,7 @@ internal PipelineMessage CreateGetRunStepsRequest(string threadId, string runId, uriBuilder.Query = $"before={before}"; } } + uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; request.Headers.Set("Accept", "application/json"); return message; @@ -1494,15 +1472,10 @@ internal PipelineMessage CreateGetRunStepRequest(string threadId, string runId, UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/threads/"); - uriBuilder.Path += path.ToString(); path.Append(threadId); - uriBuilder.Path += path.ToString(); path.Append("/runs/"); - uriBuilder.Path += path.ToString(); path.Append(runId); - uriBuilder.Path += path.ToString(); path.Append("/steps/"); - uriBuilder.Path += path.ToString(); path.Append(stepId); uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; @@ -1510,6 +1483,8 @@ internal PipelineMessage CreateGetRunStepRequest(string threadId, string runId, return message; } + private static RequestOptions DefaultRequestContext = new RequestOptions(); + private static PipelineMessageClassifier _responseErrorClassifier200; private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } diff --git a/.dotnet/src/Generated/Threads.cs b/.dotnet/src/Generated/Threads.cs index 462f88718..6332bef17 100644 --- a/.dotnet/src/Generated/Threads.cs +++ b/.dotnet/src/Generated/Threads.cs @@ -47,7 +47,7 @@ public virtual async Task> CreateThreadAsync(CreateTh if (thread is null) throw new ArgumentNullException(nameof(thread)); using BinaryContent content = BinaryContent.Create(thread); - ClientResult result = await CreateThreadAsync(content).ConfigureAwait(false); + ClientResult result = await CreateThreadAsync(content, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(ThreadObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -59,7 +59,7 @@ public virtual ClientResult CreateThread(CreateThreadRequest threa if (thread is null) throw new ArgumentNullException(nameof(thread)); using BinaryContent content = BinaryContent.Create(thread); - ClientResult result = CreateThread(content); + ClientResult result = CreateThread(content, DefaultRequestContext); return ClientResult.FromValue(ThreadObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -144,7 +144,7 @@ public virtual async Task> GetThreadAsync(string thre if (threadId is null) throw new ArgumentNullException(nameof(threadId)); if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - ClientResult result = await GetThreadAsync(threadId).ConfigureAwait(false); + ClientResult result = await GetThreadAsync(threadId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(ThreadObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -157,7 +157,7 @@ public virtual ClientResult GetThread(string threadId) if (threadId is null) throw new ArgumentNullException(nameof(threadId)); if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - ClientResult result = GetThread(threadId); + ClientResult result = GetThread(threadId, DefaultRequestContext); return ClientResult.FromValue(ThreadObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -249,7 +249,7 @@ public virtual async Task> ModifyThreadAsync(string t if (thread is null) throw new ArgumentNullException(nameof(thread)); using BinaryContent content = BinaryContent.Create(thread); - ClientResult result = await ModifyThreadAsync(threadId, content).ConfigureAwait(false); + ClientResult result = await ModifyThreadAsync(threadId, content, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(ThreadObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -265,7 +265,7 @@ public virtual ClientResult ModifyThread(string threadId, ModifyTh if (thread is null) throw new ArgumentNullException(nameof(thread)); using BinaryContent content = BinaryContent.Create(thread); - ClientResult result = ModifyThread(threadId, content); + ClientResult result = ModifyThread(threadId, content, DefaultRequestContext); return ClientResult.FromValue(ThreadObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -358,7 +358,7 @@ public virtual async Task> DeleteThreadAsync( if (threadId is null) throw new ArgumentNullException(nameof(threadId)); if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - ClientResult result = await DeleteThreadAsync(threadId).ConfigureAwait(false); + ClientResult result = await DeleteThreadAsync(threadId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(DeleteThreadResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -371,7 +371,7 @@ public virtual ClientResult DeleteThread(string threadId) if (threadId is null) throw new ArgumentNullException(nameof(threadId)); if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - ClientResult result = DeleteThread(threadId); + ClientResult result = DeleteThread(threadId, DefaultRequestContext); return ClientResult.FromValue(DeleteThreadResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } @@ -478,7 +478,6 @@ internal PipelineMessage CreateGetThreadRequest(string threadId, RequestOptions UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/threads/"); - uriBuilder.Path += path.ToString(); path.Append(threadId); uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; @@ -495,7 +494,6 @@ internal PipelineMessage CreateModifyThreadRequest(string threadId, BinaryConten UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/threads/"); - uriBuilder.Path += path.ToString(); path.Append(threadId); uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; @@ -515,7 +513,6 @@ internal PipelineMessage CreateDeleteThreadRequest(string threadId, RequestOptio UriBuilder uriBuilder = new(_endpoint.ToString()); StringBuilder path = new(); path.Append("/threads/"); - uriBuilder.Path += path.ToString(); path.Append(threadId); uriBuilder.Path += path.ToString(); request.Uri = uriBuilder.Uri; @@ -523,6 +520,8 @@ internal PipelineMessage CreateDeleteThreadRequest(string threadId, RequestOptio return message; } + private static RequestOptions DefaultRequestContext = new RequestOptions(); + private static PipelineMessageClassifier _responseErrorClassifier200; private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } From c398c45c7cec8658038ed1f01f9073f3c06d7ca8 Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado Date: Tue, 27 Feb 2024 21:35:06 -0800 Subject: [PATCH 15/50] Fix SubmitToolOutputsRunRequest, remove Embeddings customizations, edit Update-ClietModel.ps1 script to System.ClientModel 1.1.0-alpha.20240227.1 --- .dotnet/scripts/Update-ClientModel.ps1 | 12 ++- .dotnet/src/Custom/Embeddings/Embeddings.cs | 93 ---------------- .../Models/Embedding.Serialization.cs | 67 ------------ .../src/Custom/Embeddings/Models/Embedding.cs | 68 ------------ .../Embeddings/Models/EmbeddingObject.cs | 10 -- .../Models/GenerateEmbeddingsOptions.cs | 13 --- .dotnet/src/Custom/OpenAIClient.cs | 22 ---- .dotnet/src/Custom/OpenAIModelFactory.cs | 36 ------- .dotnet/src/Generated/Embeddings.cs | 20 ++-- ...> CreateEmbeddingRequest.Serialization.cs} | 48 ++++----- ...gsOptions.cs => CreateEmbeddingRequest.cs} | 78 ++++++++++++-- .../CreateEmbeddingRequestEncodingFormat.cs | 47 ++++++++ .../Models/CreateEmbeddingRequestModel.cs | 50 +++++++++ ... CreateEmbeddingResponse.Serialization.cs} | 48 ++++----- ...llection.cs => CreateEmbeddingResponse.cs} | 20 ++-- .../Models/CreateEmbeddingResponseObject.cs | 44 ++++++++ .../Models/Embedding.Serialization.cs | 40 +++++++ .dotnet/src/Generated/Models/Embedding.cs | 45 ++++++++ .../Models/EmbeddingCollectionObject.cs | 44 -------- .../src/Generated/Models/EmbeddingObject.cs | 2 +- ...ion.cs => EmbeddingUsage.Serialization.cs} | 40 +++---- ...beddingTokenUsage.cs => EmbeddingUsage.cs} | 16 +-- ...GenerateEmbeddingsOptionsEncodingFormat.cs | 47 -------- .../Models/GenerateEmbeddingsOptionsModel.cs | 50 --------- ...bmitToolOutputsRunRequest.Serialization.cs | 16 ++- .../Models/SubmitToolOutputsRunRequest.cs | 9 +- ...putsRunRequestToolOutput.Serialization.cs} | 40 +++---- ... SubmitToolOutputsRunRequestToolOutput.cs} | 12 +-- .dotnet/src/Generated/OpenAIClient.cs | 6 ++ .dotnet/src/Generated/OpenAIModelFactory.cs | 61 +++++++++-- .dotnet/src/OpenAI.csproj | 2 +- .dotnet/tests/EmbeddingsTests.cs | 101 ------------------ .../tests/Generated/Tests/EmbeddingsTests.cs | 23 ++++ .dotnet/tests/OpenAI.Tests.csproj | 1 + main.tsp | 13 +-- runs/models.tsp | 2 +- tsp-output/@typespec/openapi3/openapi.yaml | 22 ++-- 37 files changed, 543 insertions(+), 725 deletions(-) delete mode 100644 .dotnet/src/Custom/Embeddings/Embeddings.cs delete mode 100644 .dotnet/src/Custom/Embeddings/Models/Embedding.Serialization.cs delete mode 100644 .dotnet/src/Custom/Embeddings/Models/Embedding.cs delete mode 100644 .dotnet/src/Custom/Embeddings/Models/EmbeddingObject.cs delete mode 100644 .dotnet/src/Custom/Embeddings/Models/GenerateEmbeddingsOptions.cs delete mode 100644 .dotnet/src/Custom/OpenAIClient.cs delete mode 100644 .dotnet/src/Custom/OpenAIModelFactory.cs rename .dotnet/src/Generated/Models/{GenerateEmbeddingsOptions.Serialization.cs => CreateEmbeddingRequest.Serialization.cs} (67%) rename .dotnet/src/Generated/Models/{GenerateEmbeddingsOptions.cs => CreateEmbeddingRequest.cs} (58%) create mode 100644 .dotnet/src/Generated/Models/CreateEmbeddingRequestEncodingFormat.cs create mode 100644 .dotnet/src/Generated/Models/CreateEmbeddingRequestModel.cs rename .dotnet/src/Generated/Models/{EmbeddingCollection.Serialization.cs => CreateEmbeddingResponse.Serialization.cs} (65%) rename .dotnet/src/Generated/Models/{EmbeddingCollection.cs => CreateEmbeddingResponse.cs} (78%) create mode 100644 .dotnet/src/Generated/Models/CreateEmbeddingResponseObject.cs delete mode 100644 .dotnet/src/Generated/Models/EmbeddingCollectionObject.cs rename .dotnet/src/Generated/Models/{EmbeddingTokenUsage.Serialization.cs => EmbeddingUsage.Serialization.cs} (67%) rename .dotnet/src/Generated/Models/{EmbeddingTokenUsage.cs => EmbeddingUsage.cs} (85%) delete mode 100644 .dotnet/src/Generated/Models/GenerateEmbeddingsOptionsEncodingFormat.cs delete mode 100644 .dotnet/src/Generated/Models/GenerateEmbeddingsOptionsModel.cs rename .dotnet/src/Generated/Models/{SubmitToolOutputsRunRequestToolOutputs.Serialization.cs => SubmitToolOutputsRunRequestToolOutput.Serialization.cs} (68%) rename .dotnet/src/Generated/Models/{SubmitToolOutputsRunRequestToolOutputs.cs => SubmitToolOutputsRunRequestToolOutput.cs} (85%) delete mode 100644 .dotnet/tests/EmbeddingsTests.cs create mode 100644 .dotnet/tests/Generated/Tests/EmbeddingsTests.cs diff --git a/.dotnet/scripts/Update-ClientModel.ps1 b/.dotnet/scripts/Update-ClientModel.ps1 index 203cdd80c..83013e82e 100644 --- a/.dotnet/scripts/Update-ClientModel.ps1 +++ b/.dotnet/scripts/Update-ClientModel.ps1 @@ -1,12 +1,18 @@ function Update-ClientModelPackage { + $current = Get-Location $root = Split-Path $PSScriptRoot -Parent - $directory = Join-Path -Path $root -ChildPath "src" - $current = Get-Location + $directory = Join-Path -Path $root -ChildPath "src" Set-Location -Path $directory dotnet remove "OpenAI.csproj" package "System.ClientModel" - dotnet add "OpenAI.csproj" package "System.ClientModel" --version "1.1.0-alpha.20240215.1" --source "https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-net/nuget/v3/index.json" + dotnet add "OpenAI.csproj" package "System.ClientModel" --version "1.1.0-alpha.20240227.1" --source "https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-net/nuget/v3/index.json" + + $directory = Join-Path -Path $root -ChildPath "tests" + Set-Location -Path $directory + + dotnet remove "OpenAI.Tests.csproj" package "System.ClientModel" + dotnet add "OpenAI.Tests.csproj" package "System.ClientModel" --version "1.1.0-alpha.20240227.1" --source "https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-net/nuget/v3/index.json" Set-Location -Path $current } diff --git a/.dotnet/src/Custom/Embeddings/Embeddings.cs b/.dotnet/src/Custom/Embeddings/Embeddings.cs deleted file mode 100644 index 1dad5bf62..000000000 --- a/.dotnet/src/Custom/Embeddings/Embeddings.cs +++ /dev/null @@ -1,93 +0,0 @@ -using OpenAI.Models; -using System; -using System.ClientModel; -using System.ClientModel.Primitives; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace OpenAI -{ - public partial class Embeddings - { - private readonly string _model; - - /// Initializes a new instance of Embeddings. - /// The HTTP pipeline for sending and receiving REST requests and responses. - /// The key credential to copy. - /// OpenAI Endpoint. - internal Embeddings(string model, ClientPipeline pipeline, ApiKeyCredential credential, Uri endpoint) - : this(pipeline, credential, endpoint) - { - _model = model; - } - - public virtual async Task> GenerateEmbeddingAsync(string input, GenerateEmbeddingsOptions options = null) - { - options ??= new GenerateEmbeddingsOptions(); - options.Model = new GenerateEmbeddingsOptionsModel(_model); - options.Input = BinaryData.FromString(input); - ClientResult result = await CreateEmbeddingAsync(options).ConfigureAwait(false); - return ClientResult.FromValue(result.Value.Data[0], result.GetRawResponse()); - } - - public virtual ClientResult GenerateEmbedding(string input, GenerateEmbeddingsOptions options = null) - { - options ??= new GenerateEmbeddingsOptions(); - options.Model = new GenerateEmbeddingsOptionsModel(_model); - options.Input = BinaryData.FromObjectAsJson(input); - ClientResult result = CreateEmbedding(options); - return ClientResult.FromValue(result.Value.Data[0], result.GetRawResponse()); - } - - public virtual async Task> GenerateEmbeddingAsync(IEnumerable input, GenerateEmbeddingsOptions options = null) - { - options ??= new GenerateEmbeddingsOptions(); - options.Model = new GenerateEmbeddingsOptionsModel(_model); - options.Input = BinaryData.FromObjectAsJson(input.ToArray()); - ClientResult result = await CreateEmbeddingAsync(options).ConfigureAwait(false); - return ClientResult.FromValue(result.Value.Data[0], result.GetRawResponse()); - } - - public virtual ClientResult GenerateEmbedding(IEnumerable input, GenerateEmbeddingsOptions options = null) - { - options ??= new GenerateEmbeddingsOptions(); - options.Model = new GenerateEmbeddingsOptionsModel(_model); - options.Input = BinaryData.FromObjectAsJson(input.ToArray()); - ClientResult result = CreateEmbedding(options); - return ClientResult.FromValue(result.Value.Data[0], result.GetRawResponse()); - } - - public virtual async Task> GenerateEmbeddingsAsync(IEnumerable inputs, GenerateEmbeddingsOptions options = null) - { - options ??= new GenerateEmbeddingsOptions(); - options.Model = new GenerateEmbeddingsOptionsModel(_model); - options.Input = BinaryData.FromObjectAsJson(inputs.ToArray()); - return await CreateEmbeddingAsync(options).ConfigureAwait(false); - } - - public virtual ClientResult GenerateEmbeddings(IEnumerable inputs, GenerateEmbeddingsOptions options = null) - { - options ??= new GenerateEmbeddingsOptions(); - options.Model = new GenerateEmbeddingsOptionsModel(_model); - options.Input = BinaryData.FromObjectAsJson(inputs.ToArray()); - return CreateEmbedding(options); - } - - public virtual async Task> GenerateEmbeddingsAsync(IEnumerable> inputs, GenerateEmbeddingsOptions options = null) - { - options ??= new GenerateEmbeddingsOptions(); - options.Model = new GenerateEmbeddingsOptionsModel(_model); - options.Input = BinaryData.FromObjectAsJson(inputs.ToArray()); - return await CreateEmbeddingAsync(options).ConfigureAwait(false); - } - - public virtual ClientResult GenerateEmbeddings(IEnumerable> inputs, GenerateEmbeddingsOptions options = null) - { - options ??= new GenerateEmbeddingsOptions(); - options.Model = new GenerateEmbeddingsOptionsModel(_model); - options.Input = BinaryData.FromObjectAsJson(inputs.ToArray()); - return CreateEmbedding(options); - } - } -} diff --git a/.dotnet/src/Custom/Embeddings/Models/Embedding.Serialization.cs b/.dotnet/src/Custom/Embeddings/Models/Embedding.Serialization.cs deleted file mode 100644 index 602547f22..000000000 --- a/.dotnet/src/Custom/Embeddings/Models/Embedding.Serialization.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; -using System.ClientModel.Primitives; -using System.Collections.Generic; -using System.Text.Json; - -namespace OpenAI.Models -{ - public partial class Embedding - { - internal static Embedding DeserializeEmbedding(JsonElement element, ModelReaderWriterOptions options = null) - { - options ??= new ModelReaderWriterOptions("W"); - - if (element.ValueKind == JsonValueKind.Null) - { - return null; - } - long index = default; - BinaryData embedding = default; - EmbeddingObject @object = default; - IDictionary serializedAdditionalRawData = default; - Dictionary additionalPropertiesDictionary = new Dictionary(); - foreach (var property in element.EnumerateObject()) - { - if (property.NameEquals("index"u8)) - { - index = property.Value.GetInt64(); - continue; - } - if (property.NameEquals("embedding"u8)) - { - embedding = BinaryData.FromString(property.Value.GetRawText()); - continue; - } - if (property.NameEquals("object"u8)) - { - @object = new EmbeddingObject(property.Value.GetString()); - continue; - } - if (options.Format != "W") - { - additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); - } - } - - ReadOnlyMemory? embeddingAsFloats = default; - BinaryData embeddingAsBase64Data = default; - JsonDocument doc = JsonDocument.Parse(embedding); - - if (doc.RootElement.ValueKind == JsonValueKind.Array) - { - List floats = new(); - foreach (var item in doc.RootElement.EnumerateArray()) - { - floats.Add(item.GetSingle()); - } - embeddingAsFloats = new ReadOnlyMemory(floats.ToArray()); - } - else if (doc.RootElement.ValueKind == JsonValueKind.String) - { - embeddingAsBase64Data = embedding; - } - - return new(index, embedding, @object, serializedAdditionalRawData, embeddingAsFloats, embeddingAsBase64Data); - } - } -} diff --git a/.dotnet/src/Custom/Embeddings/Models/Embedding.cs b/.dotnet/src/Custom/Embeddings/Models/Embedding.cs deleted file mode 100644 index 0cf994146..000000000 --- a/.dotnet/src/Custom/Embeddings/Models/Embedding.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using System.Collections.Generic; - -#nullable disable - -namespace OpenAI.Models -{ - public partial class Embedding - { - /// - /// The embedding vector, which is a list of floats. The length of vector depends on the model as - /// listed in the [embedding guide](/docs/guides/embeddings). - /// - /// To assign an object to this property use . - /// - /// - /// To assign an already formatted json string to this property use . - /// - /// - /// - /// Supported types: - /// - /// - /// where T is of type - /// - /// - /// - /// - /// - /// - /// Examples: - /// - /// - /// BinaryData.FromObjectAsJson("foo") - /// Creates a payload of "foo". - /// - /// - /// BinaryData.FromString("\"foo\"") - /// Creates a payload of "foo". - /// - /// - /// BinaryData.FromObjectAsJson(new { key = "value" }) - /// Creates a payload of { "key": "value" }. - /// - /// - /// BinaryData.FromString("{\"key\": \"value\"}") - /// Creates a payload of { "key": "value" }. - /// - /// - /// - /// - internal BinaryData EmbeddingProperty { get; } - /// The object type, which is always "embedding". - internal EmbeddingObject Object { get; } = EmbeddingObject.Embedding; - - internal Embedding(long index, BinaryData embeddingProperty, EmbeddingObject @object, IDictionary serializedAdditionalRawData, ReadOnlyMemory? embeddingAsFloats, BinaryData embeddingAsBase64Data) - : this(index, embeddingProperty, @object, serializedAdditionalRawData) - { - EmbeddingAsFloats = embeddingAsFloats; - EmbeddingAsBase64Data = embeddingAsBase64Data; - } - - /// The embedding represented as a vector of floats. - public ReadOnlyMemory? EmbeddingAsFloats { get; } - /// The embedding represented as a Base64-encoded string. - public BinaryData EmbeddingAsBase64Data { get; } - } -} diff --git a/.dotnet/src/Custom/Embeddings/Models/EmbeddingObject.cs b/.dotnet/src/Custom/Embeddings/Models/EmbeddingObject.cs deleted file mode 100644 index a2bd2f70e..000000000 --- a/.dotnet/src/Custom/Embeddings/Models/EmbeddingObject.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace OpenAI.Models -{ - internal readonly partial struct EmbeddingObject - { - } -} diff --git a/.dotnet/src/Custom/Embeddings/Models/GenerateEmbeddingsOptions.cs b/.dotnet/src/Custom/Embeddings/Models/GenerateEmbeddingsOptions.cs deleted file mode 100644 index 64500d31a..000000000 --- a/.dotnet/src/Custom/Embeddings/Models/GenerateEmbeddingsOptions.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace OpenAI.Models -{ - public partial class GenerateEmbeddingsOptions - { - internal BinaryData Input { get; set; } - - internal GenerateEmbeddingsOptionsModel Model { get; set; } - } -} diff --git a/.dotnet/src/Custom/OpenAIClient.cs b/.dotnet/src/Custom/OpenAIClient.cs deleted file mode 100644 index 2c7ed2700..000000000 --- a/.dotnet/src/Custom/OpenAIClient.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; - -namespace OpenAI -{ - public partial class OpenAIClient - { - // TODO: This needs to be suppressed. - internal virtual Embeddings GetEmbeddingsClient() - { - return Volatile.Read(ref _cachedEmbeddings) ?? Interlocked.CompareExchange(ref _cachedEmbeddings, new Embeddings(_pipeline, _credential, _endpoint), null) ?? _cachedEmbeddings; - } - - /// Initializes a new instance of Embeddings. - public virtual Embeddings GetEmbeddingsClient(string model) - { - return Volatile.Read(ref _cachedEmbeddings) ?? Interlocked.CompareExchange(ref _cachedEmbeddings, new Embeddings(model, _pipeline, _credential, _endpoint), null) ?? _cachedEmbeddings; - } - } -} diff --git a/.dotnet/src/Custom/OpenAIModelFactory.cs b/.dotnet/src/Custom/OpenAIModelFactory.cs deleted file mode 100644 index 895344070..000000000 --- a/.dotnet/src/Custom/OpenAIModelFactory.cs +++ /dev/null @@ -1,36 +0,0 @@ -using OpenAI.Models; -using System; - -namespace OpenAI -{ - /// Model factory for models. - public static partial class OpenAIModelFactory - { - /// Initializes a new instance of . - /// The index of the embedding in the list of embeddings. - /// - /// The embedding vector, which is a list of floats. The length of vector depends on the model as - /// listed in the [embedding guide](/docs/guides/embeddings). - /// - /// The object type, which is always "embedding". - /// A new instance for mocking. - public static Embedding Embedding(long index = default, ReadOnlyMemory? embeddingAsFloats = null) - { - // TODO: We need to populate the embedding property from the embeddingAsFloats parameter. - return new Embedding(index, embeddingProperty: null, EmbeddingObject.Embedding, serializedAdditionalRawData: null, embeddingAsFloats, embeddingAsBase64Data: null); - } - - /// Initializes a new instance of . - /// The index of the embedding in the list of embeddings. - /// - /// The embedding vector, which is a list of floats. The length of vector depends on the model as - /// listed in the [embedding guide](/docs/guides/embeddings). - /// - /// The object type, which is always "embedding". - /// A new instance for mocking. - public static Embedding Embedding(long index = default, BinaryData embeddingAsBase64Data = default) - { - return new Embedding(index, embeddingAsBase64Data, EmbeddingObject.Embedding, serializedAdditionalRawData: null, embeddingAsFloats: null, embeddingAsBase64Data); - } - } -} diff --git a/.dotnet/src/Generated/Embeddings.cs b/.dotnet/src/Generated/Embeddings.cs index 0788abad9..8056ebd08 100644 --- a/.dotnet/src/Generated/Embeddings.cs +++ b/.dotnet/src/Generated/Embeddings.cs @@ -40,27 +40,27 @@ internal Embeddings(ClientPipeline pipeline, ApiKeyCredential credential, Uri en } /// Creates an embedding vector representing the input text. - /// The to use. + /// The to use. /// is null. - internal virtual async Task> CreateEmbeddingAsync(GenerateEmbeddingsOptions embedding) + public virtual async Task> CreateEmbeddingAsync(CreateEmbeddingRequest embedding) { if (embedding is null) throw new ArgumentNullException(nameof(embedding)); using BinaryContent content = BinaryContent.Create(embedding); ClientResult result = await CreateEmbeddingAsync(content, DefaultRequestContext).ConfigureAwait(false); - return ClientResult.FromValue(EmbeddingCollection.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + return ClientResult.FromValue(CreateEmbeddingResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// Creates an embedding vector representing the input text. - /// The to use. + /// The to use. /// is null. - internal virtual ClientResult CreateEmbedding(GenerateEmbeddingsOptions embedding) + public virtual ClientResult CreateEmbedding(CreateEmbeddingRequest embedding) { if (embedding is null) throw new ArgumentNullException(nameof(embedding)); using BinaryContent content = BinaryContent.Create(embedding); ClientResult result = CreateEmbedding(content, DefaultRequestContext); - return ClientResult.FromValue(EmbeddingCollection.FromResponse(result.GetRawResponse()), result.GetRawResponse()); + return ClientResult.FromValue(CreateEmbeddingResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); } /// @@ -73,7 +73,7 @@ internal virtual ClientResult CreateEmbedding(GenerateEmbed /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -83,7 +83,7 @@ internal virtual ClientResult CreateEmbedding(GenerateEmbed /// is null. /// Service returned a non-success status code. /// The response returned from the service. - internal virtual async Task CreateEmbeddingAsync(BinaryContent content, RequestOptions options = null) + public virtual async Task CreateEmbeddingAsync(BinaryContent content, RequestOptions options = null) { if (content is null) throw new ArgumentNullException(nameof(content)); options ??= new RequestOptions(); @@ -109,7 +109,7 @@ internal virtual async Task CreateEmbeddingAsync(BinaryContent con /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -119,7 +119,7 @@ internal virtual async Task CreateEmbeddingAsync(BinaryContent con /// is null. /// Service returned a non-success status code. /// The response returned from the service. - internal virtual ClientResult CreateEmbedding(BinaryContent content, RequestOptions options = null) + public virtual ClientResult CreateEmbedding(BinaryContent content, RequestOptions options = null) { if (content is null) throw new ArgumentNullException(nameof(content)); options ??= new RequestOptions(); diff --git a/.dotnet/src/Generated/Models/GenerateEmbeddingsOptions.Serialization.cs b/.dotnet/src/Generated/Models/CreateEmbeddingRequest.Serialization.cs similarity index 67% rename from .dotnet/src/Generated/Models/GenerateEmbeddingsOptions.Serialization.cs rename to .dotnet/src/Generated/Models/CreateEmbeddingRequest.Serialization.cs index 5d6ec0838..7a8ff235b 100644 --- a/.dotnet/src/Generated/Models/GenerateEmbeddingsOptions.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateEmbeddingRequest.Serialization.cs @@ -8,14 +8,14 @@ namespace OpenAI.Models { - public partial class GenerateEmbeddingsOptions : IJsonModel + public partial class CreateEmbeddingRequest : IJsonModel { - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; if (format != "J") { - throw new FormatException($"The model {nameof(GenerateEmbeddingsOptions)} does not support '{format}' format."); + throw new FormatException($"The model {nameof(CreateEmbeddingRequest)} does not support '{format}' format."); } writer.WriteStartObject(); @@ -63,19 +63,19 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelRea writer.WriteEndObject(); } - GenerateEmbeddingsOptions IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + CreateEmbeddingRequest IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; if (format != "J") { - throw new FormatException($"The model {nameof(GenerateEmbeddingsOptions)} does not support '{format}' format."); + throw new FormatException($"The model {nameof(CreateEmbeddingRequest)} does not support '{format}' format."); } using JsonDocument document = JsonDocument.ParseValue(ref reader); - return DeserializeGenerateEmbeddingsOptions(document.RootElement, options); + return DeserializeCreateEmbeddingRequest(document.RootElement, options); } - internal static GenerateEmbeddingsOptions DeserializeGenerateEmbeddingsOptions(JsonElement element, ModelReaderWriterOptions options = null) + internal static CreateEmbeddingRequest DeserializeCreateEmbeddingRequest(JsonElement element, ModelReaderWriterOptions options = null) { options ??= new ModelReaderWriterOptions("W"); @@ -84,8 +84,8 @@ internal static GenerateEmbeddingsOptions DeserializeGenerateEmbeddingsOptions(J return null; } BinaryData input = default; - GenerateEmbeddingsOptionsModel model = default; - OptionalProperty encodingFormat = default; + CreateEmbeddingRequestModel model = default; + OptionalProperty encodingFormat = default; OptionalProperty dimensions = default; OptionalProperty user = default; IDictionary serializedAdditionalRawData = default; @@ -99,7 +99,7 @@ internal static GenerateEmbeddingsOptions DeserializeGenerateEmbeddingsOptions(J } if (property.NameEquals("model"u8)) { - model = new GenerateEmbeddingsOptionsModel(property.Value.GetString()); + model = new CreateEmbeddingRequestModel(property.Value.GetString()); continue; } if (property.NameEquals("encoding_format"u8)) @@ -108,7 +108,7 @@ internal static GenerateEmbeddingsOptions DeserializeGenerateEmbeddingsOptions(J { continue; } - encodingFormat = new GenerateEmbeddingsOptionsEncodingFormat(property.Value.GetString()); + encodingFormat = new CreateEmbeddingRequestEncodingFormat(property.Value.GetString()); continue; } if (property.NameEquals("dimensions"u8)) @@ -131,46 +131,46 @@ internal static GenerateEmbeddingsOptions DeserializeGenerateEmbeddingsOptions(J } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new GenerateEmbeddingsOptions(input, model, OptionalProperty.ToNullable(encodingFormat), OptionalProperty.ToNullable(dimensions), user.Value, serializedAdditionalRawData); + return new CreateEmbeddingRequest(input, model, OptionalProperty.ToNullable(encodingFormat), OptionalProperty.ToNullable(dimensions), user.Value, serializedAdditionalRawData); } - BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; switch (format) { case "J": return ModelReaderWriter.Write(this, options); default: - throw new FormatException($"The model {nameof(GenerateEmbeddingsOptions)} does not support '{options.Format}' format."); + throw new FormatException($"The model {nameof(CreateEmbeddingRequest)} does not support '{options.Format}' format."); } } - GenerateEmbeddingsOptions IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + CreateEmbeddingRequest IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; switch (format) { case "J": { using JsonDocument document = JsonDocument.Parse(data); - return DeserializeGenerateEmbeddingsOptions(document.RootElement, options); + return DeserializeCreateEmbeddingRequest(document.RootElement, options); } default: - throw new FormatException($"The model {nameof(GenerateEmbeddingsOptions)} does not support '{options.Format}' format."); + throw new FormatException($"The model {nameof(CreateEmbeddingRequest)} does not support '{options.Format}' format."); } } - string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; /// Deserializes the model from a raw response. /// The result to deserialize the model from. - internal static GenerateEmbeddingsOptions FromResponse(PipelineResponse response) + internal static CreateEmbeddingRequest FromResponse(PipelineResponse response) { using var document = JsonDocument.Parse(response.Content); - return DeserializeGenerateEmbeddingsOptions(document.RootElement); + return DeserializeCreateEmbeddingRequest(document.RootElement); } } } diff --git a/.dotnet/src/Generated/Models/GenerateEmbeddingsOptions.cs b/.dotnet/src/Generated/Models/CreateEmbeddingRequest.cs similarity index 58% rename from .dotnet/src/Generated/Models/GenerateEmbeddingsOptions.cs rename to .dotnet/src/Generated/Models/CreateEmbeddingRequest.cs index d8a90823c..c2a286d4c 100644 --- a/.dotnet/src/Generated/Models/GenerateEmbeddingsOptions.cs +++ b/.dotnet/src/Generated/Models/CreateEmbeddingRequest.cs @@ -6,8 +6,8 @@ namespace OpenAI.Models { - /// The GenerateEmbeddingsOptions. - public partial class GenerateEmbeddingsOptions + /// The CreateEmbeddingRequest. + public partial class CreateEmbeddingRequest { /// /// Keeps track of any properties unknown to the library. @@ -41,7 +41,7 @@ public partial class GenerateEmbeddingsOptions /// private IDictionary _serializedAdditionalRawData; - /// Initializes a new instance of . + /// Initializes a new instance of . /// /// Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a /// single request, pass an array of strings or array of token arrays. Each input must not exceed @@ -56,7 +56,7 @@ public partial class GenerateEmbeddingsOptions /// descriptions of them. /// /// is null. - public GenerateEmbeddingsOptions(BinaryData input, GenerateEmbeddingsOptionsModel model) + public CreateEmbeddingRequest(BinaryData input, CreateEmbeddingRequestModel model) { if (input is null) throw new ArgumentNullException(nameof(input)); @@ -64,7 +64,7 @@ public GenerateEmbeddingsOptions(BinaryData input, GenerateEmbeddingsOptionsMode Model = model; } - /// Initializes a new instance of . + /// Initializes a new instance of . /// /// Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a /// single request, pass an array of strings or array of token arrays. Each input must not exceed @@ -91,7 +91,7 @@ public GenerateEmbeddingsOptions(BinaryData input, GenerateEmbeddingsOptionsMode /// abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). /// /// Keeps track of any properties unknown to the library. - internal GenerateEmbeddingsOptions(BinaryData input, GenerateEmbeddingsOptionsModel model, GenerateEmbeddingsOptionsEncodingFormat? encodingFormat, long? dimensions, string user, IDictionary serializedAdditionalRawData) + internal CreateEmbeddingRequest(BinaryData input, CreateEmbeddingRequestModel model, CreateEmbeddingRequestEncodingFormat? encodingFormat, long? dimensions, string user, IDictionary serializedAdditionalRawData) { Input = input; Model = model; @@ -101,15 +101,75 @@ internal GenerateEmbeddingsOptions(BinaryData input, GenerateEmbeddingsOptionsMo _serializedAdditionalRawData = serializedAdditionalRawData; } - /// Initializes a new instance of for deserialization. - internal GenerateEmbeddingsOptions() + /// Initializes a new instance of for deserialization. + internal CreateEmbeddingRequest() { } + + /// + /// Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a + /// single request, pass an array of strings or array of token arrays. Each input must not exceed + /// the max input tokens for the model (8191 tokens for `text-embedding-ada-002`) and cannot be an + /// empty string. + /// [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) + /// for counting tokens. + /// + /// To assign an object to this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// + /// Supported types: + /// + /// + /// + /// + /// + /// where T is of type + /// + /// + /// where T is of type + /// + /// + /// where T is of type IList{long} + /// + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + public BinaryData Input { get; } + /// + /// ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + /// see all of your available models, or see our [Model overview](/docs/models/overview) for + /// descriptions of them. + /// + public CreateEmbeddingRequestModel Model { get; } /// /// The format to return the embeddings in. Can be either `float` or /// [`base64`](https://pypi.org/project/pybase64/). /// - public GenerateEmbeddingsOptionsEncodingFormat? EncodingFormat { get; set; } + public CreateEmbeddingRequestEncodingFormat? EncodingFormat { get; set; } /// /// The number of dimensions the resulting output embeddings should have. Only supported in /// `text-embedding-3` and later models. diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingRequestEncodingFormat.cs b/.dotnet/src/Generated/Models/CreateEmbeddingRequestEncodingFormat.cs new file mode 100644 index 000000000..e252744e4 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateEmbeddingRequestEncodingFormat.cs @@ -0,0 +1,47 @@ +// + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for encoding_format in CreateEmbeddingRequest. + public readonly partial struct CreateEmbeddingRequestEncodingFormat : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateEmbeddingRequestEncodingFormat(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string FloatValue = "float"; + private const string Base64Value = "base64"; + + /// float. + public static CreateEmbeddingRequestEncodingFormat Float { get; } = new CreateEmbeddingRequestEncodingFormat(FloatValue); + /// base64. + public static CreateEmbeddingRequestEncodingFormat Base64 { get; } = new CreateEmbeddingRequestEncodingFormat(Base64Value); + /// Determines if two values are the same. + public static bool operator ==(CreateEmbeddingRequestEncodingFormat left, CreateEmbeddingRequestEncodingFormat right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateEmbeddingRequestEncodingFormat left, CreateEmbeddingRequestEncodingFormat right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateEmbeddingRequestEncodingFormat(string value) => new CreateEmbeddingRequestEncodingFormat(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateEmbeddingRequestEncodingFormat other && Equals(other); + /// + public bool Equals(CreateEmbeddingRequestEncodingFormat other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} + diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingRequestModel.cs b/.dotnet/src/Generated/Models/CreateEmbeddingRequestModel.cs new file mode 100644 index 000000000..628de9b7b --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateEmbeddingRequestModel.cs @@ -0,0 +1,50 @@ +// + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// Enum for model in CreateEmbeddingRequest. + public readonly partial struct CreateEmbeddingRequestModel : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateEmbeddingRequestModel(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string TextEmbeddingAda002Value = "text-embedding-ada-002"; + private const string TextEmbedding3SmallValue = "text-embedding-3-small"; + private const string TextEmbedding3LargeValue = "text-embedding-3-large"; + + /// text-embedding-ada-002. + public static CreateEmbeddingRequestModel TextEmbeddingAda002 { get; } = new CreateEmbeddingRequestModel(TextEmbeddingAda002Value); + /// text-embedding-3-small. + public static CreateEmbeddingRequestModel TextEmbedding3Small { get; } = new CreateEmbeddingRequestModel(TextEmbedding3SmallValue); + /// text-embedding-3-large. + public static CreateEmbeddingRequestModel TextEmbedding3Large { get; } = new CreateEmbeddingRequestModel(TextEmbedding3LargeValue); + /// Determines if two values are the same. + public static bool operator ==(CreateEmbeddingRequestModel left, CreateEmbeddingRequestModel right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateEmbeddingRequestModel left, CreateEmbeddingRequestModel right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateEmbeddingRequestModel(string value) => new CreateEmbeddingRequestModel(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateEmbeddingRequestModel other && Equals(other); + /// + public bool Equals(CreateEmbeddingRequestModel other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} + diff --git a/.dotnet/src/Generated/Models/EmbeddingCollection.Serialization.cs b/.dotnet/src/Generated/Models/CreateEmbeddingResponse.Serialization.cs similarity index 65% rename from .dotnet/src/Generated/Models/EmbeddingCollection.Serialization.cs rename to .dotnet/src/Generated/Models/CreateEmbeddingResponse.Serialization.cs index c4a8aa240..deaf48c02 100644 --- a/.dotnet/src/Generated/Models/EmbeddingCollection.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateEmbeddingResponse.Serialization.cs @@ -8,14 +8,14 @@ namespace OpenAI.Models { - public partial class EmbeddingCollection : IJsonModel + public partial class CreateEmbeddingResponse : IJsonModel { - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; if (format != "J") { - throw new FormatException($"The model {nameof(EmbeddingCollection)} does not support '{format}' format."); + throw new FormatException($"The model {nameof(CreateEmbeddingResponse)} does not support '{format}' format."); } writer.WriteStartObject(); @@ -50,19 +50,19 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWri writer.WriteEndObject(); } - EmbeddingCollection IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + CreateEmbeddingResponse IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; if (format != "J") { - throw new FormatException($"The model {nameof(EmbeddingCollection)} does not support '{format}' format."); + throw new FormatException($"The model {nameof(CreateEmbeddingResponse)} does not support '{format}' format."); } using JsonDocument document = JsonDocument.ParseValue(ref reader); - return DeserializeEmbeddingCollection(document.RootElement, options); + return DeserializeCreateEmbeddingResponse(document.RootElement, options); } - internal static EmbeddingCollection DeserializeEmbeddingCollection(JsonElement element, ModelReaderWriterOptions options = null) + internal static CreateEmbeddingResponse DeserializeCreateEmbeddingResponse(JsonElement element, ModelReaderWriterOptions options = null) { options ??= new ModelReaderWriterOptions("W"); @@ -72,8 +72,8 @@ internal static EmbeddingCollection DeserializeEmbeddingCollection(JsonElement e } IReadOnlyList data = default; string model = default; - EmbeddingCollectionObject @object = default; - EmbeddingTokenUsage usage = default; + CreateEmbeddingResponseObject @object = default; + EmbeddingUsage usage = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -95,12 +95,12 @@ internal static EmbeddingCollection DeserializeEmbeddingCollection(JsonElement e } if (property.NameEquals("object"u8)) { - @object = new EmbeddingCollectionObject(property.Value.GetString()); + @object = new CreateEmbeddingResponseObject(property.Value.GetString()); continue; } if (property.NameEquals("usage"u8)) { - usage = EmbeddingTokenUsage.DeserializeEmbeddingTokenUsage(property.Value); + usage = EmbeddingUsage.DeserializeEmbeddingUsage(property.Value); continue; } if (options.Format != "W") @@ -109,46 +109,46 @@ internal static EmbeddingCollection DeserializeEmbeddingCollection(JsonElement e } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new EmbeddingCollection(data, model, @object, usage, serializedAdditionalRawData); + return new CreateEmbeddingResponse(data, model, @object, usage, serializedAdditionalRawData); } - BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; switch (format) { case "J": return ModelReaderWriter.Write(this, options); default: - throw new FormatException($"The model {nameof(EmbeddingCollection)} does not support '{options.Format}' format."); + throw new FormatException($"The model {nameof(CreateEmbeddingResponse)} does not support '{options.Format}' format."); } } - EmbeddingCollection IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + CreateEmbeddingResponse IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; switch (format) { case "J": { using JsonDocument document = JsonDocument.Parse(data); - return DeserializeEmbeddingCollection(document.RootElement, options); + return DeserializeCreateEmbeddingResponse(document.RootElement, options); } default: - throw new FormatException($"The model {nameof(EmbeddingCollection)} does not support '{options.Format}' format."); + throw new FormatException($"The model {nameof(CreateEmbeddingResponse)} does not support '{options.Format}' format."); } } - string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; /// Deserializes the model from a raw response. /// The result to deserialize the model from. - internal static EmbeddingCollection FromResponse(PipelineResponse response) + internal static CreateEmbeddingResponse FromResponse(PipelineResponse response) { using var document = JsonDocument.Parse(response.Content); - return DeserializeEmbeddingCollection(document.RootElement); + return DeserializeCreateEmbeddingResponse(document.RootElement); } } } diff --git a/.dotnet/src/Generated/Models/EmbeddingCollection.cs b/.dotnet/src/Generated/Models/CreateEmbeddingResponse.cs similarity index 78% rename from .dotnet/src/Generated/Models/EmbeddingCollection.cs rename to .dotnet/src/Generated/Models/CreateEmbeddingResponse.cs index d7dd3ec73..f0695c29a 100644 --- a/.dotnet/src/Generated/Models/EmbeddingCollection.cs +++ b/.dotnet/src/Generated/Models/CreateEmbeddingResponse.cs @@ -7,8 +7,8 @@ namespace OpenAI.Models { - /// The EmbeddingCollection. - public partial class EmbeddingCollection + /// The CreateEmbeddingResponse. + public partial class CreateEmbeddingResponse { /// /// Keeps track of any properties unknown to the library. @@ -42,12 +42,12 @@ public partial class EmbeddingCollection /// private IDictionary _serializedAdditionalRawData; - /// Initializes a new instance of . + /// Initializes a new instance of . /// The list of embeddings generated by the model. /// The name of the model used to generate the embedding. /// The usage information for the request. /// , or is null. - internal EmbeddingCollection(IEnumerable data, string model, EmbeddingTokenUsage usage) + internal CreateEmbeddingResponse(IEnumerable data, string model, EmbeddingUsage usage) { if (data is null) throw new ArgumentNullException(nameof(data)); if (model is null) throw new ArgumentNullException(nameof(model)); @@ -58,13 +58,13 @@ internal EmbeddingCollection(IEnumerable data, string model, Embeddin Usage = usage; } - /// Initializes a new instance of . + /// Initializes a new instance of . /// The list of embeddings generated by the model. /// The name of the model used to generate the embedding. /// The object type, which is always "list". /// The usage information for the request. /// Keeps track of any properties unknown to the library. - internal EmbeddingCollection(IReadOnlyList data, string model, EmbeddingCollectionObject @object, EmbeddingTokenUsage usage, IDictionary serializedAdditionalRawData) + internal CreateEmbeddingResponse(IReadOnlyList data, string model, CreateEmbeddingResponseObject @object, EmbeddingUsage usage, IDictionary serializedAdditionalRawData) { Data = data; Model = model; @@ -73,8 +73,8 @@ internal EmbeddingCollection(IReadOnlyList data, string model, Embedd _serializedAdditionalRawData = serializedAdditionalRawData; } - /// Initializes a new instance of for deserialization. - internal EmbeddingCollection() + /// Initializes a new instance of for deserialization. + internal CreateEmbeddingResponse() { } @@ -83,10 +83,10 @@ internal EmbeddingCollection() /// The name of the model used to generate the embedding. public string Model { get; } /// The object type, which is always "list". - public EmbeddingCollectionObject Object { get; } = EmbeddingCollectionObject.List; + public CreateEmbeddingResponseObject Object { get; } = CreateEmbeddingResponseObject.List; /// The usage information for the request. - public EmbeddingTokenUsage Usage { get; } + public EmbeddingUsage Usage { get; } } } diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingResponseObject.cs b/.dotnet/src/Generated/Models/CreateEmbeddingResponseObject.cs new file mode 100644 index 000000000..b98b10317 --- /dev/null +++ b/.dotnet/src/Generated/Models/CreateEmbeddingResponseObject.cs @@ -0,0 +1,44 @@ +// + +using System; +using System.ComponentModel; + +namespace OpenAI.Models +{ + /// The CreateEmbeddingResponse_object. + public readonly partial struct CreateEmbeddingResponseObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreateEmbeddingResponseObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string ListValue = "list"; + + /// list. + public static CreateEmbeddingResponseObject List { get; } = new CreateEmbeddingResponseObject(ListValue); + /// Determines if two values are the same. + public static bool operator ==(CreateEmbeddingResponseObject left, CreateEmbeddingResponseObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreateEmbeddingResponseObject left, CreateEmbeddingResponseObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreateEmbeddingResponseObject(string value) => new CreateEmbeddingResponseObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreateEmbeddingResponseObject other && Equals(other); + /// + public bool Equals(CreateEmbeddingResponseObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} + diff --git a/.dotnet/src/Generated/Models/Embedding.Serialization.cs b/.dotnet/src/Generated/Models/Embedding.Serialization.cs index 0f9790a19..b3506e51c 100644 --- a/.dotnet/src/Generated/Models/Embedding.Serialization.cs +++ b/.dotnet/src/Generated/Models/Embedding.Serialization.cs @@ -3,6 +3,7 @@ using System; using OpenAI.ClientShared.Internal; using System.ClientModel.Primitives; +using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Models @@ -61,6 +62,45 @@ Embedding IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWri return DeserializeEmbedding(document.RootElement, options); } + internal static Embedding DeserializeEmbedding(JsonElement element, ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + long index = default; + BinaryData embedding = default; + EmbeddingObject @object = default; + IDictionary serializedAdditionalRawData = default; + Dictionary additionalPropertiesDictionary = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("index"u8)) + { + index = property.Value.GetInt64(); + continue; + } + if (property.NameEquals("embedding"u8)) + { + embedding = BinaryData.FromString(property.Value.GetRawText()); + continue; + } + if (property.NameEquals("object"u8)) + { + @object = new EmbeddingObject(property.Value.GetString()); + continue; + } + if (options.Format != "W") + { + additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + serializedAdditionalRawData = additionalPropertiesDictionary; + return new Embedding(index, embedding, @object, serializedAdditionalRawData); + } + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) { var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; diff --git a/.dotnet/src/Generated/Models/Embedding.cs b/.dotnet/src/Generated/Models/Embedding.cs index 9a3e895f8..ecabc7df9 100644 --- a/.dotnet/src/Generated/Models/Embedding.cs +++ b/.dotnet/src/Generated/Models/Embedding.cs @@ -79,6 +79,51 @@ internal Embedding() /// The index of the embedding in the list of embeddings. public long Index { get; } + /// + /// The embedding vector, which is a list of floats. The length of vector depends on the model as + /// listed in the [embedding guide](/docs/guides/embeddings). + /// + /// To assign an object to this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// + /// Supported types: + /// + /// + /// where T is of type + /// + /// + /// + /// + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + public BinaryData EmbeddingProperty { get; } + /// The object type, which is always "embedding". + public EmbeddingObject Object { get; } = EmbeddingObject.Embedding; } } diff --git a/.dotnet/src/Generated/Models/EmbeddingCollectionObject.cs b/.dotnet/src/Generated/Models/EmbeddingCollectionObject.cs deleted file mode 100644 index b045cf349..000000000 --- a/.dotnet/src/Generated/Models/EmbeddingCollectionObject.cs +++ /dev/null @@ -1,44 +0,0 @@ -// - -using System; -using System.ComponentModel; - -namespace OpenAI.Models -{ - /// The EmbeddingCollection_object. - public readonly partial struct EmbeddingCollectionObject : IEquatable - { - private readonly string _value; - - /// Initializes a new instance of . - /// is null. - public EmbeddingCollectionObject(string value) - { - _value = value ?? throw new ArgumentNullException(nameof(value)); - } - - private const string ListValue = "list"; - - /// list. - public static EmbeddingCollectionObject List { get; } = new EmbeddingCollectionObject(ListValue); - /// Determines if two values are the same. - public static bool operator ==(EmbeddingCollectionObject left, EmbeddingCollectionObject right) => left.Equals(right); - /// Determines if two values are not the same. - public static bool operator !=(EmbeddingCollectionObject left, EmbeddingCollectionObject right) => !left.Equals(right); - /// Converts a string to a . - public static implicit operator EmbeddingCollectionObject(string value) => new EmbeddingCollectionObject(value); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public override bool Equals(object obj) => obj is EmbeddingCollectionObject other && Equals(other); - /// - public bool Equals(EmbeddingCollectionObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public override int GetHashCode() => _value?.GetHashCode() ?? 0; - /// - public override string ToString() => _value; - } -} - diff --git a/.dotnet/src/Generated/Models/EmbeddingObject.cs b/.dotnet/src/Generated/Models/EmbeddingObject.cs index c6088b162..2cc2f012c 100644 --- a/.dotnet/src/Generated/Models/EmbeddingObject.cs +++ b/.dotnet/src/Generated/Models/EmbeddingObject.cs @@ -6,7 +6,7 @@ namespace OpenAI.Models { /// The Embedding_object. - internal readonly partial struct EmbeddingObject : IEquatable + public readonly partial struct EmbeddingObject : IEquatable { private readonly string _value; diff --git a/.dotnet/src/Generated/Models/EmbeddingTokenUsage.Serialization.cs b/.dotnet/src/Generated/Models/EmbeddingUsage.Serialization.cs similarity index 67% rename from .dotnet/src/Generated/Models/EmbeddingTokenUsage.Serialization.cs rename to .dotnet/src/Generated/Models/EmbeddingUsage.Serialization.cs index 8026af740..23beb37ad 100644 --- a/.dotnet/src/Generated/Models/EmbeddingTokenUsage.Serialization.cs +++ b/.dotnet/src/Generated/Models/EmbeddingUsage.Serialization.cs @@ -8,14 +8,14 @@ namespace OpenAI.Models { - public partial class EmbeddingTokenUsage : IJsonModel + public partial class EmbeddingUsage : IJsonModel { - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; if (format != "J") { - throw new FormatException($"The model {nameof(EmbeddingTokenUsage)} does not support '{format}' format."); + throw new FormatException($"The model {nameof(EmbeddingUsage)} does not support '{format}' format."); } writer.WriteStartObject(); @@ -41,19 +41,19 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWri writer.WriteEndObject(); } - EmbeddingTokenUsage IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + EmbeddingUsage IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; if (format != "J") { - throw new FormatException($"The model {nameof(EmbeddingTokenUsage)} does not support '{format}' format."); + throw new FormatException($"The model {nameof(EmbeddingUsage)} does not support '{format}' format."); } using JsonDocument document = JsonDocument.ParseValue(ref reader); - return DeserializeEmbeddingTokenUsage(document.RootElement, options); + return DeserializeEmbeddingUsage(document.RootElement, options); } - internal static EmbeddingTokenUsage DeserializeEmbeddingTokenUsage(JsonElement element, ModelReaderWriterOptions options = null) + internal static EmbeddingUsage DeserializeEmbeddingUsage(JsonElement element, ModelReaderWriterOptions options = null) { options ??= new ModelReaderWriterOptions("W"); @@ -83,46 +83,46 @@ internal static EmbeddingTokenUsage DeserializeEmbeddingTokenUsage(JsonElement e } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new EmbeddingTokenUsage(promptTokens, totalTokens, serializedAdditionalRawData); + return new EmbeddingUsage(promptTokens, totalTokens, serializedAdditionalRawData); } - BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; switch (format) { case "J": return ModelReaderWriter.Write(this, options); default: - throw new FormatException($"The model {nameof(EmbeddingTokenUsage)} does not support '{options.Format}' format."); + throw new FormatException($"The model {nameof(EmbeddingUsage)} does not support '{options.Format}' format."); } } - EmbeddingTokenUsage IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + EmbeddingUsage IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; switch (format) { case "J": { using JsonDocument document = JsonDocument.Parse(data); - return DeserializeEmbeddingTokenUsage(document.RootElement, options); + return DeserializeEmbeddingUsage(document.RootElement, options); } default: - throw new FormatException($"The model {nameof(EmbeddingTokenUsage)} does not support '{options.Format}' format."); + throw new FormatException($"The model {nameof(EmbeddingUsage)} does not support '{options.Format}' format."); } } - string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; /// Deserializes the model from a raw response. /// The result to deserialize the model from. - internal static EmbeddingTokenUsage FromResponse(PipelineResponse response) + internal static EmbeddingUsage FromResponse(PipelineResponse response) { using var document = JsonDocument.Parse(response.Content); - return DeserializeEmbeddingTokenUsage(document.RootElement); + return DeserializeEmbeddingUsage(document.RootElement); } } } diff --git a/.dotnet/src/Generated/Models/EmbeddingTokenUsage.cs b/.dotnet/src/Generated/Models/EmbeddingUsage.cs similarity index 85% rename from .dotnet/src/Generated/Models/EmbeddingTokenUsage.cs rename to .dotnet/src/Generated/Models/EmbeddingUsage.cs index e235e4d4b..6c03d3210 100644 --- a/.dotnet/src/Generated/Models/EmbeddingTokenUsage.cs +++ b/.dotnet/src/Generated/Models/EmbeddingUsage.cs @@ -5,8 +5,8 @@ namespace OpenAI.Models { - /// The EmbeddingTokenUsage. - public partial class EmbeddingTokenUsage + /// The EmbeddingUsage. + public partial class EmbeddingUsage { /// /// Keeps track of any properties unknown to the library. @@ -40,28 +40,28 @@ public partial class EmbeddingTokenUsage /// private IDictionary _serializedAdditionalRawData; - /// Initializes a new instance of . + /// Initializes a new instance of . /// The number of tokens used by the prompt. /// The total number of tokens used by the request. - internal EmbeddingTokenUsage(long promptTokens, long totalTokens) + internal EmbeddingUsage(long promptTokens, long totalTokens) { PromptTokens = promptTokens; TotalTokens = totalTokens; } - /// Initializes a new instance of . + /// Initializes a new instance of . /// The number of tokens used by the prompt. /// The total number of tokens used by the request. /// Keeps track of any properties unknown to the library. - internal EmbeddingTokenUsage(long promptTokens, long totalTokens, IDictionary serializedAdditionalRawData) + internal EmbeddingUsage(long promptTokens, long totalTokens, IDictionary serializedAdditionalRawData) { PromptTokens = promptTokens; TotalTokens = totalTokens; _serializedAdditionalRawData = serializedAdditionalRawData; } - /// Initializes a new instance of for deserialization. - internal EmbeddingTokenUsage() + /// Initializes a new instance of for deserialization. + internal EmbeddingUsage() { } diff --git a/.dotnet/src/Generated/Models/GenerateEmbeddingsOptionsEncodingFormat.cs b/.dotnet/src/Generated/Models/GenerateEmbeddingsOptionsEncodingFormat.cs deleted file mode 100644 index 805a38b93..000000000 --- a/.dotnet/src/Generated/Models/GenerateEmbeddingsOptionsEncodingFormat.cs +++ /dev/null @@ -1,47 +0,0 @@ -// - -using System; -using System.ComponentModel; - -namespace OpenAI.Models -{ - /// Enum for encoding_format in GenerateEmbeddingsOptions. - public readonly partial struct GenerateEmbeddingsOptionsEncodingFormat : IEquatable - { - private readonly string _value; - - /// Initializes a new instance of . - /// is null. - public GenerateEmbeddingsOptionsEncodingFormat(string value) - { - _value = value ?? throw new ArgumentNullException(nameof(value)); - } - - private const string FloatValue = "float"; - private const string Base64Value = "base64"; - - /// float. - public static GenerateEmbeddingsOptionsEncodingFormat Float { get; } = new GenerateEmbeddingsOptionsEncodingFormat(FloatValue); - /// base64. - public static GenerateEmbeddingsOptionsEncodingFormat Base64 { get; } = new GenerateEmbeddingsOptionsEncodingFormat(Base64Value); - /// Determines if two values are the same. - public static bool operator ==(GenerateEmbeddingsOptionsEncodingFormat left, GenerateEmbeddingsOptionsEncodingFormat right) => left.Equals(right); - /// Determines if two values are not the same. - public static bool operator !=(GenerateEmbeddingsOptionsEncodingFormat left, GenerateEmbeddingsOptionsEncodingFormat right) => !left.Equals(right); - /// Converts a string to a . - public static implicit operator GenerateEmbeddingsOptionsEncodingFormat(string value) => new GenerateEmbeddingsOptionsEncodingFormat(value); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public override bool Equals(object obj) => obj is GenerateEmbeddingsOptionsEncodingFormat other && Equals(other); - /// - public bool Equals(GenerateEmbeddingsOptionsEncodingFormat other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public override int GetHashCode() => _value?.GetHashCode() ?? 0; - /// - public override string ToString() => _value; - } -} - diff --git a/.dotnet/src/Generated/Models/GenerateEmbeddingsOptionsModel.cs b/.dotnet/src/Generated/Models/GenerateEmbeddingsOptionsModel.cs deleted file mode 100644 index e1a9c9135..000000000 --- a/.dotnet/src/Generated/Models/GenerateEmbeddingsOptionsModel.cs +++ /dev/null @@ -1,50 +0,0 @@ -// - -using System; -using System.ComponentModel; - -namespace OpenAI.Models -{ - /// Enum for model in GenerateEmbeddingsOptions. - public readonly partial struct GenerateEmbeddingsOptionsModel : IEquatable - { - private readonly string _value; - - /// Initializes a new instance of . - /// is null. - public GenerateEmbeddingsOptionsModel(string value) - { - _value = value ?? throw new ArgumentNullException(nameof(value)); - } - - private const string TextEmbeddingAda002Value = "text-embedding-ada-002"; - private const string TextEmbedding3SmallValue = "text-embedding-3-small"; - private const string TextEmbedding3LargeValue = "text-embedding-3-large"; - - /// text-embedding-ada-002. - public static GenerateEmbeddingsOptionsModel TextEmbeddingAda002 { get; } = new GenerateEmbeddingsOptionsModel(TextEmbeddingAda002Value); - /// text-embedding-3-small. - public static GenerateEmbeddingsOptionsModel TextEmbedding3Small { get; } = new GenerateEmbeddingsOptionsModel(TextEmbedding3SmallValue); - /// text-embedding-3-large. - public static GenerateEmbeddingsOptionsModel TextEmbedding3Large { get; } = new GenerateEmbeddingsOptionsModel(TextEmbedding3LargeValue); - /// Determines if two values are the same. - public static bool operator ==(GenerateEmbeddingsOptionsModel left, GenerateEmbeddingsOptionsModel right) => left.Equals(right); - /// Determines if two values are not the same. - public static bool operator !=(GenerateEmbeddingsOptionsModel left, GenerateEmbeddingsOptionsModel right) => !left.Equals(right); - /// Converts a string to a . - public static implicit operator GenerateEmbeddingsOptionsModel(string value) => new GenerateEmbeddingsOptionsModel(value); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public override bool Equals(object obj) => obj is GenerateEmbeddingsOptionsModel other && Equals(other); - /// - public bool Equals(GenerateEmbeddingsOptionsModel other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public override int GetHashCode() => _value?.GetHashCode() ?? 0; - /// - public override string ToString() => _value; - } -} - diff --git a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.Serialization.cs b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.Serialization.cs index a5bf6fda2..68b1ad66f 100644 --- a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.Serialization.cs @@ -20,7 +20,12 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelR writer.WriteStartObject(); writer.WritePropertyName("tool_outputs"u8); - writer.WriteObjectValue(ToolOutputs); + writer.WriteStartArray(); + foreach (var item in ToolOutputs) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); if (options.Format != "W" && _serializedAdditionalRawData != null) { foreach (var item in _serializedAdditionalRawData) @@ -59,14 +64,19 @@ internal static SubmitToolOutputsRunRequest DeserializeSubmitToolOutputsRunReque { return null; } - SubmitToolOutputsRunRequestToolOutputs toolOutputs = default; + IList toolOutputs = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) { if (property.NameEquals("tool_outputs"u8)) { - toolOutputs = SubmitToolOutputsRunRequestToolOutputs.DeserializeSubmitToolOutputsRunRequestToolOutputs(property.Value); + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(SubmitToolOutputsRunRequestToolOutput.DeserializeSubmitToolOutputsRunRequestToolOutput(item)); + } + toolOutputs = array; continue; } if (options.Format != "W") diff --git a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.cs b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.cs index abdcfb9e3..f489e6bb1 100644 --- a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.cs +++ b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.cs @@ -3,6 +3,7 @@ using System; using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using System.Linq; namespace OpenAI.Models { @@ -44,17 +45,17 @@ public partial class SubmitToolOutputsRunRequest /// Initializes a new instance of . /// A list of tools for which the outputs are being submitted. /// is null. - public SubmitToolOutputsRunRequest(SubmitToolOutputsRunRequestToolOutputs toolOutputs) + public SubmitToolOutputsRunRequest(IEnumerable toolOutputs) { if (toolOutputs is null) throw new ArgumentNullException(nameof(toolOutputs)); - ToolOutputs = toolOutputs; + ToolOutputs = toolOutputs.ToList(); } /// Initializes a new instance of . /// A list of tools for which the outputs are being submitted. /// Keeps track of any properties unknown to the library. - internal SubmitToolOutputsRunRequest(SubmitToolOutputsRunRequestToolOutputs toolOutputs, IDictionary serializedAdditionalRawData) + internal SubmitToolOutputsRunRequest(IList toolOutputs, IDictionary serializedAdditionalRawData) { ToolOutputs = toolOutputs; _serializedAdditionalRawData = serializedAdditionalRawData; @@ -66,7 +67,7 @@ internal SubmitToolOutputsRunRequest() } /// A list of tools for which the outputs are being submitted. - public SubmitToolOutputsRunRequestToolOutputs ToolOutputs { get; } + public IList ToolOutputs { get; } } } diff --git a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutputs.Serialization.cs b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutput.Serialization.cs similarity index 68% rename from .dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutputs.Serialization.cs rename to .dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutput.Serialization.cs index f7c09dcf1..709807021 100644 --- a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutputs.Serialization.cs +++ b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutput.Serialization.cs @@ -8,14 +8,14 @@ namespace OpenAI.Models { - public partial class SubmitToolOutputsRunRequestToolOutputs : IJsonModel + public partial class SubmitToolOutputsRunRequestToolOutput : IJsonModel { - void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; if (format != "J") { - throw new FormatException($"The model {nameof(SubmitToolOutputsRunRequestToolOutputs)} does not support '{format}' format."); + throw new FormatException($"The model {nameof(SubmitToolOutputsRunRequestToolOutput)} does not support '{format}' format."); } writer.WriteStartObject(); @@ -47,19 +47,19 @@ void IJsonModel.Write(Utf8JsonWriter wri writer.WriteEndObject(); } - SubmitToolOutputsRunRequestToolOutputs IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + SubmitToolOutputsRunRequestToolOutput IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; if (format != "J") { - throw new FormatException($"The model {nameof(SubmitToolOutputsRunRequestToolOutputs)} does not support '{format}' format."); + throw new FormatException($"The model {nameof(SubmitToolOutputsRunRequestToolOutput)} does not support '{format}' format."); } using JsonDocument document = JsonDocument.ParseValue(ref reader); - return DeserializeSubmitToolOutputsRunRequestToolOutputs(document.RootElement, options); + return DeserializeSubmitToolOutputsRunRequestToolOutput(document.RootElement, options); } - internal static SubmitToolOutputsRunRequestToolOutputs DeserializeSubmitToolOutputsRunRequestToolOutputs(JsonElement element, ModelReaderWriterOptions options = null) + internal static SubmitToolOutputsRunRequestToolOutput DeserializeSubmitToolOutputsRunRequestToolOutput(JsonElement element, ModelReaderWriterOptions options = null) { options ??= new ModelReaderWriterOptions("W"); @@ -89,46 +89,46 @@ internal static SubmitToolOutputsRunRequestToolOutputs DeserializeSubmitToolOutp } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new SubmitToolOutputsRunRequestToolOutputs(toolCallId.Value, output.Value, serializedAdditionalRawData); + return new SubmitToolOutputsRunRequestToolOutput(toolCallId.Value, output.Value, serializedAdditionalRawData); } - BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; switch (format) { case "J": return ModelReaderWriter.Write(this, options); default: - throw new FormatException($"The model {nameof(SubmitToolOutputsRunRequestToolOutputs)} does not support '{options.Format}' format."); + throw new FormatException($"The model {nameof(SubmitToolOutputsRunRequestToolOutput)} does not support '{options.Format}' format."); } } - SubmitToolOutputsRunRequestToolOutputs IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + SubmitToolOutputsRunRequestToolOutput IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) { - var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; switch (format) { case "J": { using JsonDocument document = JsonDocument.Parse(data); - return DeserializeSubmitToolOutputsRunRequestToolOutputs(document.RootElement, options); + return DeserializeSubmitToolOutputsRunRequestToolOutput(document.RootElement, options); } default: - throw new FormatException($"The model {nameof(SubmitToolOutputsRunRequestToolOutputs)} does not support '{options.Format}' format."); + throw new FormatException($"The model {nameof(SubmitToolOutputsRunRequestToolOutput)} does not support '{options.Format}' format."); } } - string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; /// Deserializes the model from a raw response. /// The result to deserialize the model from. - internal static SubmitToolOutputsRunRequestToolOutputs FromResponse(PipelineResponse response) + internal static SubmitToolOutputsRunRequestToolOutput FromResponse(PipelineResponse response) { using var document = JsonDocument.Parse(response.Content); - return DeserializeSubmitToolOutputsRunRequestToolOutputs(document.RootElement); + return DeserializeSubmitToolOutputsRunRequestToolOutput(document.RootElement); } } } diff --git a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutputs.cs b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutput.cs similarity index 85% rename from .dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutputs.cs rename to .dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutput.cs index 8d8a8109c..096a5584b 100644 --- a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutputs.cs +++ b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutput.cs @@ -5,8 +5,8 @@ namespace OpenAI.Models { - /// The SubmitToolOutputsRunRequestToolOutputs. - public partial class SubmitToolOutputsRunRequestToolOutputs + /// The SubmitToolOutputsRunRequestToolOutput. + public partial class SubmitToolOutputsRunRequestToolOutput { /// /// Keeps track of any properties unknown to the library. @@ -40,19 +40,19 @@ public partial class SubmitToolOutputsRunRequestToolOutputs /// private IDictionary _serializedAdditionalRawData; - /// Initializes a new instance of . - public SubmitToolOutputsRunRequestToolOutputs() + /// Initializes a new instance of . + public SubmitToolOutputsRunRequestToolOutput() { } - /// Initializes a new instance of . + /// Initializes a new instance of . /// /// The ID of the tool call in the `required_action` object within the run object the output is /// being submitted for. /// /// The output of the tool call to be submitted to continue the run. /// Keeps track of any properties unknown to the library. - internal SubmitToolOutputsRunRequestToolOutputs(string toolCallId, string output, IDictionary serializedAdditionalRawData) + internal SubmitToolOutputsRunRequestToolOutput(string toolCallId, string output, IDictionary serializedAdditionalRawData) { ToolCallId = toolCallId; Output = output; diff --git a/.dotnet/src/Generated/OpenAIClient.cs b/.dotnet/src/Generated/OpenAIClient.cs index 7565c4dd1..29785453c 100644 --- a/.dotnet/src/Generated/OpenAIClient.cs +++ b/.dotnet/src/Generated/OpenAIClient.cs @@ -89,6 +89,12 @@ public virtual Completions GetCompletionsClient() return Volatile.Read(ref _cachedCompletions) ?? Interlocked.CompareExchange(ref _cachedCompletions, new Completions(_pipeline, _credential, _endpoint), null) ?? _cachedCompletions; } + /// Initializes a new instance of Embeddings. + public virtual Embeddings GetEmbeddingsClient() + { + return Volatile.Read(ref _cachedEmbeddings) ?? Interlocked.CompareExchange(ref _cachedEmbeddings, new Embeddings(_pipeline, _credential, _endpoint), null) ?? _cachedEmbeddings; + } + /// Initializes a new instance of Files. public virtual Files GetFilesClient() { diff --git a/.dotnet/src/Generated/OpenAIModelFactory.cs b/.dotnet/src/Generated/OpenAIModelFactory.cs index dd7118fc0..8e81ba327 100644 --- a/.dotnet/src/Generated/OpenAIModelFactory.cs +++ b/.dotnet/src/Generated/OpenAIModelFactory.cs @@ -724,26 +724,71 @@ public static CreateCompletionResponseChoiceLogprobs CreateCompletionResponseCho return new CreateCompletionResponseChoiceLogprobs(tokens?.ToList(), tokenLogprobs?.ToList(), topLogprobs?.ToList(), textOffset?.ToList(), serializedAdditionalRawData: null); } - /// Initializes a new instance of . + /// Initializes a new instance of . + /// + /// Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a + /// single request, pass an array of strings or array of token arrays. Each input must not exceed + /// the max input tokens for the model (8191 tokens for `text-embedding-ada-002`) and cannot be an + /// empty string. + /// [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) + /// for counting tokens. + /// + /// + /// ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to + /// see all of your available models, or see our [Model overview](/docs/models/overview) for + /// descriptions of them. + /// + /// + /// The format to return the embeddings in. Can be either `float` or + /// [`base64`](https://pypi.org/project/pybase64/). + /// + /// + /// The number of dimensions the resulting output embeddings should have. Only supported in + /// `text-embedding-3` and later models. + /// + /// + /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect + /// abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). + /// + /// A new instance for mocking. + public static CreateEmbeddingRequest CreateEmbeddingRequest(BinaryData input = null, CreateEmbeddingRequestModel model = default, CreateEmbeddingRequestEncodingFormat? encodingFormat = null, long? dimensions = null, string user = null) + { + return new CreateEmbeddingRequest(input, model, encodingFormat, dimensions, user, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . /// The list of embeddings generated by the model. /// The name of the model used to generate the embedding. /// The object type, which is always "list". /// The usage information for the request. - /// A new instance for mocking. - public static EmbeddingCollection EmbeddingCollection(IEnumerable data = null, string model = null, EmbeddingCollectionObject @object = default, EmbeddingTokenUsage usage = null) + /// A new instance for mocking. + public static CreateEmbeddingResponse CreateEmbeddingResponse(IEnumerable data = null, string model = null, CreateEmbeddingResponseObject @object = default, EmbeddingUsage usage = null) { data ??= new List(); - return new EmbeddingCollection(data?.ToList(), model, @object, usage, serializedAdditionalRawData: null); + return new CreateEmbeddingResponse(data?.ToList(), model, @object, usage, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// The index of the embedding in the list of embeddings. + /// + /// The embedding vector, which is a list of floats. The length of vector depends on the model as + /// listed in the [embedding guide](/docs/guides/embeddings). + /// + /// The object type, which is always "embedding". + /// A new instance for mocking. + public static Embedding Embedding(long index = default, BinaryData embeddingProperty = null, EmbeddingObject @object = default) + { + return new Embedding(index, embeddingProperty, @object, serializedAdditionalRawData: null); } - /// Initializes a new instance of . + /// Initializes a new instance of . /// The number of tokens used by the prompt. /// The total number of tokens used by the request. - /// A new instance for mocking. - public static EmbeddingTokenUsage EmbeddingTokenUsage(long promptTokens = default, long totalTokens = default) + /// A new instance for mocking. + public static EmbeddingUsage EmbeddingUsage(long promptTokens = default, long totalTokens = default) { - return new EmbeddingTokenUsage(promptTokens, totalTokens, serializedAdditionalRawData: null); + return new EmbeddingUsage(promptTokens, totalTokens, serializedAdditionalRawData: null); } /// Initializes a new instance of . diff --git a/.dotnet/src/OpenAI.csproj b/.dotnet/src/OpenAI.csproj index c53137241..e03a4dc1e 100644 --- a/.dotnet/src/OpenAI.csproj +++ b/.dotnet/src/OpenAI.csproj @@ -10,7 +10,7 @@ - + diff --git a/.dotnet/tests/EmbeddingsTests.cs b/.dotnet/tests/EmbeddingsTests.cs deleted file mode 100644 index ecf35be7d..000000000 --- a/.dotnet/tests/EmbeddingsTests.cs +++ /dev/null @@ -1,101 +0,0 @@ -using NUnit.Framework; -using OpenAI.Models; -using System; -using System.ClientModel; -using System.Collections.Generic; -using System.Linq; -using System.Numerics; -using System.Text; -using System.Threading.Tasks; - -namespace OpenAI.Tests -{ - public partial class EmbeddingsTests - { - [Test] - public static void GetEmbeddingFromString() - { - ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - OpenAIClient client = new(credential); - Embeddings embeddingsClient = client.GetEmbeddingsClient("text-embedding-3-small"); - - string input = "Best hotel in town if you like luxury hotels. They have an amazing infinity pool, a spa," - + " and a really helpful concierge. The location is perfect -- right downtown, close to all " - + " the tourist attractions. We highly recommend this hotel."; - - ClientResult result = embeddingsClient.GenerateEmbedding(input); - Embedding embedding = result.Value; - - ReadOnlyMemory vector = embedding.EmbeddingAsFloats.Value; - Assert.IsTrue(vector.Length == 1536); - } - - [Test] - public static void GetEmbeddingFromArrayOfTokens() - { - ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - OpenAIClient client = new(credential); - Embeddings embeddingsClient = client.GetEmbeddingsClient("text-embedding-3-small"); - - List input = new() { 14809, 9689, 304, 6424, 422, 499, 1093, 19913, 25325, 13, 2435, 617, 459, 8056, - 56010, 7463, 11, 264, 31493, 11, 323, 264, 2216, 11190, 3613, 87103, 13, 578, 3813, 374, 4832, 1198, - 1314, 19441, 11, 3345, 311, 682, 279, 31070, 39591, 13, 1226, 7701, 7079, 420, 9689, 13 }; - - ClientResult result = embeddingsClient.GenerateEmbedding(input); - Embedding embedding = result.Value; - - ReadOnlyMemory vector = embedding.EmbeddingAsFloats.Value; - Assert.IsTrue(vector.Length == 1536); - } - - [Test] - public static void GetEmbeddingsFromArrayOfStrings() - { - ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - OpenAIClient client = new(credential); - Embeddings embeddingsClient = client.GetEmbeddingsClient("text-embedding-3-small"); - - List inputs = new() { - "Luxury", - "Best hotel in town if you like luxury hotels. They have an amazing infinity pool, a spa," - + " and a really helpful concierge. The location is perfect -- right downtown, close to all " - + " the tourist attractions. We highly recommend this hotel." - }; - - ClientResult result = embeddingsClient.GenerateEmbeddings(inputs); - EmbeddingCollection collection = result.Value; // TODO: Make EmbeddingCollection inherit from ReadOnlyCollection. - IReadOnlyList data = collection.Data; - - ReadOnlyMemory vector0 = data[0].EmbeddingAsFloats.Value; - Assert.IsTrue(vector0.Length == 1536); - - ReadOnlyMemory vector1 = data[1].EmbeddingAsFloats.Value; - Assert.IsTrue(vector1.Length == 1536); - } - - [Test] - public static void GetEmbeddingsFromArrayOfArraysOfTokens() - { - ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - OpenAIClient client = new(credential); - Embeddings embeddingsClient = client.GetEmbeddingsClient("text-embedding-3-small"); - - List> inputs = new() { - new List { 78379, 3431 }, - new List { 14809, 9689, 304, 6424, 422, 499, 1093, 19913, 25325, 13, 2435, 617, 459, 8056, - 56010, 7463, 11, 264, 31493, 11, 323, 264, 2216, 11190, 3613, 87103, 13, 578, 3813, 374, 4832, 1198, - 1314, 19441, 11, 3345, 311, 682, 279, 31070, 39591, 13, 1226, 7701, 7079, 420, 9689, 13 } - }; - - ClientResult result = embeddingsClient.GenerateEmbeddings(inputs); - EmbeddingCollection collection = result.Value; // TODO: Make EmbeddingCollection inherit from ReadOnlyCollection. - IReadOnlyList data = collection.Data; - - ReadOnlyMemory vector0 = data[0].EmbeddingAsFloats.Value; - Assert.IsTrue(vector0.Length == 1536); - - ReadOnlyMemory vector1 = data[1].EmbeddingAsFloats.Value; - Assert.IsTrue(vector1.Length == 1536); - } - } -} diff --git a/.dotnet/tests/Generated/Tests/EmbeddingsTests.cs b/.dotnet/tests/Generated/Tests/EmbeddingsTests.cs new file mode 100644 index 000000000..b4deac0fc --- /dev/null +++ b/.dotnet/tests/Generated/Tests/EmbeddingsTests.cs @@ -0,0 +1,23 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using NUnit.Framework; +using OpenAI; + +namespace OpenAI.Tests +{ + public partial class EmbeddingsTests + { + [Test] + public void SmokeTest() + { + ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + Embeddings client = new OpenAIClient(credential).GetEmbeddingsClient(); + Assert.IsNotNull(client); + } + } +} + diff --git a/.dotnet/tests/OpenAI.Tests.csproj b/.dotnet/tests/OpenAI.Tests.csproj index a279ac212..e590c0e52 100644 --- a/.dotnet/tests/OpenAI.Tests.csproj +++ b/.dotnet/tests/OpenAI.Tests.csproj @@ -14,5 +14,6 @@ + diff --git a/main.tsp b/main.tsp index e46a4467c..d7bbdec33 100644 --- a/main.tsp +++ b/main.tsp @@ -1,7 +1,6 @@ import "@typespec/http"; import "@typespec/openapi3"; import "@typespec/openapi"; -import "@azure-tools/typespec-client-generator-core"; import "./audio"; import "./assistants"; @@ -18,7 +17,6 @@ import "./runs"; import "./threads"; using TypeSpec.Http; -using Azure.ClientGenerator.Core; /** The OpenAI REST API. Please see https://platform.openai.com/docs/api-reference for more details. */ @service({ @@ -36,13 +34,4 @@ using Azure.ClientGenerator.Core; }) @server("https://api.openai.com/v1", "OpenAI Endpoint") @useAuth(BearerAuth) -namespace OpenAI; - -@@projectedName(OpenAI.CreateEmbeddingRequest, "csharp", "GenerateEmbeddingsOptions"); -@@projectedName(OpenAI.CreateEmbeddingResponse, "csharp", "EmbeddingCollection"); -@@projectedName(OpenAI.EmbeddingUsage, "csharp", "EmbeddingTokenUsage"); - -@@access(OpenAI.Embeddings.createEmbedding, Access.internal, "csharp"); -@@access(OpenAI.CreateEmbeddingRequest, Access.public, "csharp"); -@@access(OpenAI.CreateEmbeddingResponse, Access.public, "csharp"); -@@access(OpenAI.EmbeddingUsage, Access.public, "csharp"); \ No newline at end of file +namespace OpenAI; \ No newline at end of file diff --git a/runs/models.tsp b/runs/models.tsp index d5c33bb22..42d7935ef 100644 --- a/runs/models.tsp +++ b/runs/models.tsp @@ -99,7 +99,7 @@ model SubmitToolOutputsRunRequest { /** The output of the tool call to be submitted to continue the run. */ output?: string; - } + }[]; } model ListRunsResponse { diff --git a/tsp-output/@typespec/openapi3/openapi.yaml b/tsp-output/@typespec/openapi3/openapi.yaml index e27e57ba4..10cc8f54e 100644 --- a/tsp-output/@typespec/openapi3/openapi.yaml +++ b/tsp-output/@typespec/openapi3/openapi.yaml @@ -5803,16 +5803,18 @@ components: - tool_outputs properties: tool_outputs: - type: object - properties: - tool_call_id: - type: string - description: |- - The ID of the tool call in the `required_action` object within the run object the output is - being submitted for. - output: - type: string - description: The output of the tool call to be submitted to continue the run. + type: array + items: + type: object + properties: + tool_call_id: + type: string + description: |- + The ID of the tool call in the `required_action` object within the run object the output is + being submitted for. + output: + type: string + description: The output of the tool call to be submitted to continue the run. description: A list of tools for which the outputs are being submitted. SuffixString: type: string From 4decb12d1e9bd556e7cd8b3bf874e096f94c8974 Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado Date: Tue, 27 Feb 2024 23:02:08 -0800 Subject: [PATCH 16/50] Fix Update-ClientModel.ps1 script: Convenience methods with a single CancellationToken parameter --- .dotnet/scripts/Update-ClientModel.ps1 | 8 +++++--- .dotnet/src/Generated/ModelsOps.cs | 8 ++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.dotnet/scripts/Update-ClientModel.ps1 b/.dotnet/scripts/Update-ClientModel.ps1 index 83013e82e..13b8beb80 100644 --- a/.dotnet/scripts/Update-ClientModel.ps1 +++ b/.dotnet/scripts/Update-ClientModel.ps1 @@ -83,6 +83,9 @@ function Update-Subclients { $content = $content -creplace "\s+\/\/\/ The ClientDiagnostics is used to provide tracing support for the client library. ", "" $content = $content -creplace "\s+internal TelemetrySource ClientDiagnostics { get; }", "" + # Delete FromCancellationToken + $content = $content -creplace "(?s)\s+internal static RequestOptions FromCancellationToken\(CancellationToken cancellationToken = default\).*?return new RequestOptions\(\) \{ CancellationToken = cancellationToken \};.*?\}", "" + # Modify constructor $content = $content -creplace "\s+\/\/\/ The handler for diagnostic messaging in the client. ", "" $content = $content -creplace "", "" @@ -91,6 +94,7 @@ function Update-Subclients { # # Modify convenience methods $content = $content -creplace "\s+\/\/\/ The cancellation token to use. ", "" + $content = $content -creplace "\(CancellationToken cancellationToken = default\)", "()" $content = $content -creplace ", CancellationToken cancellationToken = default\)", ")" $content = $content -creplace "RequestOptions context = FromCancellationToken\(cancellationToken\);\s+", "" $content = $content -creplace "using RequestBody content = (?\w+)\.ToRequestBody\(\);", "using BinaryContent content = BinaryContent.Create(`${var});" @@ -101,6 +105,7 @@ function Update-Subclients { $content = $content -creplace "Result result = (?\w+)\((?[(\w+)(\?.ToString\(\)*)(,\s\w+)]*), context\);", "ClientResult result = `${method}(`${params}, DefaultRequestContext);" # Modify protocol methods + $content = $content -creplace "\/\/\/ Please try the simpler \w+)\(CancellationToken\)`"/> convenience overload with strongly typed models first.", "/// Please try the simpler convenience overload with strongly typed models first." $content = $content -creplace "\/\/\/ Please try the simpler \w+)\((?[(\w+)(\?*)(,\s\w+)]*),CancellationToken\)`"/> convenience overload with strongly typed models first.", "/// Please try the simpler convenience overload with strongly typed models first." $content = $content -creplace "\/\/\/ The request context, which can override default behaviors of the client pipeline on a per-call basis. ", "/// The request options, which can override default behaviors of the client pipeline on a per-call basis. " $content = $content -creplace "\/\/\/ ", "/// " @@ -134,9 +139,6 @@ function Update-Subclients { # Delete DefaultRequestContext # $content = $content -creplace "\s+private static RequestOptions DefaultRequestContext = new RequestOptions\(\);", "" - # Delete FromCancellationToken - $content = $content -creplace "(?s)\s+internal static RequestOptions FromCancellationToken\(CancellationToken cancellationToken = default\).*?return new RequestOptions\(\) \{ CancellationToken = cancellationToken \};.*?\}", "" - # Clean up ApiKeyCredential $content = $content -creplace " KeyCredential", " ApiKeyCredential" $content = $content -creplace "_keyCredential", "_credential" diff --git a/.dotnet/src/Generated/ModelsOps.cs b/.dotnet/src/Generated/ModelsOps.cs index 528bd4d2f..c4b6cbfbb 100644 --- a/.dotnet/src/Generated/ModelsOps.cs +++ b/.dotnet/src/Generated/ModelsOps.cs @@ -43,7 +43,7 @@ internal ModelsOps(ClientPipeline pipeline, ApiKeyCredential credential, Uri end /// Lists the currently available models, and provides basic information about each one such as the /// owner and availability. /// - public virtual async Task> GetModelsAsync(CancellationToken cancellationToken = default) + public virtual async Task> GetModelsAsync() { ClientResult result = await GetModelsAsync(DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(ListModelsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -53,7 +53,7 @@ public virtual async Task> GetModelsAsync(Cance /// Lists the currently available models, and provides basic information about each one such as the /// owner and availability. /// - public virtual ClientResult GetModels(CancellationToken cancellationToken = default) + public virtual ClientResult GetModels() { ClientResult result = GetModels(DefaultRequestContext); return ClientResult.FromValue(ListModelsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -70,7 +70,7 @@ public virtual ClientResult GetModels(CancellationToken canc /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -104,7 +104,7 @@ public virtual async Task GetModelsAsync(RequestOptions options) /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// From 8c0f76d98d9071f2ddc1030bf652793a91604658 Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado Date: Wed, 28 Feb 2024 11:25:40 -0800 Subject: [PATCH 17/50] Add ConvertTo-Internal.ps1 script --- .dotnet/scripts/ConvertTo-Internal.ps1 | 17 +++++++++++++++++ .dotnet/scripts/Update-ClientModel.ps1 | 10 +++++----- .dotnet/src/Generated/Assistants.cs | 7 +++---- .dotnet/src/Generated/Audio.cs | 7 +++---- .dotnet/src/Generated/Chat.cs | 7 +++---- .dotnet/src/Generated/Completions.cs | 7 +++---- .dotnet/src/Generated/Embeddings.cs | 7 +++---- .dotnet/src/Generated/Files.cs | 7 +++---- .dotnet/src/Generated/FineTuning.cs | 7 +++---- .dotnet/src/Generated/Images.cs | 7 +++---- .dotnet/src/Generated/Messages.cs | 7 +++---- .../Models/AssistantFileObject.Serialization.cs | 5 ++--- .../src/Generated/Models/AssistantFileObject.cs | 5 ++--- .../Models/AssistantFileObjectObject.cs | 5 ++--- .../Models/AssistantObject.Serialization.cs | 5 ++--- .dotnet/src/Generated/Models/AssistantObject.cs | 5 ++--- .../Generated/Models/AssistantObjectObject.cs | 5 ++--- .../Models/AudioSegment.Serialization.cs | 5 ++--- .dotnet/src/Generated/Models/AudioSegment.cs | 5 ++--- ...ompletionFunctionCallOption.Serialization.cs | 3 +-- .../Models/ChatCompletionFunctionCallOption.cs | 3 +-- .../ChatCompletionFunctions.Serialization.cs | 5 ++--- .../Generated/Models/ChatCompletionFunctions.cs | 5 ++--- ...atCompletionMessageToolCall.Serialization.cs | 5 ++--- .../Models/ChatCompletionMessageToolCall.cs | 5 ++--- ...tionMessageToolCallFunction.Serialization.cs | 5 ++--- .../ChatCompletionMessageToolCallFunction.cs | 5 ++--- .../Models/ChatCompletionMessageToolCallType.cs | 5 ++--- ...atCompletionNamedToolChoice.Serialization.cs | 3 +-- .../Models/ChatCompletionNamedToolChoice.cs | 3 +-- ...tionNamedToolChoiceFunction.Serialization.cs | 3 +-- .../ChatCompletionNamedToolChoiceFunction.cs | 3 +-- .../Models/ChatCompletionNamedToolChoiceType.cs | 3 +-- ...atCompletionResponseMessage.Serialization.cs | 5 ++--- .../Models/ChatCompletionResponseMessage.cs | 5 ++--- ...ResponseMessageFunctionCall.Serialization.cs | 5 ++--- ...ChatCompletionResponseMessageFunctionCall.cs | 5 ++--- .../Models/ChatCompletionResponseMessageRole.cs | 5 ++--- .../ChatCompletionTokenLogprob.Serialization.cs | 5 ++--- .../Models/ChatCompletionTokenLogprob.cs | 5 ++--- ...etionTokenLogprobTopLogprob.Serialization.cs | 5 ++--- .../ChatCompletionTokenLogprobTopLogprob.cs | 5 ++--- .../Models/ChatCompletionTool.Serialization.cs | 5 ++--- .../src/Generated/Models/ChatCompletionTool.cs | 5 ++--- .../Generated/Models/ChatCompletionToolType.cs | 5 ++--- .../Models/CompletionUsage.Serialization.cs | 5 ++--- .dotnet/src/Generated/Models/CompletionUsage.cs | 5 ++--- .../CreateAssistantFileRequest.Serialization.cs | 5 ++--- .../Models/CreateAssistantFileRequest.cs | 5 ++--- .../CreateAssistantRequest.Serialization.cs | 5 ++--- .../Generated/Models/CreateAssistantRequest.cs | 5 ++--- ...CreateChatCompletionRequest.Serialization.cs | 5 ++--- .../Models/CreateChatCompletionRequest.cs | 5 ++--- .../Models/CreateChatCompletionRequestModel.cs | 5 ++--- ...letionRequestResponseFormat.Serialization.cs | 5 ++--- ...CreateChatCompletionRequestResponseFormat.cs | 5 ++--- ...teChatCompletionRequestResponseFormatType.cs | 5 ++--- ...reateChatCompletionResponse.Serialization.cs | 5 ++--- .../Models/CreateChatCompletionResponse.cs | 5 ++--- ...hatCompletionResponseChoice.Serialization.cs | 5 ++--- .../CreateChatCompletionResponseChoice.cs | 5 ++--- ...eChatCompletionResponseChoiceFinishReason.cs | 5 ++--- ...etionResponseChoiceLogprobs.Serialization.cs | 5 ++--- ...reateChatCompletionResponseChoiceLogprobs.cs | 5 ++--- .../CreateChatCompletionResponseObject.cs | 5 ++--- .../CreateCompletionRequest.Serialization.cs | 5 ++--- .../Generated/Models/CreateCompletionRequest.cs | 5 ++--- .../Models/CreateCompletionRequestModel.cs | 5 ++--- .../CreateCompletionResponse.Serialization.cs | 5 ++--- .../Models/CreateCompletionResponse.cs | 5 ++--- ...ateCompletionResponseChoice.Serialization.cs | 5 ++--- .../Models/CreateCompletionResponseChoice.cs | 5 ++--- ...reateCompletionResponseChoiceFinishReason.cs | 5 ++--- ...etionResponseChoiceLogprobs.Serialization.cs | 5 ++--- .../CreateCompletionResponseChoiceLogprobs.cs | 5 ++--- .../Models/CreateCompletionResponseObject.cs | 5 ++--- .../CreateEmbeddingRequest.Serialization.cs | 5 ++--- .../Generated/Models/CreateEmbeddingRequest.cs | 5 ++--- .../CreateEmbeddingRequestEncodingFormat.cs | 5 ++--- .../Models/CreateEmbeddingRequestModel.cs | 5 ++--- .../CreateEmbeddingResponse.Serialization.cs | 5 ++--- .../Generated/Models/CreateEmbeddingResponse.cs | 5 ++--- .../Models/CreateEmbeddingResponseObject.cs | 5 ++--- .../Models/CreateFileRequest.Serialization.cs | 5 ++--- .../src/Generated/Models/CreateFileRequest.cs | 5 ++--- .../Models/CreateFileRequestPurpose.cs | 5 ++--- .../CreateFineTuningJobRequest.Serialization.cs | 5 ++--- .../Models/CreateFineTuningJobRequest.cs | 5 ++--- ...ngJobRequestHyperparameters.Serialization.cs | 5 ++--- ...CreateFineTuningJobRequestHyperparameters.cs | 5 ++--- .../Models/CreateFineTuningJobRequestModel.cs | 5 ++--- .../CreateImageEditRequest.Serialization.cs | 5 ++--- .../Generated/Models/CreateImageEditRequest.cs | 5 ++--- .../Models/CreateImageEditRequestModel.cs | 5 ++--- .../CreateImageEditRequestResponseFormat.cs | 5 ++--- .../Models/CreateImageEditRequestSize.cs | 5 ++--- .../Models/CreateImageRequest.Serialization.cs | 5 ++--- .../src/Generated/Models/CreateImageRequest.cs | 5 ++--- .../Generated/Models/CreateImageRequestModel.cs | 5 ++--- .../Models/CreateImageRequestQuality.cs | 5 ++--- .../Models/CreateImageRequestResponseFormat.cs | 5 ++--- .../Generated/Models/CreateImageRequestSize.cs | 5 ++--- .../Generated/Models/CreateImageRequestStyle.cs | 5 ++--- ...CreateImageVariationRequest.Serialization.cs | 5 ++--- .../Models/CreateImageVariationRequest.cs | 5 ++--- .../Models/CreateImageVariationRequestModel.cs | 5 ++--- ...CreateImageVariationRequestResponseFormat.cs | 5 ++--- .../Models/CreateImageVariationRequestSize.cs | 5 ++--- .../CreateMessageRequest.Serialization.cs | 5 ++--- .../Generated/Models/CreateMessageRequest.cs | 5 ++--- .../Models/CreateMessageRequestRole.cs | 5 ++--- .../CreateModerationRequest.Serialization.cs | 5 ++--- .../Generated/Models/CreateModerationRequest.cs | 5 ++--- .../Models/CreateModerationRequestModel.cs | 5 ++--- .../CreateModerationResponse.Serialization.cs | 5 ++--- .../Models/CreateModerationResponse.cs | 5 ++--- ...ateModerationResponseResult.Serialization.cs | 5 ++--- .../Models/CreateModerationResponseResult.cs | 5 ++--- ...ionResponseResultCategories.Serialization.cs | 5 ++--- .../CreateModerationResponseResultCategories.cs | 5 ++--- ...esponseResultCategoryScores.Serialization.cs | 5 ++--- ...ateModerationResponseResultCategoryScores.cs | 5 ++--- .../Models/CreateRunRequest.Serialization.cs | 5 ++--- .../src/Generated/Models/CreateRunRequest.cs | 5 ++--- .../Models/CreateSpeechRequest.Serialization.cs | 5 ++--- .../src/Generated/Models/CreateSpeechRequest.cs | 5 ++--- .../Models/CreateSpeechRequestModel.cs | 5 ++--- .../Models/CreateSpeechRequestResponseFormat.cs | 5 ++--- .../Models/CreateSpeechRequestVoice.cs | 5 ++--- .../CreateThreadAndRunRequest.Serialization.cs | 5 ++--- .../Models/CreateThreadAndRunRequest.cs | 5 ++--- .../Models/CreateThreadRequest.Serialization.cs | 5 ++--- .../src/Generated/Models/CreateThreadRequest.cs | 5 ++--- .../CreateTranscriptionRequest.Serialization.cs | 5 ++--- .../Models/CreateTranscriptionRequest.cs | 5 ++--- .../Models/CreateTranscriptionRequestModel.cs | 5 ++--- .../CreateTranscriptionRequestResponseFormat.cs | 5 ++--- ...CreateTranscriptionResponse.Serialization.cs | 5 ++--- .../Models/CreateTranscriptionResponse.cs | 5 ++--- .../Models/CreateTranscriptionResponseTask.cs | 5 ++--- .../CreateTranslationRequest.Serialization.cs | 5 ++--- .../Models/CreateTranslationRequest.cs | 5 ++--- .../Models/CreateTranslationRequestModel.cs | 5 ++--- .../CreateTranslationRequestResponseFormat.cs | 5 ++--- .../CreateTranslationResponse.Serialization.cs | 5 ++--- .../Models/CreateTranslationResponse.cs | 5 ++--- .../Models/CreateTranslationResponseTask.cs | 5 ++--- ...DeleteAssistantFileResponse.Serialization.cs | 5 ++--- .../Models/DeleteAssistantFileResponse.cs | 5 ++--- .../Models/DeleteAssistantFileResponseObject.cs | 5 ++--- .../DeleteAssistantResponse.Serialization.cs | 5 ++--- .../Generated/Models/DeleteAssistantResponse.cs | 5 ++--- .../Models/DeleteAssistantResponseObject.cs | 5 ++--- .../Models/DeleteFileResponse.Serialization.cs | 5 ++--- .../src/Generated/Models/DeleteFileResponse.cs | 5 ++--- .../Models/DeleteFileResponseObject.cs | 5 ++--- .../Models/DeleteModelResponse.Serialization.cs | 5 ++--- .../src/Generated/Models/DeleteModelResponse.cs | 5 ++--- .../Models/DeleteModelResponseObject.cs | 5 ++--- .../DeleteThreadResponse.Serialization.cs | 5 ++--- .../Generated/Models/DeleteThreadResponse.cs | 5 ++--- .../Models/DeleteThreadResponseObject.cs | 5 ++--- .../Generated/Models/Embedding.Serialization.cs | 5 ++--- .dotnet/src/Generated/Models/Embedding.cs | 5 ++--- .dotnet/src/Generated/Models/EmbeddingObject.cs | 5 ++--- .../Models/EmbeddingUsage.Serialization.cs | 5 ++--- .dotnet/src/Generated/Models/EmbeddingUsage.cs | 5 ++--- .../Models/FineTuningJob.Serialization.cs | 5 ++--- .dotnet/src/Generated/Models/FineTuningJob.cs | 5 ++--- .../Models/FineTuningJobError.Serialization.cs | 5 ++--- .../src/Generated/Models/FineTuningJobError.cs | 5 ++--- .../Models/FineTuningJobEvent.Serialization.cs | 5 ++--- .../src/Generated/Models/FineTuningJobEvent.cs | 5 ++--- .../Generated/Models/FineTuningJobEventLevel.cs | 5 ++--- ...ineTuningJobHyperparameters.Serialization.cs | 5 ++--- .../Models/FineTuningJobHyperparameters.cs | 5 ++--- .../src/Generated/Models/FineTuningJobObject.cs | 5 ++--- .../src/Generated/Models/FineTuningJobStatus.cs | 5 ++--- .../Models/FunctionObject.Serialization.cs | 5 ++--- .dotnet/src/Generated/Models/FunctionObject.cs | 5 ++--- .../Models/FunctionParameters.Serialization.cs | 5 ++--- .../src/Generated/Models/FunctionParameters.cs | 5 ++--- .../src/Generated/Models/Image.Serialization.cs | 5 ++--- .dotnet/src/Generated/Models/Image.cs | 5 ++--- .../Models/ImagesResponse.Serialization.cs | 5 ++--- .dotnet/src/Generated/Models/ImagesResponse.cs | 5 ++--- .../ListAssistantFilesResponse.Serialization.cs | 5 ++--- .../Models/ListAssistantFilesResponse.cs | 5 ++--- .../Models/ListAssistantFilesResponseObject.cs | 5 ++--- .../ListAssistantsResponse.Serialization.cs | 5 ++--- .../Generated/Models/ListAssistantsResponse.cs | 5 ++--- .../Models/ListAssistantsResponseObject.cs | 5 ++--- .../Models/ListFilesResponse.Serialization.cs | 5 ++--- .../src/Generated/Models/ListFilesResponse.cs | 5 ++--- .../Generated/Models/ListFilesResponseObject.cs | 5 ++--- ...FineTuningJobEventsResponse.Serialization.cs | 5 ++--- .../Models/ListFineTuningJobEventsResponse.cs | 5 ++--- .../ListMessageFilesResponse.Serialization.cs | 5 ++--- .../Models/ListMessageFilesResponse.cs | 5 ++--- .../Models/ListMessageFilesResponseObject.cs | 5 ++--- .../ListMessagesResponse.Serialization.cs | 5 ++--- .../Generated/Models/ListMessagesResponse.cs | 5 ++--- .../Models/ListMessagesResponseObject.cs | 5 ++--- .../Models/ListModelsResponse.Serialization.cs | 5 ++--- .../src/Generated/Models/ListModelsResponse.cs | 5 ++--- .../Models/ListModelsResponseObject.cs | 5 ++--- .dotnet/src/Generated/Models/ListOrder.cs | 5 ++--- ...natedFineTuningJobsResponse.Serialization.cs | 5 ++--- .../ListPaginatedFineTuningJobsResponse.cs | 5 ++--- .../ListRunStepsResponse.Serialization.cs | 5 ++--- .../Generated/Models/ListRunStepsResponse.cs | 5 ++--- .../Models/ListRunStepsResponseObject.cs | 5 ++--- .../Models/ListRunsResponse.Serialization.cs | 5 ++--- .../src/Generated/Models/ListRunsResponse.cs | 5 ++--- .../Generated/Models/ListRunsResponseObject.cs | 5 ++--- .../Models/MessageFileObject.Serialization.cs | 5 ++--- .../src/Generated/Models/MessageFileObject.cs | 5 ++--- .../Generated/Models/MessageFileObjectObject.cs | 5 ++--- .../Models/MessageObject.Serialization.cs | 5 ++--- .dotnet/src/Generated/Models/MessageObject.cs | 5 ++--- .../src/Generated/Models/MessageObjectObject.cs | 5 ++--- .../src/Generated/Models/MessageObjectRole.cs | 5 ++--- .../src/Generated/Models/Model.Serialization.cs | 5 ++--- .dotnet/src/Generated/Models/Model.cs | 5 ++--- .dotnet/src/Generated/Models/ModelObject.cs | 5 ++--- .../ModifyAssistantRequest.Serialization.cs | 5 ++--- .../Generated/Models/ModifyAssistantRequest.cs | 5 ++--- .../ModifyMessageRequest.Serialization.cs | 5 ++--- .../Generated/Models/ModifyMessageRequest.cs | 5 ++--- .../Models/ModifyRunRequest.Serialization.cs | 5 ++--- .../src/Generated/Models/ModifyRunRequest.cs | 5 ++--- .../Models/ModifyThreadRequest.Serialization.cs | 5 ++--- .../src/Generated/Models/ModifyThreadRequest.cs | 5 ++--- .../Models/OpenAIFile.Serialization.cs | 5 ++--- .dotnet/src/Generated/Models/OpenAIFile.cs | 5 ++--- .../src/Generated/Models/OpenAIFileObject.cs | 5 ++--- .../src/Generated/Models/OpenAIFilePurpose.cs | 5 ++--- .../src/Generated/Models/OpenAIFileStatus.cs | 5 ++--- .../Models/RunCompletionUsage.Serialization.cs | 5 ++--- .../src/Generated/Models/RunCompletionUsage.cs | 5 ++--- .../Generated/Models/RunObject.Serialization.cs | 5 ++--- .dotnet/src/Generated/Models/RunObject.cs | 5 ++--- .../Models/RunObjectLastError.Serialization.cs | 5 ++--- .../src/Generated/Models/RunObjectLastError.cs | 5 ++--- .../Generated/Models/RunObjectLastErrorCode.cs | 5 ++--- .dotnet/src/Generated/Models/RunObjectObject.cs | 5 ++--- .../RunObjectRequiredAction.Serialization.cs | 5 ++--- .../Generated/Models/RunObjectRequiredAction.cs | 5 ++--- ...iredActionSubmitToolOutputs.Serialization.cs | 5 ++--- .../RunObjectRequiredActionSubmitToolOutputs.cs | 5 ++--- .../Models/RunObjectRequiredActionType.cs | 5 ++--- .dotnet/src/Generated/Models/RunObjectStatus.cs | 5 ++--- ...etailsMessageCreationObject.Serialization.cs | 3 +-- .../RunStepDetailsMessageCreationObject.cs | 3 +-- ...eationObjectMessageCreation.Serialization.cs | 3 +-- ...tailsMessageCreationObjectMessageCreation.cs | 3 +-- .../RunStepDetailsMessageCreationObjectType.cs | 3 +-- ...nStepDetailsToolCallsObject.Serialization.cs | 3 +-- .../Models/RunStepDetailsToolCallsObject.cs | 3 +-- .../Models/RunStepDetailsToolCallsObjectType.cs | 3 +-- .../Models/RunStepObject.Serialization.cs | 5 ++--- .dotnet/src/Generated/Models/RunStepObject.cs | 5 ++--- .../RunStepObjectLastError.Serialization.cs | 5 ++--- .../Generated/Models/RunStepObjectLastError.cs | 5 ++--- .../Models/RunStepObjectLastErrorCode.cs | 5 ++--- .../src/Generated/Models/RunStepObjectObject.cs | 5 ++--- .../src/Generated/Models/RunStepObjectStatus.cs | 5 ++--- .../src/Generated/Models/RunStepObjectType.cs | 5 ++--- .../Models/RunToolCallObject.Serialization.cs | 5 ++--- .../src/Generated/Models/RunToolCallObject.cs | 5 ++--- .../RunToolCallObjectFunction.Serialization.cs | 5 ++--- .../Models/RunToolCallObjectFunction.cs | 5 ++--- .../Generated/Models/RunToolCallObjectType.cs | 5 ++--- ...SubmitToolOutputsRunRequest.Serialization.cs | 5 ++--- .../Models/SubmitToolOutputsRunRequest.cs | 5 ++--- ...OutputsRunRequestToolOutput.Serialization.cs | 5 ++--- .../SubmitToolOutputsRunRequestToolOutput.cs | 5 ++--- .../Models/ThreadObject.Serialization.cs | 5 ++--- .dotnet/src/Generated/Models/ThreadObject.cs | 5 ++--- .../src/Generated/Models/ThreadObjectObject.cs | 5 ++--- .dotnet/src/Generated/ModelsOps.cs | 7 +++---- .dotnet/src/Generated/Moderations.cs | 7 +++---- .dotnet/src/Generated/OpenAIClient.cs | 5 ++--- .dotnet/src/Generated/OpenAIClientOptions.cs | 5 ++--- .dotnet/src/Generated/OpenAIModelFactory.cs | 5 ++--- .dotnet/src/Generated/Runs.cs | 7 +++---- .dotnet/src/Generated/Threads.cs | 7 +++---- .../tests/Generated/Tests/AssistantsTests.cs | 1 - .dotnet/tests/Generated/Tests/AudioTests.cs | 1 - .dotnet/tests/Generated/Tests/ChatTests.cs | 1 - .../tests/Generated/Tests/CompletionsTests.cs | 1 - .../tests/Generated/Tests/EmbeddingsTests.cs | 1 - .dotnet/tests/Generated/Tests/FilesTests.cs | 1 - .../tests/Generated/Tests/FineTuningTests.cs | 1 - .dotnet/tests/Generated/Tests/ImagesTests.cs | 1 - .dotnet/tests/Generated/Tests/MessagesTests.cs | 1 - .dotnet/tests/Generated/Tests/ModelsOpsTests.cs | 1 - .../tests/Generated/Tests/ModerationsTests.cs | 1 - .dotnet/tests/Generated/Tests/RunsTests.cs | 1 - .dotnet/tests/Generated/Tests/ThreadsTests.cs | 1 - 300 files changed, 590 insertions(+), 871 deletions(-) create mode 100644 .dotnet/scripts/ConvertTo-Internal.ps1 diff --git a/.dotnet/scripts/ConvertTo-Internal.ps1 b/.dotnet/scripts/ConvertTo-Internal.ps1 new file mode 100644 index 000000000..ec809e075 --- /dev/null +++ b/.dotnet/scripts/ConvertTo-Internal.ps1 @@ -0,0 +1,17 @@ +$root = Split-Path $PSScriptRoot -Parent +$directory = Join-Path -Path $root -ChildPath "src\Generated" +$files = Get-ChildItem -Path $($directory + "\*") -Include "*.cs" -Recurse + +foreach ($file in $files) { + $content = Get-Content -Path $file -Raw + + Write-Output "Editing $($file.FullName)" + + $content = $content -creplace "public partial class", "internal partial class" + $content = $content -creplace "public readonly partial struct", "internal readonly partial struct" + $content = $content -creplace "public static partial class", "internal static partial class" + $content = $content -creplace "namespace OpenAI", "namespace OpenAI.Internal" + $content = $content -creplace "using OpenAI.Models;", "using OpenAI.Internal.Models;" + + $content | Set-Content -Path $file.FullName -NoNewline +} \ No newline at end of file diff --git a/.dotnet/scripts/Update-ClientModel.ps1 b/.dotnet/scripts/Update-ClientModel.ps1 index 13b8beb80..9cab3caf9 100644 --- a/.dotnet/scripts/Update-ClientModel.ps1 +++ b/.dotnet/scripts/Update-ClientModel.ps1 @@ -39,7 +39,7 @@ function Update-OpenAIClient { $content = $content -creplace "_pipeline = MessagePipeline\.Create\(options, new IPipelinePolicy\[\] \{ new KeyCredentialPolicy\(_keyCredential, AuthorizationHeader, AuthorizationApiKeyPrefix\) \}, Array\.Empty>\(\)\);", "var authenticationPolicy = ApiKeyAuthenticationPolicy.CreateBearerAuthorizationPolicy(_credential);`r`n _pipeline = ClientPipeline.Create(options,`r`n perCallPolicies: ReadOnlySpan.Empty,`r`n perTryPolicies: new PipelinePolicy[] { authenticationPolicy },`r`n beforeTransportPolicies: ReadOnlySpan.Empty);" $content = $content -creplace "\(ClientDiagnostics, ", "(" - $content | Set-Content -Path $file.FullName + $content | Set-Content -Path $file.FullName -NoNewline } function Update-OpenAIClientOptions { @@ -54,7 +54,7 @@ function Update-OpenAIClientOptions { $content = $content -creplace "using System\.ClientModel;", "using System.ClientModel.Primitives;" $content = $content -creplace ": RequestOptions", ": ClientPipelineOptions" - $content | Set-Content -Path $file.FullName + $content | Set-Content -Path $file.FullName -NoNewline } function Update-Subclients { @@ -155,7 +155,7 @@ function Update-Subclients { $content = $content -creplace "private static ResponseErrorClassifier _responseErrorClassifier200;", "private static PipelineMessageClassifier _responseErrorClassifier200;" $content = $content -creplace "private static ResponseErrorClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 \?\?= new StatusResponseClassifier\(stackalloc ushort\[\] \{ 200 \}\);", "private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 });" - $content | Set-Content -Path $file.FullName + $content | Set-Content -Path $file.FullName -NoNewline } } @@ -176,7 +176,7 @@ function Update-Models { $content = $content -creplace "\s+void IUtf8JsonWriteable\.Write\(Utf8JsonWriter writer\) => \(\(IJsonModel<(\w+)>\)this\)\.Write\(writer, new ModelReaderWriterOptions\(`"W`"\)\);`r`n", "" $content = $content -creplace "(?s)\s+\/\/\/ Convert into a Utf8JsonRequestBody\. .*?return content;.*?\}", "" - $content | Set-Content -Path $file.FullName + $content | Set-Content -Path $file.FullName -NoNewline } } @@ -192,7 +192,7 @@ function Update-Tests { $content = $content -creplace " KeyCredential", " ApiKeyCredential" - $content | Set-Content -Path $file.FullName + $content | Set-Content -Path $file.FullName -NoNewline } } diff --git a/.dotnet/src/Generated/Assistants.cs b/.dotnet/src/Generated/Assistants.cs index e725cfe7e..8ccb9e55f 100644 --- a/.dotnet/src/Generated/Assistants.cs +++ b/.dotnet/src/Generated/Assistants.cs @@ -6,13 +6,13 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -using OpenAI.Models; +using OpenAI.Internal.Models; -namespace OpenAI +namespace OpenAI.Internal { // Data plane generated sub-client. /// The Assistants sub-client. - public partial class Assistants + internal partial class Assistants { private const string AuthorizationHeader = "Authorization"; private readonly ApiKeyCredential _credential; @@ -1376,4 +1376,3 @@ internal PipelineMessage CreateDeleteAssistantFileRequest(string assistantId, st private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } } - diff --git a/.dotnet/src/Generated/Audio.cs b/.dotnet/src/Generated/Audio.cs index 963cfc0f2..9065e02c7 100644 --- a/.dotnet/src/Generated/Audio.cs +++ b/.dotnet/src/Generated/Audio.cs @@ -6,13 +6,13 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -using OpenAI.Models; +using OpenAI.Internal.Models; -namespace OpenAI +namespace OpenAI.Internal { // Data plane generated sub-client. /// The Audio sub-client. - public partial class Audio + internal partial class Audio { private const string AuthorizationHeader = "Authorization"; private readonly ApiKeyCredential _credential; @@ -387,4 +387,3 @@ internal PipelineMessage CreateCreateTranslationRequest(BinaryContent content, R private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } } - diff --git a/.dotnet/src/Generated/Chat.cs b/.dotnet/src/Generated/Chat.cs index bb3bb2cc3..69528f3d3 100644 --- a/.dotnet/src/Generated/Chat.cs +++ b/.dotnet/src/Generated/Chat.cs @@ -6,13 +6,13 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -using OpenAI.Models; +using OpenAI.Internal.Models; -namespace OpenAI +namespace OpenAI.Internal { // Data plane generated sub-client. /// The Chat sub-client. - public partial class Chat + internal partial class Chat { private const string AuthorizationHeader = "Authorization"; private readonly ApiKeyCredential _credential; @@ -159,4 +159,3 @@ internal PipelineMessage CreateCreateChatCompletionRequest(BinaryContent content private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } } - diff --git a/.dotnet/src/Generated/Completions.cs b/.dotnet/src/Generated/Completions.cs index f55f7c729..d43e6be89 100644 --- a/.dotnet/src/Generated/Completions.cs +++ b/.dotnet/src/Generated/Completions.cs @@ -6,13 +6,13 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -using OpenAI.Models; +using OpenAI.Internal.Models; -namespace OpenAI +namespace OpenAI.Internal { // Data plane generated sub-client. /// The Completions sub-client. - public partial class Completions + internal partial class Completions { private const string AuthorizationHeader = "Authorization"; private readonly ApiKeyCredential _credential; @@ -159,4 +159,3 @@ internal PipelineMessage CreateCreateCompletionRequest(BinaryContent content, Re private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } } - diff --git a/.dotnet/src/Generated/Embeddings.cs b/.dotnet/src/Generated/Embeddings.cs index 8056ebd08..eb53ff05a 100644 --- a/.dotnet/src/Generated/Embeddings.cs +++ b/.dotnet/src/Generated/Embeddings.cs @@ -6,13 +6,13 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -using OpenAI.Models; +using OpenAI.Internal.Models; -namespace OpenAI +namespace OpenAI.Internal { // Data plane generated sub-client. /// The Embeddings sub-client. - public partial class Embeddings + internal partial class Embeddings { private const string AuthorizationHeader = "Authorization"; private readonly ApiKeyCredential _credential; @@ -159,4 +159,3 @@ internal PipelineMessage CreateCreateEmbeddingRequest(BinaryContent content, Req private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } } - diff --git a/.dotnet/src/Generated/Files.cs b/.dotnet/src/Generated/Files.cs index 815ae85ce..acbd43209 100644 --- a/.dotnet/src/Generated/Files.cs +++ b/.dotnet/src/Generated/Files.cs @@ -6,13 +6,13 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -using OpenAI.Models; +using OpenAI.Internal.Models; -namespace OpenAI +namespace OpenAI.Internal { // Data plane generated sub-client. /// The Files sub-client. - public partial class Files + internal partial class Files { private const string AuthorizationHeader = "Authorization"; private readonly ApiKeyCredential _credential; @@ -656,4 +656,3 @@ internal PipelineMessage CreateDownloadFileRequest(string fileId, RequestOptions private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } } - diff --git a/.dotnet/src/Generated/FineTuning.cs b/.dotnet/src/Generated/FineTuning.cs index 827f7f18f..f8c408c7d 100644 --- a/.dotnet/src/Generated/FineTuning.cs +++ b/.dotnet/src/Generated/FineTuning.cs @@ -6,13 +6,13 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -using OpenAI.Models; +using OpenAI.Internal.Models; -namespace OpenAI +namespace OpenAI.Internal { // Data plane generated sub-client. /// The FineTuning sub-client. - public partial class FineTuning + internal partial class FineTuning { private const string AuthorizationHeader = "Authorization"; private readonly ApiKeyCredential _credential; @@ -702,4 +702,3 @@ internal PipelineMessage CreateGetFineTuningEventsRequest(string fineTuningJobId private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } } - diff --git a/.dotnet/src/Generated/Images.cs b/.dotnet/src/Generated/Images.cs index fb99a3319..e5d910962 100644 --- a/.dotnet/src/Generated/Images.cs +++ b/.dotnet/src/Generated/Images.cs @@ -6,13 +6,13 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -using OpenAI.Models; +using OpenAI.Internal.Models; -namespace OpenAI +namespace OpenAI.Internal { // Data plane generated sub-client. /// The Images sub-client. - public partial class Images + internal partial class Images { private const string AuthorizationHeader = "Authorization"; private readonly ApiKeyCredential _credential; @@ -387,4 +387,3 @@ internal PipelineMessage CreateCreateImageVariationRequest(BinaryContent content private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } } - diff --git a/.dotnet/src/Generated/Messages.cs b/.dotnet/src/Generated/Messages.cs index f3abd4bad..32579b8bd 100644 --- a/.dotnet/src/Generated/Messages.cs +++ b/.dotnet/src/Generated/Messages.cs @@ -6,13 +6,13 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -using OpenAI.Models; +using OpenAI.Internal.Models; -namespace OpenAI +namespace OpenAI.Internal { // Data plane generated sub-client. /// The Messages sub-client. - public partial class Messages + internal partial class Messages { private const string AuthorizationHeader = "Authorization"; private readonly ApiKeyCredential _credential; @@ -1084,4 +1084,3 @@ internal PipelineMessage CreateGetMessageFileRequest(string threadId, string mes private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } } - diff --git a/.dotnet/src/Generated/Models/AssistantFileObject.Serialization.cs b/.dotnet/src/Generated/Models/AssistantFileObject.Serialization.cs index c2b95887f..eebbf2b6f 100644 --- a/.dotnet/src/Generated/Models/AssistantFileObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/AssistantFileObject.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class AssistantFileObject : IJsonModel + internal partial class AssistantFileObject : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -142,4 +142,3 @@ internal static AssistantFileObject FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/AssistantFileObject.cs b/.dotnet/src/Generated/Models/AssistantFileObject.cs index ee5c47c27..bb30fc168 100644 --- a/.dotnet/src/Generated/Models/AssistantFileObject.cs +++ b/.dotnet/src/Generated/Models/AssistantFileObject.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// A list of [Files](/docs/api-reference/files) attached to an `assistant`. - public partial class AssistantFileObject + internal partial class AssistantFileObject { /// /// Keeps track of any properties unknown to the library. @@ -87,4 +87,3 @@ internal AssistantFileObject() public string AssistantId { get; } } } - diff --git a/.dotnet/src/Generated/Models/AssistantFileObjectObject.cs b/.dotnet/src/Generated/Models/AssistantFileObjectObject.cs index 7883e84f3..08816d6a5 100644 --- a/.dotnet/src/Generated/Models/AssistantFileObjectObject.cs +++ b/.dotnet/src/Generated/Models/AssistantFileObjectObject.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The AssistantFileObject_object. - public readonly partial struct AssistantFileObjectObject : IEquatable + internal readonly partial struct AssistantFileObjectObject : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public AssistantFileObjectObject(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/AssistantObject.Serialization.cs b/.dotnet/src/Generated/Models/AssistantObject.Serialization.cs index c4e51bcf9..962670141 100644 --- a/.dotnet/src/Generated/Models/AssistantObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/AssistantObject.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class AssistantObject : IJsonModel + internal partial class AssistantObject : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -288,4 +288,3 @@ internal static AssistantObject FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/AssistantObject.cs b/.dotnet/src/Generated/Models/AssistantObject.cs index 3b6d4b131..d3b5e5e20 100644 --- a/.dotnet/src/Generated/Models/AssistantObject.cs +++ b/.dotnet/src/Generated/Models/AssistantObject.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Represents an `assistant` that can call the model and use tools. - public partial class AssistantObject + internal partial class AssistantObject { /// /// Keeps track of any properties unknown to the library. @@ -198,4 +198,3 @@ internal AssistantObject() public IReadOnlyDictionary Metadata { get; } } } - diff --git a/.dotnet/src/Generated/Models/AssistantObjectObject.cs b/.dotnet/src/Generated/Models/AssistantObjectObject.cs index f7a7cb21d..64e27426c 100644 --- a/.dotnet/src/Generated/Models/AssistantObjectObject.cs +++ b/.dotnet/src/Generated/Models/AssistantObjectObject.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The AssistantObject_object. - public readonly partial struct AssistantObjectObject : IEquatable + internal readonly partial struct AssistantObjectObject : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public AssistantObjectObject(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/AudioSegment.Serialization.cs b/.dotnet/src/Generated/Models/AudioSegment.Serialization.cs index 5b4ef9b7a..e1641e3c0 100644 --- a/.dotnet/src/Generated/Models/AudioSegment.Serialization.cs +++ b/.dotnet/src/Generated/Models/AudioSegment.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class AudioSegment : IJsonModel + internal partial class AudioSegment : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -200,4 +200,3 @@ internal static AudioSegment FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/AudioSegment.cs b/.dotnet/src/Generated/Models/AudioSegment.cs index f25b206ff..0ee02b78b 100644 --- a/.dotnet/src/Generated/Models/AudioSegment.cs +++ b/.dotnet/src/Generated/Models/AudioSegment.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The AudioSegment. - public partial class AudioSegment + internal partial class AudioSegment { /// /// Keeps track of any properties unknown to the library. @@ -143,4 +143,3 @@ internal AudioSegment() public double NoSpeechProb { get; } } } - diff --git a/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.Serialization.cs index d82b8d8e5..639a83a94 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.Serialization.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { internal partial class ChatCompletionFunctionCallOption : IJsonModel { @@ -118,4 +118,3 @@ internal static ChatCompletionFunctionCallOption FromResponse(PipelineResponse r } } } - diff --git a/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.cs b/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.cs index 40c76aacd..148eb7588 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.cs @@ -4,7 +4,7 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// /// Specifying a particular function via `{"name": "my_function"}` forces the model to call that @@ -72,4 +72,3 @@ internal ChatCompletionFunctionCallOption() public string Name { get; } } } - diff --git a/.dotnet/src/Generated/Models/ChatCompletionFunctions.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionFunctions.Serialization.cs index 5558f49c3..af8f82426 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionFunctions.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionFunctions.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class ChatCompletionFunctions : IJsonModel + internal partial class ChatCompletionFunctions : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -144,4 +144,3 @@ internal static ChatCompletionFunctions FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/ChatCompletionFunctions.cs b/.dotnet/src/Generated/Models/ChatCompletionFunctions.cs index 7055cc173..a8f409a52 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionFunctions.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionFunctions.cs @@ -4,11 +4,11 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ChatCompletionFunctions. [Obsolete("deprecated")] - public partial class ChatCompletionFunctions + internal partial class ChatCompletionFunctions { /// /// Keeps track of any properties unknown to the library. @@ -93,4 +93,3 @@ internal ChatCompletionFunctions() public FunctionParameters Parameters { get; set; } } } - diff --git a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.Serialization.cs index 4806e429e..71b3260cc 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class ChatCompletionMessageToolCall : IJsonModel + internal partial class ChatCompletionMessageToolCall : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -134,4 +134,3 @@ internal static ChatCompletionMessageToolCall FromResponse(PipelineResponse resp } } } - diff --git a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.cs b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.cs index 1d5bbc882..dc5ffd9d0 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ChatCompletionMessageToolCall. - public partial class ChatCompletionMessageToolCall + internal partial class ChatCompletionMessageToolCall { /// /// Keeps track of any properties unknown to the library. @@ -81,4 +81,3 @@ internal ChatCompletionMessageToolCall() public ChatCompletionMessageToolCallFunction Function { get; set; } } } - diff --git a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.Serialization.cs index 57c8334c1..e9a8bf6c1 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class ChatCompletionMessageToolCallFunction : IJsonModel + internal partial class ChatCompletionMessageToolCallFunction : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -126,4 +126,3 @@ internal static ChatCompletionMessageToolCallFunction FromResponse(PipelineRespo } } } - diff --git a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.cs b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.cs index 892e74010..fa5776ea0 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ChatCompletionMessageToolCallFunction. - public partial class ChatCompletionMessageToolCallFunction + internal partial class ChatCompletionMessageToolCallFunction { /// /// Keeps track of any properties unknown to the library. @@ -88,4 +88,3 @@ internal ChatCompletionMessageToolCallFunction() public string Arguments { get; set; } } } - diff --git a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallType.cs b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallType.cs index bdf80b599..3da609cee 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallType.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallType.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ChatCompletionMessageToolCall_type. - public readonly partial struct ChatCompletionMessageToolCallType : IEquatable + internal readonly partial struct ChatCompletionMessageToolCallType : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public ChatCompletionMessageToolCallType(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.Serialization.cs index a5cb5af93..d4a77ea78 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.Serialization.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { internal partial class ChatCompletionNamedToolChoice : IJsonModel { @@ -126,4 +126,3 @@ internal static ChatCompletionNamedToolChoice FromResponse(PipelineResponse resp } } } - diff --git a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.cs b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.cs index 63c912acc..149097e23 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.cs @@ -4,7 +4,7 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Specifies a tool the model should use. Use to force the model to call a specific function. internal partial class ChatCompletionNamedToolChoice @@ -74,4 +74,3 @@ internal ChatCompletionNamedToolChoice() public ChatCompletionNamedToolChoiceFunction Function { get; } } } - diff --git a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.Serialization.cs index cb372631e..b85f015d9 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.Serialization.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { internal partial class ChatCompletionNamedToolChoiceFunction : IJsonModel { @@ -118,4 +118,3 @@ internal static ChatCompletionNamedToolChoiceFunction FromResponse(PipelineRespo } } } - diff --git a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.cs b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.cs index 44be066fd..520def419 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.cs @@ -4,7 +4,7 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ChatCompletionNamedToolChoiceFunction. internal partial class ChatCompletionNamedToolChoiceFunction @@ -69,4 +69,3 @@ internal ChatCompletionNamedToolChoiceFunction() public string Name { get; } } } - diff --git a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceType.cs b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceType.cs index 166411eac..0765fe138 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceType.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceType.cs @@ -3,7 +3,7 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ChatCompletionNamedToolChoice_type. internal readonly partial struct ChatCompletionNamedToolChoiceType : IEquatable @@ -41,4 +41,3 @@ public ChatCompletionNamedToolChoiceType(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.Serialization.cs index b819876dc..b2b4ee706 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class ChatCompletionResponseMessage : IJsonModel + internal partial class ChatCompletionResponseMessage : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -178,4 +178,3 @@ internal static ChatCompletionResponseMessage FromResponse(PipelineResponse resp } } } - diff --git a/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.cs b/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.cs index a27e26e91..27bcffd13 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ChatCompletionResponseMessage. - public partial class ChatCompletionResponseMessage + internal partial class ChatCompletionResponseMessage { /// /// Keeps track of any properties unknown to the library. @@ -80,4 +80,3 @@ internal ChatCompletionResponseMessage() public ChatCompletionResponseMessageFunctionCall FunctionCall { get; } } } - diff --git a/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.Serialization.cs index 6fd3d045a..5b55a6990 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class ChatCompletionResponseMessageFunctionCall : IJsonModel + internal partial class ChatCompletionResponseMessageFunctionCall : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -126,4 +126,3 @@ internal static ChatCompletionResponseMessageFunctionCall FromResponse(PipelineR } } } - diff --git a/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.cs b/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.cs index 8016f2af6..e788deaeb 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ChatCompletionResponseMessageFunctionCall. - public partial class ChatCompletionResponseMessageFunctionCall + internal partial class ChatCompletionResponseMessageFunctionCall { /// /// Keeps track of any properties unknown to the library. @@ -88,4 +88,3 @@ internal ChatCompletionResponseMessageFunctionCall() public string Name { get; } } } - diff --git a/.dotnet/src/Generated/Models/ChatCompletionResponseMessageRole.cs b/.dotnet/src/Generated/Models/ChatCompletionResponseMessageRole.cs index 08bcd42a2..5ff79558a 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionResponseMessageRole.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionResponseMessageRole.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ChatCompletionResponseMessage_role. - public readonly partial struct ChatCompletionResponseMessageRole : IEquatable + internal readonly partial struct ChatCompletionResponseMessageRole : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public ChatCompletionResponseMessageRole(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.Serialization.cs index b60cb9ec5..cbb9356bb 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class ChatCompletionTokenLogprob : IJsonModel + internal partial class ChatCompletionTokenLogprob : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -174,4 +174,3 @@ internal static ChatCompletionTokenLogprob FromResponse(PipelineResponse respons } } } - diff --git a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.cs b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.cs index bd303c7a2..0a7ae0ba5 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ChatCompletionTokenLogprob. - public partial class ChatCompletionTokenLogprob + internal partial class ChatCompletionTokenLogprob { /// /// Keeps track of any properties unknown to the library. @@ -113,4 +113,3 @@ internal ChatCompletionTokenLogprob() public IReadOnlyList TopLogprobs { get; } } } - diff --git a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.Serialization.cs index b71b5ace6..7f84c1bca 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class ChatCompletionTokenLogprobTopLogprob : IJsonModel + internal partial class ChatCompletionTokenLogprobTopLogprob : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -156,4 +156,3 @@ internal static ChatCompletionTokenLogprobTopLogprob FromResponse(PipelineRespon } } } - diff --git a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.cs b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.cs index 10e36b3a6..74a42012a 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ChatCompletionTokenLogprobTopLogprob. - public partial class ChatCompletionTokenLogprobTopLogprob + internal partial class ChatCompletionTokenLogprobTopLogprob { /// /// Keeps track of any properties unknown to the library. @@ -97,4 +97,3 @@ internal ChatCompletionTokenLogprobTopLogprob() public IReadOnlyList Bytes { get; } } } - diff --git a/.dotnet/src/Generated/Models/ChatCompletionTool.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionTool.Serialization.cs index b5913cfcd..cb99d68c8 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionTool.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionTool.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class ChatCompletionTool : IJsonModel + internal partial class ChatCompletionTool : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -126,4 +126,3 @@ internal static ChatCompletionTool FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/ChatCompletionTool.cs b/.dotnet/src/Generated/Models/ChatCompletionTool.cs index 28feedefd..8edef4914 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionTool.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionTool.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ChatCompletionTool. - public partial class ChatCompletionTool + internal partial class ChatCompletionTool { /// /// Keeps track of any properties unknown to the library. @@ -74,4 +74,3 @@ internal ChatCompletionTool() public FunctionObject Function { get; } } } - diff --git a/.dotnet/src/Generated/Models/ChatCompletionToolType.cs b/.dotnet/src/Generated/Models/ChatCompletionToolType.cs index b1dae6880..af31e3c02 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionToolType.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionToolType.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ChatCompletionTool_type. - public readonly partial struct ChatCompletionToolType : IEquatable + internal readonly partial struct ChatCompletionToolType : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public ChatCompletionToolType(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CompletionUsage.Serialization.cs b/.dotnet/src/Generated/Models/CompletionUsage.Serialization.cs index 5f4745e70..9d53d9f78 100644 --- a/.dotnet/src/Generated/Models/CompletionUsage.Serialization.cs +++ b/.dotnet/src/Generated/Models/CompletionUsage.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CompletionUsage : IJsonModel + internal partial class CompletionUsage : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -134,4 +134,3 @@ internal static CompletionUsage FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/CompletionUsage.cs b/.dotnet/src/Generated/Models/CompletionUsage.cs index 440f8ef74..64c5aa6ec 100644 --- a/.dotnet/src/Generated/Models/CompletionUsage.cs +++ b/.dotnet/src/Generated/Models/CompletionUsage.cs @@ -3,10 +3,10 @@ using System; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Usage statistics for the completion request. - public partial class CompletionUsage + internal partial class CompletionUsage { /// /// Keeps track of any properties unknown to the library. @@ -77,4 +77,3 @@ internal CompletionUsage() public long TotalTokens { get; } } } - diff --git a/.dotnet/src/Generated/Models/CreateAssistantFileRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateAssistantFileRequest.Serialization.cs index e4d8ef38b..e3a752244 100644 --- a/.dotnet/src/Generated/Models/CreateAssistantFileRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateAssistantFileRequest.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateAssistantFileRequest : IJsonModel + internal partial class CreateAssistantFileRequest : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -118,4 +118,3 @@ internal static CreateAssistantFileRequest FromResponse(PipelineResponse respons } } } - diff --git a/.dotnet/src/Generated/Models/CreateAssistantFileRequest.cs b/.dotnet/src/Generated/Models/CreateAssistantFileRequest.cs index 7a7c067c9..be3485d43 100644 --- a/.dotnet/src/Generated/Models/CreateAssistantFileRequest.cs +++ b/.dotnet/src/Generated/Models/CreateAssistantFileRequest.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateAssistantFileRequest. - public partial class CreateAssistantFileRequest + internal partial class CreateAssistantFileRequest { /// /// Keeps track of any properties unknown to the library. @@ -78,4 +78,3 @@ internal CreateAssistantFileRequest() public string FileId { get; } } } - diff --git a/.dotnet/src/Generated/Models/CreateAssistantRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateAssistantRequest.Serialization.cs index 6f034bc1e..6c7a3d0b8 100644 --- a/.dotnet/src/Generated/Models/CreateAssistantRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateAssistantRequest.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateAssistantRequest : IJsonModel + internal partial class CreateAssistantRequest : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -289,4 +289,3 @@ internal static CreateAssistantRequest FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/CreateAssistantRequest.cs b/.dotnet/src/Generated/Models/CreateAssistantRequest.cs index f99c14f37..6e08eb6ac 100644 --- a/.dotnet/src/Generated/Models/CreateAssistantRequest.cs +++ b/.dotnet/src/Generated/Models/CreateAssistantRequest.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateAssistantRequest. - public partial class CreateAssistantRequest + internal partial class CreateAssistantRequest { /// /// Keeps track of any properties unknown to the library. @@ -157,4 +157,3 @@ internal CreateAssistantRequest() public IDictionary Metadata { get; set; } } } - diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateChatCompletionRequest.Serialization.cs index 4310faf5b..dbd787e7b 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionRequest.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateChatCompletionRequest : IJsonModel + internal partial class CreateChatCompletionRequest : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -568,4 +568,3 @@ internal static CreateChatCompletionRequest FromResponse(PipelineResponse respon } } } - diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionRequest.cs b/.dotnet/src/Generated/Models/CreateChatCompletionRequest.cs index 80c7d9be5..547e318d9 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionRequest.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionRequest.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateChatCompletionRequest. - public partial class CreateChatCompletionRequest + internal partial class CreateChatCompletionRequest { /// /// Keeps track of any properties unknown to the library. @@ -508,4 +508,3 @@ internal CreateChatCompletionRequest() public IList Functions { get; } } } - diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionRequestModel.cs b/.dotnet/src/Generated/Models/CreateChatCompletionRequestModel.cs index 5110350bd..c15dcb757 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionRequestModel.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for model in CreateChatCompletionRequest. - public readonly partial struct CreateChatCompletionRequestModel : IEquatable + internal readonly partial struct CreateChatCompletionRequestModel : IEquatable { private readonly string _value; @@ -86,4 +86,3 @@ public CreateChatCompletionRequestModel(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.Serialization.cs b/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.Serialization.cs index 8a13529c4..fd284f215 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateChatCompletionRequestResponseFormat : IJsonModel + internal partial class CreateChatCompletionRequestResponseFormat : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -125,4 +125,3 @@ internal static CreateChatCompletionRequestResponseFormat FromResponse(PipelineR } } } - diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.cs b/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.cs index a1dd64235..82322b0d6 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.cs @@ -3,10 +3,10 @@ using System; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateChatCompletionRequestResponseFormat. - public partial class CreateChatCompletionRequestResponseFormat + internal partial class CreateChatCompletionRequestResponseFormat { /// /// Keeps track of any properties unknown to the library. @@ -58,4 +58,3 @@ internal CreateChatCompletionRequestResponseFormat(CreateChatCompletionRequestRe public CreateChatCompletionRequestResponseFormatType? Type { get; set; } } } - diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormatType.cs b/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormatType.cs index 894f322de..8d305ab28 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormatType.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormatType.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for type in CreateChatCompletionRequestResponseFormat. - public readonly partial struct CreateChatCompletionRequestResponseFormatType : IEquatable + internal readonly partial struct CreateChatCompletionRequestResponseFormatType : IEquatable { private readonly string _value; @@ -44,4 +44,3 @@ public CreateChatCompletionRequestResponseFormatType(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponse.Serialization.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponse.Serialization.cs index f9c94d1dc..387a43069 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponse.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateChatCompletionResponse : IJsonModel + internal partial class CreateChatCompletionResponse : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -186,4 +186,3 @@ internal static CreateChatCompletionResponse FromResponse(PipelineResponse respo } } } - diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponse.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponse.cs index 6476530ae..1f44df4c1 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionResponse.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponse.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Represents a chat completion response returned by model, based on the provided input. - public partial class CreateChatCompletionResponse + internal partial class CreateChatCompletionResponse { /// /// Keeps track of any properties unknown to the library. @@ -113,4 +113,3 @@ internal CreateChatCompletionResponse() public CompletionUsage Usage { get; } } } - diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.Serialization.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.Serialization.cs index 5cd85183e..850a633f8 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateChatCompletionResponseChoice : IJsonModel + internal partial class CreateChatCompletionResponseChoice : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -154,4 +154,3 @@ internal static CreateChatCompletionResponseChoice FromResponse(PipelineResponse } } } - diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.cs index 17342fc9d..5d127075b 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateChatCompletionResponseChoice. - public partial class CreateChatCompletionResponseChoice + internal partial class CreateChatCompletionResponseChoice { /// /// Keeps track of any properties unknown to the library. @@ -105,4 +105,3 @@ internal CreateChatCompletionResponseChoice() public CreateChatCompletionResponseChoiceLogprobs Logprobs { get; } } } - diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceFinishReason.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceFinishReason.cs index e1e180f28..817df9578 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceFinishReason.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceFinishReason.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for finish_reason in CreateChatCompletionResponseChoice. - public readonly partial struct CreateChatCompletionResponseChoiceFinishReason : IEquatable + internal readonly partial struct CreateChatCompletionResponseChoiceFinishReason : IEquatable { private readonly string _value; @@ -53,4 +53,3 @@ public CreateChatCompletionResponseChoiceFinishReason(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.Serialization.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.Serialization.cs index 6e7b9371a..26c056edb 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateChatCompletionResponseChoiceLogprobs : IJsonModel + internal partial class CreateChatCompletionResponseChoiceLogprobs : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -140,4 +140,3 @@ internal static CreateChatCompletionResponseChoiceLogprobs FromResponse(Pipeline } } } - diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.cs index db7e2ef1d..bd570efb9 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.cs @@ -4,10 +4,10 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateChatCompletionResponseChoiceLogprobs. - public partial class CreateChatCompletionResponseChoiceLogprobs + internal partial class CreateChatCompletionResponseChoiceLogprobs { /// /// Keeps track of any properties unknown to the library. @@ -66,4 +66,3 @@ internal CreateChatCompletionResponseChoiceLogprobs() public IReadOnlyList Content { get; } } } - diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponseObject.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponseObject.cs index e95f7fff6..622b7b56a 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionResponseObject.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponseObject.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateChatCompletionResponse_object. - public readonly partial struct CreateChatCompletionResponseObject : IEquatable + internal readonly partial struct CreateChatCompletionResponseObject : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public CreateChatCompletionResponseObject(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateCompletionRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateCompletionRequest.Serialization.cs index e729592b7..f5c3b1bb7 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionRequest.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateCompletionRequest : IJsonModel + internal partial class CreateCompletionRequest : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -495,4 +495,3 @@ internal static CreateCompletionRequest FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/CreateCompletionRequest.cs b/.dotnet/src/Generated/Models/CreateCompletionRequest.cs index 65ce00804..4c439168a 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionRequest.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionRequest.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateCompletionRequest. - public partial class CreateCompletionRequest + internal partial class CreateCompletionRequest { /// /// Keeps track of any properties unknown to the library. @@ -397,4 +397,3 @@ internal CreateCompletionRequest() public string User { get; set; } } } - diff --git a/.dotnet/src/Generated/Models/CreateCompletionRequestModel.cs b/.dotnet/src/Generated/Models/CreateCompletionRequestModel.cs index f0afae0c4..784f43da8 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionRequestModel.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for model in CreateCompletionRequest. - public readonly partial struct CreateCompletionRequestModel : IEquatable + internal readonly partial struct CreateCompletionRequestModel : IEquatable { private readonly string _value; @@ -47,4 +47,3 @@ public CreateCompletionRequestModel(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponse.Serialization.cs b/.dotnet/src/Generated/Models/CreateCompletionResponse.Serialization.cs index 17ea98286..2a8633f00 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionResponse.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateCompletionResponse : IJsonModel + internal partial class CreateCompletionResponse : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -186,4 +186,3 @@ internal static CreateCompletionResponse FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponse.cs b/.dotnet/src/Generated/Models/CreateCompletionResponse.cs index 944f32b56..a0bb30624 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionResponse.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionResponse.cs @@ -5,13 +5,13 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// /// Represents a completion response from the API. Note: both the streamed and non-streamed response /// objects share the same shape (unlike the chat endpoint). /// - public partial class CreateCompletionResponse + internal partial class CreateCompletionResponse { /// /// Keeps track of any properties unknown to the library. @@ -116,4 +116,3 @@ internal CreateCompletionResponse() public CompletionUsage Usage { get; } } } - diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.Serialization.cs b/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.Serialization.cs index 0f9206ba2..b68a04694 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateCompletionResponseChoice : IJsonModel + internal partial class CreateCompletionResponseChoice : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -154,4 +154,3 @@ internal static CreateCompletionResponseChoice FromResponse(PipelineResponse res } } } - diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.cs b/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.cs index a0f883635..1cf6b8df1 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateCompletionResponseChoice. - public partial class CreateCompletionResponseChoice + internal partial class CreateCompletionResponseChoice { /// /// Keeps track of any properties unknown to the library. @@ -105,4 +105,3 @@ internal CreateCompletionResponseChoice() public CreateCompletionResponseChoiceFinishReason FinishReason { get; } } } - diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceFinishReason.cs b/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceFinishReason.cs index d4ee35578..fc4a928ce 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceFinishReason.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceFinishReason.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for finish_reason in CreateCompletionResponseChoice. - public readonly partial struct CreateCompletionResponseChoiceFinishReason : IEquatable + internal readonly partial struct CreateCompletionResponseChoiceFinishReason : IEquatable { private readonly string _value; @@ -47,4 +47,3 @@ public CreateCompletionResponseChoiceFinishReason(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.Serialization.cs b/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.Serialization.cs index b3ba1559f..3658a0aab 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateCompletionResponseChoiceLogprobs : IJsonModel + internal partial class CreateCompletionResponseChoiceLogprobs : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -205,4 +205,3 @@ internal static CreateCompletionResponseChoiceLogprobs FromResponse(PipelineResp } } } - diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.cs b/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.cs index 598ec5916..be7a3a78c 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateCompletionResponseChoiceLogprobs. - public partial class CreateCompletionResponseChoiceLogprobs + internal partial class CreateCompletionResponseChoiceLogprobs { /// /// Keeps track of any properties unknown to the library. @@ -91,4 +91,3 @@ internal CreateCompletionResponseChoiceLogprobs() public IReadOnlyList TextOffset { get; } } } - diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponseObject.cs b/.dotnet/src/Generated/Models/CreateCompletionResponseObject.cs index 24c670201..00ce256fc 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionResponseObject.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionResponseObject.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateCompletionResponse_object. - public readonly partial struct CreateCompletionResponseObject : IEquatable + internal readonly partial struct CreateCompletionResponseObject : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public CreateCompletionResponseObject(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateEmbeddingRequest.Serialization.cs index 7a8ff235b..1160d6206 100644 --- a/.dotnet/src/Generated/Models/CreateEmbeddingRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateEmbeddingRequest.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateEmbeddingRequest : IJsonModel + internal partial class CreateEmbeddingRequest : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -174,4 +174,3 @@ internal static CreateEmbeddingRequest FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingRequest.cs b/.dotnet/src/Generated/Models/CreateEmbeddingRequest.cs index c2a286d4c..7a649c374 100644 --- a/.dotnet/src/Generated/Models/CreateEmbeddingRequest.cs +++ b/.dotnet/src/Generated/Models/CreateEmbeddingRequest.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateEmbeddingRequest. - public partial class CreateEmbeddingRequest + internal partial class CreateEmbeddingRequest { /// /// Keeps track of any properties unknown to the library. @@ -182,4 +182,3 @@ internal CreateEmbeddingRequest() public string User { get; set; } } } - diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingRequestEncodingFormat.cs b/.dotnet/src/Generated/Models/CreateEmbeddingRequestEncodingFormat.cs index e252744e4..18264f565 100644 --- a/.dotnet/src/Generated/Models/CreateEmbeddingRequestEncodingFormat.cs +++ b/.dotnet/src/Generated/Models/CreateEmbeddingRequestEncodingFormat.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for encoding_format in CreateEmbeddingRequest. - public readonly partial struct CreateEmbeddingRequestEncodingFormat : IEquatable + internal readonly partial struct CreateEmbeddingRequestEncodingFormat : IEquatable { private readonly string _value; @@ -44,4 +44,3 @@ public CreateEmbeddingRequestEncodingFormat(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingRequestModel.cs b/.dotnet/src/Generated/Models/CreateEmbeddingRequestModel.cs index 628de9b7b..8570f4947 100644 --- a/.dotnet/src/Generated/Models/CreateEmbeddingRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateEmbeddingRequestModel.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for model in CreateEmbeddingRequest. - public readonly partial struct CreateEmbeddingRequestModel : IEquatable + internal readonly partial struct CreateEmbeddingRequestModel : IEquatable { private readonly string _value; @@ -47,4 +47,3 @@ public CreateEmbeddingRequestModel(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingResponse.Serialization.cs b/.dotnet/src/Generated/Models/CreateEmbeddingResponse.Serialization.cs index deaf48c02..656eafe81 100644 --- a/.dotnet/src/Generated/Models/CreateEmbeddingResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateEmbeddingResponse.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateEmbeddingResponse : IJsonModel + internal partial class CreateEmbeddingResponse : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -152,4 +152,3 @@ internal static CreateEmbeddingResponse FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingResponse.cs b/.dotnet/src/Generated/Models/CreateEmbeddingResponse.cs index f0695c29a..7d4a885fc 100644 --- a/.dotnet/src/Generated/Models/CreateEmbeddingResponse.cs +++ b/.dotnet/src/Generated/Models/CreateEmbeddingResponse.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateEmbeddingResponse. - public partial class CreateEmbeddingResponse + internal partial class CreateEmbeddingResponse { /// /// Keeps track of any properties unknown to the library. @@ -89,4 +89,3 @@ internal CreateEmbeddingResponse() public EmbeddingUsage Usage { get; } } } - diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingResponseObject.cs b/.dotnet/src/Generated/Models/CreateEmbeddingResponseObject.cs index b98b10317..1d7bc7a1a 100644 --- a/.dotnet/src/Generated/Models/CreateEmbeddingResponseObject.cs +++ b/.dotnet/src/Generated/Models/CreateEmbeddingResponseObject.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateEmbeddingResponse_object. - public readonly partial struct CreateEmbeddingResponseObject : IEquatable + internal readonly partial struct CreateEmbeddingResponseObject : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public CreateEmbeddingResponseObject(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateFileRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateFileRequest.Serialization.cs index f7d3ba503..852eb6127 100644 --- a/.dotnet/src/Generated/Models/CreateFileRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateFileRequest.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateFileRequest : IJsonModel + internal partial class CreateFileRequest : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -126,4 +126,3 @@ internal static CreateFileRequest FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/CreateFileRequest.cs b/.dotnet/src/Generated/Models/CreateFileRequest.cs index 9475c30af..6f39101d1 100644 --- a/.dotnet/src/Generated/Models/CreateFileRequest.cs +++ b/.dotnet/src/Generated/Models/CreateFileRequest.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateFileRequest. - public partial class CreateFileRequest + internal partial class CreateFileRequest { /// /// Keeps track of any properties unknown to the library. @@ -105,4 +105,3 @@ internal CreateFileRequest() public CreateFileRequestPurpose Purpose { get; } } } - diff --git a/.dotnet/src/Generated/Models/CreateFileRequestPurpose.cs b/.dotnet/src/Generated/Models/CreateFileRequestPurpose.cs index 51a939757..8dc7f4cd7 100644 --- a/.dotnet/src/Generated/Models/CreateFileRequestPurpose.cs +++ b/.dotnet/src/Generated/Models/CreateFileRequestPurpose.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for purpose in CreateFileRequest. - public readonly partial struct CreateFileRequestPurpose : IEquatable + internal readonly partial struct CreateFileRequestPurpose : IEquatable { private readonly string _value; @@ -44,4 +44,3 @@ public CreateFileRequestPurpose(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.Serialization.cs index 08d63808e..c03035768 100644 --- a/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateFineTuningJobRequest : IJsonModel + internal partial class CreateFineTuningJobRequest : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -187,4 +187,3 @@ internal static CreateFineTuningJobRequest FromResponse(PipelineResponse respons } } } - diff --git a/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.cs b/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.cs index 618e6069d..e4a89072b 100644 --- a/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.cs +++ b/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateFineTuningJobRequest. - public partial class CreateFineTuningJobRequest + internal partial class CreateFineTuningJobRequest { /// /// Keeps track of any properties unknown to the library. @@ -155,4 +155,3 @@ internal CreateFineTuningJobRequest() public string Suffix { get; set; } } } - diff --git a/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.Serialization.cs b/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.Serialization.cs index 98b42074d..6cd4a835a 100644 --- a/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateFineTuningJobRequestHyperparameters : IJsonModel + internal partial class CreateFineTuningJobRequestHyperparameters : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -132,4 +132,3 @@ internal static CreateFineTuningJobRequestHyperparameters FromResponse(PipelineR } } } - diff --git a/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.cs b/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.cs index 8094fc378..9c2712095 100644 --- a/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.cs +++ b/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.cs @@ -3,10 +3,10 @@ using System; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateFineTuningJobRequestHyperparameters. - public partial class CreateFineTuningJobRequestHyperparameters + internal partial class CreateFineTuningJobRequestHyperparameters { /// /// Keeps track of any properties unknown to the library. @@ -102,4 +102,3 @@ internal CreateFineTuningJobRequestHyperparameters(BinaryData nEpochs, IDictiona public BinaryData NEpochs { get; set; } } } - diff --git a/.dotnet/src/Generated/Models/CreateFineTuningJobRequestModel.cs b/.dotnet/src/Generated/Models/CreateFineTuningJobRequestModel.cs index e36868cc4..670bdc0f5 100644 --- a/.dotnet/src/Generated/Models/CreateFineTuningJobRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateFineTuningJobRequestModel.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for model in CreateFineTuningJobRequest. - public readonly partial struct CreateFineTuningJobRequestModel : IEquatable + internal readonly partial struct CreateFineTuningJobRequestModel : IEquatable { private readonly string _value; @@ -47,4 +47,3 @@ public CreateFineTuningJobRequestModel(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateImageEditRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateImageEditRequest.Serialization.cs index 9de7cccac..5da48765a 100644 --- a/.dotnet/src/Generated/Models/CreateImageEditRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateImageEditRequest.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateImageEditRequest : IJsonModel + internal partial class CreateImageEditRequest : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -220,4 +220,3 @@ internal static CreateImageEditRequest FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/CreateImageEditRequest.cs b/.dotnet/src/Generated/Models/CreateImageEditRequest.cs index 5b78b294b..136db1035 100644 --- a/.dotnet/src/Generated/Models/CreateImageEditRequest.cs +++ b/.dotnet/src/Generated/Models/CreateImageEditRequest.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateImageEditRequest. - public partial class CreateImageEditRequest + internal partial class CreateImageEditRequest { /// /// Keeps track of any properties unknown to the library. @@ -149,4 +149,3 @@ internal CreateImageEditRequest() public string User { get; set; } } } - diff --git a/.dotnet/src/Generated/Models/CreateImageEditRequestModel.cs b/.dotnet/src/Generated/Models/CreateImageEditRequestModel.cs index 946936edb..60e9057d2 100644 --- a/.dotnet/src/Generated/Models/CreateImageEditRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateImageEditRequestModel.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for model in CreateImageEditRequest. - public readonly partial struct CreateImageEditRequestModel : IEquatable + internal readonly partial struct CreateImageEditRequestModel : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public CreateImageEditRequestModel(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateImageEditRequestResponseFormat.cs b/.dotnet/src/Generated/Models/CreateImageEditRequestResponseFormat.cs index b398ca63d..374dccec4 100644 --- a/.dotnet/src/Generated/Models/CreateImageEditRequestResponseFormat.cs +++ b/.dotnet/src/Generated/Models/CreateImageEditRequestResponseFormat.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for response_format in CreateImageEditRequest. - public readonly partial struct CreateImageEditRequestResponseFormat : IEquatable + internal readonly partial struct CreateImageEditRequestResponseFormat : IEquatable { private readonly string _value; @@ -44,4 +44,3 @@ public CreateImageEditRequestResponseFormat(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateImageEditRequestSize.cs b/.dotnet/src/Generated/Models/CreateImageEditRequestSize.cs index 8e644e852..63269c1f2 100644 --- a/.dotnet/src/Generated/Models/CreateImageEditRequestSize.cs +++ b/.dotnet/src/Generated/Models/CreateImageEditRequestSize.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for size in CreateImageEditRequest. - public readonly partial struct CreateImageEditRequestSize : IEquatable + internal readonly partial struct CreateImageEditRequestSize : IEquatable { private readonly string _value; @@ -47,4 +47,3 @@ public CreateImageEditRequestSize(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateImageRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateImageRequest.Serialization.cs index 74b4555fc..b2f3758de 100644 --- a/.dotnet/src/Generated/Models/CreateImageRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateImageRequest.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateImageRequest : IJsonModel + internal partial class CreateImageRequest : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -227,4 +227,3 @@ internal static CreateImageRequest FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/CreateImageRequest.cs b/.dotnet/src/Generated/Models/CreateImageRequest.cs index 0ddf94adb..552a5e8a7 100644 --- a/.dotnet/src/Generated/Models/CreateImageRequest.cs +++ b/.dotnet/src/Generated/Models/CreateImageRequest.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateImageRequest. - public partial class CreateImageRequest + internal partial class CreateImageRequest { /// /// Keeps track of any properties unknown to the library. @@ -138,4 +138,3 @@ internal CreateImageRequest() public string User { get; set; } } } - diff --git a/.dotnet/src/Generated/Models/CreateImageRequestModel.cs b/.dotnet/src/Generated/Models/CreateImageRequestModel.cs index e6401986c..6e8ad967e 100644 --- a/.dotnet/src/Generated/Models/CreateImageRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateImageRequestModel.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for model in CreateImageRequest. - public readonly partial struct CreateImageRequestModel : IEquatable + internal readonly partial struct CreateImageRequestModel : IEquatable { private readonly string _value; @@ -44,4 +44,3 @@ public CreateImageRequestModel(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateImageRequestQuality.cs b/.dotnet/src/Generated/Models/CreateImageRequestQuality.cs index 236be9ebf..01060a04f 100644 --- a/.dotnet/src/Generated/Models/CreateImageRequestQuality.cs +++ b/.dotnet/src/Generated/Models/CreateImageRequestQuality.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for quality in CreateImageRequest. - public readonly partial struct CreateImageRequestQuality : IEquatable + internal readonly partial struct CreateImageRequestQuality : IEquatable { private readonly string _value; @@ -44,4 +44,3 @@ public CreateImageRequestQuality(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateImageRequestResponseFormat.cs b/.dotnet/src/Generated/Models/CreateImageRequestResponseFormat.cs index e7f95d5ee..22d92d612 100644 --- a/.dotnet/src/Generated/Models/CreateImageRequestResponseFormat.cs +++ b/.dotnet/src/Generated/Models/CreateImageRequestResponseFormat.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for response_format in CreateImageRequest. - public readonly partial struct CreateImageRequestResponseFormat : IEquatable + internal readonly partial struct CreateImageRequestResponseFormat : IEquatable { private readonly string _value; @@ -44,4 +44,3 @@ public CreateImageRequestResponseFormat(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateImageRequestSize.cs b/.dotnet/src/Generated/Models/CreateImageRequestSize.cs index 091e4d3b0..9bff12b78 100644 --- a/.dotnet/src/Generated/Models/CreateImageRequestSize.cs +++ b/.dotnet/src/Generated/Models/CreateImageRequestSize.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for size in CreateImageRequest. - public readonly partial struct CreateImageRequestSize : IEquatable + internal readonly partial struct CreateImageRequestSize : IEquatable { private readonly string _value; @@ -53,4 +53,3 @@ public CreateImageRequestSize(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateImageRequestStyle.cs b/.dotnet/src/Generated/Models/CreateImageRequestStyle.cs index 98f67425f..200565a5f 100644 --- a/.dotnet/src/Generated/Models/CreateImageRequestStyle.cs +++ b/.dotnet/src/Generated/Models/CreateImageRequestStyle.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for style in CreateImageRequest. - public readonly partial struct CreateImageRequestStyle : IEquatable + internal readonly partial struct CreateImageRequestStyle : IEquatable { private readonly string _value; @@ -44,4 +44,3 @@ public CreateImageRequestStyle(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateImageVariationRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateImageVariationRequest.Serialization.cs index 642a6c439..4c9d18ed2 100644 --- a/.dotnet/src/Generated/Models/CreateImageVariationRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateImageVariationRequest.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateImageVariationRequest : IJsonModel + internal partial class CreateImageVariationRequest : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -197,4 +197,3 @@ internal static CreateImageVariationRequest FromResponse(PipelineResponse respon } } } - diff --git a/.dotnet/src/Generated/Models/CreateImageVariationRequest.cs b/.dotnet/src/Generated/Models/CreateImageVariationRequest.cs index a034e2faa..1986159f7 100644 --- a/.dotnet/src/Generated/Models/CreateImageVariationRequest.cs +++ b/.dotnet/src/Generated/Models/CreateImageVariationRequest.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateImageVariationRequest. - public partial class CreateImageVariationRequest + internal partial class CreateImageVariationRequest { /// /// Keeps track of any properties unknown to the library. @@ -117,4 +117,3 @@ internal CreateImageVariationRequest() public string User { get; set; } } } - diff --git a/.dotnet/src/Generated/Models/CreateImageVariationRequestModel.cs b/.dotnet/src/Generated/Models/CreateImageVariationRequestModel.cs index d40886648..13ab94757 100644 --- a/.dotnet/src/Generated/Models/CreateImageVariationRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateImageVariationRequestModel.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for model in CreateImageVariationRequest. - public readonly partial struct CreateImageVariationRequestModel : IEquatable + internal readonly partial struct CreateImageVariationRequestModel : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public CreateImageVariationRequestModel(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateImageVariationRequestResponseFormat.cs b/.dotnet/src/Generated/Models/CreateImageVariationRequestResponseFormat.cs index 94f353a25..5f99e6bcf 100644 --- a/.dotnet/src/Generated/Models/CreateImageVariationRequestResponseFormat.cs +++ b/.dotnet/src/Generated/Models/CreateImageVariationRequestResponseFormat.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for response_format in CreateImageVariationRequest. - public readonly partial struct CreateImageVariationRequestResponseFormat : IEquatable + internal readonly partial struct CreateImageVariationRequestResponseFormat : IEquatable { private readonly string _value; @@ -44,4 +44,3 @@ public CreateImageVariationRequestResponseFormat(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateImageVariationRequestSize.cs b/.dotnet/src/Generated/Models/CreateImageVariationRequestSize.cs index 0374c3214..f10e28466 100644 --- a/.dotnet/src/Generated/Models/CreateImageVariationRequestSize.cs +++ b/.dotnet/src/Generated/Models/CreateImageVariationRequestSize.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for size in CreateImageVariationRequest. - public readonly partial struct CreateImageVariationRequestSize : IEquatable + internal readonly partial struct CreateImageVariationRequestSize : IEquatable { private readonly string _value; @@ -47,4 +47,3 @@ public CreateImageVariationRequestSize(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateMessageRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateMessageRequest.Serialization.cs index 3386db660..bc6fa6aea 100644 --- a/.dotnet/src/Generated/Models/CreateMessageRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateMessageRequest.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateMessageRequest : IJsonModel + internal partial class CreateMessageRequest : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -184,4 +184,3 @@ internal static CreateMessageRequest FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/CreateMessageRequest.cs b/.dotnet/src/Generated/Models/CreateMessageRequest.cs index 7d2855a9f..9a609327e 100644 --- a/.dotnet/src/Generated/Models/CreateMessageRequest.cs +++ b/.dotnet/src/Generated/Models/CreateMessageRequest.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateMessageRequest. - public partial class CreateMessageRequest + internal partial class CreateMessageRequest { /// /// Keeps track of any properties unknown to the library. @@ -100,4 +100,3 @@ internal CreateMessageRequest() public IDictionary Metadata { get; set; } } } - diff --git a/.dotnet/src/Generated/Models/CreateMessageRequestRole.cs b/.dotnet/src/Generated/Models/CreateMessageRequestRole.cs index f5be49786..d0118f1cb 100644 --- a/.dotnet/src/Generated/Models/CreateMessageRequestRole.cs +++ b/.dotnet/src/Generated/Models/CreateMessageRequestRole.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateMessageRequest_role. - public readonly partial struct CreateMessageRequestRole : IEquatable + internal readonly partial struct CreateMessageRequestRole : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public CreateMessageRequestRole(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateModerationRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateModerationRequest.Serialization.cs index 50c0cf4f7..b131e485d 100644 --- a/.dotnet/src/Generated/Models/CreateModerationRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateModerationRequest.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateModerationRequest : IJsonModel + internal partial class CreateModerationRequest : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -140,4 +140,3 @@ internal static CreateModerationRequest FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/CreateModerationRequest.cs b/.dotnet/src/Generated/Models/CreateModerationRequest.cs index b92114f96..d015993c7 100644 --- a/.dotnet/src/Generated/Models/CreateModerationRequest.cs +++ b/.dotnet/src/Generated/Models/CreateModerationRequest.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateModerationRequest. - public partial class CreateModerationRequest + internal partial class CreateModerationRequest { /// /// Keeps track of any properties unknown to the library. @@ -125,4 +125,3 @@ internal CreateModerationRequest() public CreateModerationRequestModel? Model { get; set; } } } - diff --git a/.dotnet/src/Generated/Models/CreateModerationRequestModel.cs b/.dotnet/src/Generated/Models/CreateModerationRequestModel.cs index af410f3a0..2accc5ab0 100644 --- a/.dotnet/src/Generated/Models/CreateModerationRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateModerationRequestModel.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for model in CreateModerationRequest. - public readonly partial struct CreateModerationRequestModel : IEquatable + internal readonly partial struct CreateModerationRequestModel : IEquatable { private readonly string _value; @@ -44,4 +44,3 @@ public CreateModerationRequestModel(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateModerationResponse.Serialization.cs b/.dotnet/src/Generated/Models/CreateModerationResponse.Serialization.cs index 1d3fd1188..791fd71f1 100644 --- a/.dotnet/src/Generated/Models/CreateModerationResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateModerationResponse.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateModerationResponse : IJsonModel + internal partial class CreateModerationResponse : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -144,4 +144,3 @@ internal static CreateModerationResponse FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/CreateModerationResponse.cs b/.dotnet/src/Generated/Models/CreateModerationResponse.cs index caf0c4858..8f42f77c0 100644 --- a/.dotnet/src/Generated/Models/CreateModerationResponse.cs +++ b/.dotnet/src/Generated/Models/CreateModerationResponse.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Represents policy compliance report by OpenAI's content moderation model against a given input. - public partial class CreateModerationResponse + internal partial class CreateModerationResponse { /// /// Keeps track of any properties unknown to the library. @@ -84,4 +84,3 @@ internal CreateModerationResponse() public IReadOnlyList Results { get; } } } - diff --git a/.dotnet/src/Generated/Models/CreateModerationResponseResult.Serialization.cs b/.dotnet/src/Generated/Models/CreateModerationResponseResult.Serialization.cs index edabb3d30..6a69b7a0d 100644 --- a/.dotnet/src/Generated/Models/CreateModerationResponseResult.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateModerationResponseResult.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateModerationResponseResult : IJsonModel + internal partial class CreateModerationResponseResult : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -134,4 +134,3 @@ internal static CreateModerationResponseResult FromResponse(PipelineResponse res } } } - diff --git a/.dotnet/src/Generated/Models/CreateModerationResponseResult.cs b/.dotnet/src/Generated/Models/CreateModerationResponseResult.cs index d3abebbc3..baea8e148 100644 --- a/.dotnet/src/Generated/Models/CreateModerationResponseResult.cs +++ b/.dotnet/src/Generated/Models/CreateModerationResponseResult.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateModerationResponseResult. - public partial class CreateModerationResponseResult + internal partial class CreateModerationResponseResult { /// /// Keeps track of any properties unknown to the library. @@ -82,4 +82,3 @@ internal CreateModerationResponseResult() public CreateModerationResponseResultCategoryScores CategoryScores { get; } } } - diff --git a/.dotnet/src/Generated/Models/CreateModerationResponseResultCategories.Serialization.cs b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategories.Serialization.cs index 5dce74b53..4f1c9d5eb 100644 --- a/.dotnet/src/Generated/Models/CreateModerationResponseResultCategories.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategories.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateModerationResponseResultCategories : IJsonModel + internal partial class CreateModerationResponseResultCategories : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -198,4 +198,3 @@ internal static CreateModerationResponseResultCategories FromResponse(PipelineRe } } } - diff --git a/.dotnet/src/Generated/Models/CreateModerationResponseResultCategories.cs b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategories.cs index 8af6aa519..2bdc02449 100644 --- a/.dotnet/src/Generated/Models/CreateModerationResponseResultCategories.cs +++ b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategories.cs @@ -3,10 +3,10 @@ using System; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateModerationResponseResultCategories. - public partial class CreateModerationResponseResultCategories + internal partial class CreateModerationResponseResultCategories { /// /// Keeps track of any properties unknown to the library. @@ -185,4 +185,3 @@ internal CreateModerationResponseResultCategories() public bool ViolenceGraphic { get; } } } - diff --git a/.dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.Serialization.cs b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.Serialization.cs index 50b22a9d6..6a8189dc3 100644 --- a/.dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateModerationResponseResultCategoryScores : IJsonModel + internal partial class CreateModerationResponseResultCategoryScores : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -198,4 +198,3 @@ internal static CreateModerationResponseResultCategoryScores FromResponse(Pipeli } } } - diff --git a/.dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.cs b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.cs index 0ee6e8d5a..17d49937e 100644 --- a/.dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.cs +++ b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.cs @@ -3,10 +3,10 @@ using System; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateModerationResponseResultCategoryScores. - public partial class CreateModerationResponseResultCategoryScores + internal partial class CreateModerationResponseResultCategoryScores { /// /// Keeps track of any properties unknown to the library. @@ -125,4 +125,3 @@ internal CreateModerationResponseResultCategoryScores() public double ViolenceGraphic { get; } } } - diff --git a/.dotnet/src/Generated/Models/CreateRunRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateRunRequest.Serialization.cs index 4eda947a7..3bdb98f68 100644 --- a/.dotnet/src/Generated/Models/CreateRunRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateRunRequest.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateRunRequest : IJsonModel + internal partial class CreateRunRequest : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -271,4 +271,3 @@ internal static CreateRunRequest FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/CreateRunRequest.cs b/.dotnet/src/Generated/Models/CreateRunRequest.cs index ea2ac5123..e7bf9f448 100644 --- a/.dotnet/src/Generated/Models/CreateRunRequest.cs +++ b/.dotnet/src/Generated/Models/CreateRunRequest.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateRunRequest. - public partial class CreateRunRequest + internal partial class CreateRunRequest { /// /// Keeps track of any properties unknown to the library. @@ -152,4 +152,3 @@ internal CreateRunRequest() public IDictionary Metadata { get; set; } } } - diff --git a/.dotnet/src/Generated/Models/CreateSpeechRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateSpeechRequest.Serialization.cs index f2216a6e1..46fd557d6 100644 --- a/.dotnet/src/Generated/Models/CreateSpeechRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateSpeechRequest.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateSpeechRequest : IJsonModel + internal partial class CreateSpeechRequest : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -164,4 +164,3 @@ internal static CreateSpeechRequest FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/CreateSpeechRequest.cs b/.dotnet/src/Generated/Models/CreateSpeechRequest.cs index eb2c71ae0..470717796 100644 --- a/.dotnet/src/Generated/Models/CreateSpeechRequest.cs +++ b/.dotnet/src/Generated/Models/CreateSpeechRequest.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateSpeechRequest. - public partial class CreateSpeechRequest + internal partial class CreateSpeechRequest { /// /// Keeps track of any properties unknown to the library. @@ -101,4 +101,3 @@ internal CreateSpeechRequest() public double? Speed { get; set; } } } - diff --git a/.dotnet/src/Generated/Models/CreateSpeechRequestModel.cs b/.dotnet/src/Generated/Models/CreateSpeechRequestModel.cs index 590078a92..806f493d3 100644 --- a/.dotnet/src/Generated/Models/CreateSpeechRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateSpeechRequestModel.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for model in CreateSpeechRequest. - public readonly partial struct CreateSpeechRequestModel : IEquatable + internal readonly partial struct CreateSpeechRequestModel : IEquatable { private readonly string _value; @@ -44,4 +44,3 @@ public CreateSpeechRequestModel(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateSpeechRequestResponseFormat.cs b/.dotnet/src/Generated/Models/CreateSpeechRequestResponseFormat.cs index 4694fe9d7..186f59cc2 100644 --- a/.dotnet/src/Generated/Models/CreateSpeechRequestResponseFormat.cs +++ b/.dotnet/src/Generated/Models/CreateSpeechRequestResponseFormat.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for response_format in CreateSpeechRequest. - public readonly partial struct CreateSpeechRequestResponseFormat : IEquatable + internal readonly partial struct CreateSpeechRequestResponseFormat : IEquatable { private readonly string _value; @@ -50,4 +50,3 @@ public CreateSpeechRequestResponseFormat(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateSpeechRequestVoice.cs b/.dotnet/src/Generated/Models/CreateSpeechRequestVoice.cs index e764eed85..be68af49d 100644 --- a/.dotnet/src/Generated/Models/CreateSpeechRequestVoice.cs +++ b/.dotnet/src/Generated/Models/CreateSpeechRequestVoice.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for voice in CreateSpeechRequest. - public readonly partial struct CreateSpeechRequestVoice : IEquatable + internal readonly partial struct CreateSpeechRequestVoice : IEquatable { private readonly string _value; @@ -56,4 +56,3 @@ public CreateSpeechRequestVoice(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.Serialization.cs index 384147a67..b3281386f 100644 --- a/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateThreadAndRunRequest : IJsonModel + internal partial class CreateThreadAndRunRequest : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -263,4 +263,3 @@ internal static CreateThreadAndRunRequest FromResponse(PipelineResponse response } } } - diff --git a/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.cs b/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.cs index b212c90c5..942ac10f1 100644 --- a/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.cs +++ b/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateThreadAndRunRequest. - public partial class CreateThreadAndRunRequest + internal partial class CreateThreadAndRunRequest { /// /// Keeps track of any properties unknown to the library. @@ -146,4 +146,3 @@ internal CreateThreadAndRunRequest() public IDictionary Metadata { get; set; } } } - diff --git a/.dotnet/src/Generated/Models/CreateThreadRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateThreadRequest.Serialization.cs index b899f1a9d..521c12b25 100644 --- a/.dotnet/src/Generated/Models/CreateThreadRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateThreadRequest.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateThreadRequest : IJsonModel + internal partial class CreateThreadRequest : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -168,4 +168,3 @@ internal static CreateThreadRequest FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/CreateThreadRequest.cs b/.dotnet/src/Generated/Models/CreateThreadRequest.cs index a31999cb7..0fd5b0167 100644 --- a/.dotnet/src/Generated/Models/CreateThreadRequest.cs +++ b/.dotnet/src/Generated/Models/CreateThreadRequest.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateThreadRequest. - public partial class CreateThreadRequest + internal partial class CreateThreadRequest { /// /// Keeps track of any properties unknown to the library. @@ -73,4 +73,3 @@ internal CreateThreadRequest(IList messages, IDictionary Metadata { get; set; } } } - diff --git a/.dotnet/src/Generated/Models/CreateTranscriptionRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateTranscriptionRequest.Serialization.cs index 8aa3b8a97..ac4870484 100644 --- a/.dotnet/src/Generated/Models/CreateTranscriptionRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateTranscriptionRequest.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateTranscriptionRequest : IJsonModel + internal partial class CreateTranscriptionRequest : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -178,4 +178,3 @@ internal static CreateTranscriptionRequest FromResponse(PipelineResponse respons } } } - diff --git a/.dotnet/src/Generated/Models/CreateTranscriptionRequest.cs b/.dotnet/src/Generated/Models/CreateTranscriptionRequest.cs index 7cccd2c15..9bdc65381 100644 --- a/.dotnet/src/Generated/Models/CreateTranscriptionRequest.cs +++ b/.dotnet/src/Generated/Models/CreateTranscriptionRequest.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateTranscriptionRequest. - public partial class CreateTranscriptionRequest + internal partial class CreateTranscriptionRequest { /// /// Keeps track of any properties unknown to the library. @@ -143,4 +143,3 @@ internal CreateTranscriptionRequest() public double? Temperature { get; set; } } } - diff --git a/.dotnet/src/Generated/Models/CreateTranscriptionRequestModel.cs b/.dotnet/src/Generated/Models/CreateTranscriptionRequestModel.cs index c4639fe72..374f27dc3 100644 --- a/.dotnet/src/Generated/Models/CreateTranscriptionRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateTranscriptionRequestModel.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for model in CreateTranscriptionRequest. - public readonly partial struct CreateTranscriptionRequestModel : IEquatable + internal readonly partial struct CreateTranscriptionRequestModel : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public CreateTranscriptionRequestModel(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateTranscriptionRequestResponseFormat.cs b/.dotnet/src/Generated/Models/CreateTranscriptionRequestResponseFormat.cs index 1eb2b8b48..e8211eeef 100644 --- a/.dotnet/src/Generated/Models/CreateTranscriptionRequestResponseFormat.cs +++ b/.dotnet/src/Generated/Models/CreateTranscriptionRequestResponseFormat.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for response_format in CreateTranscriptionRequest. - public readonly partial struct CreateTranscriptionRequestResponseFormat : IEquatable + internal readonly partial struct CreateTranscriptionRequestResponseFormat : IEquatable { private readonly string _value; @@ -53,4 +53,3 @@ public CreateTranscriptionRequestResponseFormat(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateTranscriptionResponse.Serialization.cs b/.dotnet/src/Generated/Models/CreateTranscriptionResponse.Serialization.cs index 0052a0f0b..326257fc1 100644 --- a/.dotnet/src/Generated/Models/CreateTranscriptionResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateTranscriptionResponse.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateTranscriptionResponse : IJsonModel + internal partial class CreateTranscriptionResponse : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -184,4 +184,3 @@ internal static CreateTranscriptionResponse FromResponse(PipelineResponse respon } } } - diff --git a/.dotnet/src/Generated/Models/CreateTranscriptionResponse.cs b/.dotnet/src/Generated/Models/CreateTranscriptionResponse.cs index 47f9428ca..ce8ed266d 100644 --- a/.dotnet/src/Generated/Models/CreateTranscriptionResponse.cs +++ b/.dotnet/src/Generated/Models/CreateTranscriptionResponse.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateTranscriptionResponse. - public partial class CreateTranscriptionResponse + internal partial class CreateTranscriptionResponse { /// /// Keeps track of any properties unknown to the library. @@ -92,4 +92,3 @@ internal CreateTranscriptionResponse() public IReadOnlyList Segments { get; } } } - diff --git a/.dotnet/src/Generated/Models/CreateTranscriptionResponseTask.cs b/.dotnet/src/Generated/Models/CreateTranscriptionResponseTask.cs index 45bb38166..167892816 100644 --- a/.dotnet/src/Generated/Models/CreateTranscriptionResponseTask.cs +++ b/.dotnet/src/Generated/Models/CreateTranscriptionResponseTask.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateTranscriptionResponse_task. - public readonly partial struct CreateTranscriptionResponseTask : IEquatable + internal readonly partial struct CreateTranscriptionResponseTask : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public CreateTranscriptionResponseTask(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateTranslationRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateTranslationRequest.Serialization.cs index 2b415a177..521582c54 100644 --- a/.dotnet/src/Generated/Models/CreateTranslationRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateTranslationRequest.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateTranslationRequest : IJsonModel + internal partial class CreateTranslationRequest : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -167,4 +167,3 @@ internal static CreateTranslationRequest FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/CreateTranslationRequest.cs b/.dotnet/src/Generated/Models/CreateTranslationRequest.cs index fa5224a3e..46911bdf5 100644 --- a/.dotnet/src/Generated/Models/CreateTranslationRequest.cs +++ b/.dotnet/src/Generated/Models/CreateTranslationRequest.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateTranslationRequest. - public partial class CreateTranslationRequest + internal partial class CreateTranslationRequest { /// /// Keeps track of any properties unknown to the library. @@ -131,4 +131,3 @@ internal CreateTranslationRequest() public double? Temperature { get; set; } } } - diff --git a/.dotnet/src/Generated/Models/CreateTranslationRequestModel.cs b/.dotnet/src/Generated/Models/CreateTranslationRequestModel.cs index 10536d253..633bfd4c6 100644 --- a/.dotnet/src/Generated/Models/CreateTranslationRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateTranslationRequestModel.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for model in CreateTranslationRequest. - public readonly partial struct CreateTranslationRequestModel : IEquatable + internal readonly partial struct CreateTranslationRequestModel : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public CreateTranslationRequestModel(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateTranslationRequestResponseFormat.cs b/.dotnet/src/Generated/Models/CreateTranslationRequestResponseFormat.cs index 7c9a6ff50..39ef19095 100644 --- a/.dotnet/src/Generated/Models/CreateTranslationRequestResponseFormat.cs +++ b/.dotnet/src/Generated/Models/CreateTranslationRequestResponseFormat.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for response_format in CreateTranslationRequest. - public readonly partial struct CreateTranslationRequestResponseFormat : IEquatable + internal readonly partial struct CreateTranslationRequestResponseFormat : IEquatable { private readonly string _value; @@ -53,4 +53,3 @@ public CreateTranslationRequestResponseFormat(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/CreateTranslationResponse.Serialization.cs b/.dotnet/src/Generated/Models/CreateTranslationResponse.Serialization.cs index 10254dee9..46025de53 100644 --- a/.dotnet/src/Generated/Models/CreateTranslationResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateTranslationResponse.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class CreateTranslationResponse : IJsonModel + internal partial class CreateTranslationResponse : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -184,4 +184,3 @@ internal static CreateTranslationResponse FromResponse(PipelineResponse response } } } - diff --git a/.dotnet/src/Generated/Models/CreateTranslationResponse.cs b/.dotnet/src/Generated/Models/CreateTranslationResponse.cs index bc4f03097..0b8ebf971 100644 --- a/.dotnet/src/Generated/Models/CreateTranslationResponse.cs +++ b/.dotnet/src/Generated/Models/CreateTranslationResponse.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateTranslationResponse. - public partial class CreateTranslationResponse + internal partial class CreateTranslationResponse { /// /// Keeps track of any properties unknown to the library. @@ -92,4 +92,3 @@ internal CreateTranslationResponse() public IReadOnlyList Segments { get; } } } - diff --git a/.dotnet/src/Generated/Models/CreateTranslationResponseTask.cs b/.dotnet/src/Generated/Models/CreateTranslationResponseTask.cs index fe24f6343..db1eaf0f3 100644 --- a/.dotnet/src/Generated/Models/CreateTranslationResponseTask.cs +++ b/.dotnet/src/Generated/Models/CreateTranslationResponseTask.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The CreateTranslationResponse_task. - public readonly partial struct CreateTranslationResponseTask : IEquatable + internal readonly partial struct CreateTranslationResponseTask : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public CreateTranslationResponseTask(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.Serialization.cs b/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.Serialization.cs index 997b39d80..c3e231655 100644 --- a/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class DeleteAssistantFileResponse : IJsonModel + internal partial class DeleteAssistantFileResponse : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -134,4 +134,3 @@ internal static DeleteAssistantFileResponse FromResponse(PipelineResponse respon } } } - diff --git a/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.cs b/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.cs index 2172613e2..d4fe927c2 100644 --- a/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.cs +++ b/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.cs @@ -4,13 +4,13 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// /// Deletes the association between the assistant and the file, but does not delete the /// [File](/docs/api-reference/files) object itself. /// - public partial class DeleteAssistantFileResponse + internal partial class DeleteAssistantFileResponse { /// /// Keeps track of any properties unknown to the library. @@ -82,4 +82,3 @@ internal DeleteAssistantFileResponse() public DeleteAssistantFileResponseObject Object { get; } = DeleteAssistantFileResponseObject.AssistantFileDeleted; } } - diff --git a/.dotnet/src/Generated/Models/DeleteAssistantFileResponseObject.cs b/.dotnet/src/Generated/Models/DeleteAssistantFileResponseObject.cs index df0a1e5a6..d40f946af 100644 --- a/.dotnet/src/Generated/Models/DeleteAssistantFileResponseObject.cs +++ b/.dotnet/src/Generated/Models/DeleteAssistantFileResponseObject.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The DeleteAssistantFileResponse_object. - public readonly partial struct DeleteAssistantFileResponseObject : IEquatable + internal readonly partial struct DeleteAssistantFileResponseObject : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public DeleteAssistantFileResponseObject(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/DeleteAssistantResponse.Serialization.cs b/.dotnet/src/Generated/Models/DeleteAssistantResponse.Serialization.cs index 7b575f777..b6c0c9c62 100644 --- a/.dotnet/src/Generated/Models/DeleteAssistantResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/DeleteAssistantResponse.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class DeleteAssistantResponse : IJsonModel + internal partial class DeleteAssistantResponse : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -134,4 +134,3 @@ internal static DeleteAssistantResponse FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/DeleteAssistantResponse.cs b/.dotnet/src/Generated/Models/DeleteAssistantResponse.cs index 4ce652ffd..ab93ae628 100644 --- a/.dotnet/src/Generated/Models/DeleteAssistantResponse.cs +++ b/.dotnet/src/Generated/Models/DeleteAssistantResponse.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The DeleteAssistantResponse. - public partial class DeleteAssistantResponse + internal partial class DeleteAssistantResponse { /// /// Keeps track of any properties unknown to the library. @@ -79,4 +79,3 @@ internal DeleteAssistantResponse() public DeleteAssistantResponseObject Object { get; } = DeleteAssistantResponseObject.AssistantDeleted; } } - diff --git a/.dotnet/src/Generated/Models/DeleteAssistantResponseObject.cs b/.dotnet/src/Generated/Models/DeleteAssistantResponseObject.cs index 4ce063190..acc386d38 100644 --- a/.dotnet/src/Generated/Models/DeleteAssistantResponseObject.cs +++ b/.dotnet/src/Generated/Models/DeleteAssistantResponseObject.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The DeleteAssistantResponse_object. - public readonly partial struct DeleteAssistantResponseObject : IEquatable + internal readonly partial struct DeleteAssistantResponseObject : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public DeleteAssistantResponseObject(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/DeleteFileResponse.Serialization.cs b/.dotnet/src/Generated/Models/DeleteFileResponse.Serialization.cs index 21416fc19..2ff94aa3f 100644 --- a/.dotnet/src/Generated/Models/DeleteFileResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/DeleteFileResponse.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class DeleteFileResponse : IJsonModel + internal partial class DeleteFileResponse : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -134,4 +134,3 @@ internal static DeleteFileResponse FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/DeleteFileResponse.cs b/.dotnet/src/Generated/Models/DeleteFileResponse.cs index 06777ae53..5e91f557a 100644 --- a/.dotnet/src/Generated/Models/DeleteFileResponse.cs +++ b/.dotnet/src/Generated/Models/DeleteFileResponse.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The DeleteFileResponse. - public partial class DeleteFileResponse + internal partial class DeleteFileResponse { /// /// Keeps track of any properties unknown to the library. @@ -80,4 +80,3 @@ internal DeleteFileResponse() public bool Deleted { get; } } } - diff --git a/.dotnet/src/Generated/Models/DeleteFileResponseObject.cs b/.dotnet/src/Generated/Models/DeleteFileResponseObject.cs index 3f25d59f3..777211698 100644 --- a/.dotnet/src/Generated/Models/DeleteFileResponseObject.cs +++ b/.dotnet/src/Generated/Models/DeleteFileResponseObject.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The DeleteFileResponse_object. - public readonly partial struct DeleteFileResponseObject : IEquatable + internal readonly partial struct DeleteFileResponseObject : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public DeleteFileResponseObject(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/DeleteModelResponse.Serialization.cs b/.dotnet/src/Generated/Models/DeleteModelResponse.Serialization.cs index e1865ef13..afd368541 100644 --- a/.dotnet/src/Generated/Models/DeleteModelResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/DeleteModelResponse.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class DeleteModelResponse : IJsonModel + internal partial class DeleteModelResponse : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -134,4 +134,3 @@ internal static DeleteModelResponse FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/DeleteModelResponse.cs b/.dotnet/src/Generated/Models/DeleteModelResponse.cs index 96f122d77..1e5f9e687 100644 --- a/.dotnet/src/Generated/Models/DeleteModelResponse.cs +++ b/.dotnet/src/Generated/Models/DeleteModelResponse.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The DeleteModelResponse. - public partial class DeleteModelResponse + internal partial class DeleteModelResponse { /// /// Keeps track of any properties unknown to the library. @@ -79,4 +79,3 @@ internal DeleteModelResponse() public DeleteModelResponseObject Object { get; } = DeleteModelResponseObject.Model; } } - diff --git a/.dotnet/src/Generated/Models/DeleteModelResponseObject.cs b/.dotnet/src/Generated/Models/DeleteModelResponseObject.cs index 25f957c69..9a0e654a6 100644 --- a/.dotnet/src/Generated/Models/DeleteModelResponseObject.cs +++ b/.dotnet/src/Generated/Models/DeleteModelResponseObject.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The DeleteModelResponse_object. - public readonly partial struct DeleteModelResponseObject : IEquatable + internal readonly partial struct DeleteModelResponseObject : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public DeleteModelResponseObject(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/DeleteThreadResponse.Serialization.cs b/.dotnet/src/Generated/Models/DeleteThreadResponse.Serialization.cs index b6c04e508..ec4ac2da6 100644 --- a/.dotnet/src/Generated/Models/DeleteThreadResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/DeleteThreadResponse.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class DeleteThreadResponse : IJsonModel + internal partial class DeleteThreadResponse : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -134,4 +134,3 @@ internal static DeleteThreadResponse FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/DeleteThreadResponse.cs b/.dotnet/src/Generated/Models/DeleteThreadResponse.cs index 368b9ff80..425135cb5 100644 --- a/.dotnet/src/Generated/Models/DeleteThreadResponse.cs +++ b/.dotnet/src/Generated/Models/DeleteThreadResponse.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The DeleteThreadResponse. - public partial class DeleteThreadResponse + internal partial class DeleteThreadResponse { /// /// Keeps track of any properties unknown to the library. @@ -79,4 +79,3 @@ internal DeleteThreadResponse() public DeleteThreadResponseObject Object { get; } = DeleteThreadResponseObject.ThreadDeleted; } } - diff --git a/.dotnet/src/Generated/Models/DeleteThreadResponseObject.cs b/.dotnet/src/Generated/Models/DeleteThreadResponseObject.cs index 7e4b34167..5dcbdb507 100644 --- a/.dotnet/src/Generated/Models/DeleteThreadResponseObject.cs +++ b/.dotnet/src/Generated/Models/DeleteThreadResponseObject.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The DeleteThreadResponse_object. - public readonly partial struct DeleteThreadResponseObject : IEquatable + internal readonly partial struct DeleteThreadResponseObject : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public DeleteThreadResponseObject(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/Embedding.Serialization.cs b/.dotnet/src/Generated/Models/Embedding.Serialization.cs index b3506e51c..08a9811ea 100644 --- a/.dotnet/src/Generated/Models/Embedding.Serialization.cs +++ b/.dotnet/src/Generated/Models/Embedding.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class Embedding : IJsonModel + internal partial class Embedding : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -141,4 +141,3 @@ internal static Embedding FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/Embedding.cs b/.dotnet/src/Generated/Models/Embedding.cs index ecabc7df9..8e4f0cced 100644 --- a/.dotnet/src/Generated/Models/Embedding.cs +++ b/.dotnet/src/Generated/Models/Embedding.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Represents an embedding vector returned by embedding endpoint. - public partial class Embedding + internal partial class Embedding { /// /// Keeps track of any properties unknown to the library. @@ -126,4 +126,3 @@ internal Embedding() public EmbeddingObject Object { get; } = EmbeddingObject.Embedding; } } - diff --git a/.dotnet/src/Generated/Models/EmbeddingObject.cs b/.dotnet/src/Generated/Models/EmbeddingObject.cs index 2cc2f012c..6f4bac9bd 100644 --- a/.dotnet/src/Generated/Models/EmbeddingObject.cs +++ b/.dotnet/src/Generated/Models/EmbeddingObject.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The Embedding_object. - public readonly partial struct EmbeddingObject : IEquatable + internal readonly partial struct EmbeddingObject : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public EmbeddingObject(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/EmbeddingUsage.Serialization.cs b/.dotnet/src/Generated/Models/EmbeddingUsage.Serialization.cs index 23beb37ad..ca241d62e 100644 --- a/.dotnet/src/Generated/Models/EmbeddingUsage.Serialization.cs +++ b/.dotnet/src/Generated/Models/EmbeddingUsage.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class EmbeddingUsage : IJsonModel + internal partial class EmbeddingUsage : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -126,4 +126,3 @@ internal static EmbeddingUsage FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/EmbeddingUsage.cs b/.dotnet/src/Generated/Models/EmbeddingUsage.cs index 6c03d3210..a3c1bf356 100644 --- a/.dotnet/src/Generated/Models/EmbeddingUsage.cs +++ b/.dotnet/src/Generated/Models/EmbeddingUsage.cs @@ -3,10 +3,10 @@ using System; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The EmbeddingUsage. - public partial class EmbeddingUsage + internal partial class EmbeddingUsage { /// /// Keeps track of any properties unknown to the library. @@ -71,4 +71,3 @@ internal EmbeddingUsage() public long TotalTokens { get; } } } - diff --git a/.dotnet/src/Generated/Models/FineTuningJob.Serialization.cs b/.dotnet/src/Generated/Models/FineTuningJob.Serialization.cs index 930aa5fc5..c8457dfdf 100644 --- a/.dotnet/src/Generated/Models/FineTuningJob.Serialization.cs +++ b/.dotnet/src/Generated/Models/FineTuningJob.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class FineTuningJob : IJsonModel + internal partial class FineTuningJob : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -292,4 +292,3 @@ internal static FineTuningJob FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/FineTuningJob.cs b/.dotnet/src/Generated/Models/FineTuningJob.cs index 773d90651..52609ca25 100644 --- a/.dotnet/src/Generated/Models/FineTuningJob.cs +++ b/.dotnet/src/Generated/Models/FineTuningJob.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The FineTuningJob. - public partial class FineTuningJob + internal partial class FineTuningJob { /// /// Keeps track of any properties unknown to the library. @@ -233,4 +233,3 @@ internal FineTuningJob() public FineTuningJobError Error { get; } } } - diff --git a/.dotnet/src/Generated/Models/FineTuningJobError.Serialization.cs b/.dotnet/src/Generated/Models/FineTuningJobError.Serialization.cs index 6bfe0c908..fab47e3bd 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobError.Serialization.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobError.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class FineTuningJobError : IJsonModel + internal partial class FineTuningJobError : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -155,4 +155,3 @@ internal static FineTuningJobError FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/FineTuningJobError.cs b/.dotnet/src/Generated/Models/FineTuningJobError.cs index 98268009c..c3798392a 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobError.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobError.cs @@ -3,10 +3,10 @@ using System; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The FineTuningJobError. - public partial class FineTuningJobError + internal partial class FineTuningJobError { /// /// Keeps track of any properties unknown to the library. @@ -72,4 +72,3 @@ internal FineTuningJobError(string message, string code, string param, IDictiona public string Param { get; } } } - diff --git a/.dotnet/src/Generated/Models/FineTuningJobEvent.Serialization.cs b/.dotnet/src/Generated/Models/FineTuningJobEvent.Serialization.cs index f61e577d3..0176faabe 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobEvent.Serialization.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobEvent.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class FineTuningJobEvent : IJsonModel + internal partial class FineTuningJobEvent : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -150,4 +150,3 @@ internal static FineTuningJobEvent FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/FineTuningJobEvent.cs b/.dotnet/src/Generated/Models/FineTuningJobEvent.cs index 1ed3dacf3..30f900667 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobEvent.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobEvent.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The FineTuningJobEvent. - public partial class FineTuningJobEvent + internal partial class FineTuningJobEvent { /// /// Keeps track of any properties unknown to the library. @@ -95,4 +95,3 @@ internal FineTuningJobEvent() public string Message { get; } } } - diff --git a/.dotnet/src/Generated/Models/FineTuningJobEventLevel.cs b/.dotnet/src/Generated/Models/FineTuningJobEventLevel.cs index 1e0ae3a85..cc9aa24a5 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobEventLevel.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobEventLevel.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for level in FineTuningJobEvent. - public readonly partial struct FineTuningJobEventLevel : IEquatable + internal readonly partial struct FineTuningJobEventLevel : IEquatable { private readonly string _value; @@ -47,4 +47,3 @@ public FineTuningJobEventLevel(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.Serialization.cs b/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.Serialization.cs index 3b4a5c3aa..c08e0565b 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.Serialization.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class FineTuningJobHyperparameters : IJsonModel + internal partial class FineTuningJobHyperparameters : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -132,4 +132,3 @@ internal static FineTuningJobHyperparameters FromResponse(PipelineResponse respo } } } - diff --git a/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.cs b/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.cs index 830aef443..40a9d6547 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.cs @@ -3,10 +3,10 @@ using System; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The FineTuningJobHyperparameters. - public partial class FineTuningJobHyperparameters + internal partial class FineTuningJobHyperparameters { /// /// Keeps track of any properties unknown to the library. @@ -108,4 +108,3 @@ internal FineTuningJobHyperparameters(BinaryData nEpochs, IDictionary The FineTuningJob_object. - public readonly partial struct FineTuningJobObject : IEquatable + internal readonly partial struct FineTuningJobObject : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public FineTuningJobObject(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/FineTuningJobStatus.cs b/.dotnet/src/Generated/Models/FineTuningJobStatus.cs index f9715b5b6..73c350bca 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobStatus.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobStatus.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for status in FineTuningJob. - public readonly partial struct FineTuningJobStatus : IEquatable + internal readonly partial struct FineTuningJobStatus : IEquatable { private readonly string _value; @@ -56,4 +56,3 @@ public FineTuningJobStatus(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/FunctionObject.Serialization.cs b/.dotnet/src/Generated/Models/FunctionObject.Serialization.cs index fec24f853..1b0e30bd1 100644 --- a/.dotnet/src/Generated/Models/FunctionObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/FunctionObject.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class FunctionObject : IJsonModel + internal partial class FunctionObject : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -144,4 +144,3 @@ internal static FunctionObject FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/FunctionObject.cs b/.dotnet/src/Generated/Models/FunctionObject.cs index ddd65ebfa..456b879f2 100644 --- a/.dotnet/src/Generated/Models/FunctionObject.cs +++ b/.dotnet/src/Generated/Models/FunctionObject.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The FunctionObject. - public partial class FunctionObject + internal partial class FunctionObject { /// /// Keeps track of any properties unknown to the library. @@ -92,4 +92,3 @@ internal FunctionObject() public FunctionParameters Parameters { get; set; } } } - diff --git a/.dotnet/src/Generated/Models/FunctionParameters.Serialization.cs b/.dotnet/src/Generated/Models/FunctionParameters.Serialization.cs index 3d473765a..5af866e0b 100644 --- a/.dotnet/src/Generated/Models/FunctionParameters.Serialization.cs +++ b/.dotnet/src/Generated/Models/FunctionParameters.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class FunctionParameters : IJsonModel + internal partial class FunctionParameters : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -104,4 +104,3 @@ internal static FunctionParameters FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/FunctionParameters.cs b/.dotnet/src/Generated/Models/FunctionParameters.cs index 8490bdc5f..bb8e5abff 100644 --- a/.dotnet/src/Generated/Models/FunctionParameters.cs +++ b/.dotnet/src/Generated/Models/FunctionParameters.cs @@ -4,7 +4,7 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// /// The parameters the functions accepts, described as a JSON Schema object. See the @@ -13,7 +13,7 @@ namespace OpenAI.Models /// about the format.\n\nTo describe a function that accepts no parameters, provide the value /// `{\"type\": \"object\", \"properties\": {}}`. /// - public partial class FunctionParameters + internal partial class FunctionParameters { /// Initializes a new instance of . public FunctionParameters() @@ -61,4 +61,3 @@ internal FunctionParameters(IDictionary additionalProperties public IDictionary AdditionalProperties { get; } } } - diff --git a/.dotnet/src/Generated/Models/Image.Serialization.cs b/.dotnet/src/Generated/Models/Image.Serialization.cs index dc41f82a8..e568bb123 100644 --- a/.dotnet/src/Generated/Models/Image.Serialization.cs +++ b/.dotnet/src/Generated/Models/Image.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class Image : IJsonModel + internal partial class Image : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -151,4 +151,3 @@ internal static Image FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/Image.cs b/.dotnet/src/Generated/Models/Image.cs index 7d6c304f2..ca021414d 100644 --- a/.dotnet/src/Generated/Models/Image.cs +++ b/.dotnet/src/Generated/Models/Image.cs @@ -3,10 +3,10 @@ using System; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Represents the url or the content of an image generated by the OpenAI API. - public partial class Image + internal partial class Image { /// /// Keeps track of any properties unknown to the library. @@ -81,4 +81,3 @@ internal Image(BinaryData b64Json, Uri url, string revisedPrompt, IDictionary + internal partial class ImagesResponse : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -136,4 +136,3 @@ internal static ImagesResponse FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/ImagesResponse.cs b/.dotnet/src/Generated/Models/ImagesResponse.cs index 44b649f3f..c73c3741c 100644 --- a/.dotnet/src/Generated/Models/ImagesResponse.cs +++ b/.dotnet/src/Generated/Models/ImagesResponse.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ImagesResponse. - public partial class ImagesResponse + internal partial class ImagesResponse { /// /// Keeps track of any properties unknown to the library. @@ -76,4 +76,3 @@ internal ImagesResponse() public IReadOnlyList Data { get; } } } - diff --git a/.dotnet/src/Generated/Models/ListAssistantFilesResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListAssistantFilesResponse.Serialization.cs index 6e6f9758b..d0c12f66b 100644 --- a/.dotnet/src/Generated/Models/ListAssistantFilesResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListAssistantFilesResponse.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class ListAssistantFilesResponse : IJsonModel + internal partial class ListAssistantFilesResponse : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -160,4 +160,3 @@ internal static ListAssistantFilesResponse FromResponse(PipelineResponse respons } } } - diff --git a/.dotnet/src/Generated/Models/ListAssistantFilesResponse.cs b/.dotnet/src/Generated/Models/ListAssistantFilesResponse.cs index 4537942a4..96063de70 100644 --- a/.dotnet/src/Generated/Models/ListAssistantFilesResponse.cs +++ b/.dotnet/src/Generated/Models/ListAssistantFilesResponse.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ListAssistantFilesResponse. - public partial class ListAssistantFilesResponse + internal partial class ListAssistantFilesResponse { /// /// Keeps track of any properties unknown to the library. @@ -95,4 +95,3 @@ internal ListAssistantFilesResponse() public bool HasMore { get; } } } - diff --git a/.dotnet/src/Generated/Models/ListAssistantFilesResponseObject.cs b/.dotnet/src/Generated/Models/ListAssistantFilesResponseObject.cs index 4b8e72c7e..bfb6cd5f6 100644 --- a/.dotnet/src/Generated/Models/ListAssistantFilesResponseObject.cs +++ b/.dotnet/src/Generated/Models/ListAssistantFilesResponseObject.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ListAssistantFilesResponse_object. - public readonly partial struct ListAssistantFilesResponseObject : IEquatable + internal readonly partial struct ListAssistantFilesResponseObject : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public ListAssistantFilesResponseObject(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/ListAssistantsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListAssistantsResponse.Serialization.cs index 573a35240..a94da2024 100644 --- a/.dotnet/src/Generated/Models/ListAssistantsResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListAssistantsResponse.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class ListAssistantsResponse : IJsonModel + internal partial class ListAssistantsResponse : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -160,4 +160,3 @@ internal static ListAssistantsResponse FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/ListAssistantsResponse.cs b/.dotnet/src/Generated/Models/ListAssistantsResponse.cs index bf553f319..032d0dd9a 100644 --- a/.dotnet/src/Generated/Models/ListAssistantsResponse.cs +++ b/.dotnet/src/Generated/Models/ListAssistantsResponse.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ListAssistantsResponse. - public partial class ListAssistantsResponse + internal partial class ListAssistantsResponse { /// /// Keeps track of any properties unknown to the library. @@ -95,4 +95,3 @@ internal ListAssistantsResponse() public bool HasMore { get; } } } - diff --git a/.dotnet/src/Generated/Models/ListAssistantsResponseObject.cs b/.dotnet/src/Generated/Models/ListAssistantsResponseObject.cs index 207fe09fa..8c9ff2360 100644 --- a/.dotnet/src/Generated/Models/ListAssistantsResponseObject.cs +++ b/.dotnet/src/Generated/Models/ListAssistantsResponseObject.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ListAssistantsResponse_object. - public readonly partial struct ListAssistantsResponseObject : IEquatable + internal readonly partial struct ListAssistantsResponseObject : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public ListAssistantsResponseObject(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/ListFilesResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListFilesResponse.Serialization.cs index 24134e771..088451116 100644 --- a/.dotnet/src/Generated/Models/ListFilesResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListFilesResponse.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class ListFilesResponse : IJsonModel + internal partial class ListFilesResponse : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -136,4 +136,3 @@ internal static ListFilesResponse FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/ListFilesResponse.cs b/.dotnet/src/Generated/Models/ListFilesResponse.cs index 7447294ac..a79ec60fc 100644 --- a/.dotnet/src/Generated/Models/ListFilesResponse.cs +++ b/.dotnet/src/Generated/Models/ListFilesResponse.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ListFilesResponse. - public partial class ListFilesResponse + internal partial class ListFilesResponse { /// /// Keeps track of any properties unknown to the library. @@ -74,4 +74,3 @@ internal ListFilesResponse() public ListFilesResponseObject Object { get; } = ListFilesResponseObject.List; } } - diff --git a/.dotnet/src/Generated/Models/ListFilesResponseObject.cs b/.dotnet/src/Generated/Models/ListFilesResponseObject.cs index 1c8be15c3..c2a5e6e52 100644 --- a/.dotnet/src/Generated/Models/ListFilesResponseObject.cs +++ b/.dotnet/src/Generated/Models/ListFilesResponseObject.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ListFilesResponse_object. - public readonly partial struct ListFilesResponseObject : IEquatable + internal readonly partial struct ListFilesResponseObject : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public ListFilesResponseObject(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.Serialization.cs index 588d06c98..b2595af03 100644 --- a/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class ListFineTuningJobEventsResponse : IJsonModel + internal partial class ListFineTuningJobEventsResponse : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -136,4 +136,3 @@ internal static ListFineTuningJobEventsResponse FromResponse(PipelineResponse re } } } - diff --git a/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.cs b/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.cs index b79f9a929..6ff86e39b 100644 --- a/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.cs +++ b/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ListFineTuningJobEventsResponse. - public partial class ListFineTuningJobEventsResponse + internal partial class ListFineTuningJobEventsResponse { /// /// Keeps track of any properties unknown to the library. @@ -77,4 +77,3 @@ internal ListFineTuningJobEventsResponse() public IReadOnlyList Data { get; } } } - diff --git a/.dotnet/src/Generated/Models/ListMessageFilesResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListMessageFilesResponse.Serialization.cs index c8585eaf5..6f16b2c6c 100644 --- a/.dotnet/src/Generated/Models/ListMessageFilesResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListMessageFilesResponse.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class ListMessageFilesResponse : IJsonModel + internal partial class ListMessageFilesResponse : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -160,4 +160,3 @@ internal static ListMessageFilesResponse FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/ListMessageFilesResponse.cs b/.dotnet/src/Generated/Models/ListMessageFilesResponse.cs index be35d9455..80fdc2499 100644 --- a/.dotnet/src/Generated/Models/ListMessageFilesResponse.cs +++ b/.dotnet/src/Generated/Models/ListMessageFilesResponse.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ListMessageFilesResponse. - public partial class ListMessageFilesResponse + internal partial class ListMessageFilesResponse { /// /// Keeps track of any properties unknown to the library. @@ -95,4 +95,3 @@ internal ListMessageFilesResponse() public bool HasMore { get; } } } - diff --git a/.dotnet/src/Generated/Models/ListMessageFilesResponseObject.cs b/.dotnet/src/Generated/Models/ListMessageFilesResponseObject.cs index 01cd0514a..b1eae36d8 100644 --- a/.dotnet/src/Generated/Models/ListMessageFilesResponseObject.cs +++ b/.dotnet/src/Generated/Models/ListMessageFilesResponseObject.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ListMessageFilesResponse_object. - public readonly partial struct ListMessageFilesResponseObject : IEquatable + internal readonly partial struct ListMessageFilesResponseObject : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public ListMessageFilesResponseObject(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/ListMessagesResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListMessagesResponse.Serialization.cs index fd1dad634..dbf0afd83 100644 --- a/.dotnet/src/Generated/Models/ListMessagesResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListMessagesResponse.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class ListMessagesResponse : IJsonModel + internal partial class ListMessagesResponse : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -160,4 +160,3 @@ internal static ListMessagesResponse FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/ListMessagesResponse.cs b/.dotnet/src/Generated/Models/ListMessagesResponse.cs index 56ef1f2ec..fc2d652e0 100644 --- a/.dotnet/src/Generated/Models/ListMessagesResponse.cs +++ b/.dotnet/src/Generated/Models/ListMessagesResponse.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ListMessagesResponse. - public partial class ListMessagesResponse + internal partial class ListMessagesResponse { /// /// Keeps track of any properties unknown to the library. @@ -95,4 +95,3 @@ internal ListMessagesResponse() public bool HasMore { get; } } } - diff --git a/.dotnet/src/Generated/Models/ListMessagesResponseObject.cs b/.dotnet/src/Generated/Models/ListMessagesResponseObject.cs index 01ad83164..a3d4be1eb 100644 --- a/.dotnet/src/Generated/Models/ListMessagesResponseObject.cs +++ b/.dotnet/src/Generated/Models/ListMessagesResponseObject.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ListMessagesResponse_object. - public readonly partial struct ListMessagesResponseObject : IEquatable + internal readonly partial struct ListMessagesResponseObject : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public ListMessagesResponseObject(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/ListModelsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListModelsResponse.Serialization.cs index 36da18e24..45281c137 100644 --- a/.dotnet/src/Generated/Models/ListModelsResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListModelsResponse.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class ListModelsResponse : IJsonModel + internal partial class ListModelsResponse : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -136,4 +136,3 @@ internal static ListModelsResponse FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/ListModelsResponse.cs b/.dotnet/src/Generated/Models/ListModelsResponse.cs index ee8f8e350..b0751334c 100644 --- a/.dotnet/src/Generated/Models/ListModelsResponse.cs +++ b/.dotnet/src/Generated/Models/ListModelsResponse.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ListModelsResponse. - public partial class ListModelsResponse + internal partial class ListModelsResponse { /// /// Keeps track of any properties unknown to the library. @@ -75,4 +75,3 @@ internal ListModelsResponse() public IReadOnlyList Data { get; } } } - diff --git a/.dotnet/src/Generated/Models/ListModelsResponseObject.cs b/.dotnet/src/Generated/Models/ListModelsResponseObject.cs index 081da58be..b9e471c75 100644 --- a/.dotnet/src/Generated/Models/ListModelsResponseObject.cs +++ b/.dotnet/src/Generated/Models/ListModelsResponseObject.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ListModelsResponse_object. - public readonly partial struct ListModelsResponseObject : IEquatable + internal readonly partial struct ListModelsResponseObject : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public ListModelsResponseObject(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/ListOrder.cs b/.dotnet/src/Generated/Models/ListOrder.cs index 95b097763..0a2a6e6cf 100644 --- a/.dotnet/src/Generated/Models/ListOrder.cs +++ b/.dotnet/src/Generated/Models/ListOrder.cs @@ -3,9 +3,9 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public readonly partial struct ListOrder : IEquatable + internal readonly partial struct ListOrder : IEquatable { private readonly string _value; @@ -43,4 +43,3 @@ public ListOrder(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.Serialization.cs index 16a324034..c1344e078 100644 --- a/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class ListPaginatedFineTuningJobsResponse : IJsonModel + internal partial class ListPaginatedFineTuningJobsResponse : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -144,4 +144,3 @@ internal static ListPaginatedFineTuningJobsResponse FromResponse(PipelineRespons } } } - diff --git a/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.cs b/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.cs index 3bb6a7d15..e99c79598 100644 --- a/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.cs +++ b/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ListPaginatedFineTuningJobsResponse. - public partial class ListPaginatedFineTuningJobsResponse + internal partial class ListPaginatedFineTuningJobsResponse { /// /// Keeps track of any properties unknown to the library. @@ -83,4 +83,3 @@ internal ListPaginatedFineTuningJobsResponse() public bool HasMore { get; } } } - diff --git a/.dotnet/src/Generated/Models/ListRunStepsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListRunStepsResponse.Serialization.cs index a91044a98..4a9b71ed8 100644 --- a/.dotnet/src/Generated/Models/ListRunStepsResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListRunStepsResponse.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class ListRunStepsResponse : IJsonModel + internal partial class ListRunStepsResponse : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -160,4 +160,3 @@ internal static ListRunStepsResponse FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/ListRunStepsResponse.cs b/.dotnet/src/Generated/Models/ListRunStepsResponse.cs index 641a91e04..6582d2fc6 100644 --- a/.dotnet/src/Generated/Models/ListRunStepsResponse.cs +++ b/.dotnet/src/Generated/Models/ListRunStepsResponse.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ListRunStepsResponse. - public partial class ListRunStepsResponse + internal partial class ListRunStepsResponse { /// /// Keeps track of any properties unknown to the library. @@ -95,4 +95,3 @@ internal ListRunStepsResponse() public bool HasMore { get; } } } - diff --git a/.dotnet/src/Generated/Models/ListRunStepsResponseObject.cs b/.dotnet/src/Generated/Models/ListRunStepsResponseObject.cs index 2b613b3e4..98dd2d37c 100644 --- a/.dotnet/src/Generated/Models/ListRunStepsResponseObject.cs +++ b/.dotnet/src/Generated/Models/ListRunStepsResponseObject.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ListRunStepsResponse_object. - public readonly partial struct ListRunStepsResponseObject : IEquatable + internal readonly partial struct ListRunStepsResponseObject : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public ListRunStepsResponseObject(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/ListRunsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListRunsResponse.Serialization.cs index a934e890e..c6b501c8a 100644 --- a/.dotnet/src/Generated/Models/ListRunsResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListRunsResponse.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class ListRunsResponse : IJsonModel + internal partial class ListRunsResponse : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -160,4 +160,3 @@ internal static ListRunsResponse FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/ListRunsResponse.cs b/.dotnet/src/Generated/Models/ListRunsResponse.cs index f3fb538c7..233e26060 100644 --- a/.dotnet/src/Generated/Models/ListRunsResponse.cs +++ b/.dotnet/src/Generated/Models/ListRunsResponse.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ListRunsResponse. - public partial class ListRunsResponse + internal partial class ListRunsResponse { /// /// Keeps track of any properties unknown to the library. @@ -95,4 +95,3 @@ internal ListRunsResponse() public bool HasMore { get; } } } - diff --git a/.dotnet/src/Generated/Models/ListRunsResponseObject.cs b/.dotnet/src/Generated/Models/ListRunsResponseObject.cs index f8a80ed2d..f3f0e1a1e 100644 --- a/.dotnet/src/Generated/Models/ListRunsResponseObject.cs +++ b/.dotnet/src/Generated/Models/ListRunsResponseObject.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ListRunsResponse_object. - public readonly partial struct ListRunsResponseObject : IEquatable + internal readonly partial struct ListRunsResponseObject : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public ListRunsResponseObject(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/MessageFileObject.Serialization.cs b/.dotnet/src/Generated/Models/MessageFileObject.Serialization.cs index 62d4e0d8e..61eb5abae 100644 --- a/.dotnet/src/Generated/Models/MessageFileObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/MessageFileObject.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class MessageFileObject : IJsonModel + internal partial class MessageFileObject : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -142,4 +142,3 @@ internal static MessageFileObject FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/MessageFileObject.cs b/.dotnet/src/Generated/Models/MessageFileObject.cs index 1f4f67e75..508d68981 100644 --- a/.dotnet/src/Generated/Models/MessageFileObject.cs +++ b/.dotnet/src/Generated/Models/MessageFileObject.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// A list of files attached to a `message`. - public partial class MessageFileObject + internal partial class MessageFileObject { /// /// Keeps track of any properties unknown to the library. @@ -87,4 +87,3 @@ internal MessageFileObject() public string MessageId { get; } } } - diff --git a/.dotnet/src/Generated/Models/MessageFileObjectObject.cs b/.dotnet/src/Generated/Models/MessageFileObjectObject.cs index f1185adf5..19c46e334 100644 --- a/.dotnet/src/Generated/Models/MessageFileObjectObject.cs +++ b/.dotnet/src/Generated/Models/MessageFileObjectObject.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The MessageFileObject_object. - public readonly partial struct MessageFileObjectObject : IEquatable + internal readonly partial struct MessageFileObjectObject : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public MessageFileObjectObject(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/MessageObject.Serialization.cs b/.dotnet/src/Generated/Models/MessageObject.Serialization.cs index bc6f566b7..27a044c39 100644 --- a/.dotnet/src/Generated/Models/MessageObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/MessageObject.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class MessageObject : IJsonModel + internal partial class MessageObject : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -276,4 +276,3 @@ internal static MessageObject FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/MessageObject.cs b/.dotnet/src/Generated/Models/MessageObject.cs index 0ed781f8d..f796b78be 100644 --- a/.dotnet/src/Generated/Models/MessageObject.cs +++ b/.dotnet/src/Generated/Models/MessageObject.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The MessageObject. - public partial class MessageObject + internal partial class MessageObject { /// /// Keeps track of any properties unknown to the library. @@ -197,4 +197,3 @@ internal MessageObject() public IReadOnlyDictionary Metadata { get; } } } - diff --git a/.dotnet/src/Generated/Models/MessageObjectObject.cs b/.dotnet/src/Generated/Models/MessageObjectObject.cs index 978ab0a6a..120249ab6 100644 --- a/.dotnet/src/Generated/Models/MessageObjectObject.cs +++ b/.dotnet/src/Generated/Models/MessageObjectObject.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The MessageObject_object. - public readonly partial struct MessageObjectObject : IEquatable + internal readonly partial struct MessageObjectObject : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public MessageObjectObject(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/MessageObjectRole.cs b/.dotnet/src/Generated/Models/MessageObjectRole.cs index 53ee3cafe..1b637beb6 100644 --- a/.dotnet/src/Generated/Models/MessageObjectRole.cs +++ b/.dotnet/src/Generated/Models/MessageObjectRole.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for role in MessageObject. - public readonly partial struct MessageObjectRole : IEquatable + internal readonly partial struct MessageObjectRole : IEquatable { private readonly string _value; @@ -44,4 +44,3 @@ public MessageObjectRole(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/Model.Serialization.cs b/.dotnet/src/Generated/Models/Model.Serialization.cs index 4b0cb8d8a..13d7f1f3a 100644 --- a/.dotnet/src/Generated/Models/Model.Serialization.cs +++ b/.dotnet/src/Generated/Models/Model.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class Model : IJsonModel + internal partial class Model : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -142,4 +142,3 @@ internal static Model FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/Model.cs b/.dotnet/src/Generated/Models/Model.cs index 66fe38632..d5b78f33f 100644 --- a/.dotnet/src/Generated/Models/Model.cs +++ b/.dotnet/src/Generated/Models/Model.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Describes an OpenAI model offering that can be used with the API. - public partial class Model + internal partial class Model { /// /// Keeps track of any properties unknown to the library. @@ -87,4 +87,3 @@ internal Model() public string OwnedBy { get; } } } - diff --git a/.dotnet/src/Generated/Models/ModelObject.cs b/.dotnet/src/Generated/Models/ModelObject.cs index 70fd47f04..5971c3917 100644 --- a/.dotnet/src/Generated/Models/ModelObject.cs +++ b/.dotnet/src/Generated/Models/ModelObject.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The Model_object. - public readonly partial struct ModelObject : IEquatable + internal readonly partial struct ModelObject : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public ModelObject(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/ModifyAssistantRequest.Serialization.cs b/.dotnet/src/Generated/Models/ModifyAssistantRequest.Serialization.cs index 7635f00f3..41c39aac7 100644 --- a/.dotnet/src/Generated/Models/ModifyAssistantRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/ModifyAssistantRequest.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class ModifyAssistantRequest : IJsonModel + internal partial class ModifyAssistantRequest : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -292,4 +292,3 @@ internal static ModifyAssistantRequest FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/ModifyAssistantRequest.cs b/.dotnet/src/Generated/Models/ModifyAssistantRequest.cs index 9882b6462..ae45a5a00 100644 --- a/.dotnet/src/Generated/Models/ModifyAssistantRequest.cs +++ b/.dotnet/src/Generated/Models/ModifyAssistantRequest.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ModifyAssistantRequest. - public partial class ModifyAssistantRequest + internal partial class ModifyAssistantRequest { /// /// Keeps track of any properties unknown to the library. @@ -143,4 +143,3 @@ internal ModifyAssistantRequest(string model, string name, string description, s public IDictionary Metadata { get; set; } } } - diff --git a/.dotnet/src/Generated/Models/ModifyMessageRequest.Serialization.cs b/.dotnet/src/Generated/Models/ModifyMessageRequest.Serialization.cs index 2c5c37dec..bf8d29430 100644 --- a/.dotnet/src/Generated/Models/ModifyMessageRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/ModifyMessageRequest.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class ModifyMessageRequest : IJsonModel + internal partial class ModifyMessageRequest : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -143,4 +143,3 @@ internal static ModifyMessageRequest FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/ModifyMessageRequest.cs b/.dotnet/src/Generated/Models/ModifyMessageRequest.cs index a087c656d..72cc4c5bc 100644 --- a/.dotnet/src/Generated/Models/ModifyMessageRequest.cs +++ b/.dotnet/src/Generated/Models/ModifyMessageRequest.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ModifyMessageRequest. - public partial class ModifyMessageRequest + internal partial class ModifyMessageRequest { /// /// Keeps track of any properties unknown to the library. @@ -68,4 +68,3 @@ internal ModifyMessageRequest(IDictionary metadata, IDictionary< public IDictionary Metadata { get; set; } } } - diff --git a/.dotnet/src/Generated/Models/ModifyRunRequest.Serialization.cs b/.dotnet/src/Generated/Models/ModifyRunRequest.Serialization.cs index 1976fd93e..40da11ec2 100644 --- a/.dotnet/src/Generated/Models/ModifyRunRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/ModifyRunRequest.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class ModifyRunRequest : IJsonModel + internal partial class ModifyRunRequest : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -143,4 +143,3 @@ internal static ModifyRunRequest FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/ModifyRunRequest.cs b/.dotnet/src/Generated/Models/ModifyRunRequest.cs index 1be502ea5..6def465a0 100644 --- a/.dotnet/src/Generated/Models/ModifyRunRequest.cs +++ b/.dotnet/src/Generated/Models/ModifyRunRequest.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ModifyRunRequest. - public partial class ModifyRunRequest + internal partial class ModifyRunRequest { /// /// Keeps track of any properties unknown to the library. @@ -68,4 +68,3 @@ internal ModifyRunRequest(IDictionary metadata, IDictionary Metadata { get; set; } } } - diff --git a/.dotnet/src/Generated/Models/ModifyThreadRequest.Serialization.cs b/.dotnet/src/Generated/Models/ModifyThreadRequest.Serialization.cs index e5bc72917..5c6618494 100644 --- a/.dotnet/src/Generated/Models/ModifyThreadRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/ModifyThreadRequest.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class ModifyThreadRequest : IJsonModel + internal partial class ModifyThreadRequest : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -143,4 +143,3 @@ internal static ModifyThreadRequest FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/ModifyThreadRequest.cs b/.dotnet/src/Generated/Models/ModifyThreadRequest.cs index 084d68686..df90174fa 100644 --- a/.dotnet/src/Generated/Models/ModifyThreadRequest.cs +++ b/.dotnet/src/Generated/Models/ModifyThreadRequest.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ModifyThreadRequest. - public partial class ModifyThreadRequest + internal partial class ModifyThreadRequest { /// /// Keeps track of any properties unknown to the library. @@ -68,4 +68,3 @@ internal ModifyThreadRequest(IDictionary metadata, IDictionary Metadata { get; set; } } } - diff --git a/.dotnet/src/Generated/Models/OpenAIFile.Serialization.cs b/.dotnet/src/Generated/Models/OpenAIFile.Serialization.cs index fe73a6958..98890a027 100644 --- a/.dotnet/src/Generated/Models/OpenAIFile.Serialization.cs +++ b/.dotnet/src/Generated/Models/OpenAIFile.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class OpenAIFile : IJsonModel + internal partial class OpenAIFile : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -177,4 +177,3 @@ internal static OpenAIFile FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/OpenAIFile.cs b/.dotnet/src/Generated/Models/OpenAIFile.cs index 05b42f6de..99f8e94ad 100644 --- a/.dotnet/src/Generated/Models/OpenAIFile.cs +++ b/.dotnet/src/Generated/Models/OpenAIFile.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The `File` object represents a document that has been uploaded to OpenAI. - public partial class OpenAIFile + internal partial class OpenAIFile { /// /// Keeps track of any properties unknown to the library. @@ -133,4 +133,3 @@ internal OpenAIFile() public string StatusDetails { get; } } } - diff --git a/.dotnet/src/Generated/Models/OpenAIFileObject.cs b/.dotnet/src/Generated/Models/OpenAIFileObject.cs index 268a0888e..db29f0450 100644 --- a/.dotnet/src/Generated/Models/OpenAIFileObject.cs +++ b/.dotnet/src/Generated/Models/OpenAIFileObject.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The OpenAIFile_object. - public readonly partial struct OpenAIFileObject : IEquatable + internal readonly partial struct OpenAIFileObject : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public OpenAIFileObject(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/OpenAIFilePurpose.cs b/.dotnet/src/Generated/Models/OpenAIFilePurpose.cs index 98a369e91..97d4f29b4 100644 --- a/.dotnet/src/Generated/Models/OpenAIFilePurpose.cs +++ b/.dotnet/src/Generated/Models/OpenAIFilePurpose.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for purpose in OpenAIFile. - public readonly partial struct OpenAIFilePurpose : IEquatable + internal readonly partial struct OpenAIFilePurpose : IEquatable { private readonly string _value; @@ -50,4 +50,3 @@ public OpenAIFilePurpose(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/OpenAIFileStatus.cs b/.dotnet/src/Generated/Models/OpenAIFileStatus.cs index cddc7cf60..bd8c906d5 100644 --- a/.dotnet/src/Generated/Models/OpenAIFileStatus.cs +++ b/.dotnet/src/Generated/Models/OpenAIFileStatus.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for status in OpenAIFile. - public readonly partial struct OpenAIFileStatus : IEquatable + internal readonly partial struct OpenAIFileStatus : IEquatable { private readonly string _value; @@ -47,4 +47,3 @@ public OpenAIFileStatus(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/RunCompletionUsage.Serialization.cs b/.dotnet/src/Generated/Models/RunCompletionUsage.Serialization.cs index b730fa9c8..b1cdb73da 100644 --- a/.dotnet/src/Generated/Models/RunCompletionUsage.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunCompletionUsage.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class RunCompletionUsage : IJsonModel + internal partial class RunCompletionUsage : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -134,4 +134,3 @@ internal static RunCompletionUsage FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/RunCompletionUsage.cs b/.dotnet/src/Generated/Models/RunCompletionUsage.cs index a1bd07938..8e804dce9 100644 --- a/.dotnet/src/Generated/Models/RunCompletionUsage.cs +++ b/.dotnet/src/Generated/Models/RunCompletionUsage.cs @@ -3,13 +3,13 @@ using System; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// /// Usage statistics related to the run. This value will be `null` if the run is not in a terminal /// state (i.e. `in_progress`, `queued`, etc.). /// - public partial class RunCompletionUsage + internal partial class RunCompletionUsage { /// /// Keeps track of any properties unknown to the library. @@ -80,4 +80,3 @@ internal RunCompletionUsage() public long TotalTokens { get; } } } - diff --git a/.dotnet/src/Generated/Models/RunObject.Serialization.cs b/.dotnet/src/Generated/Models/RunObject.Serialization.cs index 1c7779a88..07fa205c1 100644 --- a/.dotnet/src/Generated/Models/RunObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunObject.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class RunObject : IJsonModel + internal partial class RunObject : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -408,4 +408,3 @@ internal static RunObject FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/RunObject.cs b/.dotnet/src/Generated/Models/RunObject.cs index a1baf8de2..282cac58a 100644 --- a/.dotnet/src/Generated/Models/RunObject.cs +++ b/.dotnet/src/Generated/Models/RunObject.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Represents an execution run on a [thread](/docs/api-reference/threads). - public partial class RunObject + internal partial class RunObject { /// /// Keeps track of any properties unknown to the library. @@ -260,4 +260,3 @@ internal RunObject() public RunCompletionUsage Usage { get; } } } - diff --git a/.dotnet/src/Generated/Models/RunObjectLastError.Serialization.cs b/.dotnet/src/Generated/Models/RunObjectLastError.Serialization.cs index f3486aafe..6466b1546 100644 --- a/.dotnet/src/Generated/Models/RunObjectLastError.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunObjectLastError.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class RunObjectLastError : IJsonModel + internal partial class RunObjectLastError : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -126,4 +126,3 @@ internal static RunObjectLastError FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/RunObjectLastError.cs b/.dotnet/src/Generated/Models/RunObjectLastError.cs index b46274c65..b824da830 100644 --- a/.dotnet/src/Generated/Models/RunObjectLastError.cs +++ b/.dotnet/src/Generated/Models/RunObjectLastError.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The RunObjectLastError. - public partial class RunObjectLastError + internal partial class RunObjectLastError { /// /// Keeps track of any properties unknown to the library. @@ -75,4 +75,3 @@ internal RunObjectLastError() public string Message { get; } } } - diff --git a/.dotnet/src/Generated/Models/RunObjectLastErrorCode.cs b/.dotnet/src/Generated/Models/RunObjectLastErrorCode.cs index d851f2397..500d3a25a 100644 --- a/.dotnet/src/Generated/Models/RunObjectLastErrorCode.cs +++ b/.dotnet/src/Generated/Models/RunObjectLastErrorCode.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for code in RunObjectLastError. - public readonly partial struct RunObjectLastErrorCode : IEquatable + internal readonly partial struct RunObjectLastErrorCode : IEquatable { private readonly string _value; @@ -44,4 +44,3 @@ public RunObjectLastErrorCode(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/RunObjectObject.cs b/.dotnet/src/Generated/Models/RunObjectObject.cs index 19925055a..f03e8122b 100644 --- a/.dotnet/src/Generated/Models/RunObjectObject.cs +++ b/.dotnet/src/Generated/Models/RunObjectObject.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The RunObject_object. - public readonly partial struct RunObjectObject : IEquatable + internal readonly partial struct RunObjectObject : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public RunObjectObject(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/RunObjectRequiredAction.Serialization.cs b/.dotnet/src/Generated/Models/RunObjectRequiredAction.Serialization.cs index 98fb7bbc1..b20e400db 100644 --- a/.dotnet/src/Generated/Models/RunObjectRequiredAction.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunObjectRequiredAction.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class RunObjectRequiredAction : IJsonModel + internal partial class RunObjectRequiredAction : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -126,4 +126,3 @@ internal static RunObjectRequiredAction FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/RunObjectRequiredAction.cs b/.dotnet/src/Generated/Models/RunObjectRequiredAction.cs index 034fedcca..c3515dfbd 100644 --- a/.dotnet/src/Generated/Models/RunObjectRequiredAction.cs +++ b/.dotnet/src/Generated/Models/RunObjectRequiredAction.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The RunObjectRequiredAction. - public partial class RunObjectRequiredAction + internal partial class RunObjectRequiredAction { /// /// Keeps track of any properties unknown to the library. @@ -74,4 +74,3 @@ internal RunObjectRequiredAction() public RunObjectRequiredActionSubmitToolOutputs SubmitToolOutputs { get; } } } - diff --git a/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.Serialization.cs b/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.Serialization.cs index 0f374b56a..79032ea03 100644 --- a/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class RunObjectRequiredActionSubmitToolOutputs : IJsonModel + internal partial class RunObjectRequiredActionSubmitToolOutputs : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -128,4 +128,3 @@ internal static RunObjectRequiredActionSubmitToolOutputs FromResponse(PipelineRe } } } - diff --git a/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.cs b/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.cs index ffdc5ff0f..044c28ed8 100644 --- a/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.cs +++ b/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The RunObjectRequiredActionSubmitToolOutputs. - public partial class RunObjectRequiredActionSubmitToolOutputs + internal partial class RunObjectRequiredActionSubmitToolOutputs { /// /// Keeps track of any properties unknown to the library. @@ -70,4 +70,3 @@ internal RunObjectRequiredActionSubmitToolOutputs() public IReadOnlyList ToolCalls { get; } } } - diff --git a/.dotnet/src/Generated/Models/RunObjectRequiredActionType.cs b/.dotnet/src/Generated/Models/RunObjectRequiredActionType.cs index d8d1c8f07..c1ce2fd12 100644 --- a/.dotnet/src/Generated/Models/RunObjectRequiredActionType.cs +++ b/.dotnet/src/Generated/Models/RunObjectRequiredActionType.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The RunObjectRequiredAction_type. - public readonly partial struct RunObjectRequiredActionType : IEquatable + internal readonly partial struct RunObjectRequiredActionType : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public RunObjectRequiredActionType(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/RunObjectStatus.cs b/.dotnet/src/Generated/Models/RunObjectStatus.cs index cd13d9b49..c369bec80 100644 --- a/.dotnet/src/Generated/Models/RunObjectStatus.cs +++ b/.dotnet/src/Generated/Models/RunObjectStatus.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for status in RunObject. - public readonly partial struct RunObjectStatus : IEquatable + internal readonly partial struct RunObjectStatus : IEquatable { private readonly string _value; @@ -62,4 +62,3 @@ public RunObjectStatus(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.Serialization.cs b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.Serialization.cs index 38408c8d1..60be54dde 100644 --- a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.Serialization.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { internal partial class RunStepDetailsMessageCreationObject : IJsonModel { @@ -126,4 +126,3 @@ internal static RunStepDetailsMessageCreationObject FromResponse(PipelineRespons } } } - diff --git a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.cs b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.cs index ffac3bdb1..1de631b8d 100644 --- a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.cs +++ b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.cs @@ -4,7 +4,7 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Details of the message creation by the run step. internal partial class RunStepDetailsMessageCreationObject @@ -74,4 +74,3 @@ internal RunStepDetailsMessageCreationObject() public RunStepDetailsMessageCreationObjectMessageCreation MessageCreation { get; } } } - diff --git a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.Serialization.cs b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.Serialization.cs index 1d02bc66a..b1f56e27c 100644 --- a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.Serialization.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { internal partial class RunStepDetailsMessageCreationObjectMessageCreation : IJsonModel { @@ -118,4 +118,3 @@ internal static RunStepDetailsMessageCreationObjectMessageCreation FromResponse( } } } - diff --git a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.cs b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.cs index 447962ae3..a7e725f0a 100644 --- a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.cs +++ b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.cs @@ -4,7 +4,7 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The RunStepDetailsMessageCreationObjectMessageCreation. internal partial class RunStepDetailsMessageCreationObjectMessageCreation @@ -69,4 +69,3 @@ internal RunStepDetailsMessageCreationObjectMessageCreation() public string MessageId { get; } } } - diff --git a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectType.cs b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectType.cs index bf0a1f637..e5d49a8d3 100644 --- a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectType.cs +++ b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectType.cs @@ -3,7 +3,7 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The RunStepDetailsMessageCreationObject_type. internal readonly partial struct RunStepDetailsMessageCreationObjectType : IEquatable @@ -41,4 +41,3 @@ public RunStepDetailsMessageCreationObjectType(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.Serialization.cs b/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.Serialization.cs index ebf127b7d..c38c64703 100644 --- a/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.Serialization.cs @@ -6,7 +6,7 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { internal partial class RunStepDetailsToolCallsObject : IJsonModel { @@ -155,4 +155,3 @@ internal static RunStepDetailsToolCallsObject FromResponse(PipelineResponse resp } } } - diff --git a/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.cs b/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.cs index f290db55e..37fb29ed7 100644 --- a/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.cs +++ b/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.cs @@ -5,7 +5,7 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Details of the tool call. internal partial class RunStepDetailsToolCallsObject @@ -111,4 +111,3 @@ internal RunStepDetailsToolCallsObject() public IReadOnlyList ToolCalls { get; } } } - diff --git a/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObjectType.cs b/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObjectType.cs index a307fc4c4..5593d5a5b 100644 --- a/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObjectType.cs +++ b/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObjectType.cs @@ -3,7 +3,7 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The RunStepDetailsToolCallsObject_type. internal readonly partial struct RunStepDetailsToolCallsObjectType : IEquatable @@ -41,4 +41,3 @@ public RunStepDetailsToolCallsObjectType(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/RunStepObject.Serialization.cs b/.dotnet/src/Generated/Models/RunStepObject.Serialization.cs index a73966402..b824f8e76 100644 --- a/.dotnet/src/Generated/Models/RunStepObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunStepObject.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class RunStepObject : IJsonModel + internal partial class RunStepObject : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -340,4 +340,3 @@ internal static RunStepObject FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/RunStepObject.cs b/.dotnet/src/Generated/Models/RunStepObject.cs index 24cbfec6e..ebd98f23f 100644 --- a/.dotnet/src/Generated/Models/RunStepObject.cs +++ b/.dotnet/src/Generated/Models/RunStepObject.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Represents a step in execution of a run. - public partial class RunStepObject + internal partial class RunStepObject { /// /// Keeps track of any properties unknown to the library. @@ -232,4 +232,3 @@ internal RunStepObject() public RunCompletionUsage Usage { get; } } } - diff --git a/.dotnet/src/Generated/Models/RunStepObjectLastError.Serialization.cs b/.dotnet/src/Generated/Models/RunStepObjectLastError.Serialization.cs index 71a0e8a2f..bced34068 100644 --- a/.dotnet/src/Generated/Models/RunStepObjectLastError.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunStepObjectLastError.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class RunStepObjectLastError : IJsonModel + internal partial class RunStepObjectLastError : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -126,4 +126,3 @@ internal static RunStepObjectLastError FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/RunStepObjectLastError.cs b/.dotnet/src/Generated/Models/RunStepObjectLastError.cs index 2bf3b1db8..32d41e0fd 100644 --- a/.dotnet/src/Generated/Models/RunStepObjectLastError.cs +++ b/.dotnet/src/Generated/Models/RunStepObjectLastError.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The RunStepObjectLastError. - public partial class RunStepObjectLastError + internal partial class RunStepObjectLastError { /// /// Keeps track of any properties unknown to the library. @@ -75,4 +75,3 @@ internal RunStepObjectLastError() public string Message { get; } } } - diff --git a/.dotnet/src/Generated/Models/RunStepObjectLastErrorCode.cs b/.dotnet/src/Generated/Models/RunStepObjectLastErrorCode.cs index 9bf035ea1..2d8832e99 100644 --- a/.dotnet/src/Generated/Models/RunStepObjectLastErrorCode.cs +++ b/.dotnet/src/Generated/Models/RunStepObjectLastErrorCode.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for code in RunStepObjectLastError. - public readonly partial struct RunStepObjectLastErrorCode : IEquatable + internal readonly partial struct RunStepObjectLastErrorCode : IEquatable { private readonly string _value; @@ -44,4 +44,3 @@ public RunStepObjectLastErrorCode(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/RunStepObjectObject.cs b/.dotnet/src/Generated/Models/RunStepObjectObject.cs index 21477c60d..376e9e3cc 100644 --- a/.dotnet/src/Generated/Models/RunStepObjectObject.cs +++ b/.dotnet/src/Generated/Models/RunStepObjectObject.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The RunStepObject_object. - public readonly partial struct RunStepObjectObject : IEquatable + internal readonly partial struct RunStepObjectObject : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public RunStepObjectObject(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/RunStepObjectStatus.cs b/.dotnet/src/Generated/Models/RunStepObjectStatus.cs index 21abb0c10..f46f639d7 100644 --- a/.dotnet/src/Generated/Models/RunStepObjectStatus.cs +++ b/.dotnet/src/Generated/Models/RunStepObjectStatus.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for status in RunStepObject. - public readonly partial struct RunStepObjectStatus : IEquatable + internal readonly partial struct RunStepObjectStatus : IEquatable { private readonly string _value; @@ -53,4 +53,3 @@ public RunStepObjectStatus(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/RunStepObjectType.cs b/.dotnet/src/Generated/Models/RunStepObjectType.cs index 432a90099..30257f499 100644 --- a/.dotnet/src/Generated/Models/RunStepObjectType.cs +++ b/.dotnet/src/Generated/Models/RunStepObjectType.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Enum for type in RunStepObject. - public readonly partial struct RunStepObjectType : IEquatable + internal readonly partial struct RunStepObjectType : IEquatable { private readonly string _value; @@ -44,4 +44,3 @@ public RunStepObjectType(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/RunToolCallObject.Serialization.cs b/.dotnet/src/Generated/Models/RunToolCallObject.Serialization.cs index 47b58bfd9..8c1145c63 100644 --- a/.dotnet/src/Generated/Models/RunToolCallObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunToolCallObject.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class RunToolCallObject : IJsonModel + internal partial class RunToolCallObject : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -134,4 +134,3 @@ internal static RunToolCallObject FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/RunToolCallObject.cs b/.dotnet/src/Generated/Models/RunToolCallObject.cs index d70655724..83c3a699c 100644 --- a/.dotnet/src/Generated/Models/RunToolCallObject.cs +++ b/.dotnet/src/Generated/Models/RunToolCallObject.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Tool call objects. - public partial class RunToolCallObject + internal partial class RunToolCallObject { /// /// Keeps track of any properties unknown to the library. @@ -90,4 +90,3 @@ internal RunToolCallObject() public RunToolCallObjectFunction Function { get; } } } - diff --git a/.dotnet/src/Generated/Models/RunToolCallObjectFunction.Serialization.cs b/.dotnet/src/Generated/Models/RunToolCallObjectFunction.Serialization.cs index a62970151..d7af27898 100644 --- a/.dotnet/src/Generated/Models/RunToolCallObjectFunction.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunToolCallObjectFunction.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class RunToolCallObjectFunction : IJsonModel + internal partial class RunToolCallObjectFunction : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -126,4 +126,3 @@ internal static RunToolCallObjectFunction FromResponse(PipelineResponse response } } } - diff --git a/.dotnet/src/Generated/Models/RunToolCallObjectFunction.cs b/.dotnet/src/Generated/Models/RunToolCallObjectFunction.cs index 1fab15eac..15f52388a 100644 --- a/.dotnet/src/Generated/Models/RunToolCallObjectFunction.cs +++ b/.dotnet/src/Generated/Models/RunToolCallObjectFunction.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The RunToolCallObjectFunction. - public partial class RunToolCallObjectFunction + internal partial class RunToolCallObjectFunction { /// /// Keeps track of any properties unknown to the library. @@ -76,4 +76,3 @@ internal RunToolCallObjectFunction() public string Arguments { get; } } } - diff --git a/.dotnet/src/Generated/Models/RunToolCallObjectType.cs b/.dotnet/src/Generated/Models/RunToolCallObjectType.cs index d882bc7f3..b036b215c 100644 --- a/.dotnet/src/Generated/Models/RunToolCallObjectType.cs +++ b/.dotnet/src/Generated/Models/RunToolCallObjectType.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The RunToolCallObject_type. - public readonly partial struct RunToolCallObjectType : IEquatable + internal readonly partial struct RunToolCallObjectType : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public RunToolCallObjectType(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.Serialization.cs b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.Serialization.cs index 68b1ad66f..a4b178b12 100644 --- a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class SubmitToolOutputsRunRequest : IJsonModel + internal partial class SubmitToolOutputsRunRequest : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -128,4 +128,3 @@ internal static SubmitToolOutputsRunRequest FromResponse(PipelineResponse respon } } } - diff --git a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.cs b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.cs index f489e6bb1..76e994a43 100644 --- a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.cs +++ b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.cs @@ -5,10 +5,10 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The SubmitToolOutputsRunRequest. - public partial class SubmitToolOutputsRunRequest + internal partial class SubmitToolOutputsRunRequest { /// /// Keeps track of any properties unknown to the library. @@ -70,4 +70,3 @@ internal SubmitToolOutputsRunRequest() public IList ToolOutputs { get; } } } - diff --git a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutput.Serialization.cs b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutput.Serialization.cs index 709807021..ab9abfeb1 100644 --- a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutput.Serialization.cs +++ b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutput.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class SubmitToolOutputsRunRequestToolOutput : IJsonModel + internal partial class SubmitToolOutputsRunRequestToolOutput : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -132,4 +132,3 @@ internal static SubmitToolOutputsRunRequestToolOutput FromResponse(PipelineRespo } } } - diff --git a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutput.cs b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutput.cs index 096a5584b..78c4c374f 100644 --- a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutput.cs +++ b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutput.cs @@ -3,10 +3,10 @@ using System; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The SubmitToolOutputsRunRequestToolOutput. - public partial class SubmitToolOutputsRunRequestToolOutput + internal partial class SubmitToolOutputsRunRequestToolOutput { /// /// Keeps track of any properties unknown to the library. @@ -68,4 +68,3 @@ internal SubmitToolOutputsRunRequestToolOutput(string toolCallId, string output, public string Output { get; set; } } } - diff --git a/.dotnet/src/Generated/Models/ThreadObject.Serialization.cs b/.dotnet/src/Generated/Models/ThreadObject.Serialization.cs index 4644d1aa9..c87050e03 100644 --- a/.dotnet/src/Generated/Models/ThreadObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/ThreadObject.Serialization.cs @@ -6,9 +6,9 @@ using System.Collections.Generic; using System.Text.Json; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { - public partial class ThreadObject : IJsonModel + internal partial class ThreadObject : IJsonModel { void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { @@ -165,4 +165,3 @@ internal static ThreadObject FromResponse(PipelineResponse response) } } } - diff --git a/.dotnet/src/Generated/Models/ThreadObject.cs b/.dotnet/src/Generated/Models/ThreadObject.cs index 22d754976..b4cf5143d 100644 --- a/.dotnet/src/Generated/Models/ThreadObject.cs +++ b/.dotnet/src/Generated/Models/ThreadObject.cs @@ -4,10 +4,10 @@ using OpenAI.ClientShared.Internal; using System.Collections.Generic; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Represents a thread that contains [messages](/docs/api-reference/messages). - public partial class ThreadObject + internal partial class ThreadObject { /// /// Keeps track of any properties unknown to the library. @@ -98,4 +98,3 @@ internal ThreadObject() public IReadOnlyDictionary Metadata { get; } } } - diff --git a/.dotnet/src/Generated/Models/ThreadObjectObject.cs b/.dotnet/src/Generated/Models/ThreadObjectObject.cs index 8eb382a0b..0b10ab32c 100644 --- a/.dotnet/src/Generated/Models/ThreadObjectObject.cs +++ b/.dotnet/src/Generated/Models/ThreadObjectObject.cs @@ -3,10 +3,10 @@ using System; using System.ComponentModel; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// The ThreadObject_object. - public readonly partial struct ThreadObjectObject : IEquatable + internal readonly partial struct ThreadObjectObject : IEquatable { private readonly string _value; @@ -41,4 +41,3 @@ public ThreadObjectObject(string value) public override string ToString() => _value; } } - diff --git a/.dotnet/src/Generated/ModelsOps.cs b/.dotnet/src/Generated/ModelsOps.cs index c4b6cbfbb..3110695ec 100644 --- a/.dotnet/src/Generated/ModelsOps.cs +++ b/.dotnet/src/Generated/ModelsOps.cs @@ -6,13 +6,13 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -using OpenAI.Models; +using OpenAI.Internal.Models; -namespace OpenAI +namespace OpenAI.Internal { // Data plane generated sub-client. /// The ModelsOps sub-client. - public partial class ModelsOps + internal partial class ModelsOps { private const string AuthorizationHeader = "Authorization"; private readonly ApiKeyCredential _credential; @@ -392,4 +392,3 @@ internal PipelineMessage CreateDeleteRequest(string model, RequestOptions option private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } } - diff --git a/.dotnet/src/Generated/Moderations.cs b/.dotnet/src/Generated/Moderations.cs index 3c728d50a..ef4c93f63 100644 --- a/.dotnet/src/Generated/Moderations.cs +++ b/.dotnet/src/Generated/Moderations.cs @@ -6,13 +6,13 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -using OpenAI.Models; +using OpenAI.Internal.Models; -namespace OpenAI +namespace OpenAI.Internal { // Data plane generated sub-client. /// The Moderations sub-client. - public partial class Moderations + internal partial class Moderations { private const string AuthorizationHeader = "Authorization"; private readonly ApiKeyCredential _credential; @@ -159,4 +159,3 @@ internal PipelineMessage CreateCreateModerationRequest(BinaryContent content, Re private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } } - diff --git a/.dotnet/src/Generated/OpenAIClient.cs b/.dotnet/src/Generated/OpenAIClient.cs index 29785453c..abe16ec58 100644 --- a/.dotnet/src/Generated/OpenAIClient.cs +++ b/.dotnet/src/Generated/OpenAIClient.cs @@ -5,11 +5,11 @@ using System.ClientModel.Primitives; using System.Threading; -namespace OpenAI +namespace OpenAI.Internal { // Data plane generated client. /// The OpenAI service client. - public partial class OpenAIClient + internal partial class OpenAIClient { private const string AuthorizationHeader = "Authorization"; private readonly ApiKeyCredential _credential; @@ -144,4 +144,3 @@ public virtual Threads GetThreadsClient() } } } - diff --git a/.dotnet/src/Generated/OpenAIClientOptions.cs b/.dotnet/src/Generated/OpenAIClientOptions.cs index 31df0818d..10b7372d4 100644 --- a/.dotnet/src/Generated/OpenAIClientOptions.cs +++ b/.dotnet/src/Generated/OpenAIClientOptions.cs @@ -2,11 +2,10 @@ using System.ClientModel.Primitives; -namespace OpenAI +namespace OpenAI.Internal { /// Client options for OpenAIClient. - public partial class OpenAIClientOptions : ClientPipelineOptions + internal partial class OpenAIClientOptions : ClientPipelineOptions { } } - diff --git a/.dotnet/src/Generated/OpenAIModelFactory.cs b/.dotnet/src/Generated/OpenAIModelFactory.cs index 8e81ba327..ad51183cf 100644 --- a/.dotnet/src/Generated/OpenAIModelFactory.cs +++ b/.dotnet/src/Generated/OpenAIModelFactory.cs @@ -4,10 +4,10 @@ using System.Collections.Generic; using System.Linq; -namespace OpenAI.Models +namespace OpenAI.Internal.Models { /// Model factory for models. - public static partial class OpenAIModelFactory + internal static partial class OpenAIModelFactory { /// Initializes a new instance of . /// One of the available [TTS models](/docs/models/tts): `tts-1` or `tts-1-hd`. @@ -1577,4 +1577,3 @@ public static DeleteThreadResponse DeleteThreadResponse(string id = null, bool d } } } - diff --git a/.dotnet/src/Generated/Runs.cs b/.dotnet/src/Generated/Runs.cs index 5d79922ec..66d2cfc1c 100644 --- a/.dotnet/src/Generated/Runs.cs +++ b/.dotnet/src/Generated/Runs.cs @@ -6,13 +6,13 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -using OpenAI.Models; +using OpenAI.Internal.Models; -namespace OpenAI +namespace OpenAI.Internal { // Data plane generated sub-client. /// The Runs sub-client. - public partial class Runs + internal partial class Runs { private const string AuthorizationHeader = "Authorization"; private readonly ApiKeyCredential _credential; @@ -1489,4 +1489,3 @@ internal PipelineMessage CreateGetRunStepRequest(string threadId, string runId, private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } } - diff --git a/.dotnet/src/Generated/Threads.cs b/.dotnet/src/Generated/Threads.cs index 6332bef17..8e2ac77e4 100644 --- a/.dotnet/src/Generated/Threads.cs +++ b/.dotnet/src/Generated/Threads.cs @@ -6,13 +6,13 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -using OpenAI.Models; +using OpenAI.Internal.Models; -namespace OpenAI +namespace OpenAI.Internal { // Data plane generated sub-client. /// The Threads sub-client. - public partial class Threads + internal partial class Threads { private const string AuthorizationHeader = "Authorization"; private readonly ApiKeyCredential _credential; @@ -526,4 +526,3 @@ internal PipelineMessage CreateDeleteThreadRequest(string threadId, RequestOptio private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); } } - diff --git a/.dotnet/tests/Generated/Tests/AssistantsTests.cs b/.dotnet/tests/Generated/Tests/AssistantsTests.cs index 6c1ba99d2..dde077712 100644 --- a/.dotnet/tests/Generated/Tests/AssistantsTests.cs +++ b/.dotnet/tests/Generated/Tests/AssistantsTests.cs @@ -20,4 +20,3 @@ public void SmokeTest() } } } - diff --git a/.dotnet/tests/Generated/Tests/AudioTests.cs b/.dotnet/tests/Generated/Tests/AudioTests.cs index 6ff9cd6f5..f14a6f69d 100644 --- a/.dotnet/tests/Generated/Tests/AudioTests.cs +++ b/.dotnet/tests/Generated/Tests/AudioTests.cs @@ -20,4 +20,3 @@ public void SmokeTest() } } } - diff --git a/.dotnet/tests/Generated/Tests/ChatTests.cs b/.dotnet/tests/Generated/Tests/ChatTests.cs index 17a9746da..b1ac76e65 100644 --- a/.dotnet/tests/Generated/Tests/ChatTests.cs +++ b/.dotnet/tests/Generated/Tests/ChatTests.cs @@ -20,4 +20,3 @@ public void SmokeTest() } } } - diff --git a/.dotnet/tests/Generated/Tests/CompletionsTests.cs b/.dotnet/tests/Generated/Tests/CompletionsTests.cs index 159a4444d..59958da6b 100644 --- a/.dotnet/tests/Generated/Tests/CompletionsTests.cs +++ b/.dotnet/tests/Generated/Tests/CompletionsTests.cs @@ -20,4 +20,3 @@ public void SmokeTest() } } } - diff --git a/.dotnet/tests/Generated/Tests/EmbeddingsTests.cs b/.dotnet/tests/Generated/Tests/EmbeddingsTests.cs index b4deac0fc..b4e115c86 100644 --- a/.dotnet/tests/Generated/Tests/EmbeddingsTests.cs +++ b/.dotnet/tests/Generated/Tests/EmbeddingsTests.cs @@ -20,4 +20,3 @@ public void SmokeTest() } } } - diff --git a/.dotnet/tests/Generated/Tests/FilesTests.cs b/.dotnet/tests/Generated/Tests/FilesTests.cs index c08f7aee8..64ebbed83 100644 --- a/.dotnet/tests/Generated/Tests/FilesTests.cs +++ b/.dotnet/tests/Generated/Tests/FilesTests.cs @@ -20,4 +20,3 @@ public void SmokeTest() } } } - diff --git a/.dotnet/tests/Generated/Tests/FineTuningTests.cs b/.dotnet/tests/Generated/Tests/FineTuningTests.cs index 7504035a2..324b4d458 100644 --- a/.dotnet/tests/Generated/Tests/FineTuningTests.cs +++ b/.dotnet/tests/Generated/Tests/FineTuningTests.cs @@ -20,4 +20,3 @@ public void SmokeTest() } } } - diff --git a/.dotnet/tests/Generated/Tests/ImagesTests.cs b/.dotnet/tests/Generated/Tests/ImagesTests.cs index 097054471..96b7146de 100644 --- a/.dotnet/tests/Generated/Tests/ImagesTests.cs +++ b/.dotnet/tests/Generated/Tests/ImagesTests.cs @@ -20,4 +20,3 @@ public void SmokeTest() } } } - diff --git a/.dotnet/tests/Generated/Tests/MessagesTests.cs b/.dotnet/tests/Generated/Tests/MessagesTests.cs index ab0223685..89933cb52 100644 --- a/.dotnet/tests/Generated/Tests/MessagesTests.cs +++ b/.dotnet/tests/Generated/Tests/MessagesTests.cs @@ -20,4 +20,3 @@ public void SmokeTest() } } } - diff --git a/.dotnet/tests/Generated/Tests/ModelsOpsTests.cs b/.dotnet/tests/Generated/Tests/ModelsOpsTests.cs index 0560956dc..3ac25fa3d 100644 --- a/.dotnet/tests/Generated/Tests/ModelsOpsTests.cs +++ b/.dotnet/tests/Generated/Tests/ModelsOpsTests.cs @@ -20,4 +20,3 @@ public void SmokeTest() } } } - diff --git a/.dotnet/tests/Generated/Tests/ModerationsTests.cs b/.dotnet/tests/Generated/Tests/ModerationsTests.cs index 7fc5a1d0b..0413ef684 100644 --- a/.dotnet/tests/Generated/Tests/ModerationsTests.cs +++ b/.dotnet/tests/Generated/Tests/ModerationsTests.cs @@ -20,4 +20,3 @@ public void SmokeTest() } } } - diff --git a/.dotnet/tests/Generated/Tests/RunsTests.cs b/.dotnet/tests/Generated/Tests/RunsTests.cs index bd4de7947..8bc6927a9 100644 --- a/.dotnet/tests/Generated/Tests/RunsTests.cs +++ b/.dotnet/tests/Generated/Tests/RunsTests.cs @@ -20,4 +20,3 @@ public void SmokeTest() } } } - diff --git a/.dotnet/tests/Generated/Tests/ThreadsTests.cs b/.dotnet/tests/Generated/Tests/ThreadsTests.cs index b5ea58e10..e7f4583af 100644 --- a/.dotnet/tests/Generated/Tests/ThreadsTests.cs +++ b/.dotnet/tests/Generated/Tests/ThreadsTests.cs @@ -20,4 +20,3 @@ public void SmokeTest() } } } - From f1198ade3b7b5f4aa91459ff63846f8e9488db69 Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado Date: Wed, 28 Feb 2024 16:18:58 -0800 Subject: [PATCH 18/50] Port over custom code --- .dotnet/Directory.Build.props | 5 + .dotnet/scripts/Add-Customizations.ps1 | 28 + .dotnet/scripts/ConvertTo-Internal.ps1 | 44 +- .dotnet/scripts/Update-ClientModel.ps1 | 8 +- .dotnet/src/Custom/Assistants/Assistant.cs | 48 + .../Assistants/AssistantClient.Protocol.cs | 429 +++++++++ .../src/Custom/Assistants/AssistantClient.cs | 771 ++++++++++++++++ .../Assistants/AssistantCreationOptions.cs | 65 ++ .../Assistants/AssistantFileAssociation.cs | 17 + .../AssistantModificationOptions.cs | 71 ++ .../src/Custom/Assistants/AssistantThread.cs | 31 + .../CodeInterpreterToolDefinition.cs | 38 + .../Assistants/CodeInterpreterToolInfo.cs | 33 + .../Custom/Assistants/CreatedAtSortOrder.cs | 7 + .../Assistants/FunctionToolDefinition.cs | 89 ++ .../src/Custom/Assistants/FunctionToolInfo.cs | 82 ++ .../src/Custom/Assistants/ListQueryPage.cs | 114 +++ .../MessageContent.Serialization.cs | 94 ++ .../src/Custom/Assistants/MessageContent.cs | 6 + .../Assistants/MessageCreationOptions.cs | 30 + .../Assistants/MessageFileAssociation.cs | 17 + .../Assistants/MessageImageFileContent.cs | 55 ++ .dotnet/src/Custom/Assistants/MessageRole.cs | 16 + .../Custom/Assistants/MessageTextContent.cs | 72 ++ .../Assistants/RequiredFunctionToolCall.cs | 66 ++ .../src/Custom/Assistants/RequiredToolCall.cs | 37 + .../Assistants/RetrievalToolDefinition.cs | 38 + .../Custom/Assistants/RetrievalToolInfo.cs | 33 + .../Custom/Assistants/RunCreationOptions.cs | 67 ++ .dotnet/src/Custom/Assistants/RunError.cs | 24 + .dotnet/src/Custom/Assistants/RunErrorCode.cs | 37 + .../Assistants/RunModificationOptions.cs | 24 + .../RunRequiredAction.Serialization.cs | 107 +++ .../Custom/Assistants/RunRequiredAction.cs | 8 + .dotnet/src/Custom/Assistants/RunStatus.cs | 13 + .../src/Custom/Assistants/RunTokenUsage.cs | 20 + .../TextContentAnnotation.Serialization.cs | 93 ++ .../Assistants/TextContentAnnotation.cs | 6 + .../TextContentFileCitationAnnotation.cs | 95 ++ .../TextContentFilePathAnnotation.cs | 85 ++ .../Assistants/ThreadCreationOptions.cs | 26 + .../Assistants/ThreadInitializationMessage.cs | 45 + .../src/Custom/Assistants/ThreadMessage.cs | 62 ++ .../Assistants/ThreadModificationOptions.cs | 24 + .dotnet/src/Custom/Assistants/ThreadRun.cs | 105 +++ .../ToolDefinition.Serialization.cs | 98 ++ .../src/Custom/Assistants/ToolDefinition.cs | 5 + .../Assistants/ToolInfo.Serialization.cs | 97 ++ .dotnet/src/Custom/Assistants/ToolInfo.cs | 5 + .../Assistants/ToolOutput.Serialization.cs | 97 ++ .dotnet/src/Custom/Assistants/ToolOutput.cs | 27 + .dotnet/src/Custom/Audio/AudioClient.cs | 385 ++++++++ .dotnet/src/Custom/Audio/AudioDataFormat.cs | 92 ++ .../src/Custom/Audio/AudioTranscription.cs | 72 ++ .../Custom/Audio/AudioTranscriptionFormat.cs | 12 + .../Custom/Audio/AudioTranscriptionOptions.cs | 14 + .dotnet/src/Custom/Audio/AudioTranslation.cs | 32 + .../Custom/Audio/AudioTranslationOptions.cs | 11 + .../src/Custom/Audio/TextToSpeechOptions.cs | 29 + .dotnet/src/Custom/Audio/TextToSpeechVoice.cs | 64 ++ .dotnet/src/Custom/Audio/TranscribedWord.cs | 45 + .../src/Custom/Audio/TranscriptionSegment.cs | 109 +++ .dotnet/src/Custom/Chat/ChatClient.cs | 400 +++++++++ .dotnet/src/Custom/Chat/ChatCompletion.cs | 81 ++ .../Custom/Chat/ChatCompletionCollection.cs | 13 + .../src/Custom/Chat/ChatCompletionOptions.cs | 115 +++ .dotnet/src/Custom/Chat/ChatFinishReason.cs | 77 ++ .../Chat/ChatFunctionCall.Serialization.cs | 37 + .dotnet/src/Custom/Chat/ChatFunctionCall.cs | 47 + .../src/Custom/Chat/ChatFunctionConstraint.cs | 73 ++ .../src/Custom/Chat/ChatFunctionDefinition.cs | 60 ++ .../src/Custom/Chat/ChatFunctionToolCall.cs | 69 ++ .../Custom/Chat/ChatFunctionToolDefinition.cs | 60 ++ .../Chat/ChatLogProbabilityCollection.cs | 43 + .../Custom/Chat/ChatLogProbabilityResult.cs | 43 + .../Chat/ChatLogProbabilityResultItem.cs | 42 + .dotnet/src/Custom/Chat/ChatMessageContent.cs | 112 +++ .../src/Custom/Chat/ChatMessageContentKind.cs | 19 + .../Chat/ChatRequestAssistantMessage.cs | 129 +++ .../Custom/Chat/ChatRequestFunctionMessage.cs | 40 + .../Chat/ChatRequestMessage.Serialization.cs | 94 ++ .dotnet/src/Custom/Chat/ChatRequestMessage.cs | 108 +++ .../Custom/Chat/ChatRequestSystemMessage.cs | 39 + .../src/Custom/Chat/ChatRequestToolMessage.cs | 53 ++ .../src/Custom/Chat/ChatRequestUserMessage.cs | 65 ++ .dotnet/src/Custom/Chat/ChatResponseFormat.cs | 44 + .dotnet/src/Custom/Chat/ChatRole.cs | 85 ++ .dotnet/src/Custom/Chat/ChatTokenUsage.cs | 21 + .../Custom/Chat/ChatToolCall.Serialization.cs | 38 + .dotnet/src/Custom/Chat/ChatToolCall.cs | 15 + .dotnet/src/Custom/Chat/ChatToolConstraint.cs | 87 ++ .dotnet/src/Custom/Chat/ChatToolDefinition.cs | 11 + .../src/Custom/Chat/StreamingChatUpdate.cs | 336 +++++++ .../Chat/StreamingFunctionToolCallUpdate.cs | 90 ++ .../Custom/Chat/StreamingToolCallUpdate.cs | 97 ++ .dotnet/src/Custom/Embeddings/Embedding.cs | 44 + .../src/Custom/Embeddings/EmbeddingClient.cs | 121 +++ .../Custom/Embeddings/EmbeddingCollection.cs | 19 + .../src/Custom/Embeddings/EmbeddingOptions.cs | 8 + .../Custom/Embeddings/EmbeddingTokenUsage.cs | 16 + .dotnet/src/Custom/Files/FileClient.cs | 352 ++++++++ .dotnet/src/Custom/Files/OpenAIFileInfo.cs | 36 + .../Custom/Files/OpenAIFileInfoCollection.cs | 11 + .dotnet/src/Custom/Images/GeneratedImage.cs | 48 + .dotnet/src/Custom/Images/ImageClient.cs | 245 +++++ .../Images/ImageGenerationCollection.cs | 12 + .../Custom/Images/ImageGenerationOptions.cs | 75 ++ .dotnet/src/Custom/Images/ImageQuality.cs | 24 + .../src/Custom/Images/ImageResponseFormat.cs | 32 + .dotnet/src/Custom/Images/ImageSize.cs | 43 + .dotnet/src/Custom/Images/ImageStyle.cs | 18 + .../LegacyCompletionClient.cs | 106 +++ .../Custom/Models/ModelDetailCollection.cs | 13 + .dotnet/src/Custom/Models/ModelDetails.cs | 29 + .../Custom/Models/ModelManagementClient.cs | 197 ++++ .../Custom/Moderations/ModerationClient.cs | 106 +++ .dotnet/src/Custom/OpenAIClient.cs | 191 ++++ .dotnet/src/Custom/OpenAIClientConnector.cs | 33 + .dotnet/src/Custom/OpenAIClientOptions.cs | 32 + .dotnet/src/Generated/OpenAIClient.cs | 78 +- .dotnet/src/Generated/OpenAIModelFactory.cs | 844 ------------------ .dotnet/src/OpenAI.csproj | 2 +- ...deAnalysis.SetsRequiredMembersAttribute.cs | 8 + ...rvices.CompilerFeatureRequiredAttribute.cs | 15 + ...Runtime.CompilerServices.IsExternalInit.cs | 9 + ...ompilerServices.RequiredMemberAttribute.cs | 8 + .../Utility/GenericActionPipelinePolicy.cs | 35 + .dotnet/src/Utility/SseAsyncEnumerator.cs | 59 ++ .dotnet/src/Utility/SseLine.cs | 29 + .dotnet/src/Utility/SseReader.cs | 118 +++ .dotnet/src/Utility/StreamingResult.cs | 95 ++ .../System.ClientModel.MultipartContent.cs | 367 ++++++++ ...em.ClientModel.MultipartFormDataContent.cs | 117 +++ .../tests/Generated/Tests/AssistantsTests.cs | 22 - .dotnet/tests/Generated/Tests/AudioTests.cs | 22 - .dotnet/tests/Generated/Tests/ChatTests.cs | 22 - .../tests/Generated/Tests/CompletionsTests.cs | 22 - .../tests/Generated/Tests/EmbeddingsTests.cs | 22 - .dotnet/tests/Generated/Tests/FilesTests.cs | 22 - .../tests/Generated/Tests/FineTuningTests.cs | 22 - .dotnet/tests/Generated/Tests/ImagesTests.cs | 22 - .../tests/Generated/Tests/MessagesTests.cs | 22 - .../tests/Generated/Tests/ModelsOpsTests.cs | 22 - .../tests/Generated/Tests/ModerationsTests.cs | 22 - .dotnet/tests/Generated/Tests/RunsTests.cs | 22 - .dotnet/tests/Generated/Tests/ThreadsTests.cs | 22 - .dotnet/tests/OpenAI.Tests.csproj | 1 + .dotnet/tests/Samples/AssistantsSamples.cs | 167 ++++ .dotnet/tests/Samples/Chat/ChatSamples.cs | 128 +++ .../Samples/Chat/Sample_FunctionCalling.cs | 148 +++ .dotnet/tests/Samples/CombinationSamples.cs | 150 ++++ .dotnet/tests/Samples/EmbeddingSamples.cs | 95 ++ .dotnet/tests/Samples/ImageSamples.cs | 46 + .dotnet/tests/TestScenarios/AssistantTests.cs | 161 ++++ .../tests/TestScenarios/ChatClientTests.cs | 89 ++ .../TestScenarios/ChatToolConstraints.cs | 70 ++ .dotnet/tests/TestScenarios/ChatToolTests.cs | 90 ++ .dotnet/tests/TestScenarios/ChatWithVision.cs | 33 + .../TestScenarios/EmbeddingClientTests.cs | 52 ++ .../tests/TestScenarios/FileClientTests.cs | 43 + .../TestScenarios/ImageGenerationTests.cs | 36 + .../tests/TestScenarios/LegacyCompletions.cs | 32 + .../tests/TestScenarios/ModelClientTests.cs | 28 + .../tests/TestScenarios/TextToSpeechTests.cs | 35 + .../tests/TestScenarios/TranscriptionTests.cs | 43 + .../tests/TestScenarios/TranslationTests.cs | 24 + .dotnet/tests/Utility/TestHelpers.cs | 77 ++ .dotnet/tests/Utility/TestPipelinePolicy.cs | 35 + .dotnet/tests/data/hello_world.m4a | Bin 0 -> 79968 bytes .dotnet/tests/data/hola_mundo.m4a | Bin 0 -> 202099 bytes .dotnet/tests/data/stop_sign.png | Bin 0 -> 2125 bytes 171 files changed, 11302 insertions(+), 1184 deletions(-) create mode 100644 .dotnet/Directory.Build.props create mode 100644 .dotnet/scripts/Add-Customizations.ps1 create mode 100644 .dotnet/src/Custom/Assistants/Assistant.cs create mode 100644 .dotnet/src/Custom/Assistants/AssistantClient.Protocol.cs create mode 100644 .dotnet/src/Custom/Assistants/AssistantClient.cs create mode 100644 .dotnet/src/Custom/Assistants/AssistantCreationOptions.cs create mode 100644 .dotnet/src/Custom/Assistants/AssistantFileAssociation.cs create mode 100644 .dotnet/src/Custom/Assistants/AssistantModificationOptions.cs create mode 100644 .dotnet/src/Custom/Assistants/AssistantThread.cs create mode 100644 .dotnet/src/Custom/Assistants/CodeInterpreterToolDefinition.cs create mode 100644 .dotnet/src/Custom/Assistants/CodeInterpreterToolInfo.cs create mode 100644 .dotnet/src/Custom/Assistants/CreatedAtSortOrder.cs create mode 100644 .dotnet/src/Custom/Assistants/FunctionToolDefinition.cs create mode 100644 .dotnet/src/Custom/Assistants/FunctionToolInfo.cs create mode 100644 .dotnet/src/Custom/Assistants/ListQueryPage.cs create mode 100644 .dotnet/src/Custom/Assistants/MessageContent.Serialization.cs create mode 100644 .dotnet/src/Custom/Assistants/MessageContent.cs create mode 100644 .dotnet/src/Custom/Assistants/MessageCreationOptions.cs create mode 100644 .dotnet/src/Custom/Assistants/MessageFileAssociation.cs create mode 100644 .dotnet/src/Custom/Assistants/MessageImageFileContent.cs create mode 100644 .dotnet/src/Custom/Assistants/MessageRole.cs create mode 100644 .dotnet/src/Custom/Assistants/MessageTextContent.cs create mode 100644 .dotnet/src/Custom/Assistants/RequiredFunctionToolCall.cs create mode 100644 .dotnet/src/Custom/Assistants/RequiredToolCall.cs create mode 100644 .dotnet/src/Custom/Assistants/RetrievalToolDefinition.cs create mode 100644 .dotnet/src/Custom/Assistants/RetrievalToolInfo.cs create mode 100644 .dotnet/src/Custom/Assistants/RunCreationOptions.cs create mode 100644 .dotnet/src/Custom/Assistants/RunError.cs create mode 100644 .dotnet/src/Custom/Assistants/RunErrorCode.cs create mode 100644 .dotnet/src/Custom/Assistants/RunModificationOptions.cs create mode 100644 .dotnet/src/Custom/Assistants/RunRequiredAction.Serialization.cs create mode 100644 .dotnet/src/Custom/Assistants/RunRequiredAction.cs create mode 100644 .dotnet/src/Custom/Assistants/RunStatus.cs create mode 100644 .dotnet/src/Custom/Assistants/RunTokenUsage.cs create mode 100644 .dotnet/src/Custom/Assistants/TextContentAnnotation.Serialization.cs create mode 100644 .dotnet/src/Custom/Assistants/TextContentAnnotation.cs create mode 100644 .dotnet/src/Custom/Assistants/TextContentFileCitationAnnotation.cs create mode 100644 .dotnet/src/Custom/Assistants/TextContentFilePathAnnotation.cs create mode 100644 .dotnet/src/Custom/Assistants/ThreadCreationOptions.cs create mode 100644 .dotnet/src/Custom/Assistants/ThreadInitializationMessage.cs create mode 100644 .dotnet/src/Custom/Assistants/ThreadMessage.cs create mode 100644 .dotnet/src/Custom/Assistants/ThreadModificationOptions.cs create mode 100644 .dotnet/src/Custom/Assistants/ThreadRun.cs create mode 100644 .dotnet/src/Custom/Assistants/ToolDefinition.Serialization.cs create mode 100644 .dotnet/src/Custom/Assistants/ToolDefinition.cs create mode 100644 .dotnet/src/Custom/Assistants/ToolInfo.Serialization.cs create mode 100644 .dotnet/src/Custom/Assistants/ToolInfo.cs create mode 100644 .dotnet/src/Custom/Assistants/ToolOutput.Serialization.cs create mode 100644 .dotnet/src/Custom/Assistants/ToolOutput.cs create mode 100644 .dotnet/src/Custom/Audio/AudioClient.cs create mode 100644 .dotnet/src/Custom/Audio/AudioDataFormat.cs create mode 100644 .dotnet/src/Custom/Audio/AudioTranscription.cs create mode 100644 .dotnet/src/Custom/Audio/AudioTranscriptionFormat.cs create mode 100644 .dotnet/src/Custom/Audio/AudioTranscriptionOptions.cs create mode 100644 .dotnet/src/Custom/Audio/AudioTranslation.cs create mode 100644 .dotnet/src/Custom/Audio/AudioTranslationOptions.cs create mode 100644 .dotnet/src/Custom/Audio/TextToSpeechOptions.cs create mode 100644 .dotnet/src/Custom/Audio/TextToSpeechVoice.cs create mode 100644 .dotnet/src/Custom/Audio/TranscribedWord.cs create mode 100644 .dotnet/src/Custom/Audio/TranscriptionSegment.cs create mode 100644 .dotnet/src/Custom/Chat/ChatClient.cs create mode 100644 .dotnet/src/Custom/Chat/ChatCompletion.cs create mode 100644 .dotnet/src/Custom/Chat/ChatCompletionCollection.cs create mode 100644 .dotnet/src/Custom/Chat/ChatCompletionOptions.cs create mode 100644 .dotnet/src/Custom/Chat/ChatFinishReason.cs create mode 100644 .dotnet/src/Custom/Chat/ChatFunctionCall.Serialization.cs create mode 100644 .dotnet/src/Custom/Chat/ChatFunctionCall.cs create mode 100644 .dotnet/src/Custom/Chat/ChatFunctionConstraint.cs create mode 100644 .dotnet/src/Custom/Chat/ChatFunctionDefinition.cs create mode 100644 .dotnet/src/Custom/Chat/ChatFunctionToolCall.cs create mode 100644 .dotnet/src/Custom/Chat/ChatFunctionToolDefinition.cs create mode 100644 .dotnet/src/Custom/Chat/ChatLogProbabilityCollection.cs create mode 100644 .dotnet/src/Custom/Chat/ChatLogProbabilityResult.cs create mode 100644 .dotnet/src/Custom/Chat/ChatLogProbabilityResultItem.cs create mode 100644 .dotnet/src/Custom/Chat/ChatMessageContent.cs create mode 100644 .dotnet/src/Custom/Chat/ChatMessageContentKind.cs create mode 100644 .dotnet/src/Custom/Chat/ChatRequestAssistantMessage.cs create mode 100644 .dotnet/src/Custom/Chat/ChatRequestFunctionMessage.cs create mode 100644 .dotnet/src/Custom/Chat/ChatRequestMessage.Serialization.cs create mode 100644 .dotnet/src/Custom/Chat/ChatRequestMessage.cs create mode 100644 .dotnet/src/Custom/Chat/ChatRequestSystemMessage.cs create mode 100644 .dotnet/src/Custom/Chat/ChatRequestToolMessage.cs create mode 100644 .dotnet/src/Custom/Chat/ChatRequestUserMessage.cs create mode 100644 .dotnet/src/Custom/Chat/ChatResponseFormat.cs create mode 100644 .dotnet/src/Custom/Chat/ChatRole.cs create mode 100644 .dotnet/src/Custom/Chat/ChatTokenUsage.cs create mode 100644 .dotnet/src/Custom/Chat/ChatToolCall.Serialization.cs create mode 100644 .dotnet/src/Custom/Chat/ChatToolCall.cs create mode 100644 .dotnet/src/Custom/Chat/ChatToolConstraint.cs create mode 100644 .dotnet/src/Custom/Chat/ChatToolDefinition.cs create mode 100644 .dotnet/src/Custom/Chat/StreamingChatUpdate.cs create mode 100644 .dotnet/src/Custom/Chat/StreamingFunctionToolCallUpdate.cs create mode 100644 .dotnet/src/Custom/Chat/StreamingToolCallUpdate.cs create mode 100644 .dotnet/src/Custom/Embeddings/Embedding.cs create mode 100644 .dotnet/src/Custom/Embeddings/EmbeddingClient.cs create mode 100644 .dotnet/src/Custom/Embeddings/EmbeddingCollection.cs create mode 100644 .dotnet/src/Custom/Embeddings/EmbeddingOptions.cs create mode 100644 .dotnet/src/Custom/Embeddings/EmbeddingTokenUsage.cs create mode 100644 .dotnet/src/Custom/Files/FileClient.cs create mode 100644 .dotnet/src/Custom/Files/OpenAIFileInfo.cs create mode 100644 .dotnet/src/Custom/Files/OpenAIFileInfoCollection.cs create mode 100644 .dotnet/src/Custom/Images/GeneratedImage.cs create mode 100644 .dotnet/src/Custom/Images/ImageClient.cs create mode 100644 .dotnet/src/Custom/Images/ImageGenerationCollection.cs create mode 100644 .dotnet/src/Custom/Images/ImageGenerationOptions.cs create mode 100644 .dotnet/src/Custom/Images/ImageQuality.cs create mode 100644 .dotnet/src/Custom/Images/ImageResponseFormat.cs create mode 100644 .dotnet/src/Custom/Images/ImageSize.cs create mode 100644 .dotnet/src/Custom/Images/ImageStyle.cs create mode 100644 .dotnet/src/Custom/LegacyCompletions/LegacyCompletionClient.cs create mode 100644 .dotnet/src/Custom/Models/ModelDetailCollection.cs create mode 100644 .dotnet/src/Custom/Models/ModelDetails.cs create mode 100644 .dotnet/src/Custom/Models/ModelManagementClient.cs create mode 100644 .dotnet/src/Custom/Moderations/ModerationClient.cs create mode 100644 .dotnet/src/Custom/OpenAIClient.cs create mode 100644 .dotnet/src/Custom/OpenAIClientConnector.cs create mode 100644 .dotnet/src/Custom/OpenAIClientOptions.cs create mode 100644 .dotnet/src/Polyfill/System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute.cs create mode 100644 .dotnet/src/Polyfill/System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute.cs create mode 100644 .dotnet/src/Polyfill/System.Runtime.CompilerServices.IsExternalInit.cs create mode 100644 .dotnet/src/Polyfill/System.Runtime.CompilerServices.RequiredMemberAttribute.cs create mode 100644 .dotnet/src/Utility/GenericActionPipelinePolicy.cs create mode 100644 .dotnet/src/Utility/SseAsyncEnumerator.cs create mode 100644 .dotnet/src/Utility/SseLine.cs create mode 100644 .dotnet/src/Utility/SseReader.cs create mode 100644 .dotnet/src/Utility/StreamingResult.cs create mode 100644 .dotnet/src/Utility/System.ClientModel.MultipartContent.cs create mode 100644 .dotnet/src/Utility/System.ClientModel.MultipartFormDataContent.cs delete mode 100644 .dotnet/tests/Generated/Tests/AssistantsTests.cs delete mode 100644 .dotnet/tests/Generated/Tests/AudioTests.cs delete mode 100644 .dotnet/tests/Generated/Tests/ChatTests.cs delete mode 100644 .dotnet/tests/Generated/Tests/CompletionsTests.cs delete mode 100644 .dotnet/tests/Generated/Tests/EmbeddingsTests.cs delete mode 100644 .dotnet/tests/Generated/Tests/FilesTests.cs delete mode 100644 .dotnet/tests/Generated/Tests/FineTuningTests.cs delete mode 100644 .dotnet/tests/Generated/Tests/ImagesTests.cs delete mode 100644 .dotnet/tests/Generated/Tests/MessagesTests.cs delete mode 100644 .dotnet/tests/Generated/Tests/ModelsOpsTests.cs delete mode 100644 .dotnet/tests/Generated/Tests/ModerationsTests.cs delete mode 100644 .dotnet/tests/Generated/Tests/RunsTests.cs delete mode 100644 .dotnet/tests/Generated/Tests/ThreadsTests.cs create mode 100644 .dotnet/tests/Samples/AssistantsSamples.cs create mode 100644 .dotnet/tests/Samples/Chat/ChatSamples.cs create mode 100644 .dotnet/tests/Samples/Chat/Sample_FunctionCalling.cs create mode 100644 .dotnet/tests/Samples/CombinationSamples.cs create mode 100644 .dotnet/tests/Samples/EmbeddingSamples.cs create mode 100644 .dotnet/tests/Samples/ImageSamples.cs create mode 100644 .dotnet/tests/TestScenarios/AssistantTests.cs create mode 100644 .dotnet/tests/TestScenarios/ChatClientTests.cs create mode 100644 .dotnet/tests/TestScenarios/ChatToolConstraints.cs create mode 100644 .dotnet/tests/TestScenarios/ChatToolTests.cs create mode 100644 .dotnet/tests/TestScenarios/ChatWithVision.cs create mode 100644 .dotnet/tests/TestScenarios/EmbeddingClientTests.cs create mode 100644 .dotnet/tests/TestScenarios/FileClientTests.cs create mode 100644 .dotnet/tests/TestScenarios/ImageGenerationTests.cs create mode 100644 .dotnet/tests/TestScenarios/LegacyCompletions.cs create mode 100644 .dotnet/tests/TestScenarios/ModelClientTests.cs create mode 100644 .dotnet/tests/TestScenarios/TextToSpeechTests.cs create mode 100644 .dotnet/tests/TestScenarios/TranscriptionTests.cs create mode 100644 .dotnet/tests/TestScenarios/TranslationTests.cs create mode 100644 .dotnet/tests/Utility/TestHelpers.cs create mode 100644 .dotnet/tests/Utility/TestPipelinePolicy.cs create mode 100644 .dotnet/tests/data/hello_world.m4a create mode 100644 .dotnet/tests/data/hola_mundo.m4a create mode 100644 .dotnet/tests/data/stop_sign.png diff --git a/.dotnet/Directory.Build.props b/.dotnet/Directory.Build.props new file mode 100644 index 000000000..a95ac958c --- /dev/null +++ b/.dotnet/Directory.Build.props @@ -0,0 +1,5 @@ + + + latest + + \ No newline at end of file diff --git a/.dotnet/scripts/Add-Customizations.ps1 b/.dotnet/scripts/Add-Customizations.ps1 new file mode 100644 index 000000000..c7eb4412b --- /dev/null +++ b/.dotnet/scripts/Add-Customizations.ps1 @@ -0,0 +1,28 @@ +function Update-SystemTextJsonPackage { + $current = Get-Location + $root = Split-Path $PSScriptRoot -Parent + + # Update System.Text.Json package to 8.0.2 in OpenAI.csproj + $directory = Join-Path -Path $root -ChildPath "src" + Set-Location -Path $directory + dotnet remove "OpenAI.csproj" package "System.Text.Json" + dotnet add "OpenAI.csproj" package "System.Text.Json" --version "8.0.2" + + Set-Location -Path $current +} + +function Update-MicrosoftBclAsyncInterfacesPackage { + $current = Get-Location + $root = Split-Path $PSScriptRoot -Parent + + # Update Microsoft.Bcl.AsyncInterfaces package to 8.0.0 in OpenAI.Tests.csproj + $directory = Join-Path -Path $root -ChildPath "tests" + Set-Location -Path $directory + dotnet remove "OpenAI.Tests.csproj" package "Microsoft.Bcl.AsyncInterfaces" + dotnet add "OpenAI.Tests.csproj" package "Microsoft.Bcl.AsyncInterfaces" --version "8.0.0" + + Set-Location -Path $current +} + +Update-SystemTextJsonPackage +Update-MicrosoftBclAsyncInterfacesPackage \ No newline at end of file diff --git a/.dotnet/scripts/ConvertTo-Internal.ps1 b/.dotnet/scripts/ConvertTo-Internal.ps1 index ec809e075..60f66e75e 100644 --- a/.dotnet/scripts/ConvertTo-Internal.ps1 +++ b/.dotnet/scripts/ConvertTo-Internal.ps1 @@ -1,17 +1,41 @@ -$root = Split-Path $PSScriptRoot -Parent -$directory = Join-Path -Path $root -ChildPath "src\Generated" -$files = Get-ChildItem -Path $($directory + "\*") -Include "*.cs" -Recurse +function Edit-GeneratedSources { + $root = Split-Path $PSScriptRoot -Parent -foreach ($file in $files) { + $directory = Join-Path -Path $root -ChildPath "src\Generated" + $files = Get-ChildItem -Path $($directory + "\*") -Include "*.cs" -Recurse + + foreach ($file in $files) { + $content = Get-Content -Path $file -Raw + + Write-Output "Editing $($file.FullName)" + + $content = $content -creplace "public partial class", "internal partial class" + $content = $content -creplace "public readonly partial struct", "internal readonly partial struct" + $content = $content -creplace "public static partial class", "internal static partial class" + $content = $content -creplace "namespace OpenAI", "namespace OpenAI.Internal" + $content = $content -creplace "using OpenAI.Models;", "using OpenAI.Internal.Models;" + + $content | Set-Content -Path $file.FullName -NoNewline + } + + $file = Get-ChildItem -Path $directory -Filter "OpenAIClient.cs" $content = Get-Content -Path $file -Raw Write-Output "Editing $($file.FullName)" - $content = $content -creplace "public partial class", "internal partial class" - $content = $content -creplace "public readonly partial struct", "internal readonly partial struct" - $content = $content -creplace "public static partial class", "internal static partial class" - $content = $content -creplace "namespace OpenAI", "namespace OpenAI.Internal" - $content = $content -creplace "using OpenAI.Models;", "using OpenAI.Internal.Models;" + $content = $content -creplace "private (OpenAI.)?(?\w+) _cached(\w+);", "private OpenAI.Internal.`${var} _cached`${var};" + $content = $content -creplace "public virtual (OpenAI.)?(?\w+) Get(\w+)Client", "public virtual OpenAI.Internal.`${var} Get`${var}Client" + $content = $content -creplace "ref _cached(\w+), new (OpenAI.)?(?\w+)", "ref _cached`${var}, new OpenAI.Internal.`${var}" $content | Set-Content -Path $file.FullName -NoNewline -} \ No newline at end of file +} + +function Remove-GeneratedTests { + $root = Split-Path $PSScriptRoot -Parent + + $directory = Join-Path -Path $root -ChildPath "tests\Generated" + Remove-Item -LiteralPath $directory -Recurse -Force +} + +Edit-GeneratedSources +Remove-GeneratedTests diff --git a/.dotnet/scripts/Update-ClientModel.ps1 b/.dotnet/scripts/Update-ClientModel.ps1 index 9cab3caf9..a833fc8b7 100644 --- a/.dotnet/scripts/Update-ClientModel.ps1 +++ b/.dotnet/scripts/Update-ClientModel.ps1 @@ -1,16 +1,16 @@ -function Update-ClientModelPackage { +function Update-SystemClientModelPackage { $current = Get-Location $root = Split-Path $PSScriptRoot -Parent + # Update System.ClientModel package in OpenAI.csproj $directory = Join-Path -Path $root -ChildPath "src" Set-Location -Path $directory - dotnet remove "OpenAI.csproj" package "System.ClientModel" dotnet add "OpenAI.csproj" package "System.ClientModel" --version "1.1.0-alpha.20240227.1" --source "https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-net/nuget/v3/index.json" + # Update System.ClientModel package in OpenAI.Tests.csproj $directory = Join-Path -Path $root -ChildPath "tests" Set-Location -Path $directory - dotnet remove "OpenAI.Tests.csproj" package "System.ClientModel" dotnet add "OpenAI.Tests.csproj" package "System.ClientModel" --version "1.1.0-alpha.20240227.1" --source "https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-net/nuget/v3/index.json" @@ -196,7 +196,7 @@ function Update-Tests { } } -Update-ClientModelPackage +Update-SystemClientModelPackage Update-OpenAIClient Update-OpenAIClientOptions Update-Subclients diff --git a/.dotnet/src/Custom/Assistants/Assistant.cs b/.dotnet/src/Custom/Assistants/Assistant.cs new file mode 100644 index 000000000..02dcede78 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/Assistant.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Assistants; + +public partial class Assistant +{ + public string Id { get; } + public DateTimeOffset CreatedAt { get; } + public string Name { get; } + public string Description { get; } + public string DefaultModel { get; } + public string DefaultInstructions { get; } + public IReadOnlyList DefaultTools { get; } + /// + /// An optional key/value mapping of additional, supplemental data items to attach to the . + /// This information may be useful for storing custom details in a structured format. + /// + /// + /// + /// Keys can be a maximum of 64 characters in length. + /// Values can be a maximum of 512 characters in length. + /// + /// + public IReadOnlyDictionary Metadata { get; } + + internal Assistant(Internal.Models.AssistantObject internalAssistant) + { + Id = internalAssistant.Id; + CreatedAt = internalAssistant.CreatedAt; + Name = internalAssistant.Name; + Description = internalAssistant.Description; + DefaultModel = internalAssistant.Model; + DefaultInstructions = internalAssistant.Instructions; + Metadata = internalAssistant.Metadata; + + if (internalAssistant.Tools != null) + { + List tools = []; + foreach (BinaryData unionToolDefinitionData in internalAssistant.Tools) + { + tools.Add(ToolDefinition.DeserializeToolDefinition(JsonDocument.Parse(unionToolDefinitionData).RootElement)); + } + DefaultTools = tools; + } + } +} diff --git a/.dotnet/src/Custom/Assistants/AssistantClient.Protocol.cs b/.dotnet/src/Custom/Assistants/AssistantClient.Protocol.cs new file mode 100644 index 000000000..a0f55c3e0 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/AssistantClient.Protocol.cs @@ -0,0 +1,429 @@ +using System.ClientModel; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.ComponentModel; +using System.Threading.Tasks; + +namespace OpenAI.Assistants; + +public partial class AssistantClient +{ + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult CreateAssistant(BinaryContent content, RequestOptions context = null) + { + return Shim.CreateAssistant(content, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task CreateAssistantAsync(BinaryContent content, RequestOptions context = null) + { + return Shim.CreateAssistantAsync(content, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult GetAssistant(string assistantId, RequestOptions context) + { + return Shim.GetAssistant(assistantId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task GetAssistantAsync(string assistantId, RequestOptions context) + { + return Shim.GetAssistantAsync(assistantId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult GetAssistants( + int? maxResults, + string createdSortOrder, + string previousAssistantId, + string subsequentAssistantId, + RequestOptions context) + { + return Shim.GetAssistants(maxResults, createdSortOrder, previousAssistantId, subsequentAssistantId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task GetAssistantsAsync( + int? maxResults, + string createdSortOrder, + string previousAssistantId, + string subsequentAssistantId, + RequestOptions context) + { + return Shim.GetAssistantsAsync(maxResults, createdSortOrder, previousAssistantId, subsequentAssistantId, context); + } + + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult ModifyAssistant(string assistantId, BinaryContent content, RequestOptions context = null) + { + return Shim.ModifyAssistant(assistantId, content, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task ModifyAssistantAsync(string assistantId, BinaryContent content, RequestOptions context = null) + { + return Shim.ModifyAssistantAsync(assistantId, content, context); + } + + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult DeleteAssistant(string assistantId, RequestOptions context) + { + return Shim.DeleteAssistant(assistantId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task DeleteAssistantAsync(string assistantId, RequestOptions context) + { + return Shim.DeleteAssistantAsync(assistantId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult CreateAssistantFileAssociation( + string assistantId, + BinaryContent content, + RequestOptions context = null) + { + return Shim.CreateAssistantFile(assistantId, content, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task CreateAssistantFileAssociationAsync( + string assistantId, + BinaryContent content, + RequestOptions context = null) + { + return Shim.CreateAssistantFileAsync(assistantId, content, context); + } + + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult GetAssistantFileAssociation(string assistantId, string fileId, RequestOptions context) + { + return Shim.GetAssistantFile(assistantId, fileId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task GetAssistantFileAssociationAsync(string assistantId, string fileId, RequestOptions context) + { + return Shim.GetAssistantFileAsync(assistantId, fileId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult GetAssistantFileAssociations( + string assistantId, + int? maxResults, + string createdSortOrder, + string previousId, + string subsequentId, + RequestOptions context) + { + return Shim.GetAssistantFiles(assistantId, maxResults, createdSortOrder, previousId, subsequentId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task GetAssistantFileAssociationsAsync( + string assistantId, + int? maxResults, + string createdSortOrder, + string previousId, + string subsequentId, + RequestOptions context) + { + return Shim + .GetAssistantFilesAsync(assistantId, maxResults, createdSortOrder, previousId, subsequentId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult RemoveAssistantFileAssociation(string assistantId, string fileId, RequestOptions context) + { + return Shim.DeleteAssistantFile(assistantId, fileId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task RemoveAssistantFileAssociationAsync(string assistantId, string fileId, RequestOptions context) + { + return Shim.DeleteAssistantFileAsync(assistantId, fileId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult CreateThread(BinaryContent content, RequestOptions context = null) + { + return ThreadShim.CreateThread(content, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task CreateThreadAsync(BinaryContent content, RequestOptions context = null) + { + return ThreadShim.CreateThreadAsync(content, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult GetThread(string threadId, RequestOptions context) + { + return ThreadShim.GetThread(threadId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task GetThreadAsync(string threadId, RequestOptions context) + { + return ThreadShim.GetThreadAsync(threadId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult ModifyThread(string threadId, BinaryContent content, RequestOptions context = null) + { + return ThreadShim.ModifyThread(threadId, content, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task ModifyThreadAsync(string threadId, BinaryContent content, RequestOptions context = null) + { + return ThreadShim.ModifyThreadAsync(threadId, content, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult DeleteThread(string threadId, RequestOptions context) + { + return ThreadShim.DeleteThread(threadId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task DeleteThreadAsync(string threadId, RequestOptions context) + { + return ThreadShim.DeleteThreadAsync(threadId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult CreateMessage(string threadId, BinaryContent content, RequestOptions context = null) + { + return MessageShim.CreateMessage(threadId, content, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task CreateMessageAsync(string threadId, BinaryContent content, RequestOptions context = null) + { + return MessageShim.CreateMessageAsync(threadId, content, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult GetMessage(string threadId, string messageId, RequestOptions context) + { + return MessageShim.GetMessage(threadId, messageId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task GetMessageAsync(string threadId, string messageId, RequestOptions context) + { + return MessageShim.GetMessageAsync(threadId, messageId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult GetMessages( + string threadId, + int? maxResults, + string createdSortOrder, + string previousMessageId, + string subsequentMessageId, + RequestOptions context) + { + return MessageShim + .GetMessages(threadId, maxResults, createdSortOrder, previousMessageId, subsequentMessageId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task GetMessagesAsync( + string threadId, + int? maxResults, + string createdSortOrder, + string previousMessageId, + string subsequentMessageId, + RequestOptions context) + { + return MessageShim + .GetMessagesAsync(threadId, maxResults, createdSortOrder, previousMessageId, subsequentMessageId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult GetMessageFileAssociation(string threadId, string messageId, string fileId, RequestOptions context) + { + return MessageShim.GetMessageFile(threadId, messageId, fileId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task GetMessageFileAssociationAsync( + string threadId, + string messageId, + string fileId, + RequestOptions context) + { + return MessageShim.GetMessageFileAsync(threadId, messageId, fileId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult GetMessageFileAssociations( + string threadId, + string messageId, + int? maxResults, + string createdSortOrder, + string previousId , + string subsequentId, + RequestOptions context) + { + return MessageShim + .GetMessageFiles(threadId, messageId, maxResults, createdSortOrder, previousId, subsequentId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task GetMessageFileAssociationsAsync( + string threadId, + string messageId, + int? maxResults, + string createdSortOrder, + string previousId, + string subsequentId, + RequestOptions context) + { + return MessageShim + .GetMessageFilesAsync(threadId, messageId, maxResults, createdSortOrder, previousId, subsequentId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult CreateRun(string threadId, BinaryContent content, RequestOptions context = null) + { + return RunShim.CreateRun(threadId, content, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task CreateRunAsync(string threadId, BinaryContent content, RequestOptions context = null) + { + return RunShim.CreateRunAsync(threadId, content, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult CreateThreadAndRun(BinaryContent content, RequestOptions context = null) + { + return RunShim.CreateThreadAndRun(content, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task CreateThreadAndRunAsync(BinaryContent content, RequestOptions context = null) + { + return RunShim.CreateThreadAndRunAsync(content, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult GetRun(string threadId, string runId, RequestOptions context) + { + return RunShim.GetRun(threadId, runId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task GetRunAsync(string threadId, string runId, RequestOptions context) + { + return RunShim.GetRunAsync(threadId, runId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult GetRuns( + string threadId, + int? maxResults, + string createdSortOrder, + string previousRunId, + string subsequentRunId, + RequestOptions context) + { + return RunShim.GetRuns(threadId, maxResults, createdSortOrder, previousRunId, subsequentRunId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task GetRunsAsync( + string threadId, + int? maxResults, + string createdSortOrder, + string previousRunId, + string subsequentRunId, + RequestOptions context) + { + return RunShim.GetRunsAsync(threadId, maxResults, createdSortOrder, previousRunId, subsequentRunId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult ModifyRun(string threadId, string runId, BinaryContent content, RequestOptions context = null) + { + return RunShim.ModifyRun(threadId, runId, content, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task ModifyRunAsync( + string threadId, + string runId, + BinaryContent content, + RequestOptions context = null) + { + return RunShim.ModifyRunAsync(threadId, runId, content, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult CancelRun(string threadId, string runId, RequestOptions context) + { + return RunShim.CancelRun(threadId, runId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task CancelRunAsync(string threadId, string runId, RequestOptions context) + { + return RunShim.CancelRunAsync(threadId, runId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult SubmitToolOutputs(string threadId, string runId, BinaryContent content, RequestOptions context = null) + { + return RunShim.SubmitToolOuputsToRun(threadId, runId, content, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task SubmitToolOutputsAsync(string threadId, string runId, BinaryContent content, RequestOptions context = null) + { + return RunShim.SubmitToolOuputsToRunAsync(threadId, runId, content, context); + } + + public virtual ClientResult GetRunStep(string threadId, string runId, string stepId, RequestOptions context) + { + return RunShim.GetRunStep(threadId, runId, stepId, context); + } + + public virtual Task GetRunStepAsync(string threadId, string runId, string stepId, RequestOptions context) + { + return RunShim.GetRunStepAsync(threadId, runId, stepId, context); + } + + public virtual ClientResult GetRunSteps( + string threadId, + string runId, + int? maxResults, + string createdSortOrder, + string previousStepId, + string subsequentStepId, + RequestOptions context) + { + return RunShim + .GetRunSteps(threadId, runId, maxResults, createdSortOrder, previousStepId, subsequentStepId, context); + } + + public virtual Task GetRunStepsAsync( + string threadId, + string runId, + int? maxResults, + string createdSortOrder, + string previousStepId, + string subsequentStepId, + RequestOptions context) + { + return RunShim + .GetRunStepsAsync(threadId, runId, maxResults, createdSortOrder, previousStepId, subsequentStepId, context); + } +} diff --git a/.dotnet/src/Custom/Assistants/AssistantClient.cs b/.dotnet/src/Custom/Assistants/AssistantClient.cs new file mode 100644 index 000000000..72f33f119 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/AssistantClient.cs @@ -0,0 +1,771 @@ +using System; +using System.ClientModel; +using System.ClientModel.Internal; + +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using OpenAI.Internal; +using System.Text.Json; +using OpenAI.ClientShared.Internal; + +namespace OpenAI.Assistants; + +/// +/// The service client for OpenAI assistants. +/// +public partial class AssistantClient +{ + private OpenAIClientConnector _clientConnector; + private Internal.Assistants Shim => _clientConnector.InternalClient.GetAssistantsClient(); + private Internal.Threads ThreadShim => _clientConnector.InternalClient.GetThreadsClient(); + private Internal.Messages MessageShim => _clientConnector.InternalClient.GetMessagesClient(); + private Internal.Runs RunShim => _clientConnector.InternalClient.GetRunsClient(); + + /// + /// Initializes a new instance of , used for assistant requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The connection endpoint to use. + /// The API key used to authenticate with the service endpoint. + /// Additional options to customize the client. + public AssistantClient(Uri endpoint, ApiKeyCredential credential, OpenAIClientOptions options = null) + { + options ??= new(); + options.AddPolicy( + new GenericActionPipelinePolicy((m) => m.Request?.Headers.Set("OpenAI-Beta", "assistants=v1")), + PipelinePosition.PerCall); + _clientConnector = new("none", endpoint, credential, options); + } + + /// + /// Initializes a new instance of , used for assistant requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The connection endpoint to use. + /// Additional options to customize the client. + public AssistantClient(Uri endpoint, OpenAIClientOptions options = null) + : this(endpoint, credential: null, options) + { } + + /// + /// Initializes a new instance of , used for assistant requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The API key used to authenticate with the service endpoint. + /// Additional options to customize the client. + public AssistantClient(ApiKeyCredential credential, OpenAIClientOptions options = null) + : this(endpoint: null, credential, options) + { } + + /// + /// Initializes a new instance of , used for assistant requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// Additional options to customize the client. + public AssistantClient(OpenAIClientOptions options = null) + : this(endpoint: null, credential: null, options) + { } + + public virtual ClientResult CreateAssistant(string modelName, AssistantCreationOptions options = null) + { + Internal.Models.CreateAssistantRequest request = CreateInternalCreateAssistantRequest(modelName, options); + ClientResult internalResult = Shim.CreateAssistant(request); + return ClientResult.FromValue(new Assistant(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual async Task> CreateAssistantAsync(string modelName, AssistantCreationOptions options = null) + { + Internal.Models.CreateAssistantRequest request = CreateInternalCreateAssistantRequest(modelName, options); + ClientResult internalResult + = await Shim.CreateAssistantAsync(request).ConfigureAwait(false); + return ClientResult.FromValue(new Assistant(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual ClientResult GetAssistant(string assistantId) + { + ClientResult internalResult = Shim.GetAssistant(assistantId); + return ClientResult.FromValue(new Assistant(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual async Task> GetAssistantAsync( + string assistantId) + { + ClientResult internalResult + = await Shim.GetAssistantAsync(assistantId).ConfigureAwait(false); + return ClientResult.FromValue(new Assistant(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual ClientResult> GetAssistants( + int? maxResults = null, + CreatedAtSortOrder? createdSortOrder = null, + string previousAssistantId = null, + string subsequentAssistantId = null) + { + ClientResult internalFunc() => Shim.GetAssistants( + maxResults, + ToInternalListOrder(createdSortOrder), + previousAssistantId, + subsequentAssistantId); + return GetListQueryPage(internalFunc); + } + + public virtual Task>> GetAssistantsAsync( + int? maxResults = null, + CreatedAtSortOrder? createdSortOrder = null, + string previousAssistantId = null, + string subsequentAssistantId = null) + { + Task> internalAsyncFunc() => Shim.GetAssistantsAsync( + maxResults, + ToInternalListOrder(createdSortOrder), + previousAssistantId, + subsequentAssistantId); + return GetListQueryPageAsync(internalAsyncFunc); + } + + public virtual ClientResult ModifyAssistant( + string assistantId, + AssistantModificationOptions options) + { + ClientResult internalResult + = Shim.ModifyAssistant(assistantId, CreateInternalModifyAssistantRequest(options)); + return ClientResult.FromValue(new Assistant(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual async Task> ModifyAssistantAsync( + string assistantId, + AssistantModificationOptions options) + { + Internal.Models.ModifyAssistantRequest request = CreateInternalModifyAssistantRequest(options); + ClientResult internalResult + = await Shim.ModifyAssistantAsync(assistantId, request).ConfigureAwait(false); + return ClientResult.FromValue(new Assistant(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual ClientResult DeleteAssistant(string assistantId) + { + ClientResult internalResponse = Shim.DeleteAssistant(assistantId); + return ClientResult.FromValue(internalResponse.Value.Deleted, internalResponse.GetRawResponse()); + } + + public virtual async Task> DeleteAssistantAsync( + string assistantId) + { + ClientResult internalResponse + = await Shim.DeleteAssistantAsync(assistantId).ConfigureAwait(false); + return ClientResult.FromValue(internalResponse.Value.Deleted, internalResponse.GetRawResponse()); + } + + public virtual ClientResult CreateAssistantFileAssociation( + string assistantId, + string fileId) + { + ClientResult internalResult + = Shim.CreateAssistantFile(assistantId, new(fileId)); + return ClientResult.FromValue(new AssistantFileAssociation(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual async Task> CreateAssistantFileAssociationAsync( + string assistantId, + string fileId) + { + ClientResult internalResult + = await Shim.CreateAssistantFileAsync(assistantId, new(fileId)).ConfigureAwait(false); + return ClientResult.FromValue(new AssistantFileAssociation(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual ClientResult GetAssistantFileAssociation( + string assistantId, + string fileId) + { + ClientResult internalResult = Shim.GetAssistantFile(assistantId, fileId); + return ClientResult.FromValue(new AssistantFileAssociation(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual async Task> GetAssistantFileAssociationAsync( + string assistantId, + string fileId) + { + ClientResult internalResult + = await Shim.GetAssistantFileAsync(assistantId, fileId).ConfigureAwait(false); + return ClientResult.FromValue(new AssistantFileAssociation(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual ClientResult> GetAssistantFileAssociations( + string assistantId, + int? maxResults = null, + CreatedAtSortOrder? createdSortOrder = null, + string previousId = null, + string subsequentId = null) + { + ClientResult internalFunc() => Shim.GetAssistantFiles( + assistantId, + maxResults, + ToInternalListOrder(createdSortOrder), + previousId, + subsequentId); + return GetListQueryPage(internalFunc); + } + + public virtual Task>> GetAssistantFileAssociationsAsync( + string assistantId, + int? maxResults = null, + CreatedAtSortOrder? createdSortOrder = null, + string previousId = null, + string subsequentId = null) + { + Func>> internalFunc + = () => Shim.GetAssistantFilesAsync( + assistantId, + maxResults, + ToInternalListOrder(createdSortOrder), + previousId, + subsequentId); + return GetListQueryPageAsync(internalFunc); + } + + public virtual ClientResult RemoveAssistantFileAssociation( + string assistantId, + string fileId) + { + ClientResult internalResult + = Shim.DeleteAssistantFile(assistantId, fileId); + return ClientResult.FromValue(internalResult.Value.Deleted, internalResult.GetRawResponse()); + } + + public virtual async Task> RemoveAssistantFileAssociationAsync( + string assistantId, + string fileId) + { + ClientResult internalResult + = await Shim.DeleteAssistantFileAsync(assistantId, fileId).ConfigureAwait(false); + return ClientResult.FromValue(internalResult.Value.Deleted, internalResult.GetRawResponse()); + } + + public virtual ClientResult CreateThread( + ThreadCreationOptions options = null) + { + Internal.Models.CreateThreadRequest request = CreateInternalCreateThreadRequest(options); + ClientResult internalResult = ThreadShim.CreateThread(request); + return ClientResult.FromValue(new AssistantThread(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual async Task> CreateThreadAsync( + ThreadCreationOptions options = null) + { + Internal.Models.CreateThreadRequest request = CreateInternalCreateThreadRequest(options); + ClientResult internalResult + = await ThreadShim.CreateThreadAsync(request).ConfigureAwait(false); + return ClientResult.FromValue(new AssistantThread(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual ClientResult GetThread(string threadId) + { + ClientResult internalResult = ThreadShim.GetThread(threadId); + return ClientResult.FromValue(new AssistantThread(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual async Task> GetThreadAsync( + string threadId) + { + ClientResult internalResult + = await ThreadShim.GetThreadAsync(threadId).ConfigureAwait(false); + return ClientResult.FromValue(new AssistantThread(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual ClientResult ModifyThread( + string threadId, + ThreadModificationOptions options) + { + Internal.Models.ModifyThreadRequest request = new( + options.Metadata, + serializedAdditionalRawData: null); + ClientResult internalResult = ThreadShim.ModifyThread(threadId, request); + return ClientResult.FromValue(new AssistantThread(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual async Task> ModifyThreadAsync( + string threadId, + ThreadModificationOptions options) + { + Internal.Models.ModifyThreadRequest request = new( + options.Metadata, + serializedAdditionalRawData: null); + ClientResult internalResult + = await ThreadShim.ModifyThreadAsync(threadId, request); + return ClientResult.FromValue(new AssistantThread(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual ClientResult DeleteThread(string threadId) + { + ClientResult internalResult = ThreadShim.DeleteThread(threadId); + return ClientResult.FromValue(internalResult.Value.Deleted, internalResult.GetRawResponse()); + } + + public virtual async Task> DeleteThreadAsync(string threadId) + { + ClientResult internalResult + = await ThreadShim.DeleteThreadAsync(threadId).ConfigureAwait(false); + return ClientResult.FromValue(internalResult.Value.Deleted, internalResult.GetRawResponse()); + } + + public virtual ClientResult CreateMessage( + string threadId, + MessageRole role, + string content, + MessageCreationOptions options = null) + { + Internal.Models.CreateMessageRequest request = new( + ToInternalRequestRole(role), + content, + options.FileIds, + options.Metadata, + serializedAdditionalRawData: null); + ClientResult internalResult = MessageShim.CreateMessage(threadId, request); + return ClientResult.FromValue(new ThreadMessage(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual async Task> CreateMessageAsync( + string threadId, + MessageRole role, + string content, + MessageCreationOptions options = null) + { + Internal.Models.CreateMessageRequest request = new( + ToInternalRequestRole(role), + content, + options.FileIds, + options.Metadata, + serializedAdditionalRawData: null); + ClientResult internalResult + = await MessageShim.CreateMessageAsync(threadId, request).ConfigureAwait(false); + return ClientResult.FromValue(new ThreadMessage(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual ClientResult GetMessage( + string threadId, + string messageId) + { + ClientResult internalResult = MessageShim.GetMessage(threadId, messageId); + return ClientResult.FromValue(new ThreadMessage(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual async Task> GetMessageAsync( + string threadId, + string messageId) + { + ClientResult internalResult + = await MessageShim.GetMessageAsync(threadId, messageId).ConfigureAwait(false); + return ClientResult.FromValue(new ThreadMessage(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual ClientResult> GetMessages( + string threadId, + int? maxResults = null, + CreatedAtSortOrder? createdSortOrder = null, + string previousMessageId = null, + string subsequentMessageId = null) + { + ClientResult internalFunc() => MessageShim.GetMessages( + threadId, + maxResults, + ToInternalListOrder(createdSortOrder), + previousMessageId, + subsequentMessageId); + return GetListQueryPage(internalFunc); + } + + public virtual Task>> GetMessagesAsync( + string threadId, + int? maxResults = null, + CreatedAtSortOrder? createdSortOrder = null, + string previousMessageId = null, + string subsequentMessageId = null) + { + Func>> internalFunc = () => MessageShim.GetMessagesAsync( + threadId, + maxResults, + ToInternalListOrder(createdSortOrder), + previousMessageId, + subsequentMessageId); + return GetListQueryPageAsync(internalFunc); + } + + public virtual ClientResult GetMessageFileAssociation( + string threadId, + string messageId, + string fileId) + { + ClientResult internalResult + = MessageShim.GetMessageFile(threadId, messageId, fileId); + return ClientResult.FromValue(new MessageFileAssociation(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual async Task> GetMessageFileAssociationAsync( + string threadId, + string messageId, + string fileId) + { + ClientResult internalResult + = await MessageShim.GetMessageFileAsync(threadId, messageId, fileId).ConfigureAwait(false); + return ClientResult.FromValue(new MessageFileAssociation(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual ClientResult> GetMessageFileAssociations( + string threadId, + string messageId, + int? maxResults = null, + CreatedAtSortOrder? createdSortOrder = null, + string previousId = null, + string subsequentId = null) + { + ClientResult internalFunc() => MessageShim.GetMessageFiles( + threadId, + messageId, + maxResults, + ToInternalListOrder(createdSortOrder), + previousId, + subsequentId); + return GetListQueryPage(internalFunc); + } + + public virtual Task>> GetMessageFileAssociationsAsync( + string threadId, + string messageId, + int? maxResults = null, + CreatedAtSortOrder? createdSortOrder = null, + string previousId = null, + string subsequentId = null) + { + Task> internalFunc() => MessageShim.GetMessageFilesAsync( + threadId, + messageId, + maxResults, + ToInternalListOrder(createdSortOrder), + previousId, + subsequentId); + return GetListQueryPageAsync(internalFunc); + } + + public virtual ClientResult CreateRun( + string threadId, + string assistantId, + RunCreationOptions options = null) + { + Internal.Models.CreateRunRequest request = CreateInternalCreateRunRequest(assistantId, options); + ClientResult internalResult = RunShim.CreateRun(threadId, request); + return ClientResult.FromValue(new ThreadRun(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual async Task> CreateRunAsync( + string threadId, + string assistantId, + RunCreationOptions options = null) + { + Internal.Models.CreateRunRequest request = CreateInternalCreateRunRequest(assistantId, options); + ClientResult internalResult + = await RunShim.CreateRunAsync(threadId, request).ConfigureAwait(false); + return ClientResult.FromValue(new ThreadRun(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual ClientResult CreateThreadAndRun( + string assistantId, + ThreadCreationOptions threadOptions = null, + RunCreationOptions runOptions = null) + { + Internal.Models.CreateThreadAndRunRequest request + = CreateInternalCreateThreadAndRunRequest(assistantId, threadOptions, runOptions); + ClientResult internalResult = RunShim.CreateThreadAndRun(request); + return ClientResult.FromValue(new ThreadRun(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual async Task> CreateThreadAndRunAsync( + string assistantId, + ThreadCreationOptions threadOptions = null, + RunCreationOptions runOptions = null) + { + Internal.Models.CreateThreadAndRunRequest request + = CreateInternalCreateThreadAndRunRequest(assistantId, threadOptions, runOptions); + ClientResult internalResult + = await RunShim.CreateThreadAndRunAsync(request).ConfigureAwait(false); + return ClientResult.FromValue(new ThreadRun(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual ClientResult GetRun(string threadId, string runId) + { + ClientResult internalResult = RunShim.GetRun(threadId, runId); + return ClientResult.FromValue(new ThreadRun(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual async Task> GetRunAsync(string threadId, string runId) + { + ClientResult internalResult + = await RunShim.GetRunAsync(threadId, runId).ConfigureAwait(false); + return ClientResult.FromValue(new ThreadRun(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual ClientResult> GetRuns( + string threadId, + int? maxResults = null, + CreatedAtSortOrder? createdSortOrder = null, + string previousRunId = null, + string subsequentRunId = null) + { + ClientResult internalFunc() => RunShim.GetRuns( + threadId, + maxResults, + ToInternalListOrder(createdSortOrder), + previousRunId, + subsequentRunId); + return GetListQueryPage(internalFunc); + } + + public virtual Task>> GetRunsAsync( + string threadId, + int? maxResults = null, + CreatedAtSortOrder? createdSortOrder = null, + string previousRunId = null, + string subsequentRunId = null) + { + Func>> internalFunc = () => RunShim.GetRunsAsync( + threadId, + maxResults, + ToInternalListOrder(createdSortOrder), + previousRunId, + subsequentRunId); + return GetListQueryPageAsync(internalFunc); + } + + public virtual ClientResult ModifyRun(string threadId, string runId, RunModificationOptions options) + { + Internal.Models.ModifyRunRequest request = new(options.Metadata, serializedAdditionalRawData: null); + ClientResult internalResult = RunShim.ModifyRun(threadId, runId, request); + return ClientResult.FromValue(new ThreadRun(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual async Task> ModifyRunAsync(string threadId, string runId, RunModificationOptions options) + { + Internal.Models.ModifyRunRequest request = new(options.Metadata, serializedAdditionalRawData: null); + ClientResult internalResult + = await RunShim.ModifyRunAsync(threadId, runId, request).ConfigureAwait(false); + return ClientResult.FromValue(new ThreadRun(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual ClientResult CancelRun(string threadId, string runId) + { + ClientResult internalResult = RunShim.CancelRun(threadId, runId); + return ClientResult.FromValue(true, internalResult.GetRawResponse()); + } + + public virtual async Task> CancelRunAsync(string threadId, string runId) + { + ClientResult internalResult + = await RunShim.CancelRunAsync(threadId, runId); + return ClientResult.FromValue(true, internalResult.GetRawResponse()); + } + + public virtual ClientResult SubmitToolOutputs(string threadId, string runId, IEnumerable toolOutputs) + { + BinaryContent content = BinaryContent.Create(BinaryData.FromObjectAsJson(new + { + tool_outputs = toolOutputs + }, + new JsonSerializerOptions() + { + PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower + })); + ClientResult internalResult = RunShim.SubmitToolOuputsToRun(threadId, runId, content, default); + return ClientResult.FromValue(true, internalResult.GetRawResponse()); + } + + public virtual async Task> SubmitToolOutputsAsync(string threadId, string runId, IEnumerable toolOutputs) + { + BinaryContent content = BinaryContent.Create(BinaryData.FromObjectAsJson(new + { + tool_outputs = toolOutputs + }, + new JsonSerializerOptions() + { + PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower + })); + ClientResult internalResult + = await RunShim.SubmitToolOuputsToRunAsync(threadId, runId, content, default).ConfigureAwait(false); + return ClientResult.FromValue(true, internalResult.GetRawResponse()); + } + + internal static Internal.Models.CreateAssistantRequest CreateInternalCreateAssistantRequest( + string modelName, + AssistantCreationOptions options) + { + options ??= new(); + return new Internal.Models.CreateAssistantRequest( + modelName, + options.Name, + options.Description, + options.Instructions, + ToInternalBinaryDataList(options.Tools), + options.FileIds, + options.Metadata, + serializedAdditionalRawData: null); + } + + internal static Internal.Models.ModifyAssistantRequest CreateInternalModifyAssistantRequest(AssistantModificationOptions options) + { + return new Internal.Models.ModifyAssistantRequest( + options.Model, + options.Name, + options.Description, + options.Instructions, + ToInternalBinaryDataList(options.Tools), + options.FileIds, + options.Metadata, + serializedAdditionalRawData: null); + } + + internal static Internal.Models.CreateThreadRequest CreateInternalCreateThreadRequest(ThreadCreationOptions options) + { + options ??= new(); + return new Internal.Models.CreateThreadRequest( + ToInternalCreateMessageRequestList(options.Messages), + options.Metadata, + serializedAdditionalRawData: null); + } + + internal static Internal.Models.CreateRunRequest CreateInternalCreateRunRequest( + string assistantId, + RunCreationOptions options = null) + { + options ??= new(); + return new( + assistantId, + options.OverrideModel, + options.OverrideInstructions, + options.AdditionalInstructions, + ToInternalBinaryDataList(options.OverrideTools), + options.Metadata, + serializedAdditionalRawData: null); + } + + internal static Internal.Models.CreateThreadAndRunRequest CreateInternalCreateThreadAndRunRequest( + string assistantId, + ThreadCreationOptions threadOptions, + RunCreationOptions runOptions) + { + threadOptions ??= new(); + runOptions ??= new(); + Internal.Models.CreateThreadRequest internalThreadOptions = CreateInternalCreateThreadRequest(threadOptions); + return new Internal.Models.CreateThreadAndRunRequest( + assistantId, + internalThreadOptions, + runOptions?.OverrideModel, + runOptions.OverrideInstructions, + ToInternalBinaryDataList(runOptions?.OverrideTools), + runOptions?.Metadata, + serializedAdditionalRawData: null); + } + + internal static OptionalList ToInternalBinaryDataList(IEnumerable values) + where T : IPersistableModel + { + OptionalList internalList = []; + foreach (T value in values) + { + internalList.Add(ModelReaderWriter.Write(value)); + } + return internalList; + } + + internal static Internal.Models.ListOrder? ToInternalListOrder(CreatedAtSortOrder? order) + { + if (order == null) + { + return null; + } + return order switch + { + CreatedAtSortOrder.OldestFirst => Internal.Models.ListOrder.Asc, + CreatedAtSortOrder.NewestFirst => Internal.Models.ListOrder.Desc, + _ => throw new ArgumentException(nameof(order)), + }; + } + + internal static Internal.Models.CreateMessageRequestRole ToInternalRequestRole(MessageRole role) + => role switch + { + MessageRole.User => Internal.Models.CreateMessageRequestRole.User, + _ => throw new ArgumentException(nameof(role)), + }; + + internal static OptionalList ToInternalCreateMessageRequestList( + IEnumerable messages) + { + OptionalList internalList = []; + foreach (ThreadInitializationMessage message in messages) + { + internalList.Add(new Internal.Models.CreateMessageRequest( + ToInternalRequestRole(message.Role), + message.Content, + message.FileIds, + message.Metadata, + serializedAdditionalRawData: null)); + } + return internalList; + } + + internal virtual ClientResult> GetListQueryPage(Func> internalFunc) + where T : class + where U : class + { + ClientResult internalResult = internalFunc.Invoke(); + ListQueryPage convertedValue = ListQueryPage.Create(internalResult.Value) as ListQueryPage; + return ClientResult.FromValue(convertedValue, internalResult.GetRawResponse()); + } + + internal virtual async Task>> GetListQueryPageAsync(Func>> internalAsyncFunc) + where T : class + where U : class + { + ClientResult internalResult = await internalAsyncFunc.Invoke(); + ListQueryPage convertedValue = ListQueryPage.Create(internalResult.Value) as ListQueryPage; + return ClientResult.FromValue(convertedValue, internalResult.GetRawResponse()); + } +} diff --git a/.dotnet/src/Custom/Assistants/AssistantCreationOptions.cs b/.dotnet/src/Custom/Assistants/AssistantCreationOptions.cs new file mode 100644 index 000000000..9b9f23321 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/AssistantCreationOptions.cs @@ -0,0 +1,65 @@ +using OpenAI.ClientShared.Internal; +using System.ClientModel.Internal; + +using System.Collections.Generic; + +namespace OpenAI.Assistants; + +/// +/// Represents additional options available when creating a new . +/// +public partial class AssistantCreationOptions +{ + /// + /// An optional display name for the assistant. + /// + public string Name { get; set; } + /// + /// A description to associate with the assistant. + /// + public string Description { get; set; } + + /// + /// Default instructions for the assistant to use when creating messages. + /// + public string Instructions { get; set; } + + /// + /// A collection of default tool definitions to enable for the assistant. Available tools include: + /// + /// + /// + /// code_interpreter - + /// - works with data, math, and computer code + /// + /// + /// retrieval - + /// - dynamically enriches an assistant's context with content from uploaded, indexed files + /// + /// + /// function - + /// - enables caller-provided custom functions for actions and enrichment + /// + /// + /// + /// + public IList Tools { get; } = new OptionalList(); + + /// + /// A collection of IDs for previously uploaded files that are made accessible to the assistant. These IDs are the + /// basis for the functionality of file-based tools like retrieval. + /// + public IList FileIds { get; } = new OptionalList(); + + /// + /// An optional key/value mapping of additional, supplemental data items to attach to the . + /// This information may be useful for storing custom details in a structured format. + /// + /// + /// + /// Keys can be a maximum of 64 characters in length. + /// Values can be a maximum of 512 characters in length. + /// + /// + public IDictionary Metadata { get; } = new OptionalDictionary(); +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Assistants/AssistantFileAssociation.cs b/.dotnet/src/Custom/Assistants/AssistantFileAssociation.cs new file mode 100644 index 000000000..7a563c06e --- /dev/null +++ b/.dotnet/src/Custom/Assistants/AssistantFileAssociation.cs @@ -0,0 +1,17 @@ +using System; + +namespace OpenAI.Assistants; + +public partial class AssistantFileAssociation +{ + public string AssistantId { get; } + public string FileId { get; } + public DateTimeOffset CreatedAt { get; } + + internal AssistantFileAssociation(Internal.Models.AssistantFileObject internalFile) + { + AssistantId = internalFile.AssistantId; + FileId = internalFile.Id; + CreatedAt = internalFile.CreatedAt; + } +} diff --git a/.dotnet/src/Custom/Assistants/AssistantModificationOptions.cs b/.dotnet/src/Custom/Assistants/AssistantModificationOptions.cs new file mode 100644 index 000000000..1c72d4490 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/AssistantModificationOptions.cs @@ -0,0 +1,71 @@ +using OpenAI.ClientShared.Internal; +using System.ClientModel.Internal; + +using System.Collections.Generic; + +namespace OpenAI.Assistants; + +/// +/// Represents additional options available when modifying an existing . +/// +public partial class AssistantModificationOptions +{ + /// + /// The new model that the assistant should use when creating messages. + /// + public string Model { get; } + + /// + /// A new, friendly name for the assistant. Its will remain unchanged. + /// + public string Name { get; } + + /// + /// A new description to associate with the assistant. + /// + public string Description { get; } + + /// + /// New, default instructions for the assistant to use when creating messages. + /// + public string Instructions { get; } + + /// + /// A new collection of default tool definitions to enable for the assistant. Available tools include: + /// + /// + /// + /// code_interpreter - + /// - works with data, math, and computer code + /// + /// + /// retrieval - + /// - dynamically enriches an assistant's context with content from uploaded, indexed files + /// + /// + /// function - + /// - enables caller-provided custom functions for actions and enrichment + /// + /// + /// + /// + public IList Tools { get; } = new OptionalList(); + + /// + /// A new collection of IDs for previously uploaded files that are made accessible to the assistant. These IDs are + /// the basis for the functionality of file-based tools like retrieval. + /// + public IList FileIds { get; } = new OptionalList(); + + /// + /// A replacement for the optional key/value mapping of additional, supplemental data items to attach to the + /// . This information may be useful for storing custom details in a structured format. + /// + /// + /// + /// Keys can be a maximum of 64 characters in length. + /// Values can be a maximum of 512 characters in length. + /// + /// + public IDictionary Metadata { get; } = new OptionalDictionary(); +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Assistants/AssistantThread.cs b/.dotnet/src/Custom/Assistants/AssistantThread.cs new file mode 100644 index 000000000..f6c85c9ad --- /dev/null +++ b/.dotnet/src/Custom/Assistants/AssistantThread.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +namespace OpenAI.Assistants; + +public partial class AssistantThread +{ + public string Id { get; } + + public DateTimeOffset CreatedAt { get; } + + /// + /// An optional key/value mapping of additional, supplemental data items to attach to the . + /// This information may be useful for storing custom details in a structured format. + /// + /// + /// + /// Keys can be a maximum of 64 characters in length. + /// Values can be a maximum of 512 characters in length. + /// + /// + public IReadOnlyDictionary Metadata { get; } + + + internal AssistantThread(Internal.Models.ThreadObject internalThread) + { + Id = internalThread.Id; + Metadata = internalThread.Metadata; + CreatedAt = internalThread.CreatedAt; + } + +} diff --git a/.dotnet/src/Custom/Assistants/CodeInterpreterToolDefinition.cs b/.dotnet/src/Custom/Assistants/CodeInterpreterToolDefinition.cs new file mode 100644 index 000000000..995e9ffb3 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/CodeInterpreterToolDefinition.cs @@ -0,0 +1,38 @@ +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Text.Json; + +namespace OpenAI.Assistants; + +public partial class CodeInterpreterToolDefinition : ToolDefinition +{ + public CodeInterpreterToolDefinition() + { } + + internal static CodeInterpreterToolDefinition DeserializeCodeInterpreterToolDefinition( + JsonElement element, + ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("code_interpreter"u8)) + { + continue; + } + } + + return new CodeInterpreterToolDefinition(); + } + + internal override void WriteDerived(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + writer.WriteString("type"u8, "code_interpreter"u8); + } +} diff --git a/.dotnet/src/Custom/Assistants/CodeInterpreterToolInfo.cs b/.dotnet/src/Custom/Assistants/CodeInterpreterToolInfo.cs new file mode 100644 index 000000000..b464fd2f3 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/CodeInterpreterToolInfo.cs @@ -0,0 +1,33 @@ +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Text.Json; + +namespace OpenAI.Assistants; + +public partial class CodeInterpreterToolInfo : ToolInfo +{ + internal CodeInterpreterToolInfo() + { } + + internal static CodeInterpreterToolInfo DeserializeCodeInterpreterToolInfo( + JsonElement element, + ModelReaderWriterOptions options) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + + foreach (var property in element.EnumerateObject()) + { + } + return new CodeInterpreterToolInfo(); + } + + internal override void WriteDerived(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + writer.WriteString("type"u8, "code_interpreter"u8); + } +} diff --git a/.dotnet/src/Custom/Assistants/CreatedAtSortOrder.cs b/.dotnet/src/Custom/Assistants/CreatedAtSortOrder.cs new file mode 100644 index 000000000..d10e11781 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/CreatedAtSortOrder.cs @@ -0,0 +1,7 @@ +namespace OpenAI.Assistants; + +public enum CreatedAtSortOrder +{ + NewestFirst, + OldestFirst, +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Assistants/FunctionToolDefinition.cs b/.dotnet/src/Custom/Assistants/FunctionToolDefinition.cs new file mode 100644 index 000000000..57592ac9e --- /dev/null +++ b/.dotnet/src/Custom/Assistants/FunctionToolDefinition.cs @@ -0,0 +1,89 @@ +using System; +using System.ClientModel.Internal; + +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using OpenAI.ClientShared.Internal; + +namespace OpenAI.Assistants; + +public partial class FunctionToolDefinition : ToolDefinition +{ + public required string Name { get; set; } + public string Description { get; set; } + public BinaryData Parameters { get; set; } + + [SetsRequiredMembers] + public FunctionToolDefinition(string name, string description = null, BinaryData parameters = null) + { + Name = name; + Description = description; + Parameters = parameters; + } + + public FunctionToolDefinition() + { } + + internal static FunctionToolDefinition DeserializeFunctionToolDefinition( + JsonElement element, + ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + + string name = null; + string description = null; + BinaryData parameters = null; + + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("function"u8)) + { + foreach (var functionProperty in property.Value.EnumerateObject()) + { + if (functionProperty.NameEquals("name"u8)) + { + name = functionProperty.Value.GetString(); + continue; + } + if (functionProperty.NameEquals("description"u8)) + { + description = functionProperty.Value.GetString(); + continue; + } + if (functionProperty.NameEquals("parameters")) + { + parameters = BinaryData.FromObjectAsJson(functionProperty.Value.GetRawText()); + continue; + } + } + } + } + + return new FunctionToolDefinition(name, description, parameters); + } + + internal override void WriteDerived(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + writer.WriteString("type"u8, "function"u8); + writer.WritePropertyName("function"u8); + writer.WriteStartObject(); + writer.WriteString("name"u8, Name); + if (OptionalProperty.IsDefined(Description)) + { + writer.WriteString("description"u8, Description); + } + if (OptionalProperty.IsDefined(Parameters)) + { + writer.WritePropertyName("parameters"u8); + writer.WriteRawValue(Parameters.ToString()); + } + writer.WriteEndObject(); + } +} diff --git a/.dotnet/src/Custom/Assistants/FunctionToolInfo.cs b/.dotnet/src/Custom/Assistants/FunctionToolInfo.cs new file mode 100644 index 000000000..a85cd9158 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/FunctionToolInfo.cs @@ -0,0 +1,82 @@ +using System; +using System.ClientModel.Internal; + +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Text.Json; +using OpenAI.ClientShared.Internal; + +namespace OpenAI.Assistants; + +public partial class FunctionToolInfo : ToolInfo +{ + public string Name { get; } + public string Description { get; } + public BinaryData Parameters { get; } + + internal FunctionToolInfo(string name, string description, BinaryData parameters) + { + Name = name; + Description = description; + Parameters = parameters; + } + + internal static FunctionToolInfo DeserializeFunctionToolInfo( + JsonElement element, + ModelReaderWriterOptions options) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + + string name = null; + string description = null; + BinaryData parameters = null; + + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("function"u8)) + { + foreach (var functionObjectProperty in property.Value.EnumerateObject()) + { + if (functionObjectProperty.NameEquals("name"u8)) + { + name = functionObjectProperty.Value.GetString(); + continue; + } + if (functionObjectProperty.NameEquals("description"u8)) + { + description = functionObjectProperty.Value.GetString(); + continue; + } + if (functionObjectProperty.NameEquals("parameters"u8)) + { + parameters = BinaryData.FromObjectAsJson(functionObjectProperty.Value.GetRawText()); + continue; + } + } + } + } + return new FunctionToolInfo(name, description, parameters); + } + + internal override void WriteDerived(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + writer.WriteString("type"u8, "function"u8); + writer.WritePropertyName("function"u8); + writer.WriteStartObject(); + writer.WriteString("name"u8, Name); + if (OptionalProperty.IsDefined(Description)) + { + writer.WriteString("description"u8, Description); + } + if (OptionalProperty.IsDefined(Parameters)) + { + writer.WriteRawValue(Parameters.ToString()); + } + writer.WriteEndObject(); + } +} diff --git a/.dotnet/src/Custom/Assistants/ListQueryPage.cs b/.dotnet/src/Custom/Assistants/ListQueryPage.cs new file mode 100644 index 000000000..3d11c9b48 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/ListQueryPage.cs @@ -0,0 +1,114 @@ +using OpenAI.ClientShared.Internal; +using System; +using System.ClientModel.Internal; + +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI.Assistants; + +public abstract partial class ListQueryPage +{ + public string FirstId { get; } + public string LastId { get; } + public bool HasMore { get; } + + internal ListQueryPage(string firstId, string lastId, bool hasMore) + { + FirstId = firstId; + LastId = lastId; + HasMore = hasMore; + } + + internal static ListQueryPage Create(Internal.Models.ListAssistantsResponse internalResponse) + { + OptionalList assistants = new(); + foreach (Internal.Models.AssistantObject internalAssistant in internalResponse.Data) + { + assistants.Add(new(internalAssistant)); + } + return new(assistants, internalResponse.FirstId, internalResponse.LastId, internalResponse.HasMore); + } + + internal static ListQueryPage Create(Internal.Models.ListAssistantFilesResponse internalResponse) + { + OptionalList assistantFileAssociations = new(); + foreach (Internal.Models.AssistantFileObject internalFile in internalResponse.Data) + { + assistantFileAssociations.Add(new(internalFile)); + } + return new(assistantFileAssociations, internalResponse.FirstId, internalResponse.LastId, internalResponse.HasMore); + } + + internal static ListQueryPage Create(Internal.Models.ListMessagesResponse internalResponse) + { + OptionalList messages = new(); + foreach (Internal.Models.MessageObject internalMessage in internalResponse.Data) + { + messages.Add(new(internalMessage)); + } + return new(messages, internalResponse.FirstId, internalResponse.LastId, internalResponse.HasMore); + } + + internal static ListQueryPage Create(Internal.Models.ListMessageFilesResponse internalResponse) + { + OptionalList messageFileAssociations = new(); + foreach (Internal.Models.MessageFileObject internalFile in internalResponse.Data) + { + messageFileAssociations.Add(new(internalFile)); + } + return new(messageFileAssociations, internalResponse.FirstId, internalResponse.LastId, internalResponse.HasMore); + } + + internal static ListQueryPage Create(Internal.Models.ListRunsResponse internalResponse) + { + OptionalList runs = new(); + foreach (Internal.Models.RunObject internalRun in internalResponse.Data) + { + runs.Add(new(internalRun)); + } + return new(runs, internalResponse.FirstId, internalResponse.LastId, internalResponse.HasMore); + } + + internal static ListQueryPage Create(T internalResponse) + where T : class + { + return internalResponse switch + { + Internal.Models.ListAssistantsResponse internalAssistantsResponse => Create(internalAssistantsResponse), + Internal.Models.ListAssistantFilesResponse internalFilesResponse => Create(internalFilesResponse), + Internal.Models.ListMessagesResponse internalMessagesResponse => Create(internalMessagesResponse), + Internal.Models.ListMessageFilesResponse internalMessageFilesResponse => Create(internalMessageFilesResponse), + Internal.Models.ListRunsResponse internalRunsResponse => Create(internalRunsResponse), + _ => throw new ArgumentException( + $"Unknown type for generic {nameof(ListQueryPage)} conversion: {internalResponse.GetType()}"), + }; + } +} + +public partial class ListQueryPage : ListQueryPage, IReadOnlyList + where T : class +{ + public IReadOnlyList Items { get; } + + /// + public int Count => Items.Count; + + /// + public T this[int index] + { + get => Items[index]; + } + + internal ListQueryPage(IEnumerable items, string firstId, string lastId, bool hasMore) + : base(firstId, lastId, hasMore) + { + Items = items.ToList(); + } + + /// + public IEnumerator GetEnumerator() => Items.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => Items.GetEnumerator(); +} diff --git a/.dotnet/src/Custom/Assistants/MessageContent.Serialization.cs b/.dotnet/src/Custom/Assistants/MessageContent.Serialization.cs new file mode 100644 index 000000000..4d88129b3 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/MessageContent.Serialization.cs @@ -0,0 +1,94 @@ +using System; +using System.ClientModel.Internal; + +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Text.Json; + +namespace OpenAI.Assistants; + +public abstract partial class MessageContent : IJsonModel +{ + MessageContent IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(MessageContent)} does not support '{format}' format."); + } + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeMessageContent(document.RootElement, options); + } + + MessageContent IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeMessageContent(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(MessageContent)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + writer.WriteStartObject(); + WriteDerived(writer, options); + writer.WriteEndObject(); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(MessageContent)} does not support '{options.Format}' format."); + } + } + + internal abstract void WriteDerived(Utf8JsonWriter writer, ModelReaderWriterOptions options); + + internal static MessageContent DeserializeMessageContent( + JsonElement element, + ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("type"u8)) + { + if (property.Value.ValueEquals("text"u8)) + { + return MessageTextContent.DeserializeMessageTextContent(element, options); + } + else if (property.Value.ValueEquals("image_file"u8)) + { + return MessageImageFileContent.DeserializeMessageImageFileContent(element, options); + } + else + { + throw new ArgumentException(property.Value.GetString()); + } + } + } + throw new ArgumentException(nameof(element)); + } + +} diff --git a/.dotnet/src/Custom/Assistants/MessageContent.cs b/.dotnet/src/Custom/Assistants/MessageContent.cs new file mode 100644 index 000000000..928137621 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/MessageContent.cs @@ -0,0 +1,6 @@ +namespace OpenAI.Assistants; + + +public abstract partial class MessageContent +{ +} diff --git a/.dotnet/src/Custom/Assistants/MessageCreationOptions.cs b/.dotnet/src/Custom/Assistants/MessageCreationOptions.cs new file mode 100644 index 000000000..a0916f7dd --- /dev/null +++ b/.dotnet/src/Custom/Assistants/MessageCreationOptions.cs @@ -0,0 +1,30 @@ +using OpenAI.ClientShared.Internal; +using System.ClientModel.Internal; + +using System.Collections.Generic; + +namespace OpenAI.Assistants; + +/// +/// Represents additional options available when creating a new . +/// +public partial class MessageCreationOptions +{ + /// + /// A collection of IDs for previously uploaded files that are made accessible to the message. These IDs are the + /// basis for the functionality of file-based tools like retrieval. + /// + public IList FileIds { get; } = new OptionalList(); + + /// + /// An optional key/value mapping of additional, supplemental data items to attach to the . + /// This information may be useful for storing custom details in a structured format. + /// + /// + /// + /// Keys can be a maximum of 64 characters in length. + /// Values can be a maximum of 512 characters in length. + /// + /// + public IDictionary Metadata { get; } = new OptionalDictionary(); +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Assistants/MessageFileAssociation.cs b/.dotnet/src/Custom/Assistants/MessageFileAssociation.cs new file mode 100644 index 000000000..93e7e3d68 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/MessageFileAssociation.cs @@ -0,0 +1,17 @@ +using System; + +namespace OpenAI.Assistants; + +public partial class MessageFileAssociation +{ + public string MessageId { get; } + public string FileId { get; } + public DateTimeOffset CreatedAt { get; } + + internal MessageFileAssociation(Internal.Models.MessageFileObject internalFile) + { + MessageId = internalFile.MessageId; + FileId = internalFile.Id; + CreatedAt = internalFile.CreatedAt; + } +} diff --git a/.dotnet/src/Custom/Assistants/MessageImageFileContent.cs b/.dotnet/src/Custom/Assistants/MessageImageFileContent.cs new file mode 100644 index 000000000..68997b045 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/MessageImageFileContent.cs @@ -0,0 +1,55 @@ +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Text.Json; + +namespace OpenAI.Assistants; + +public class MessageImageFileContent : MessageContent +{ + public string FileId { get; } + + internal MessageImageFileContent(string fileId) + { + FileId = fileId; + } + + internal override void WriteDerived(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + writer.WriteString("type"u8, "image_file"u8); + writer.WritePropertyName("image_file"u8); + writer.WriteStartObject(); + writer.WriteString("file_id"u8, FileId); + writer.WriteEndObject(); + } + + + internal static MessageContent DeserializeMessageImageFileContent( + JsonElement element, + ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + + string fileId = null; + + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("image_file"u8)) + { + foreach (var textObjectProperty in property.Value.EnumerateObject()) + { + if (textObjectProperty.NameEquals("file_id"u8)) + { + fileId = textObjectProperty.Value.GetString(); + continue; + } + } + } + } + return new MessageImageFileContent(fileId); + } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Assistants/MessageRole.cs b/.dotnet/src/Custom/Assistants/MessageRole.cs new file mode 100644 index 000000000..c59e5abd2 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/MessageRole.cs @@ -0,0 +1,16 @@ +namespace OpenAI.Assistants; + +/// +/// Represents the role associated with the message which indicates its source and purpose. +/// +public enum MessageRole +{ + /// + /// The user role, associated with caller input into the model. + /// + User, + /// + /// The assistant role, associated with model output in response to inputs from the user and tools. + /// + Assistant, +} diff --git a/.dotnet/src/Custom/Assistants/MessageTextContent.cs b/.dotnet/src/Custom/Assistants/MessageTextContent.cs new file mode 100644 index 000000000..43c0433ad --- /dev/null +++ b/.dotnet/src/Custom/Assistants/MessageTextContent.cs @@ -0,0 +1,72 @@ +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Assistants; + +public class MessageTextContent : MessageContent +{ + /// + /// The content text. The interpretation of this value will depend on which kind of chat message the content is + /// associated with. + /// + public string Text { get; } + + public IReadOnlyList Annotations { get; } + + internal MessageTextContent(string text, IReadOnlyList annotations) + { + Text = text; + Annotations = annotations; + } + + internal override void WriteDerived(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + writer.WriteString("type"u8, "text"u8); + writer.WritePropertyName("text"u8); + writer.WriteStartObject(); + writer.WriteString("value"u8, Text); + writer.WriteEndObject(); + } + + internal static MessageContent DeserializeMessageTextContent( + JsonElement element, + ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + + string text = null; + List annotations = null; + + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("text"u8)) + { + foreach (var textObjectProperty in property.Value.EnumerateObject()) + { + if (textObjectProperty.NameEquals("value"u8)) + { + text = textObjectProperty.Value.GetString(); + continue; + } + if (textObjectProperty.NameEquals("annotations"u8)) + { + annotations ??= []; + foreach (var annotationObject in textObjectProperty.Value.EnumerateArray()) + { + annotations.Add(TextContentAnnotation.DeserializeTextContentAnnotation(annotationObject, options)); + } + continue; + } + } + } + } + return new MessageTextContent(text, annotations); + } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Assistants/RequiredFunctionToolCall.cs b/.dotnet/src/Custom/Assistants/RequiredFunctionToolCall.cs new file mode 100644 index 000000000..f0807495c --- /dev/null +++ b/.dotnet/src/Custom/Assistants/RequiredFunctionToolCall.cs @@ -0,0 +1,66 @@ +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Text.Json; + +namespace OpenAI.Assistants; + +public partial class RequiredFunctionToolCall : RequiredToolCall +{ + public string Name { get; } + public string Arguments { get; } + + internal RequiredFunctionToolCall(string id, string name, string arguments) + : base(id) + { + Name = name; + Arguments = arguments; + } + + internal static RequiredFunctionToolCall DeserializeRequiredFunctionToolCall( + JsonElement element, + ModelReaderWriterOptions options) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + + string id = null; + string name = null; + string arguments = null; + + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("function"u8)) + { + foreach (var functionProperty in property.Value.EnumerateObject()) + { + if (functionProperty.NameEquals("name"u8)) + { + name = functionProperty.Value.GetString(); + continue; + } + if (functionProperty.NameEquals("arguments"u8)) + { + arguments = functionProperty.Value.GetString(); + continue; + } + } + continue; + } + if (property.NameEquals("id"u8)) + { + id = property.Value.GetString(); + continue; + } + } + return new RequiredFunctionToolCall(id, name, arguments); + } + + internal override void WriteDerived(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + writer.WriteString("type"u8, "retrieval"u8); + } +} diff --git a/.dotnet/src/Custom/Assistants/RequiredToolCall.cs b/.dotnet/src/Custom/Assistants/RequiredToolCall.cs new file mode 100644 index 000000000..19e951d2c --- /dev/null +++ b/.dotnet/src/Custom/Assistants/RequiredToolCall.cs @@ -0,0 +1,37 @@ +using System; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Text.Json; + +namespace OpenAI.Assistants; + +public abstract partial class RequiredToolCall : RunRequiredAction +{ + public string Id { get; } + + internal RequiredToolCall(string id) + { + Id = id; + } + + internal static RequiredToolCall DeserializeRequiredToolCall( + JsonElement element, + ModelReaderWriterOptions options) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("function"u8)) + { + return RequiredFunctionToolCall.DeserializeRequiredFunctionToolCall(element, options); + } + } + throw new ArgumentException(nameof(element)); + } +} diff --git a/.dotnet/src/Custom/Assistants/RetrievalToolDefinition.cs b/.dotnet/src/Custom/Assistants/RetrievalToolDefinition.cs new file mode 100644 index 000000000..f18579c87 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/RetrievalToolDefinition.cs @@ -0,0 +1,38 @@ +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Text.Json; + +namespace OpenAI.Assistants; + +public partial class RetrievalToolDefinition : ToolDefinition +{ + public RetrievalToolDefinition() + { } + + internal static RetrievalToolDefinition DeserializeRetrievalToolDefinition( + JsonElement element, + ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("retrieval"u8)) + { + continue; + } + } + + return new RetrievalToolDefinition(); + } + + internal override void WriteDerived(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + writer.WriteString("type"u8, "retrieval"u8); + } +} diff --git a/.dotnet/src/Custom/Assistants/RetrievalToolInfo.cs b/.dotnet/src/Custom/Assistants/RetrievalToolInfo.cs new file mode 100644 index 000000000..1b58f35a4 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/RetrievalToolInfo.cs @@ -0,0 +1,33 @@ +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Text.Json; + +namespace OpenAI.Assistants; + +public partial class RetrievalToolInfo : ToolInfo +{ + internal RetrievalToolInfo() + { } + + internal static RetrievalToolInfo DeserializeRetrievalToolInfo( + JsonElement element, + ModelReaderWriterOptions options) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + + foreach (var property in element.EnumerateObject()) + { + } + return new RetrievalToolInfo(); + } + + internal override void WriteDerived(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + writer.WriteString("type"u8, "retrieval"u8); + } +} diff --git a/.dotnet/src/Custom/Assistants/RunCreationOptions.cs b/.dotnet/src/Custom/Assistants/RunCreationOptions.cs new file mode 100644 index 000000000..f7106eaac --- /dev/null +++ b/.dotnet/src/Custom/Assistants/RunCreationOptions.cs @@ -0,0 +1,67 @@ +using OpenAI.ClientShared.Internal; +using System.ClientModel.Internal; + +using System.Collections.Generic; + +namespace OpenAI.Assistants; + +/// +/// Represents additional options available when creating a new . +/// +public partial class RunCreationOptions +{ + + + /// + /// A run-specific model name that will override the assistant's defined model. If not provided, the assistant's + /// selection will be used. + /// + public string OverrideModel { get; set; } + + /// + /// A run specific replacement for the assistant's default instructions that will override the assistant-level + /// instructions. If not specified, the assistant's instructions will be used. + /// + public string OverrideInstructions { get; set; } + + /// + /// Run-specific additional instructions that will be appended to the assistant-level instructions solely for this + /// run. Unlike , the assistant's instructions are preserved and these additional + /// instructions are concatenated. + /// + public string AdditionalInstructions { get; set; } + + /// + /// A run-specific collection of tool definitions that will override the assistant-level defaults. If not provided, + /// the assistant's defined tools will be used. Available tools include: + /// + /// + /// + /// code_interpreter - + /// - works with data, math, and computer code + /// + /// + /// retrieval - + /// - dynamically enriches an Run's context with content from uploaded, indexed files + /// + /// + /// function - + /// - enables caller-provided custom functions for actions and enrichment + /// + /// + /// + /// + public IList OverrideTools { get; } = new OptionalList(); + + /// + /// An optional key/value mapping of additional, supplemental data items to attach to the . + /// This information may be useful for storing custom details in a structured format. + /// + /// + /// + /// Keys can be a maximum of 64 characters in length. + /// Values can be a maximum of 512 characters in length. + /// + /// + public IDictionary Metadata { get; } = new OptionalDictionary(); +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Assistants/RunError.cs b/.dotnet/src/Custom/Assistants/RunError.cs new file mode 100644 index 000000000..b53777c3d --- /dev/null +++ b/.dotnet/src/Custom/Assistants/RunError.cs @@ -0,0 +1,24 @@ +using OpenAI.Chat; + +namespace OpenAI.Assistants; + +public partial class RunError +{ + public RunErrorCode ErrorCode { get; } + public string ErrorMessage { get; } + + internal RunError(RunErrorCode errorCode, string errorMessage) + { + ErrorCode = errorCode; + ErrorMessage = errorMessage; + } + + internal RunError(Internal.Models.RunObjectLastError internalError) + { + if (internalError.Code != null) + { + ErrorCode = new(internalError.Code.ToString()); + } + ErrorMessage = internalError.Message; + } +} diff --git a/.dotnet/src/Custom/Assistants/RunErrorCode.cs b/.dotnet/src/Custom/Assistants/RunErrorCode.cs new file mode 100644 index 000000000..d2eb1b65e --- /dev/null +++ b/.dotnet/src/Custom/Assistants/RunErrorCode.cs @@ -0,0 +1,37 @@ +using System; +using System.ComponentModel; + +namespace OpenAI.Assistants; + +public readonly struct RunErrorCode : IEquatable +{ + private readonly string _value; + + public static RunErrorCode ServerError { get; } = new(Internal.Models.RunObjectLastErrorCode.ServerError.ToString()); + public static RunErrorCode RateLimitExceeded { get; } = new(Internal.Models.RunObjectLastErrorCode.RateLimitExceeded.ToString()); + public static RunErrorCode InvalidPrompt { get; } = new("invalid_prompt"); + + public RunErrorCode(string status) + { + _value = status; + } + + /// Determines if two values are the same. + public static bool operator ==(RunErrorCode left, RunErrorCode right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(RunErrorCode left, RunErrorCode right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator RunErrorCode(string value) => new RunErrorCode(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is RunErrorCode other && Equals(other); + /// + public bool Equals(RunErrorCode other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Assistants/RunModificationOptions.cs b/.dotnet/src/Custom/Assistants/RunModificationOptions.cs new file mode 100644 index 000000000..88739b12e --- /dev/null +++ b/.dotnet/src/Custom/Assistants/RunModificationOptions.cs @@ -0,0 +1,24 @@ +using OpenAI.ClientShared.Internal; +using System.ClientModel.Internal; + +using System.Collections.Generic; + +namespace OpenAI.Assistants; + +/// +/// Represents additional options available when modifying an existing . +/// +public partial class RunModificationOptions +{ + /// + /// A replacement for the optional key/value mapping of additional, supplemental data items to attach to the + /// . This information may be useful for storing custom details in a structured format. + /// + /// + /// + /// Keys can be a maximum of 64 characters in length. + /// Values can be a maximum of 512 characters in length. + /// + /// + public IDictionary Metadata { get; } = new OptionalDictionary(); +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Assistants/RunRequiredAction.Serialization.cs b/.dotnet/src/Custom/Assistants/RunRequiredAction.Serialization.cs new file mode 100644 index 000000000..e9ba0d3ac --- /dev/null +++ b/.dotnet/src/Custom/Assistants/RunRequiredAction.Serialization.cs @@ -0,0 +1,107 @@ +using System; +using System.ClientModel.Internal; + +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Assistants; + +public abstract partial class RunRequiredAction : IJsonModel> +{ + IList IJsonModel>.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel>)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(RunRequiredAction)} does not support '{format}' format."); + } + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeRunRequiredActions(document.RootElement, options); + } + + IList IPersistableModel>.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel>)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeRunRequiredActions(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(RunRequiredAction)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel>.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + void IJsonModel>.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + writer.WriteStartObject(); + WriteDerived(writer, options); + writer.WriteEndObject(); + } + + BinaryData IPersistableModel>.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel>)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(RunRequiredAction)} does not support '{options.Format}' format."); + } + } + + internal abstract void WriteDerived(Utf8JsonWriter writer, ModelReaderWriterOptions options); + + internal static IList DeserializeRunRequiredActions( + JsonElement element, + ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + + List actions = null; + + foreach (var topProperty in element.EnumerateObject()) + { + if (topProperty.NameEquals("submit_tool_outputs"u8)) + { + foreach (var submitObjectProperty in topProperty.Value.EnumerateObject()) + { + if (submitObjectProperty.NameEquals("tool_calls"u8)) + { + foreach (var toolCallObject in submitObjectProperty.Value.EnumerateArray()) + { + foreach (var toolCallProperty in toolCallObject.EnumerateObject()) + { + if ((toolCallProperty.NameEquals("type"u8) && toolCallProperty.Value.ValueEquals("function"u8)) + || (toolCallProperty.NameEquals("function"u8))) + { + actions ??= []; + actions.Add(RequiredFunctionToolCall.DeserializeRequiredFunctionToolCall( + toolCallObject, + options)); + continue; + } + } + } + } + } + } + } + + return actions; + } +} diff --git a/.dotnet/src/Custom/Assistants/RunRequiredAction.cs b/.dotnet/src/Custom/Assistants/RunRequiredAction.cs new file mode 100644 index 000000000..be9a12215 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/RunRequiredAction.cs @@ -0,0 +1,8 @@ +using System; + +namespace OpenAI.Assistants; + +public partial class RunRequiredAction +{ + +} diff --git a/.dotnet/src/Custom/Assistants/RunStatus.cs b/.dotnet/src/Custom/Assistants/RunStatus.cs new file mode 100644 index 000000000..25888b8d2 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/RunStatus.cs @@ -0,0 +1,13 @@ +namespace OpenAI.Assistants; + +public enum RunStatus +{ + Queued, + InProgress, + RequiresAction, + Cancelling, + CompletedSuccessfully, + Cancelled, + Failed, + Expired, +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Assistants/RunTokenUsage.cs b/.dotnet/src/Custom/Assistants/RunTokenUsage.cs new file mode 100644 index 000000000..6ec585b3d --- /dev/null +++ b/.dotnet/src/Custom/Assistants/RunTokenUsage.cs @@ -0,0 +1,20 @@ +namespace OpenAI.Assistants; + +public partial class RunTokenUsage +{ + public long InputTokens { get; } + public long OutputTokens { get; } + public long TotalTokens { get; } + + internal RunTokenUsage(long inputTokens, long outputTokens, long totalTokens) + { + InputTokens = inputTokens; + OutputTokens = outputTokens; + TotalTokens = totalTokens; + } + + internal RunTokenUsage(Internal.Models.RunCompletionUsage internalUsage) + : this(internalUsage.PromptTokens, internalUsage.CompletionTokens, internalUsage.TotalTokens) + { + } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Assistants/TextContentAnnotation.Serialization.cs b/.dotnet/src/Custom/Assistants/TextContentAnnotation.Serialization.cs new file mode 100644 index 000000000..b7ba4eedb --- /dev/null +++ b/.dotnet/src/Custom/Assistants/TextContentAnnotation.Serialization.cs @@ -0,0 +1,93 @@ +using System; +using System.ClientModel.Internal; + +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Text.Json; + +namespace OpenAI.Assistants; + +public abstract partial class TextContentAnnotation : IJsonModel +{ + TextContentAnnotation IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(TextContentAnnotation)} does not support '{format}' format."); + } + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeTextContentAnnotation(document.RootElement, options); + } + + TextContentAnnotation IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeTextContentAnnotation(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(TextContentAnnotation)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + writer.WriteStartObject(); + WriteDerived(writer, options); + writer.WriteEndObject(); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(TextContentAnnotation)} does not support '{options.Format}' format."); + } + } + + internal static TextContentAnnotation DeserializeTextContentAnnotation( + JsonElement element, + ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("type"u8)) + { + if (property.Value.ValueEquals("file_citation"u8)) + { + return TextContentFileCitationAnnotation.DeserializeTextContentFileCitationAnnotation(element, options); + } + else if (property.Value.ValueEquals("file_path"u8)) + { + return TextContentFilePathAnnotation.DeserializeTextContentFilePathAnnotation(element, options); + } + else + { + throw new ArgumentException(property.Value.GetString()); + } + } + } + throw new ArgumentException(nameof(element)); + } + + internal abstract void WriteDerived(Utf8JsonWriter writer, ModelReaderWriterOptions options); +} diff --git a/.dotnet/src/Custom/Assistants/TextContentAnnotation.cs b/.dotnet/src/Custom/Assistants/TextContentAnnotation.cs new file mode 100644 index 000000000..bd3f390c0 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/TextContentAnnotation.cs @@ -0,0 +1,6 @@ +namespace OpenAI.Assistants; + + +public abstract partial class TextContentAnnotation +{ +} diff --git a/.dotnet/src/Custom/Assistants/TextContentFileCitationAnnotation.cs b/.dotnet/src/Custom/Assistants/TextContentFileCitationAnnotation.cs new file mode 100644 index 000000000..459b91a94 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/TextContentFileCitationAnnotation.cs @@ -0,0 +1,95 @@ +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Text.Json; + +namespace OpenAI.Assistants; + +public class TextContentFileCitationAnnotation : TextContentAnnotation +{ + public string TextToReplace { get; } + + public string FileId { get; } + + public string Quote { get; } + + public int StartIndex { get; } + + public int EndIndex { get; } + + internal TextContentFileCitationAnnotation(string textToReplace, string citationFileId, string citationQuote, int startIndex, int endIndex) + { + TextToReplace = textToReplace; + FileId = citationFileId; + Quote = citationQuote; + StartIndex = startIndex; + EndIndex = endIndex; + } + + internal override void WriteDerived(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + writer.WriteString("type"u8, "file_citation"u8); + writer.WriteString("text"u8, TextToReplace); + writer.WritePropertyName("file_citation"u8); + writer.WriteStartObject(); + writer.WriteString("file_id"u8, FileId); + writer.WriteString("quote"u8, Quote); + writer.WriteEndObject(); + writer.WriteNumber("start_index"u8, StartIndex); + writer.WriteNumber("end_index"u8, EndIndex); + } + + + internal static TextContentFileCitationAnnotation DeserializeTextContentFileCitationAnnotation( + JsonElement element, + ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + + string textToReplace = null; + int startIndex = 0; + int endIndex = 0; + string citationFileId = null; + string citationQuote = null; + + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("text"u8)) + { + textToReplace = property.Value.GetString(); + continue; + } + if (property.NameEquals("start_index"u8)) + { + startIndex = property.Value.GetInt32(); + continue; + } + if (property.NameEquals("end_index"u8)) + { + endIndex = property.Value.GetInt32(); + continue; + } + if (property.NameEquals("file_citation"u8)) + { + foreach (var filePathObjectProperty in property.Value.EnumerateObject()) + { + if (filePathObjectProperty.NameEquals("file_id"u8)) + { + citationFileId = filePathObjectProperty.Value.GetString(); + continue; + } + if (filePathObjectProperty.NameEquals("quote"u8)) + { + citationQuote = filePathObjectProperty.Value.GetString(); + continue; + } + } + } + } + return new TextContentFileCitationAnnotation(textToReplace, citationFileId, citationQuote, startIndex, endIndex); + } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Assistants/TextContentFilePathAnnotation.cs b/.dotnet/src/Custom/Assistants/TextContentFilePathAnnotation.cs new file mode 100644 index 000000000..7e716bc6c --- /dev/null +++ b/.dotnet/src/Custom/Assistants/TextContentFilePathAnnotation.cs @@ -0,0 +1,85 @@ +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Text.Json; + +namespace OpenAI.Assistants; + +public class TextContentFilePathAnnotation : TextContentAnnotation +{ + public string TextToReplace { get; } + + public string FileId { get; } + + public int StartIndex { get; } + + public int EndIndex { get; } + + internal TextContentFilePathAnnotation(string textToReplace, string createdFileId, int startIndex, int endIndex) + { + TextToReplace = textToReplace; + FileId = createdFileId; + StartIndex = startIndex; + EndIndex = endIndex; + } + + internal override void WriteDerived(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + writer.WriteString("type"u8, "file_path"u8); + writer.WriteString("text"u8, TextToReplace); + writer.WritePropertyName("file_path"u8); + writer.WriteStartObject(); + writer.WriteString("file_id"u8, FileId); + writer.WriteEndObject(); + writer.WriteNumber("start_index"u8, StartIndex); + writer.WriteNumber("end_index"u8, EndIndex); + } + + internal static TextContentFilePathAnnotation DeserializeTextContentFilePathAnnotation( + JsonElement element, + ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + + string textToReplace = null; + int startIndex = 0; + int endIndex = 0; + string createdFileId = null; + + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("text"u8)) + { + textToReplace = property.Value.GetString(); + continue; + } + if (property.NameEquals("start_index"u8)) + { + startIndex = property.Value.GetInt32(); + continue; + } + if (property.NameEquals ("end_index"u8)) + { + endIndex = property.Value.GetInt32(); + continue; + } + if (property.NameEquals("file_path"u8)) + { + foreach (var filePathObjectProperty in property.Value.EnumerateObject()) + { + if (filePathObjectProperty.NameEquals("file_id"u8)) + { + createdFileId = filePathObjectProperty.Value.GetString(); + continue; + } + } + } + } + return new TextContentFilePathAnnotation(textToReplace, createdFileId, startIndex, endIndex); + } + +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Assistants/ThreadCreationOptions.cs b/.dotnet/src/Custom/Assistants/ThreadCreationOptions.cs new file mode 100644 index 000000000..404b697e8 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/ThreadCreationOptions.cs @@ -0,0 +1,26 @@ +using OpenAI.ClientShared.Internal; +using System.ClientModel.Internal; + +using System.Collections.Generic; + +namespace OpenAI.Assistants; + +/// +/// Represents additional options available when creating a new . +/// +public partial class ThreadCreationOptions +{ + public IList Messages { get; } = new OptionalList(); + + /// + /// An optional key/value mapping of additional, supplemental data items to attach to the . + /// This information may be useful for storing custom details in a structured format. + /// + /// + /// + /// Keys can be a maximum of 64 characters in length. + /// Values can be a maximum of 512 characters in length. + /// + /// + public IDictionary Metadata { get; } = new OptionalDictionary(); +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Assistants/ThreadInitializationMessage.cs b/.dotnet/src/Custom/Assistants/ThreadInitializationMessage.cs new file mode 100644 index 000000000..069bd34b4 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/ThreadInitializationMessage.cs @@ -0,0 +1,45 @@ +using OpenAI.ClientShared.Internal; +using System.ClientModel.Internal; + +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; + +namespace OpenAI.Assistants; + +public partial class ThreadInitializationMessage +{ + public required MessageRole Role { get; set; } + + public required string Content { get; set; } + + /// + /// A list of File IDs that the message should use.There can be a maximum of 10 files attached to a message. Useful + /// for tools like retrieval and code_interpreter that can access and use files. + /// + public IList FileIds { get; } = new OptionalList(); + + /// + /// An optional key/value mapping of additional, supplemental data items to attach to the . + /// This information may be useful for storing custom details in a structured format. + /// + /// + /// + /// Keys can be a maximum of 64 characters in length. + /// Values can be a maximum of 512 characters in length. + /// + /// + public IDictionary Metadata { get; } = new OptionalDictionary(); + + [SetsRequiredMembers] + public ThreadInitializationMessage(MessageRole role, string content) + { + Role = role; + Content = content; + } + + public ThreadInitializationMessage() + { } + + public static implicit operator ThreadInitializationMessage(string content) + => new(MessageRole.User, content); +} diff --git a/.dotnet/src/Custom/Assistants/ThreadMessage.cs b/.dotnet/src/Custom/Assistants/ThreadMessage.cs new file mode 100644 index 000000000..01b481b36 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/ThreadMessage.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Assistants; + +public partial class ThreadMessage +{ + public string Id { get; } + public DateTimeOffset CreatedAt { get; } + public string ThreadId { get; } + public MessageRole Role { get; } + public IReadOnlyList ContentItems { get; } + public string AssistantId { get; } + + public string RunId { get; } + public IReadOnlyList FileIds { get; } + /// + /// An optional key/value mapping of additional, supplemental data items to attach to the . + /// This information may be useful for storing custom details in a structured format. + /// + /// + /// + /// Keys can be a maximum of 64 characters in length. + /// Values can be a maximum of 512 characters in length. + /// + /// + public IReadOnlyDictionary Metadata { get; } + + internal ThreadMessage(Internal.Models.MessageObject internalMessage) + { + MessageRole convertedRole = MessageRole.User; + if (internalMessage.Role.ToString() == "user") + { + convertedRole = MessageRole.User; + } + else if (internalMessage.Role.ToString() == "assistant") + { + convertedRole = MessageRole.Assistant; + } + else + { + throw new ArgumentException(internalMessage.Role.ToString()); + } + + List content = []; + foreach (BinaryData unionContentData in internalMessage.Content) + { + content.Add(MessageContent.DeserializeMessageContent(JsonDocument.Parse(unionContentData).RootElement)); + } + + Id = internalMessage.Id; + AssistantId = internalMessage.AssistantId; + ThreadId = internalMessage.ThreadId; + RunId = internalMessage.RunId; + Metadata = internalMessage.Metadata; + FileIds = internalMessage.FileIds; + CreatedAt = internalMessage.CreatedAt; + Role = convertedRole; + ContentItems = content; + } +} diff --git a/.dotnet/src/Custom/Assistants/ThreadModificationOptions.cs b/.dotnet/src/Custom/Assistants/ThreadModificationOptions.cs new file mode 100644 index 000000000..07e6380ea --- /dev/null +++ b/.dotnet/src/Custom/Assistants/ThreadModificationOptions.cs @@ -0,0 +1,24 @@ +using OpenAI.ClientShared.Internal; +using System.ClientModel.Internal; + +using System.Collections.Generic; + +namespace OpenAI.Assistants; + +/// +/// Represents additional options available when modifying an existing . +/// +public partial class ThreadModificationOptions +{ + /// + /// A replacement for the optional key/value mapping of additional, supplemental data items to attach to the + /// . This information may be useful for storing custom details in a structured format. + /// + /// + /// + /// Keys can be a maximum of 64 characters in length. + /// Values can be a maximum of 512 characters in length. + /// + /// + public IDictionary Metadata { get; } = new OptionalDictionary(); +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Assistants/ThreadRun.cs b/.dotnet/src/Custom/Assistants/ThreadRun.cs new file mode 100644 index 000000000..fa65d9c08 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/ThreadRun.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Assistants; + +public partial class ThreadRun +{ + public string Id { get; } + public string ThreadId { get; } + public string AssistantId { get; } + public DateTimeOffset CreatedAt { get; } + + public RunStatus Status { get; } + + public IReadOnlyList RequiredActions { get; } + + public RunError LastError { get; } + public DateTimeOffset? ExpiresAt { get; } + public DateTimeOffset? StartedAt { get; } + public DateTimeOffset? CancelledAt { get; } + public DateTimeOffset? FailedAt { get; } + public DateTimeOffset? CompletedAt { get; } + public string Model { get; } + public string Instructions { get; } + public IReadOnlyList Tools { get; } + public IReadOnlyList FileIds { get; } + /// + /// An optional key/value mapping of additional, supplemental data items to attach to the . + /// This information may be useful for storing custom details in a structured format. + /// + /// + /// + /// Keys can be a maximum of 64 characters in length. + /// Values can be a maximum of 512 characters in length. + /// + /// + public IReadOnlyDictionary Metadata { get; } + public RunTokenUsage Usage { get; } + + internal ThreadRun(Internal.Models.RunObject internalRun) + { + Id = internalRun.Id; + ThreadId = internalRun.ThreadId; + AssistantId = internalRun.AssistantId; + CreatedAt = internalRun.CreatedAt; + FailedAt = internalRun.FailedAt; + ExpiresAt = internalRun.ExpiresAt; + StartedAt = internalRun.StartedAt; + CancelledAt = internalRun.CancelledAt; + CompletedAt = internalRun.CompletedAt; + Status = internalRun.Status.ToString() switch + { + "queued" => RunStatus.Queued, + "in_progress" => RunStatus.InProgress, + "requires_action" => RunStatus.RequiresAction, + "cancelling" => RunStatus.Cancelling, + "cancelled" => RunStatus.Cancelled, + "failed" => RunStatus.Failed, + "completed" => RunStatus.CompletedSuccessfully, + "expired" => RunStatus.Expired, + _ => throw new ArgumentException(nameof(Status)), + }; + Metadata = internalRun.Metadata; + FileIds = internalRun.FileIds; + Metadata = internalRun.Metadata; + Model = internalRun.Model; + Instructions = internalRun.Instructions; + + if (internalRun.LastError != null) + { + LastError = new(internalRun.LastError); + } + + if (internalRun.Usage != null) + { + Usage = new(internalRun.Usage); + } + + if (internalRun.Tools != null) + { + List tools = []; + foreach (BinaryData unionToolInfo in internalRun.Tools) + { + tools.Add(ToolInfo.DeserializeToolInfo(JsonDocument.Parse(unionToolInfo).RootElement)); + } + Tools = tools; + } + + IReadOnlyList internalFunctionCalls + = internalRun.RequiredAction?.SubmitToolOutputs?.ToolCalls; + if (internalFunctionCalls != null) + { + List actions = []; + foreach (Internal.Models.RunToolCallObject internalToolCall in internalFunctionCalls) + { + actions.Add(new RequiredFunctionToolCall( + internalToolCall.Id, + internalToolCall.Function.Name, + internalToolCall.Function.Arguments)); + } + RequiredActions = actions; + } + } +} diff --git a/.dotnet/src/Custom/Assistants/ToolDefinition.Serialization.cs b/.dotnet/src/Custom/Assistants/ToolDefinition.Serialization.cs new file mode 100644 index 000000000..a4975c9bb --- /dev/null +++ b/.dotnet/src/Custom/Assistants/ToolDefinition.Serialization.cs @@ -0,0 +1,98 @@ +using System; +using System.ClientModel.Internal; + +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Text.Json; + +namespace OpenAI.Assistants; + +public abstract partial class ToolDefinition : IJsonModel +{ + ToolDefinition IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ToolDefinition)} does not support '{format}' format."); + } + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeToolDefinition(document.RootElement, options); + } + + ToolDefinition IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeToolDefinition(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ToolDefinition)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + writer.WriteStartObject(); + WriteDerived(writer, options); + writer.WriteEndObject(); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ToolDefinition)} does not support '{options.Format}' format."); + } + } + + internal abstract void WriteDerived(Utf8JsonWriter writer, ModelReaderWriterOptions options); + + internal static ToolDefinition DeserializeToolDefinition( + JsonElement element, + ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("type"u8)) + { + if (property.Value.ValueEquals("code_interpreter"u8)) + { + return CodeInterpreterToolDefinition.DeserializeCodeInterpreterToolDefinition(element, options); + } + else if (property.Value.ValueEquals("retrieval"u8)) + { + return RetrievalToolDefinition.DeserializeRetrievalToolDefinition(element, options); + } + else if (property.Value.ValueEquals("function"u8)) + { + return FunctionToolDefinition.DeserializeFunctionToolDefinition(element, options); + } + else + { + throw new ArgumentException(property.Value.GetString()); + } + } + } + throw new ArgumentException(nameof(element)); + } + +} diff --git a/.dotnet/src/Custom/Assistants/ToolDefinition.cs b/.dotnet/src/Custom/Assistants/ToolDefinition.cs new file mode 100644 index 000000000..b39de3b21 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/ToolDefinition.cs @@ -0,0 +1,5 @@ +namespace OpenAI.Assistants; + +public abstract partial class ToolDefinition +{ +} diff --git a/.dotnet/src/Custom/Assistants/ToolInfo.Serialization.cs b/.dotnet/src/Custom/Assistants/ToolInfo.Serialization.cs new file mode 100644 index 000000000..ae8d31b33 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/ToolInfo.Serialization.cs @@ -0,0 +1,97 @@ +using System; +using System.ClientModel.Internal; + +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Text.Json; + +namespace OpenAI.Assistants; + +public abstract partial class ToolInfo : IJsonModel +{ + ToolInfo IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ToolInfo)} does not support '{format}' format."); + } + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeToolInfo(document.RootElement, options); + } + + ToolInfo IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeToolInfo(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ToolInfo)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + writer.WriteStartObject(); + WriteDerived(writer, options); + writer.WriteEndObject(); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ToolInfo)} does not support '{options.Format}' format."); + } + } + + internal abstract void WriteDerived(Utf8JsonWriter writer, ModelReaderWriterOptions options); + + internal static ToolInfo DeserializeToolInfo( + JsonElement element, + ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("type"u8)) + { + if (property.Value.ValueEquals("code_interpreter"u8)) + { + return CodeInterpreterToolInfo.DeserializeCodeInterpreterToolInfo(element, options); + } + else if (property.Value.ValueEquals("retrieval"u8)) + { + return RetrievalToolInfo.DeserializeRetrievalToolInfo(element, options); + } + else if (property.Value.ValueEquals("function"u8)) + { + return FunctionToolInfo.DeserializeFunctionToolInfo(element, options); + } + else + { + throw new ArgumentException(property.Value.GetString()); + } + } + } + throw new ArgumentException(nameof(element)); + } +} diff --git a/.dotnet/src/Custom/Assistants/ToolInfo.cs b/.dotnet/src/Custom/Assistants/ToolInfo.cs new file mode 100644 index 000000000..1708f94d2 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/ToolInfo.cs @@ -0,0 +1,5 @@ +namespace OpenAI.Assistants; + +public abstract partial class ToolInfo +{ +} diff --git a/.dotnet/src/Custom/Assistants/ToolOutput.Serialization.cs b/.dotnet/src/Custom/Assistants/ToolOutput.Serialization.cs new file mode 100644 index 000000000..8d5783eaa --- /dev/null +++ b/.dotnet/src/Custom/Assistants/ToolOutput.Serialization.cs @@ -0,0 +1,97 @@ +using System; +using System.ClientModel.Internal; + +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Text.Json; +using OpenAI.ClientShared.Internal; + +namespace OpenAI.Assistants; + +public partial class ToolOutput : IJsonModel +{ + ToolOutput IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + if (format != "J") + { + throw new FormatException($"The model {nameof(ToolOutput)} does not support '{format}' format."); + } + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return DeserializeToolOutput(document.RootElement, options); + } + + ToolOutput IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + { + using JsonDocument document = JsonDocument.Parse(data); + return DeserializeToolOutput(document.RootElement, options); + } + default: + throw new FormatException($"The model {nameof(ToolOutput)} does not support '{options.Format}' format."); + } + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + writer.WriteStartObject(); + if (OptionalProperty.IsDefined(Id)) + { + writer.WriteString("tool_call_id"u8, Id); + } + if (OptionalProperty.IsDefined(Output)) + { + writer.WriteString("output"u8, Output); + } + writer.WriteEndObject(); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + var format = options.Format == "W" ? ((IPersistableModel)this).GetFormatFromOptions(options) : options.Format; + + switch (format) + { + case "J": + return ModelReaderWriter.Write(this, options); + default: + throw new FormatException($"The model {nameof(ToolOutput)} does not support '{options.Format}' format."); + } + } + + internal static ToolOutput DeserializeToolOutput( + JsonElement element, + ModelReaderWriterOptions options = null) + { + options ??= new ModelReaderWriterOptions("W"); + + string id = null; + string output = null; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("tool_call_id"u8)) + { + id = property.Value.ToString(); + continue; + } + if (property.NameEquals("output"u8)) + { + output = property.Value.ToString(); + continue; + } + } + return new ToolOutput(id, output); + } +} diff --git a/.dotnet/src/Custom/Assistants/ToolOutput.cs b/.dotnet/src/Custom/Assistants/ToolOutput.cs new file mode 100644 index 000000000..762466f89 --- /dev/null +++ b/.dotnet/src/Custom/Assistants/ToolOutput.cs @@ -0,0 +1,27 @@ +using System.Diagnostics.CodeAnalysis; +using System.Text.Json.Serialization; + +namespace OpenAI.Assistants; + +public partial class ToolOutput +{ + [JsonPropertyName("tool_call_id")] + public required string Id { get; set; } + [JsonPropertyName("output")] + public string Output { get; set; } + + public ToolOutput() + { } + + [SetsRequiredMembers] + public ToolOutput(string toolCallId, string output = null) + { + Id = toolCallId; + Output = output; + } + + [SetsRequiredMembers] + public ToolOutput(RequiredToolCall toolCall, string output = null) + : this(toolCall.Id, output) + { } +} diff --git a/.dotnet/src/Custom/Audio/AudioClient.cs b/.dotnet/src/Custom/Audio/AudioClient.cs new file mode 100644 index 000000000..c5835c6d9 --- /dev/null +++ b/.dotnet/src/Custom/Audio/AudioClient.cs @@ -0,0 +1,385 @@ +using OpenAI.ClientShared.Internal; +using System; +using System.ClientModel; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.ComponentModel; +using System.Text; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; + +namespace OpenAI.Audio; + +/// The service client for OpenAI audio operations. +public partial class AudioClient +{ + private OpenAIClientConnector _clientConnector; + private Internal.Audio Shim => _clientConnector.InternalClient.GetAudioClient(); + + /// + /// Initializes a new instance of , used for audio operation requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The connection endpoint to use. + /// The model name for audio operations that the client should use. + /// The API key used to authenticate with the service endpoint. + /// Additional options to customize the client. + public AudioClient(Uri endpoint, string model, ApiKeyCredential credential, OpenAIClientOptions options = null) + { + _clientConnector = new(model, endpoint, credential, options); + } + + /// + /// Initializes a new instance of , used for audio operation requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The connection endpoint to use. + /// The model name for audio operations that the client should use. + /// Additional options to customize the client. + public AudioClient(Uri endpoint, string model, OpenAIClientOptions options = null) + : this(endpoint, model, credential: null, options) + { } + + /// + /// Initializes a new instance of , used for audio operation requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The model name for audio operations that the client should use. + /// The API key used to authenticate with the service endpoint. + /// Additional options to customize the client. + public AudioClient(string model, ApiKeyCredential credential, OpenAIClientOptions options = null) + : this(endpoint: null, model, credential, options) + { } + + /// + /// Initializes a new instance of , used for audio operation requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The model name for audio operations that the client should use. + /// Additional options to customize the client. + public AudioClient(string model, OpenAIClientOptions options = null) + : this(endpoint: null, model, credential: null, options) + { } + + /// + /// Creates text-to-speech audio that reflects the specified voice speaking the provided input text. + /// + /// + /// Unless otherwise specified via , the mp3 format of + /// will be used for the generated audio. + /// + /// The text for the voice to speak. + /// The voice to use. + /// Additional options to control the text-to-speech operation. + /// + /// A result containing generated, spoken audio in the specified output format. + /// Unless otherwise specified via , the mp3 format of + /// will be used for the generated audio. + /// + public virtual ClientResult GenerateSpeechFromText( + string text, + TextToSpeechVoice voice, + TextToSpeechOptions options = null) + { + Internal.Models.CreateSpeechRequest request = CreateInternalTtsRequest(text, voice, options); + return Shim.CreateSpeech(request); + } + + /// + /// Creates text-to-speech audio that reflects the specified voice speaking the provided input text. + /// + /// + /// Unless otherwise specified via , the mp3 format of + /// will be used for the generated audio. + /// + /// The text for the voice to speak. + /// The voice to use. + /// Additional options to control the text-to-speech operation. + /// + /// A result containing generated, spoken audio in the specified output format. + /// Unless otherwise specified via , the mp3 format of + /// will be used for the generated audio. + /// + public virtual Task> GenerateSpeechFromTextAsync( + string text, + TextToSpeechVoice voice, + TextToSpeechOptions options = null) + { + Internal.Models.CreateSpeechRequest request = CreateInternalTtsRequest(text, voice, options); + return Shim.CreateSpeechAsync(request); + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult GenerateSpeechFromText(BinaryContent content, RequestOptions context = null) + => Shim.CreateSpeech(content, context); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task GenerateSpeechFromTextAsync(BinaryContent content, RequestOptions context = null) + => Shim.CreateSpeechAsync(content, context); + + public virtual ClientResult TranscribeAudio(BinaryData audioBytes, string filename, AudioTranscriptionOptions options = null) + { + PipelineMessage message = CreateInternalTranscriptionRequestMessage(audioBytes, filename, options); + Shim.Pipeline.Send(message); + return GetTranscriptionResultFromResponse(message.Response); + } + + public virtual async Task> TranscribeAudioAsync(BinaryData audioBytes, string filename, AudioTranscriptionOptions options = null) + { + PipelineMessage message = CreateInternalTranscriptionRequestMessage(audioBytes, filename, options); + await Shim.Pipeline.SendAsync(message); + return GetTranscriptionResultFromResponse(message.Response); + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult TranscribeAudio(BinaryContent content, RequestOptions context = null) + => Shim.CreateTranscription(content, context); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task TranscribeAudioAsync(BinaryContent content, RequestOptions context = null) + => Shim.CreateTranscriptionAsync(content, context); + + public virtual ClientResult TranslateAudio(BinaryData audioBytes, string filename, AudioTranslationOptions options = null) + { + PipelineMessage message = CreateInternalTranslationRequestMessage(audioBytes, filename, options); + Shim.Pipeline.Send(message); + return GetTranslationResultFromResponse(message.Response); + } + + public virtual async Task> TranslateAudioAsync(BinaryData audioBytes, string filename, AudioTranslationOptions options = null) + { + PipelineMessage message = CreateInternalTranslationRequestMessage(audioBytes, filename, options); + await Shim.Pipeline.SendAsync(message); + return GetTranslationResultFromResponse(message.Response); + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult TranslateAudio(BinaryContent content, RequestOptions context = null) + => Shim.CreateTranslation(content, context); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task TranslateAudioAsync(BinaryContent content, RequestOptions context = null) + => Shim.CreateTranslationAsync(content, context); + + private PipelineMessage CreateInternalTranscriptionRequestMessage(BinaryData audioBytes, string filename, AudioTranscriptionOptions options) + { + PipelineMessage message = Shim.Pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_clientConnector.Endpoint.AbsoluteUri); + StringBuilder path = new(); + path.Append("/audio/transcriptions"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + + MultipartFormDataContent requestContent = CreateInternalTranscriptionRequestContent(audioBytes, filename, options); + requestContent.ApplyToRequest(request); + + return message; + } + + private PipelineMessage CreateInternalTranslationRequestMessage(BinaryData audioBytes, string filename, AudioTranslationOptions options) + { + PipelineMessage message = Shim.Pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_clientConnector.Endpoint.AbsoluteUri); + StringBuilder path = new(); + path.Append("/audio/translations"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + + MultipartFormDataContent requestContent = CreateInternalTranscriptionRequestContent(audioBytes, filename, options); + requestContent.ApplyToRequest(request); + + return message; + } + + private MultipartFormDataContent CreateInternalTranscriptionRequestContent(BinaryData audioBytes, string filename, AudioTranscriptionOptions options) + { + options ??= new(); + return CreateInternalTranscriptionRequestContent( + audioBytes, + filename, + options.Language, + options.Prompt, + options.ResponseFormat, + options.Temperature, + options.EnableWordTimestamps, + options.EnableSegmentTimestamps); + } + + private MultipartFormDataContent CreateInternalTranscriptionRequestContent(BinaryData audioBytes, string filename, AudioTranslationOptions options) + { + options ??= new(); + return CreateInternalTranscriptionRequestContent( + audioBytes, + filename, + language: null, + options.Prompt, + options.ResponseFormat, + options.Temperature, + enableWordTimestamps: null, + enableSegmentTimestamps: null); + } + + private MultipartFormDataContent CreateInternalTranscriptionRequestContent( + BinaryData audioBytes, + string filename, + string language = null, + string prompt = null, + AudioTranscriptionFormat? transcriptionFormat = null, + float? temperature = null, + bool? enableWordTimestamps = null, + bool? enableSegmentTimestamps = null) + { + MultipartFormDataContent content = new(); + content.Add(MultipartContent.Create(BinaryData.FromString(_clientConnector.Model)), name: "model", []); + if (OptionalProperty.IsDefined(language)) + { + content.Add(MultipartContent.Create(BinaryData.FromString(language)), name: "language", []); + } + if (OptionalProperty.IsDefined(prompt)) + { + content.Add(MultipartContent.Create(BinaryData.FromString(prompt)), name: "prompt", []); + } + if (OptionalProperty.IsDefined(transcriptionFormat)) + { + content.Add(MultipartContent.Create(BinaryData.FromString(transcriptionFormat switch + { + AudioTranscriptionFormat.Simple => "json", + AudioTranscriptionFormat.Detailed => "verbose_json", + AudioTranscriptionFormat.Srt => "srt", + AudioTranscriptionFormat.Vtt => "vtt", + _ => throw new ArgumentException(nameof(transcriptionFormat)), + })), + name: "response_format", + []); + } + if (OptionalProperty.IsDefined(temperature)) + { + content.Add(MultipartContent.Create(BinaryData.FromString($"{temperature}")), name: "temperature", []); + } + if (OptionalProperty.IsDefined(enableWordTimestamps) || OptionalProperty.IsDefined(enableSegmentTimestamps)) + { + List granularities = []; + if (enableWordTimestamps == true) + { + granularities.Add("word"); + } + if (enableSegmentTimestamps == true) + { + granularities.Add("segment"); + } + content.Add(MultipartContent.Create(BinaryData.FromObjectAsJson(granularities)), name: "timestamp_granularities", []); + } + content.Add(MultipartContent.Create(audioBytes), name: "file", fileName: filename, []); + + return content; + } + + private static ClientResult GetTranscriptionResultFromResponse(PipelineResponse response) + { + if (response.IsError) + { + throw new ClientResultException(response); + } + + using JsonDocument responseDocument = JsonDocument.Parse(response.Content); + return ClientResult.FromValue(AudioTranscription.DeserializeAudioTranscription(responseDocument.RootElement), response); + } + + private static ClientResult GetTranslationResultFromResponse(PipelineResponse response) + { + if (response.IsError) + { + throw new ClientResultException(response); + } + + using JsonDocument responseDocument = JsonDocument.Parse(response.Content); + return ClientResult.FromValue(AudioTranslation.DeserializeAudioTranscription(responseDocument.RootElement), response); + } + + private Internal.Models.CreateSpeechRequest CreateInternalTtsRequest( + string input, + TextToSpeechVoice voice, + TextToSpeechOptions options = null) + { + options ??= new(); + Internal.Models.CreateSpeechRequestResponseFormat? internalResponseFormat = null; + if (options.ResponseFormat != null) + { + internalResponseFormat = options.ResponseFormat switch + { + AudioDataFormat.Aac => "aac", + AudioDataFormat.Flac => "flac", + AudioDataFormat.M4a => "m4a", + AudioDataFormat.Mp3 => "mp3", + AudioDataFormat.Mp4 => "mp4", + AudioDataFormat.Mpeg => "mpeg", + AudioDataFormat.Mpga => "mpga", + AudioDataFormat.Ogg => "ogg", + AudioDataFormat.Opus => "opus", + AudioDataFormat.Wav => "wav", + AudioDataFormat.Webm => "webm", + _ => throw new ArgumentException(nameof(options.ResponseFormat)), + }; + } + return new Internal.Models.CreateSpeechRequest( + _clientConnector.Model, + input, + voice.ToString(), + internalResponseFormat, + options?.SpeedMultiplier, + serializedAdditionalRawData: null); + } + private static PipelineMessageClassifier _responseErrorClassifier200; + private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); + +} diff --git a/.dotnet/src/Custom/Audio/AudioDataFormat.cs b/.dotnet/src/Custom/Audio/AudioDataFormat.cs new file mode 100644 index 000000000..b8840ca44 --- /dev/null +++ b/.dotnet/src/Custom/Audio/AudioDataFormat.cs @@ -0,0 +1,92 @@ +namespace OpenAI.Audio; + +/// +/// Represents an audio data format available as either input or output into an audio operation. +/// +public enum AudioDataFormat +{ + /// + /// MP3, an all-purpose audio compression format with a moderate tradeoff of quality for data size. + /// + /// mp3 is supported for input into translation and transcription as well as for output from text-to-speech. + /// + /// + Mp3, + /// + /// AAC, an alternative all-purpose format to MP3 preferred by YouTube, Android, and iOS. + /// + /// aac is supported for input into translation and transcription as well as for output from text-to-speech. + /// + /// + Aac, + /// + /// OGG, a balanced, open-source, general use format favored by Spotify. + /// + /// ogg is supported as input into translation and transcription but is not available for + /// text-to-speech output. + /// + /// + Ogg, + /// + /// FLAC, a high-quality, lossless compression format preferred for audio archival and enthusiast use. + /// + /// flac is supported for input into translation and transcription as well as for output from text-to-speech. + /// + /// + Flac, + /// + /// MP4, a multimedia container format that generally features bigger sizes and higher quality relative to MP3. + /// + /// mp4 is supported as input into translation and transcription but is not available for + /// text-to-speech output. + /// + /// + Mp4, + /// + /// MPEG, a multimedia container format that can contain any of several different underlying audio formats. + /// + /// mpeg is supported as input into translation and transcription but is not available for + /// text-to-speech output. + /// + /// + Mpeg, + /// + /// MPGA, effectively an alias for MP3. + /// + /// mpga is supported as input into translation and transcription but is not available for + /// text-to-speech output. + /// + /// + Mpga, + /// + /// M4A, the audio-only counterpart to MP4 that generally features larger data sizes and higher quality than MP3. + /// + /// m4a is supported as input into translation and transcription but is not available for + /// text-to-speech output. + /// + /// + M4a, + /// + /// Opus, a higher-quality compression format that features integrated optimizations for speech. + /// + /// opus is supported for input into translation and transcription as well as for output from text-to-speech. + /// + /// + Opus, + /// + /// WAV, an uncompressed, lossless format with maximum quality, highest file size, and minimal decoding. + /// + /// wav is supported as input into translation and transcription but is not available for + /// text-to-speech output. + /// + /// + Wav, + /// + /// WebM, a multimedia container that generally uses Opus or OGG audio. + /// + /// webm is supported as input into translation and transcription but is not available for + /// text-to-speech output. + /// + /// + Webm, +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Audio/AudioTranscription.cs b/.dotnet/src/Custom/Audio/AudioTranscription.cs new file mode 100644 index 000000000..5f55ef9cb --- /dev/null +++ b/.dotnet/src/Custom/Audio/AudioTranscription.cs @@ -0,0 +1,72 @@ +using System; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Audio; + +public partial class AudioTranscription +{ + public string Language { get; } + public TimeSpan? Duration { get; } + public string Text { get; } + public IReadOnlyList Words { get; } + public IReadOnlyList Segments { get; } + + internal AudioTranscription(string language, TimeSpan? duration, string text, IReadOnlyList words, IReadOnlyList segments) + { + Language = language; + Duration = duration; + Text = text; + Words = words; + Segments = segments; + } + + internal static AudioTranscription DeserializeAudioTranscription(JsonElement element, ModelReaderWriterOptions options = default) + { + string language = null; + TimeSpan? duration = null; + string text = null; + List words = null; + List segments = null; + + foreach (JsonProperty topLevelProperty in element.EnumerateObject()) + { + if (topLevelProperty.NameEquals("language"u8)) + { + language = topLevelProperty.Value.GetString(); + continue; + } + if (topLevelProperty.NameEquals("duration"u8)) + { + duration = TimeSpan.FromSeconds(topLevelProperty.Value.GetSingle()); + continue; + } + if (topLevelProperty.NameEquals("text"u8)) + { + text = topLevelProperty.Value.GetString(); + continue; + } + if (topLevelProperty.NameEquals("words"u8)) + { + words = []; + foreach (JsonElement wordElement in topLevelProperty.Value.EnumerateArray()) + { + words.Add(TranscribedWord.DeserializeTranscribedWord(wordElement, options)); + } + continue; + } + if (topLevelProperty.NameEquals("segments"u8)) + { + segments = []; + foreach (JsonElement segmentElement in topLevelProperty.Value.EnumerateArray()) + { + segments.Add(TranscriptionSegment.DeserializeTranscriptionSegment(segmentElement, options)); + } + continue; + } + } + + return new AudioTranscription(language, duration, text, words, segments); + } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Audio/AudioTranscriptionFormat.cs b/.dotnet/src/Custom/Audio/AudioTranscriptionFormat.cs new file mode 100644 index 000000000..585099b7a --- /dev/null +++ b/.dotnet/src/Custom/Audio/AudioTranscriptionFormat.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; + +namespace OpenAI.Audio; + +public enum AudioTranscriptionFormat +{ + Simple, + Detailed, + Srt, + Vtt, +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Audio/AudioTranscriptionOptions.cs b/.dotnet/src/Custom/Audio/AudioTranscriptionOptions.cs new file mode 100644 index 000000000..2b473f74d --- /dev/null +++ b/.dotnet/src/Custom/Audio/AudioTranscriptionOptions.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; + +namespace OpenAI.Audio; + +public partial class AudioTranscriptionOptions +{ + public string Language { get; set; } + public string Prompt { get; set; } + public AudioTranscriptionFormat? ResponseFormat { get; set; } + public float? Temperature { get; set; } + public bool? EnableWordTimestamps { get; set; } + public bool? EnableSegmentTimestamps { get; set; } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Audio/AudioTranslation.cs b/.dotnet/src/Custom/Audio/AudioTranslation.cs new file mode 100644 index 000000000..49de258bf --- /dev/null +++ b/.dotnet/src/Custom/Audio/AudioTranslation.cs @@ -0,0 +1,32 @@ +using System; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Audio; + +public partial class AudioTranslation +{ + public string Text { get; } + + internal AudioTranslation(string text) + { + Text = text; + } + + internal static AudioTranslation DeserializeAudioTranscription(JsonElement element, ModelReaderWriterOptions options = default) + { + string text = null; + + foreach (JsonProperty property in element.EnumerateObject()) + { + if (property.NameEquals("text"u8)) + { + text = property.Value.GetString(); + continue; + } + } + + return new AudioTranslation(text); + } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Audio/AudioTranslationOptions.cs b/.dotnet/src/Custom/Audio/AudioTranslationOptions.cs new file mode 100644 index 000000000..38e05a047 --- /dev/null +++ b/.dotnet/src/Custom/Audio/AudioTranslationOptions.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; + +namespace OpenAI.Audio; + +public partial class AudioTranslationOptions +{ + public string Prompt { get; set; } + public AudioTranscriptionFormat? ResponseFormat { get; set; } + public float? Temperature { get; set; } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Audio/TextToSpeechOptions.cs b/.dotnet/src/Custom/Audio/TextToSpeechOptions.cs new file mode 100644 index 000000000..476d564af --- /dev/null +++ b/.dotnet/src/Custom/Audio/TextToSpeechOptions.cs @@ -0,0 +1,29 @@ +namespace OpenAI.Audio; + +/// +/// A representation of additional options available to control the behavior of a text-to-speech audio generation +/// operation. +/// +public partial class TextToSpeechOptions +{ + /// + /// The desired format of the generated text-to-speech audio. If not specified, a default value of mp3 will + /// be used. + /// + /// Supported output formats include: + /// + /// mp3 - + /// opus - + /// aac - + /// flac - + /// + /// + /// + public AudioDataFormat? ResponseFormat { get; set; } + + /// + /// A multiplicative speed factor to apply to the generated audio, with 1.0 being the default and valid + /// values ranging from 0.25 to 4.0. + /// + public float? SpeedMultiplier { get; set; } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Audio/TextToSpeechVoice.cs b/.dotnet/src/Custom/Audio/TextToSpeechVoice.cs new file mode 100644 index 000000000..55bc324c5 --- /dev/null +++ b/.dotnet/src/Custom/Audio/TextToSpeechVoice.cs @@ -0,0 +1,64 @@ +using System; + +namespace OpenAI.Audio; + +/// +/// Represents the available text-to-speech voices. +/// +public readonly struct TextToSpeechVoice : IEquatable +{ + private readonly Internal.Models.CreateSpeechRequestVoice _internalVoice; + + /// + /// Creates a new instance of . + /// + /// The textual representation of the value to use. + public TextToSpeechVoice(string value) + : this(new Internal.Models.CreateSpeechRequestVoice(value)) + { } + + internal TextToSpeechVoice(Internal.Models.CreateSpeechRequestVoice internalVoice) + { + _internalVoice = internalVoice; + } + + /// + /// The onyx voice. + /// + public static TextToSpeechVoice Onyx { get; } = new TextToSpeechVoice(Internal.Models.CreateSpeechRequestVoice.Onyx); + /// + /// The shimmer voice. + /// + public static TextToSpeechVoice Shimmer { get; } = new TextToSpeechVoice(Internal.Models.CreateSpeechRequestVoice.Shimmer); + /// + /// The alloy voice. + /// + public static TextToSpeechVoice Alloy { get; } = new TextToSpeechVoice(Internal.Models.CreateSpeechRequestVoice.Alloy); + /// + /// The fable voice. + /// + public static TextToSpeechVoice Fable { get; } = new TextToSpeechVoice(Internal.Models.CreateSpeechRequestVoice.Fable); + /// + /// The echo voice. + /// + public static TextToSpeechVoice Echo { get; } = new TextToSpeechVoice(Internal.Models.CreateSpeechRequestVoice.Echo); + + /// + public static bool operator ==(TextToSpeechVoice left, TextToSpeechVoice right) + => left._internalVoice == right._internalVoice; + /// + public static implicit operator TextToSpeechVoice(string value) + => new TextToSpeechVoice(new Internal.Models.CreateSpeechRequestVoice(value)); + /// + public static bool operator !=(TextToSpeechVoice left, TextToSpeechVoice right) + => left._internalVoice != right._internalVoice; + /// + public bool Equals(TextToSpeechVoice other) => _internalVoice.Equals(other._internalVoice); + /// + public override string ToString() => _internalVoice.ToString(); + /// + public override bool Equals(object obj) => + (obj is TextToSpeechVoice voice && this.Equals(voice)) || _internalVoice.Equals(obj); + /// + public override int GetHashCode() => _internalVoice.GetHashCode(); +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Audio/TranscribedWord.cs b/.dotnet/src/Custom/Audio/TranscribedWord.cs new file mode 100644 index 000000000..94e26fde3 --- /dev/null +++ b/.dotnet/src/Custom/Audio/TranscribedWord.cs @@ -0,0 +1,45 @@ +using System; +using System.ClientModel.Primitives; +using System.Text.Json; + +namespace OpenAI.Audio; + +public partial class TranscribedWord +{ + public string Word { get; } + public TimeSpan Start { get; } + public TimeSpan End { get; } + + internal TranscribedWord(string word, TimeSpan start, TimeSpan end) + { + Word = word; + Start = start; + End = end; + } + + internal static TranscribedWord DeserializeTranscribedWord(JsonElement element, ModelReaderWriterOptions options = default) + { + string word = null; + TimeSpan? start = null; + TimeSpan? end = null; + foreach (JsonProperty wordProperty in element.EnumerateObject()) + { + if (wordProperty.NameEquals("word"u8)) + { + word = wordProperty.Value.GetString(); + continue; + } + if (wordProperty.NameEquals("start"u8)) + { + start = TimeSpan.FromSeconds(wordProperty.Value.GetSingle()); + continue; + } + if (wordProperty.NameEquals("end"u8)) + { + end = TimeSpan.FromSeconds(wordProperty.Value.GetSingle()); + continue; + } + } + return new TranscribedWord(word, start.Value, end.Value); + } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Audio/TranscriptionSegment.cs b/.dotnet/src/Custom/Audio/TranscriptionSegment.cs new file mode 100644 index 000000000..c1ee0632e --- /dev/null +++ b/.dotnet/src/Custom/Audio/TranscriptionSegment.cs @@ -0,0 +1,109 @@ +using System; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; +using System.Threading; + +namespace OpenAI.Audio; + +public partial class TranscriptionSegment +{ + public int Id { get; } + public int SeekOffset { get; } + public TimeSpan Start { get; } + public TimeSpan End { get; } + public string Text { get; } + public IReadOnlyList TokenIds { get; } + public float Temperature { get; } + public float AverageLogProbability { get; } + public float CompressionRatio { get; } + public float NoSpeechProbability { get; } + + internal TranscriptionSegment(int id, int seekOffset, TimeSpan start, TimeSpan end, string text, IReadOnlyList tokenIds, float temperature, float averageLogProbability, float compressionRatio, float noSpeechProbability) + { + Id = id; + SeekOffset = seekOffset; + Start = start; + End = end; + Text = text; + TokenIds = tokenIds; + Temperature = temperature; + AverageLogProbability = averageLogProbability; + CompressionRatio = compressionRatio; + NoSpeechProbability = noSpeechProbability; + } + + internal static TranscriptionSegment DeserializeTranscriptionSegment(JsonElement element, ModelReaderWriterOptions options = default) + { + int id = 0; + int seekOffset = 0; + TimeSpan start = default; + TimeSpan end = default; + string text = null; + List tokenIds = null; + float temperature = 0; + float averageLogProbability = 0; + float compressionRatio = 0; + float noSpeechProbability = 0; + + foreach (JsonProperty topLevelProperty in element.EnumerateObject()) + { + if (topLevelProperty.NameEquals("id"u8)) + { + id = topLevelProperty.Value.GetInt32(); + continue; + } + if (topLevelProperty.NameEquals("seek"u8)) + { + seekOffset = topLevelProperty.Value.GetInt32(); + continue; + } + if (topLevelProperty.NameEquals("start"u8)) + { + start = TimeSpan.FromSeconds(topLevelProperty.Value.GetSingle()); + continue; + } + if (topLevelProperty.NameEquals("end"u8)) + { + end = TimeSpan.FromSeconds(topLevelProperty.Value.GetSingle()); + continue; + } + if (topLevelProperty.NameEquals("text"u8)) + { + text = topLevelProperty.Value.GetString(); + continue; + } + if (topLevelProperty.NameEquals("tokens"u8)) + { + tokenIds = []; + foreach (JsonElement tokenIdElement in topLevelProperty.Value.EnumerateArray()) + { + tokenIds.Add(tokenIdElement.GetInt32()); + } + continue; + } + if (topLevelProperty.NameEquals("temperature"u8)) + { + temperature = topLevelProperty.Value.GetSingle(); + continue; + } + if (topLevelProperty.NameEquals("avg_logprob"u8)) + { + averageLogProbability = topLevelProperty.Value.GetSingle(); + continue; + } + if (topLevelProperty.NameEquals("compression_ratio"u8)) + { + compressionRatio = topLevelProperty.Value.GetSingle(); + continue; + } + if (topLevelProperty.NameEquals("no_speech_prob"u8)) + { + noSpeechProbability = topLevelProperty.Value.GetSingle(); + continue; + } + } + + return new TranscriptionSegment(id, seekOffset, start, end, text, tokenIds, temperature, averageLogProbability, compressionRatio, noSpeechProbability); + } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Chat/ChatClient.cs b/.dotnet/src/Custom/Chat/ChatClient.cs new file mode 100644 index 000000000..e9990e3c9 --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatClient.cs @@ -0,0 +1,400 @@ +using System; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.ComponentModel; +using System.Text; +using System.Threading.Tasks; + +namespace OpenAI.Chat; + +/// The service client for the OpenAI Chat Completions endpoint. +public partial class ChatClient +{ + private OpenAIClientConnector _clientConnector; + private Internal.Chat Shim => _clientConnector.InternalClient.GetChatClient(); + + /// + /// Initializes a new instance of , used for Chat Completion requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The connection endpoint to use. + /// The model name for chat completions that the client should use. + /// The API key used to authenticate with the service endpoint. + /// Additional options to customize the client. + public ChatClient(Uri endpoint, string model, ApiKeyCredential credential, OpenAIClientOptions options = null) + { + _clientConnector = new(model, endpoint, credential, options); + } + + /// + /// Initializes a new instance of , used for Chat Completion requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The connection endpoint to use. + /// The model name for chat completions that the client should use. + /// Additional options to customize the client. + public ChatClient(Uri endpoint, string model, OpenAIClientOptions options = null) + : this(endpoint, model, credential: null, options) + { } + + /// + /// Initializes a new instance of , used for Chat Completion requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The model name for chat completions that the client should use. + /// The API key used to authenticate with the service endpoint. + /// Additional options to customize the client. + public ChatClient(string model, ApiKeyCredential credential, OpenAIClientOptions options = null) + : this(endpoint: null, model, credential, options) + { } + + /// + /// Initializes a new instance of , used for Chat Completion requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The model name for chat completions that the client should use. + /// Additional options to customize the client. + public ChatClient(string model, OpenAIClientOptions options = null) + : this(endpoint: null, model, credential: null, options) + { } + + /// + /// Generates a single chat completion result for a single, simple user message. + /// + /// The user message to provide as a prompt for chat completion. + /// Additional options for the chat completion request. + /// A result for a single chat completion. + public virtual ClientResult CompleteChat(string message, ChatCompletionOptions options = null) + => CompleteChat(new List() { new ChatRequestUserMessage(message) }, options); + + /// + /// Generates a single chat completion result for a single, simple user message. + /// + /// The user message to provide as a prompt for chat completion. + /// Additional options for the chat completion request. + /// A result for a single chat completion. + public virtual Task> CompleteChatAsync(string message, ChatCompletionOptions options = null) + => CompleteChatAsync( + new List() { new ChatRequestUserMessage(message) }, options); + + /// + /// Generates a single chat completion result for a provided set of input chat messages. + /// + /// The messages to provide as input and history for chat completion. + /// Additional options for the chat completion request. + /// A result for a single chat completion. + public virtual ClientResult CompleteChat( + IEnumerable messages, + ChatCompletionOptions options = null) + { + Internal.Models.CreateChatCompletionRequest request = CreateInternalRequest(messages, options); + ClientResult response = Shim.CreateChatCompletion(request); + ChatCompletion chatCompletion = new(response.Value, internalChoiceIndex: 0); + return ClientResult.FromValue(chatCompletion, response.GetRawResponse()); + } + + /// + /// Generates a single chat completion result for a provided set of input chat messages. + /// + /// The messages to provide as input and history for chat completion. + /// Additional options for the chat completion request. + /// A result for a single chat completion. + public virtual async Task> CompleteChatAsync( + IEnumerable messages, + ChatCompletionOptions options = null) + { + Internal.Models.CreateChatCompletionRequest request = CreateInternalRequest(messages, options); + ClientResult response = await Shim.CreateChatCompletionAsync(request).ConfigureAwait(false); + ChatCompletion chatCompletion = new(response.Value, internalChoiceIndex: 0); + return ClientResult.FromValue(chatCompletion, response.GetRawResponse()); + } + + /// + /// Generates a collection of chat completion results for a provided set of input chat messages. + /// + /// The messages to provide as input and history for chat completion. + /// + /// The number of independent, alternative response choices that should be generated. + /// + /// Additional options for the chat completion request. + /// The cancellation token for the operation. + /// A result for a single chat completion. + public virtual ClientResult CompleteChat( + IEnumerable messages, + int choiceCount, + ChatCompletionOptions options = null) + { + Internal.Models.CreateChatCompletionRequest request = CreateInternalRequest(messages, options, choiceCount); + ClientResult response = Shim.CreateChatCompletion(request); + List chatCompletions = []; + for (int i = 0; i < response.Value.Choices.Count; i++) + { + chatCompletions.Add(new(response.Value, response.Value.Choices[i].Index)); + } + return ClientResult.FromValue(new ChatCompletionCollection(chatCompletions), response.GetRawResponse()); + } + + /// + /// Generates a collection of chat completion results for a provided set of input chat messages. + /// + /// The messages to provide as input and history for chat completion. + /// + /// The number of independent, alternative response choices that should be generated. + /// + /// Additional options for the chat completion request. + /// A result for a single chat completion. + public virtual async Task> CompleteChatAsync( + IEnumerable messages, + int choiceCount, + ChatCompletionOptions options = null) + { + Internal.Models.CreateChatCompletionRequest request = CreateInternalRequest(messages, options, choiceCount); + ClientResult response = await Shim.CreateChatCompletionAsync(request).ConfigureAwait(false); + List chatCompletions = []; + for (int i = 0; i < response.Value.Choices.Count; i++) + { + chatCompletions.Add(new(response.Value, response.Value.Choices[i].Index)); + } + return ClientResult.FromValue(new ChatCompletionCollection(chatCompletions), response.GetRawResponse()); + } + + /// + /// Begins a streaming response for a chat completion request using a single, simple user message as input. + /// + /// + /// can be enumerated over using the await foreach pattern using the + /// interface. + /// + /// The user message to provide as a prompt for chat completion. + /// + /// The number of independent, alternative choices that the chat completion request should generate. + /// + /// Additional options for the chat completion request. + /// A streaming result with incremental chat completion updates. + public virtual StreamingClientResult CompleteChatStreaming( + string message, + int? choiceCount = null, + ChatCompletionOptions options = null) + => CompleteChatStreaming( + new List { new ChatRequestUserMessage(message) }, + choiceCount, + options); + + /// + /// Begins a streaming response for a chat completion request using a single, simple user message as input. + /// + /// + /// can be enumerated over using the await foreach pattern using the + /// interface. + /// + /// The user message to provide as a prompt for chat completion. + /// + /// The number of independent, alternative choices that the chat completion request should generate. + /// + /// Additional options for the chat completion request. + /// A streaming result with incremental chat completion updates. + public virtual Task> CompleteChatStreamingAsync( + string message, + int? choiceCount = null, + ChatCompletionOptions options = null) + => CompleteChatStreamingAsync( + new List { new ChatRequestUserMessage(message) }, + choiceCount, + options); + + /// + /// Begins a streaming response for a chat completion request using the provided chat messages as input and + /// history. + /// + /// + /// can be enumerated over using the await foreach pattern using the + /// interface. + /// + /// The messages to provide as input for chat completion. + /// + /// The number of independent, alternative choices that the chat completion request should generate. + /// + /// Additional options for the chat completion request. + /// The cancellation token for the operation. + /// A streaming result with incremental chat completion updates. + public virtual StreamingClientResult CompleteChatStreaming( + IEnumerable messages, + int? choiceCount = null, + ChatCompletionOptions options = null) + { + PipelineMessage requestMessage = CreateCustomRequestMessage(messages, choiceCount, options); + requestMessage.BufferResponse = false; + Shim.Pipeline.Send(requestMessage); + PipelineResponse response = requestMessage.ExtractResponse(); + + if (response.IsError) + { + throw new ClientResultException(response); + } + + ClientResult genericResult = ClientResult.FromResponse(response); + return StreamingClientResult.CreateFromResponse( + genericResult, + (responseForEnumeration) => SseAsyncEnumerator.EnumerateFromSseStream( + responseForEnumeration.GetRawResponse().ContentStream, + e => StreamingChatUpdate.DeserializeStreamingChatUpdates(e))); + } + + /// + /// Begins a streaming response for a chat completion request using the provided chat messages as input and + /// history. + /// + /// + /// can be enumerated over using the await foreach pattern using the + /// interface. + /// + /// The messages to provide as input for chat completion. + /// + /// The number of independent, alternative choices that the chat completion request should generate. + /// + /// Additional options for the chat completion request. + /// The cancellation token for the operation. + /// A streaming result with incremental chat completion updates. + public virtual async Task> CompleteChatStreamingAsync( + IEnumerable messages, + int? choiceCount = null, + ChatCompletionOptions options = null) + { + PipelineMessage requestMessage = CreateCustomRequestMessage(messages, choiceCount, options); + requestMessage.BufferResponse = false; + await Shim.Pipeline.SendAsync(requestMessage); + PipelineResponse response = requestMessage.ExtractResponse(); + + if (response.IsError) + { + throw new ClientResultException(response); + } + + ClientResult genericResult = ClientResult.FromResponse(response); + return StreamingClientResult.CreateFromResponse( + genericResult, + (responseForEnumeration) => SseAsyncEnumerator.EnumerateFromSseStream( + responseForEnumeration.GetRawResponse().ContentStream, + e => StreamingChatUpdate.DeserializeStreamingChatUpdates(e))); + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult CompleteChat(BinaryContent content, RequestOptions context = null) + => Shim.CreateChatCompletion(content, context); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task CompleteChatAsync(BinaryContent content, RequestOptions context = null) + => Shim.CreateChatCompletionAsync(content, context); + + private Internal.Models.CreateChatCompletionRequest CreateInternalRequest( + IEnumerable messages, + ChatCompletionOptions options = null, + int? choiceCount = null, + bool? stream = null) + { + options ??= new(); + Internal.Models.CreateChatCompletionRequestResponseFormat? internalFormat = null; + if (options.ResponseFormat is not null) + { + internalFormat = new(options.ResponseFormat switch + { + ChatResponseFormat.Text => Internal.Models.CreateChatCompletionRequestResponseFormatType.Text, + ChatResponseFormat.JsonObject => Internal.Models.CreateChatCompletionRequestResponseFormatType.JsonObject, + _ => throw new ArgumentException(nameof(options.ResponseFormat)), + }, null); + } + List messageDataItems = []; + foreach (ChatRequestMessage message in messages) + { + messageDataItems.Add(ModelReaderWriter.Write(message)); + } + Dictionary additionalData = []; + return new Internal.Models.CreateChatCompletionRequest( + messageDataItems, + _clientConnector.Model, + options?.FrequencyPenalty, + options?.GetInternalLogitBias(), + options?.IncludeLogProbabilities, + options?.LogProbabilityCount, + options?.MaxTokens, + choiceCount, + options?.PresencePenalty, + internalFormat, + options?.Seed, + options?.GetInternalStopSequences(), + stream, + options?.Temperature, + options?.NucleusSamplingFactor, + options?.GetInternalTools(), + options?.ToolConstraint?.GetBinaryData(), + options?.User, + options?.FunctionConstraint?.ToBinaryData(), + options?.GetInternalFunctions(), + additionalData + ); + } + + private PipelineMessage CreateCustomRequestMessage(IEnumerable messages, int? choiceCount, ChatCompletionOptions options) + { + Internal.Models.CreateChatCompletionRequest internalRequest = CreateInternalRequest(messages, options, choiceCount, stream: true); + BinaryContent content = BinaryContent.Create(internalRequest); + + PipelineMessage message = Shim.Pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + message.BufferResponse = false; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_clientConnector.Endpoint.AbsoluteUri); + StringBuilder path = new(); + path.Append("/chat/completions"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); + request.Headers.Set("Content-Type", "application/json"); + request.Content = content; + + return message; + } + + private static PipelineMessageClassifier _responseErrorClassifier200; + private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); +} diff --git a/.dotnet/src/Custom/Chat/ChatCompletion.cs b/.dotnet/src/Custom/Chat/ChatCompletion.cs new file mode 100644 index 000000000..119f62e1d --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatCompletion.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; + +namespace OpenAI.Chat; + +/// +public class ChatCompletion +{ + private Internal.Models.CreateChatCompletionResponse _internalResponse; + private long _internalChoiceIndex; + + /// + public string Id => _internalResponse.Id; + /// + public string SystemFingerprint => _internalResponse.SystemFingerprint; + /// + public DateTimeOffset CreatedAt => _internalResponse.Created; + /// + public ChatTokenUsage Usage { get; } + /// + public ChatFinishReason FinishReason { get; } + /// + public ChatMessageContent Content { get; } + /// + public IReadOnlyList ToolCalls { get; } + /// + public ChatFunctionCall FunctionCall { get; } + /// + public ChatRole Role { get; } + /// + public ChatLogProbabilityCollection LogProbabilities { get; } + /// + public long Index => _internalResponse.Choices[(int)_internalChoiceIndex].Index; + + internal ChatCompletion(Internal.Models.CreateChatCompletionResponse internalResponse, long internalChoiceIndex) + { + Internal.Models.CreateChatCompletionResponseChoice internalChoice = internalResponse.Choices[(int)internalChoiceIndex]; + _internalResponse = internalResponse; + _internalChoiceIndex = internalChoiceIndex; + Role = internalChoice.Message.Role.ToString() switch + { + "system" => ChatRole.System, + "user" => ChatRole.User, + "assistant" => ChatRole.Assistant, + "tool" => ChatRole.Tool, + "function" => ChatRole.Function, + _ => throw new ArgumentException(nameof(internalChoice.Message.Role)), + }; + Usage = new(_internalResponse.Usage); + FinishReason = internalChoice.FinishReason.ToString() switch + { + "stop" => ChatFinishReason.Stopped, + "length" => ChatFinishReason.Length, + "tool_calls" => ChatFinishReason.ToolCalls, + "function_call" => ChatFinishReason.FunctionCall, + "content_filter" => ChatFinishReason.ContentFilter, + _ => throw new ArgumentException(nameof(internalChoice.FinishReason)), + }; + Content = internalChoice.Message.Content; + if (internalChoice.Message.ToolCalls != null) + { + List toolCalls = []; + foreach (Internal.Models.ChatCompletionMessageToolCall internalToolCall in internalChoice.Message.ToolCalls) + { + if (internalToolCall.Type == "function") + { + toolCalls.Add(new ChatFunctionToolCall(internalToolCall.Id, internalToolCall.Function.Name, internalToolCall.Function.Arguments)); + } + } + ToolCalls = toolCalls; + } + if (internalChoice.Message.FunctionCall != null) + { + FunctionCall = new(internalChoice.Message.FunctionCall.Name, internalChoice.Message.FunctionCall.Arguments); + } + if (internalChoice.Logprobs != null) + { + LogProbabilities = ChatLogProbabilityCollection.FromInternalData(internalChoice.Logprobs); + } + } +} diff --git a/.dotnet/src/Custom/Chat/ChatCompletionCollection.cs b/.dotnet/src/Custom/Chat/ChatCompletionCollection.cs new file mode 100644 index 000000000..d677b65a9 --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatCompletionCollection.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace OpenAI.Chat; + +/// +/// Represents a chat completions response payload that contains information about multiple requested chat completion +/// choices. +/// +public class ChatCompletionCollection : ReadOnlyCollection +{ + internal ChatCompletionCollection(IList list) : base(list) { } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Chat/ChatCompletionOptions.cs b/.dotnet/src/Custom/Chat/ChatCompletionOptions.cs new file mode 100644 index 000000000..b5b8114e7 --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatCompletionOptions.cs @@ -0,0 +1,115 @@ +using OpenAI.ClientShared.Internal; +using System; +using System.ClientModel.Internal; + +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Chat; + +/// +/// Request-level options for chat completion. +/// +public partial class ChatCompletionOptions +{ + /// + public double? FrequencyPenalty { get; set; } + /// + public IDictionary TokenSelectionBiases { get; set; } = new OptionalDictionary(); + /// + public bool? IncludeLogProbabilities { get; set; } + /// + public long? LogProbabilityCount { get; set; } + /// + public long? MaxTokens { get; set; } + /// + public double? PresencePenalty { get; set; } + /// + public ChatResponseFormat? ResponseFormat { get; set; } + /// + public long? Seed { get; set; } + /// + public IList StopSequences { get; } = new OptionalList(); + /// + public double? Temperature { get; set; } + /// + public double? NucleusSamplingFactor { get; set; } + /// + public IList Tools { get; } = new OptionalList(); + /// + public ChatToolConstraint? ToolConstraint { get; set; } + /// + public string User { get; set; } + /// + public IList Functions { get; } = new OptionalList(); + /// + public ChatFunctionConstraint? FunctionConstraint { get; set; } + + internal BinaryData GetInternalStopSequences() + { + if (!OptionalProperty.IsCollectionDefined(StopSequences)) + { + return null; + } + return BinaryData.FromObjectAsJson(StopSequences); + } + + internal IDictionary GetInternalLogitBias() + { + OptionalDictionary packedLogitBias = []; + foreach (KeyValuePair pair in TokenSelectionBiases) + { + packedLogitBias[$"{pair.Key}"] = pair.Value; + } + return packedLogitBias; + } + + internal IList GetInternalTools() + { + OptionalList internalTools = []; + foreach (ChatToolDefinition tool in Tools) + { + if (tool is ChatFunctionToolDefinition functionTool) + { + Internal.Models.FunctionObject functionObject = new( + functionTool.Description, + functionTool.Name, + CreateInternalFunctionParameters(functionTool.Parameters), + serializedAdditionalRawData: null); + internalTools.Add(new(functionObject)); + } + } + return internalTools; + } + + internal IList GetInternalFunctions() + { + OptionalList internalFunctions = []; + foreach (ChatFunctionDefinition function in Functions) + { + Internal.Models.ChatCompletionFunctions internalFunction = new( + function.Description, + function.Name, + CreateInternalFunctionParameters(function.Parameters), + serializedAdditionalRawData: null); + internalFunctions.Add(internalFunction); + } + return internalFunctions; + } + + internal static Internal.Models.FunctionParameters CreateInternalFunctionParameters(BinaryData parameters) + { + if (parameters == null) + { + return null; + } + JsonElement parametersElement = JsonDocument.Parse(parameters.ToString()).RootElement; + Internal.Models.FunctionParameters internalParameters = new(); + foreach (JsonProperty property in parametersElement.EnumerateObject()) + { + BinaryData propertyData = BinaryData.FromString(property.Value.GetRawText()); + internalParameters.AdditionalProperties.Add(property.Name, propertyData); + } + return internalParameters; + } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Chat/ChatFinishReason.cs b/.dotnet/src/Custom/Chat/ChatFinishReason.cs new file mode 100644 index 000000000..48196d52d --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatFinishReason.cs @@ -0,0 +1,77 @@ +namespace OpenAI.Chat; + +/// +/// The reason the model stopped generating tokens. This will be: +/// +/// +/// Property +/// REST +/// Condition +/// +/// +/// +/// stop +/// The model encountered a natural stop point or provided stop sequence. +/// +/// +/// +/// length +/// The maximum number of tokens specified in the request was reached. +/// +/// +/// +/// content_filter +/// Content was omitted due to a triggered content filter rule. +/// +/// +/// +/// tool_calls +/// +/// With no explicit tool_choice, the model called one or more tools that were defined in the request. +/// +/// +/// +/// +/// function_call +/// (Deprecated) The model called a function that was defined in the request. +/// +/// +/// +public enum ChatFinishReason +{ + /// + /// Indicates that the model encountered a natural stop point or provided stop sequence. + /// + Stopped, + /// + /// Indicates that the model reached the maximum number of tokens allowed for the request. + /// + Length, + /// + /// Indicates that content was omitted due to a triggered content filter rule. + /// + ContentFilter, + /// + /// Indicates that the model called a function that was defined in the request. + /// + /// + /// To resolve tool calls, append the message associated with the tool calls followed by matching instances of + /// for each tool call, then perform another chat completion with the combined + /// set of messages. + /// + /// Note: is not provided as the finish_reason if the model calls a + /// tool in response to an explicit tool_choice via . + /// In that case, calling the specified tool is assumed and the expected reason is . + /// + /// + ToolCalls, + /// + /// Indicates that the model called a function that was defined in the request. + /// + /// + /// To resolve a function call, append the message associated with the function call followed by a + /// with the appropriate name and arguments, then perform another chat + /// completion with the combined set of messages. + /// + FunctionCall, +} diff --git a/.dotnet/src/Custom/Chat/ChatFunctionCall.Serialization.cs b/.dotnet/src/Custom/Chat/ChatFunctionCall.Serialization.cs new file mode 100644 index 000000000..eb198cfd4 --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatFunctionCall.Serialization.cs @@ -0,0 +1,37 @@ +using System; +using System.ClientModel.Internal; + +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; + +namespace OpenAI.Chat; + +public partial class ChatFunctionCall : IJsonModel +{ + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + writer.WriteStartObject(); + writer.WriteString("name"u8, Name); + writer.WriteString("arguments"u8, Arguments); + writer.WriteEndObject(); + } + + ChatFunctionCall IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + throw new NotImplementedException(); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + throw new NotImplementedException(); + } + + ChatFunctionCall IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + throw new NotImplementedException(); + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; +} diff --git a/.dotnet/src/Custom/Chat/ChatFunctionCall.cs b/.dotnet/src/Custom/Chat/ChatFunctionCall.cs new file mode 100644 index 000000000..822f1577f --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatFunctionCall.cs @@ -0,0 +1,47 @@ +using System.Diagnostics.CodeAnalysis; + +namespace OpenAI.Chat; + +/// +/// Represents an assistant call against a supplied that is needed by the +/// model to continue the logical conversation. +/// +/// +/// +/// Note that functions are deprecated in favor of tools and using +/// instances with will enable the use of tool_calls via +/// instead of this type. +/// +/// +/// The model makes a function_call in response to evaluation of supplied name> and +/// description information in functions and is resolved by providing a new +/// with matching functioning output on a subsequent chat completion +/// request. +/// +/// +public partial class ChatFunctionCall +{ + /// + /// The name of the function being called by the model. + /// + public required string Name { get; set; } + /// + /// The arguments to the function being called by the model. + /// + public required string Arguments { get; set; } + /// + /// Creates a new instance of . + /// + public ChatFunctionCall() { } + /// + /// Creates a new instance of . + /// + /// The name of the function that was called by the model. + /// The arguments to the function that was called by the model. + [SetsRequiredMembers] + public ChatFunctionCall(string functionName, string arguments) + { + Name = functionName; + Arguments = arguments; + } +} diff --git a/.dotnet/src/Custom/Chat/ChatFunctionConstraint.cs b/.dotnet/src/Custom/Chat/ChatFunctionConstraint.cs new file mode 100644 index 000000000..fe9e7bf66 --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatFunctionConstraint.cs @@ -0,0 +1,73 @@ +using System; + +namespace OpenAI.Chat; + +/// +/// Represents a desired manner in which the model should use the functions defined in a chat completion request. +/// +public readonly partial struct ChatFunctionConstraint : IEquatable +{ + private readonly string _value; + private readonly bool _isPredefined; + + /// + /// auto specifies that the model should freely call any or none of the provided functions. + /// This is the implied default when not otherwise specified. + /// + public static ChatFunctionConstraint Auto { get; } = new("auto", isPredefined: true); + /// + /// none specifies that the model should not call any of the provided functions. Note that the definition + /// of the functions may still influence the chat completion content even when not called. + /// + public static ChatFunctionConstraint None { get; } = new("none", isPredefined: true); + + /// + /// Creates a new instance of that specifies that the model should invoke a + /// specific, named function. + /// + /// The name of the function that the model should call. + public ChatFunctionConstraint(string functionName) + : this(functionName, isPredefined: false) + { + } + + internal ChatFunctionConstraint(string functionNameOrPredefinedLabel, bool isPredefined) + { + _value = functionNameOrPredefinedLabel; + _isPredefined = isPredefined; + } + + /// + public static bool operator ==(ChatFunctionConstraint left, ChatFunctionConstraint right) + => left._isPredefined == right._isPredefined && left._value == right._value; + /// + public static implicit operator ChatFunctionConstraint(string value) => new(value); + /// + public static bool operator !=(ChatFunctionConstraint left, ChatFunctionConstraint right) + => left._isPredefined != right._isPredefined || left._value != right._value; + /// + public bool Equals(ChatFunctionConstraint other) + => other._isPredefined.Equals(_isPredefined) && other._value.Equals(_value); + /// + public override string ToString() => ToBinaryData().ToString(); + /// + public override bool Equals(object obj) + => obj is ChatFunctionConstraint constraint && constraint.Equals(this); + /// + public override int GetHashCode() => $"{_value}-{_isPredefined}".GetHashCode(); + + internal BinaryData ToBinaryData() + { + if (_isPredefined) + { + return BinaryData.FromString(_value); + } + else + { + return BinaryData.FromObjectAsJson(new + { + name = _value, + }); + } + } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Chat/ChatFunctionDefinition.cs b/.dotnet/src/Custom/Chat/ChatFunctionDefinition.cs new file mode 100644 index 000000000..ddcbb6ffa --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatFunctionDefinition.cs @@ -0,0 +1,60 @@ +using System; +using System.Diagnostics.CodeAnalysis; + +namespace OpenAI.Chat; + +/// +/// Represents the definition of a function that the model may call, as supplied in a chat completion request. +/// +public class ChatFunctionDefinition +{ + /// + /// The name of the function. + /// + public required string Name { get; set; } + /// + /// A friendly description of the function. This supplements in informing the model about when + /// it should call the function. + /// + public string Description { get; set; } + /// + /// The parameter information for the function, provided in JSON Schema format. + /// + /// + /// The method provides + /// an easy definition interface using the dynamic type: + /// + /// Parameters = BinaryData.FromObjectAsJson(new + /// { + /// type = "object", + /// properties = new + /// { + /// your_function_argument = new + /// { + /// type = "string", + /// description = "the description of your function argument" + /// } + /// }, + /// required = new[] { "your_function_argument" } + /// }) + /// + /// + public BinaryData Parameters { get; set; } + /// + /// Creates a new instance of . + /// + public ChatFunctionDefinition() { } + /// + /// Creates a new instance of . + /// + /// The name of the function. + /// A description of the function's behavior or purpose. + /// The parameter information for the function, in JSON Schema format. + [SetsRequiredMembers] + public ChatFunctionDefinition(string name, string description = null, BinaryData parameters = null) + { + Name = name; + Description = description; + Parameters = parameters; + } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Chat/ChatFunctionToolCall.cs b/.dotnet/src/Custom/Chat/ChatFunctionToolCall.cs new file mode 100644 index 000000000..5a6a823b6 --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatFunctionToolCall.cs @@ -0,0 +1,69 @@ +using System; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; + +namespace OpenAI.Chat; + +/// +/// Represents a call made by the model to a function tool that was defined in a chat completion request. +/// +public class ChatFunctionToolCall : ChatToolCall +{ + internal Internal.Models.ChatCompletionMessageToolCallFunction InternalToolCall { get; } + + /// + /// Gets the name of the function. + /// + public required string Name + { + get => InternalToolCall.Name; + set => InternalToolCall.Name = value; + } + + /// + /// Gets the arguments to the function. + /// + public required string Arguments + { + get => InternalToolCall.Arguments; + set => InternalToolCall.Arguments = value; + + } + /// + /// Creates a new instance of . + /// + public ChatFunctionToolCall() + { + InternalToolCall = new(); + } + + /// + /// Creates a new instance of . + /// + /// + /// The ID of the tool call, used when resolving the tool call with a future + /// . + /// + /// The name of the function. + /// The arguments to the function. + [SetsRequiredMembers] + public ChatFunctionToolCall(string toolCallId, string functionName, string arguments) + : this() + { + Id = toolCallId; + Name = functionName; + Arguments = arguments; + } + + internal override void WriteDerivedAdditions(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + writer.WriteString("type"u8, "function"u8); + writer.WritePropertyName("function"u8); + writer.WriteStartObject(); + writer.WriteString("name"u8, Name); + writer.WriteString("arguments"u8, Arguments); + writer.WriteEndObject(); + } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Chat/ChatFunctionToolDefinition.cs b/.dotnet/src/Custom/Chat/ChatFunctionToolDefinition.cs new file mode 100644 index 000000000..313b76aec --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatFunctionToolDefinition.cs @@ -0,0 +1,60 @@ +using System; +using System.Diagnostics.CodeAnalysis; + +namespace OpenAI.Chat; + +/// +/// Represents the definition of a function tool that is callable by the model for a chat completion request. +/// +public class ChatFunctionToolDefinition : ChatToolDefinition +{ + /// + /// The name of the function that the tool represents. + /// + public required string Name { get; set; } + /// + /// A friendly description of the function. This supplements in informing the model about when + /// it should call the function. + /// + public string Description { get; set; } + /// + /// The parameter information for the function, provided in JSON Schema format. + /// + /// + /// The method provides + /// an easy definition interface using the dynamic type: + /// + /// Parameters = BinaryData.FromObjectAsJson(new + /// { + /// type = "object", + /// properties = new + /// { + /// your_function_argument = new + /// { + /// type = "string", + /// description = "the description of your function argument" + /// } + /// }, + /// required = new[] { "your_function_argument" } + /// }) + /// + /// + public BinaryData Parameters { get; set; } + /// + /// Creates a new instance of . + /// + public ChatFunctionToolDefinition() { } + /// + /// Creates a new instance of . + /// + /// The name of the function. + /// The description of the function. + /// The parameters into the function, in JSON Schema format. + [SetsRequiredMembers] + public ChatFunctionToolDefinition(string name, string description = null, BinaryData parameters = null) + { + Name = name; + Description = description; + Parameters = parameters; + } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Chat/ChatLogProbabilityCollection.cs b/.dotnet/src/Custom/Chat/ChatLogProbabilityCollection.cs new file mode 100644 index 000000000..bc63dbbd6 --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatLogProbabilityCollection.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace OpenAI.Chat; + +/// +/// Represents a collection of log probability result information as requested via +/// . +/// +public class ChatLogProbabilityCollection : ReadOnlyCollection +{ + internal ChatLogProbabilityCollection(IList list) : base(list) { } + internal static ChatLogProbabilityCollection FromInternalData( + Internal.Models.CreateChatCompletionResponseChoiceLogprobs internalLogprobs) + { + if (internalLogprobs == null) + { + return null; + } + List logProbabilities = []; + foreach (Internal.Models.ChatCompletionTokenLogprob internalLogprob in internalLogprobs.Content) + { + List alternateLogProbabilities = null; + if (internalLogprob.TopLogprobs != null) + { + alternateLogProbabilities = []; + foreach (Internal.Models.ChatCompletionTokenLogprobTopLogprob internalTopLogprob in internalLogprob.TopLogprobs) + { + alternateLogProbabilities.Add(new( + internalLogprob.Token, + internalLogprob.Logprob, + internalLogprob.Bytes)); + } + } + logProbabilities.Add(new( + internalLogprob.Token, + internalLogprob.Logprob, + internalLogprob.Bytes, + alternateLogProbabilities)); + } + return new ChatLogProbabilityCollection(logProbabilities); + } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Chat/ChatLogProbabilityResult.cs b/.dotnet/src/Custom/Chat/ChatLogProbabilityResult.cs new file mode 100644 index 000000000..0520b3ecc --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatLogProbabilityResult.cs @@ -0,0 +1,43 @@ +namespace OpenAI.Chat; + +using System.Collections.Generic; +using System.Linq; + +/// +/// Represents a single token's log probability information, as requested via +/// . +/// +public class ChatLogProbabilityResult +{ + /// + /// The token for which this log probability information applies. + /// + public string Token { get; } + /// + /// The logprob for the token. + /// + public double LogProbability { get; } + /// + /// A list of integers representing the UTF-8 bytes representation of the token. Useful in instances where + /// characters are represented by multiple tokens and their byte representations must be combined to generate + /// the correct text representation. Can be null if there is no bytes representation for the token. + /// + public IReadOnlyList Utf8ByteValues { get; } + /// + /// List of the most likely tokens and their log probability at this token position. In rare cases, + /// there may be fewer than the number of requested top_logprobs returned, as supplied via + /// . + /// + public IReadOnlyList AlternateLogProbabilities { get; } + internal ChatLogProbabilityResult( + string token, + double logProbability, + IEnumerable byteValues, + IEnumerable alternateLogProbabilities) + { + Token = token; + LogProbability = logProbability; + Utf8ByteValues = byteValues.ToList(); + AlternateLogProbabilities = alternateLogProbabilities.ToList(); + } +} diff --git a/.dotnet/src/Custom/Chat/ChatLogProbabilityResultItem.cs b/.dotnet/src/Custom/Chat/ChatLogProbabilityResultItem.cs new file mode 100644 index 000000000..1bb2d45c1 --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatLogProbabilityResultItem.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; + +namespace OpenAI.Chat; + +/// +/// Represents a single item of log probability information as requested via +/// and +/// . +/// +public class ChatLogProbabilityResultItem +{ + /// + /// The token for which this log probability information applies. + /// + public string Token { get; } + /// + /// The logprob for the token. + /// + public double LogProbability { get; } + /// + /// A list of integers representing the UTF-8 bytes representation of the token. Useful in instances where + /// characters are represented by multiple tokens and their byte representations must be combined to generate + /// the correct text representation. Can be null if there is no bytes representation for the token. + /// + public IReadOnlyList Utf8ByteValues { get; } + /// + /// Creates a new instance of . + /// + protected ChatLogProbabilityResultItem() { } + /// + /// Creates a new instance of . + /// + /// The token represented by this item. + /// The logprob for the token. + /// The UTF8 byte value sequence representation for the token. + internal ChatLogProbabilityResultItem(string token, double logProbability, IEnumerable byteValues) + { + Token = token; + LogProbability = logProbability; + Utf8ByteValues = new List(byteValues); + } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Chat/ChatMessageContent.cs b/.dotnet/src/Custom/Chat/ChatMessageContent.cs new file mode 100644 index 000000000..a39fbf184 --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatMessageContent.cs @@ -0,0 +1,112 @@ +using System; + +namespace OpenAI.Chat; + +/// +/// Represents the common base type for a piece of message content used for chat completions. +/// +public partial class ChatMessageContent +{ + /// + /// The type of message content data, e.g. text or image, that this instance + /// represents. + /// + public ChatMessageContentKind ContentKind { get; } + + private object _contentValue; + private string _contentMediaTypeName; + + internal ChatMessageContent(object value, ChatMessageContentKind kind, string contentMediaTypeName = null) + { + _contentValue = value; + ContentKind = kind; + _contentMediaTypeName = contentMediaTypeName; + } + + /// + /// Creates a new instance of that encapsulates text content. + /// + /// The content for the new instance. + /// A new instance of . + public static ChatMessageContent CreateText(string text) => new(text, ChatMessageContentKind.Text); + + /// + /// Creates a new instance of that encapsulates image content obtained from + /// an internet location that will be accessible to the model when evaluating a message with this content. + /// + /// + /// An internet location pointing to an image. This must be accessible to the model. + /// + /// A new instance of . + public static ChatMessageContent CreateImage(Uri imageUri) => new(imageUri, ChatMessageContentKind.Image); + + /// + /// Creates a new instance of that encapsulates binary image content. + /// + /// The binary representation of the image content. + /// The media type name, e.g. image/png, for the image. + /// A new instance of . + public static ChatMessageContent CreateImage(BinaryData imageBytes, string mediaType) + => new(imageBytes, ChatMessageContentKind.Image, mediaType); + + /// + /// Provides the associated with a content item using + /// . + /// + /// + /// will infer from the content type and `ChatMessageContent` known to be text can typically + /// be treated like a string without calling this explicitly. + /// + /// The content string for the text content item. + /// The content does not support a text representation. + public string ToText() + => ContentKind switch + { + ChatMessageContentKind.Text => _contentValue?.ToString(), + _ => throw new InvalidOperationException( + $"{nameof(ToText)} conversion not supported for content kind: {ContentKind}"), + }; + + /// + /// Provides a associated with a content item. These URIs can refer to an internet location + /// accessible to the target model or can be base64-encoded data URIs. + /// + /// A URI representation of the content item. + /// The content does not support a URI representation. + public Uri ToUri() + => ContentKind switch + { + ChatMessageContentKind.Image => _contentValue switch + { + Uri imageUri => imageUri, + BinaryData imageData => new Uri($"data:{_contentMediaTypeName};base64,{Convert.ToBase64String(imageData.ToArray())}"), + _ => throw new InvalidOperationException( + $"Cannot convert underlying image data type '{_contentValue?.GetType()}' to a {nameof(Uri)}"), + }, + _ => throw new InvalidOperationException( + $"{nameof(ToText)} conversion not supported for content kind: {ContentKind}"), + }; + + /// + /// The implicit conversion operator that infers an equivalent instance from + /// a plain . + /// + /// The text for the message content. + public static implicit operator ChatMessageContent(string value) => CreateText(value); + + /// + /// An implicit operator allowing a content item to be treated as a string. + /// + /// + public static implicit operator string(ChatMessageContent content) => content.ToText(); + + /// + public override string ToString() + { + if (ContentKind == ChatMessageContentKind.Text) + { + return ToText(); + } + return base.ToString(); + } +} diff --git a/.dotnet/src/Custom/Chat/ChatMessageContentKind.cs b/.dotnet/src/Custom/Chat/ChatMessageContentKind.cs new file mode 100644 index 000000000..7fafc8889 --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatMessageContentKind.cs @@ -0,0 +1,19 @@ +namespace OpenAI.Chat; + +/// +/// Represents the possibles of underlying data for a chat message's content property. +/// +public enum ChatMessageContentKind +{ + /// + /// Plain text content, represented as a . + /// + Text, + /// + /// Image content, as used exclusively by gpt-4-vision-preview when providing an array of content items + /// into a chat completion request. + /// + Image, + // Audio, + // Video, +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Chat/ChatRequestAssistantMessage.cs b/.dotnet/src/Custom/Chat/ChatRequestAssistantMessage.cs new file mode 100644 index 000000000..ecfba14c7 --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatRequestAssistantMessage.cs @@ -0,0 +1,129 @@ +using System; +using System.ClientModel.Internal; + +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Text.Json; +using OpenAI.ClientShared.Internal; + +namespace OpenAI.Chat; + +/// +/// Represents a chat message of the assistant role as supplied to a chat completion request. As assistant +/// messages are originated by the model on responses, instances typically +/// represent chat history or example interactions to guide model behavior. +/// +public class ChatRequestAssistantMessage : ChatRequestMessage +{ + /// + /// An optional name associated with the assistant message. This is typically defined with a system + /// message and is used to differentiate between multiple participants of the same role. + /// + public string Name { get; set; } + /// + /// The tool_calls furnished by the model that are needed to continue the logical conversation across chat + /// completion requests. A instance corresponds to a supplied + /// instance and is resolved by providing a + /// that correlates via id to the item in tool_calls. + /// + public IReadOnlyList ToolCalls { get; } + /// + /// Deprecated in favor of tool_calls. + /// + /// The function_call furnished by the model that is needed to continue the logical conversation + /// across chat completion requests. A instance corresponds to a supplied + /// instance and is resolved by providing a + /// that correlates via name to the function_call. + /// + /// + public ChatFunctionCall FunctionCall { get; } + + // Assistant messages may present ONE OF: + // - Ordinary text content without tools or a function, in which case the content is required; + // - A list of tool calls, together with optional text content + // - A function call, together with optional text content + + /// + /// Creates a new instance of that represents ordinary text content and + /// does not feature tool or function calls. + /// + /// The text content of the message. + public ChatRequestAssistantMessage(string content) + : base(ChatRole.Assistant, content) + { } + + /// + /// Creates a new instance of that represents tool_calls that + /// were provided by the model. + /// + /// The tool_calls made by the model. + /// Optional text content associated with the message. + public ChatRequestAssistantMessage(IEnumerable toolCalls, string content = null) + : base(ChatRole.Assistant, content) + { + ToolCalls = new List(toolCalls); + } + + /// + /// Creates a new instance of that represents a function_call + /// (deprecated in favor of tool_calls) that was made by the model. + /// + /// The function_call made by the model. + /// Optional text content associated with the message. + public ChatRequestAssistantMessage(ChatFunctionCall functionCall, string content = null) + : base(ChatRole.Assistant, content) + { + FunctionCall = functionCall; + } + + /// + /// Creates a new instance of from a with + /// an assistant role response. + /// + /// + /// This constructor will copy the content, tool_calls, and function_call from a chat + /// completion response into a new assistant role request message. + /// + /// + /// The from which the conversation history request message should be created. + /// + /// + /// The role of the provided chat completion response was not . + /// + public ChatRequestAssistantMessage(ChatCompletion chatCompletion) + : base(ChatRole.Assistant, chatCompletion?.Content) + { + if (chatCompletion?.Role != ChatRole.Assistant) + { + throw new ArgumentException( + $"Can't instantiate a {nameof(ChatRequestAssistantMessage)} from a chat completion" + + $" with finish reason: {chatCompletion?.FinishReason}"); + } + ToolCalls = chatCompletion.ToolCalls; + FunctionCall = chatCompletion.FunctionCall; + } + + internal override void WriteDerivedAdditions(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + if (OptionalProperty.IsDefined(Name)) + { + writer.WriteString("name"u8, Name); + } + if (OptionalProperty.IsCollectionDefined(ToolCalls)) + { + writer.WritePropertyName("tool_calls"u8); + writer.WriteStartArray(); + foreach (ChatToolCall toolCall in ToolCalls) + { + (toolCall as IJsonModel).Write(writer, options); + } + writer.WriteEndArray(); + } + if (OptionalProperty.IsDefined(FunctionCall)) + { + writer.WritePropertyName("function_call"u8); + (FunctionCall as IJsonModel).Write(writer, options); + } + } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Chat/ChatRequestFunctionMessage.cs b/.dotnet/src/Custom/Chat/ChatRequestFunctionMessage.cs new file mode 100644 index 000000000..f1190771e --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatRequestFunctionMessage.cs @@ -0,0 +1,40 @@ +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Text.Json; + +namespace OpenAI.Chat; + +/// +/// Represents a chat message of the function role as provided to a chat completion request. A function message +/// resolves a prior function_call received from the model and correlates to both a supplied +/// instance as well as a made by the model on an +/// assistant response message. +/// +public class ChatRequestFunctionMessage : ChatRequestMessage +{ + /// + /// The name of the called function that this message provides information from. + /// + public string FunctionName { get; set; } // JSON "name" + + /// + /// Creates a new instance of . + /// + /// + /// The name of the called function that this message provides information from. + /// + /// + /// The textual content that represents the output or result from the called function. There is no format + /// restriction (e.g. JSON) imposed on this content. + /// + public ChatRequestFunctionMessage(string functionName, string content) + : base(ChatRole.Function, content) + { + FunctionName = functionName; + } + + internal override void WriteDerivedAdditions(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + writer.WriteString("name"u8, FunctionName); + } +} diff --git a/.dotnet/src/Custom/Chat/ChatRequestMessage.Serialization.cs b/.dotnet/src/Custom/Chat/ChatRequestMessage.Serialization.cs new file mode 100644 index 000000000..0cf026fd9 --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatRequestMessage.Serialization.cs @@ -0,0 +1,94 @@ +using System; +using System.ClientModel.Internal; + +using System.ClientModel; +using System.ClientModel.Primitives; +using System.ComponentModel.Design; +using System.Text.Json; +using OpenAI.ClientShared.Internal; + +namespace OpenAI.Chat; + +public abstract partial class ChatRequestMessage : IJsonModel +{ + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + writer.WriteStartObject(); + writer.WriteString("role"u8, Role switch + { + ChatRole.System => "system", + ChatRole.User => "user", + ChatRole.Assistant => "assistant", + ChatRole.Tool => "tool", + ChatRole.Function => "function", + _ => throw new ArgumentException(nameof(Role)) + }); + if (OptionalProperty.IsDefined(Content)) + { + writer.WritePropertyName("content"u8); + if (Content.Span.Length == 0) + { + writer.WriteNullValue(); + } + else if (Content.Span.Length == 1) + { + if (Content.Span[0].ContentKind == ChatMessageContentKind.Text) + { + writer.WriteStringValue(Content.Span[0].ToText()); + } + else + { + throw new InvalidOperationException(); + } + } + else if (Content.Span.Length > 1) + { + writer.WriteStartArray(); + foreach (ChatMessageContent contentItem in Content.Span) + { + writer.WriteStartObject(); + if (contentItem.ContentKind == ChatMessageContentKind.Text) + { + writer.WriteString("type"u8, "text"u8); + writer.WriteString("text"u8, contentItem.ToText()); + } + else if (contentItem.ContentKind == ChatMessageContentKind.Image) + { + writer.WriteString("type"u8, "image_url"u8); + writer.WritePropertyName("image_url"u8); + writer.WriteStartObject(); + writer.WriteString("url"u8, contentItem.ToUri().AbsoluteUri); + writer.WriteEndObject(); + } + else + { + throw new InvalidOperationException(); + } + writer.WriteEndObject(); + } + writer.WriteEndArray(); + } + } + WriteDerivedAdditions(writer, options); + writer.WriteEndObject(); + } + + ChatRequestMessage IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + throw new NotImplementedException(); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + throw new NotImplementedException(); + } + + ChatRequestMessage IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + throw new NotImplementedException(); + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + internal abstract void WriteDerivedAdditions(Utf8JsonWriter writer, ModelReaderWriterOptions options); +} diff --git a/.dotnet/src/Custom/Chat/ChatRequestMessage.cs b/.dotnet/src/Custom/Chat/ChatRequestMessage.cs new file mode 100644 index 000000000..38444eb4e --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatRequestMessage.cs @@ -0,0 +1,108 @@ +using System; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Collections; +using System.Collections.Generic; + +namespace OpenAI.Chat; + +/// +/// A common, base representation of a message provided as input into a chat completion request. +/// +/// +/// +/// +/// Type - +/// Role - +/// Description +/// +/// +/// - +/// system - +/// Instructions to the model that guide the behavior of future assistant messages. +/// +/// +/// - +/// user - +/// Input messages from the caller, typically paired with assistant messages in a conversation. +/// +/// +/// - +/// assistant - +/// +/// Output messages from the model with responses to the user or calls to tools or functions that are +/// needed to continue the logical conversation. +/// +/// +/// +/// - +/// tool - +/// +/// Resolution information for a in an earlier +/// that was made against a supplied +/// . +/// +/// +/// +/// - +/// function - +/// +/// Resolution information for a in an earlier +/// that was made against a supplied +/// . Note that functions are deprecated in favor of +/// tool_calls. +/// +/// +/// +/// +public abstract partial class ChatRequestMessage +{ + /// + /// The role associated with the message. + /// + public ChatRole Role { get; } + + /// + /// The content associated with the message. The interpretation of this content will vary depending on the message type. + /// + public ReadOnlyMemory Content => _contentItems.AsMemory(); + private readonly ChatMessageContent[] _contentItems; + + internal ChatRequestMessage(ChatRole role, ChatMessageContent content) + : this(role, [content]) + { } + + internal ChatRequestMessage(ChatRole role, ChatMessageContent[] content) + { + Role = role; + _contentItems = content; + } + + /// + public static ChatRequestSystemMessage CreateSystemMessage(string content) + => new ChatRequestSystemMessage(content); + + /// + public static ChatRequestUserMessage CreateUserMessage(string content) + => new ChatRequestUserMessage(content); + + /// + public static ChatRequestUserMessage CreateUserMessage(IEnumerable contentItems) + => new ChatRequestUserMessage(contentItems); + + /// + public static ChatRequestUserMessage CreateUserMessage(params ChatMessageContent[] contentItems) + => new ChatRequestUserMessage(contentItems); + + /// + public static ChatRequestAssistantMessage CreateAssistantMessage(string content) + => new ChatRequestAssistantMessage(content); + + /// + public static ChatRequestToolMessage CreateToolMessage(string toolCallId, string content) + => new ChatRequestToolMessage(toolCallId, content); + + /// + public static ChatRequestFunctionMessage CreateFunctionMessage(string toolCallId, string content) + => new ChatRequestFunctionMessage(toolCallId, content); +} diff --git a/.dotnet/src/Custom/Chat/ChatRequestSystemMessage.cs b/.dotnet/src/Custom/Chat/ChatRequestSystemMessage.cs new file mode 100644 index 000000000..d391aad3b --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatRequestSystemMessage.cs @@ -0,0 +1,39 @@ +using System; +using System.ClientModel.Internal; + +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Dynamic; +using System.Runtime.InteropServices; +using System.Text.Json; +using OpenAI.ClientShared.Internal; + +namespace OpenAI.Chat; + +/// +/// Represents a chat message of the system role as supplied to a chat completion request. A system message is +/// generally supplied as the first message to a chat completion request and guides the model's behavior across future +/// assistant role response messages. These messages may help control behavior, style, tone, and +/// restrictions for a model-based assistant. +/// +public class ChatRequestSystemMessage : ChatRequestMessage +{ + /// + /// An optional name for the participant. + /// + public string Name { get; set; } // JSON "name" + + /// + /// Creates a new instance of . + /// + /// The system message text that guides the model's behavior. + public ChatRequestSystemMessage(string content) : base(ChatRole.System, content) { } + + internal override void WriteDerivedAdditions(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + if (OptionalProperty.IsDefined(Name)) + { + writer.WriteString("name"u8, Name); + } + } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Chat/ChatRequestToolMessage.cs b/.dotnet/src/Custom/Chat/ChatRequestToolMessage.cs new file mode 100644 index 000000000..7ec17eea5 --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatRequestToolMessage.cs @@ -0,0 +1,53 @@ +using System; +using System.ClientModel.Internal; + +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Text.Json; + +namespace OpenAI.Chat; + +/// +/// Represents a chat message of the tool role as supplied to a chat completion request. A tool message +/// encapsulates a resolution of a made by the model. The typical interaction flow featuring +/// tool messages is: +/// +/// A provides a on a request; +/// +/// Based on the name and description information of provided tools, the model responds with one or +/// more instances that need to be resolved to continue the logical conversation; +/// +/// +/// For each , the matching tool is invoked and its output is supplied back to the model +/// via a to resolve the tool call and allow the logical conversation to +/// continue. +/// +/// +/// +public class ChatRequestToolMessage : ChatRequestMessage +{ + /// + /// The id correlating to the prior made by the model. + /// + public string ToolCallId { get; set; } + + /// + /// Creates a new instance of . + /// + /// The id correlating to a made by the model. + /// + /// The textual content, produced by the defined tool in response to the correlated , + /// that resolves the tool call and allows the logical conversation to continue. No format restrictions (e.g. + /// JSON) are imposed on the content emitted by tools. + /// + public ChatRequestToolMessage(string toolCallId, string content) + : base(ChatRole.Tool, content) + { + ToolCallId = toolCallId; + } + + internal override void WriteDerivedAdditions(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + writer.WriteString("tool_call_id"u8, ToolCallId); + } +} diff --git a/.dotnet/src/Custom/Chat/ChatRequestUserMessage.cs b/.dotnet/src/Custom/Chat/ChatRequestUserMessage.cs new file mode 100644 index 000000000..f1e7a3588 --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatRequestUserMessage.cs @@ -0,0 +1,65 @@ +using System.ClientModel.Internal; + +using System; +using System.Collections.Generic; +using System.Dynamic; +using System.Text.Json; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Linq; +using OpenAI.ClientShared.Internal; + +namespace OpenAI.Chat; + +/// +/// Represents a chat message of the user role as supplied to a chat completion request. A user message contains +/// information originating from the caller and serves as a prompt for the model to complete. User messages may result +/// in either direct assistant message responses or in calls to supplied tools or functions. +/// +public class ChatRequestUserMessage : ChatRequestMessage +{ + /// + /// An optional name for the participant. + /// + public string Name { get; set; } + + /// + /// Creates a new instance of with ordinary text content. + /// + /// The textual content associated with the message. + public ChatRequestUserMessage(string content) + : base(ChatRole.User, ChatMessageContent.CreateText(content)) + { } + + /// + /// Creates a new instance of using a collection of content items that can + /// include text and image information. This content format is currently only applicable to the + /// gpt-4-vision-preview model and will not be accepted by other models. + /// + /// + /// The collection of text and image content items associated with the message. + /// + public ChatRequestUserMessage(IEnumerable contentItems) + : base(ChatRole.User, contentItems.ToArray()) + { } + + /// + /// Creates a new instance of using a collection of content items that can + /// include text and image information. This content format is currently only applicable to the + /// gpt-4-vision-preview model and will not be accepted by other models. + /// + /// + /// The collection of text and image content items associated with the message. + /// + public ChatRequestUserMessage(params ChatMessageContent[] contentItems) + : this(contentItems as IEnumerable) + { } + + internal override void WriteDerivedAdditions(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + if (OptionalProperty.IsDefined(Name)) + { + writer.WriteString("name"u8, Name); + } + } +} diff --git a/.dotnet/src/Custom/Chat/ChatResponseFormat.cs b/.dotnet/src/Custom/Chat/ChatResponseFormat.cs new file mode 100644 index 000000000..b7d539655 --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatResponseFormat.cs @@ -0,0 +1,44 @@ +using System; + +namespace OpenAI.Chat; + +/// +/// Represents a requested response_format for the model to use, enabling "JSON mode" for guaranteed valid output. +/// +/// +/// Important: when using JSON mode, the model must also be instructed to produce JSON via a +/// system or user message. +/// +/// Without this paired, message-based accompaniment, 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 is length, which +/// indicates that the generation exceeded max_tokens or the conversation exceeded the max context length for +/// the model. +/// +/// +public enum ChatResponseFormat +{ + /// + /// Specifies that the model should provide plain, textual output. + /// + Text, + /// + /// Specifies that the model should enable "JSON mode" and better guarantee the emission of valid JSON. + /// + /// + /// Important: when using JSON mode, the model must also be instructed to produce JSON via a + /// system or user message. + /// + /// Without this paired, message-based accompaniment, 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 is length, which + /// indicates that the generation exceeded max_tokens or the conversation exceeded the max context length for + /// the model. + /// + /// + JsonObject, +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Chat/ChatRole.cs b/.dotnet/src/Custom/Chat/ChatRole.cs new file mode 100644 index 000000000..724baa74f --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatRole.cs @@ -0,0 +1,85 @@ +namespace OpenAI.Chat; + +/// +/// Represents the role of a chat completion message. +/// +/// +/// +/// +/// Type - +/// Role - +/// Description +/// +/// +/// - +/// system - +/// Instructions to the model that guide the behavior of future assistant messages. +/// +/// +/// - +/// user - +/// Input messages from the caller, typically paired with assistant messages in a conversation. +/// +/// +/// - +/// assistant - +/// +/// Output messages from the model with responses to the user or calls to tools or functions that are +/// needed to continue the logical conversation. +/// +/// +/// +/// - +/// tool - +/// +/// Resolution information for a in an earlier +/// that was made against a supplied +/// . +/// +/// +/// +/// - +/// function - +/// +/// Resolution information for a in an earlier +/// that was made against a supplied +/// . Note that functions are deprecated in favor of +/// tool_calls. +/// +/// +/// +/// +public enum ChatRole +{ + /// + /// The system role, which provides instructions to the model that guide the behavior of future + /// assistant messages + /// + System, + /// + /// The assistant role that provides output from the model that either issues completions in response to + /// user messages or calls provided tools or functions. + /// + Assistant, + /// + /// The user role that provides input from the caller as a prompt for model responses. + /// + User, + /// + /// The tool role that provides resolving information to prior tool_calls made by the model against + /// supplied tools. + /// + Tool, + /// + /// + /// The function role that provides resolving information to a prior function_call made by the model + /// against a definition supplied in functions. + /// + /// + /// + /// functions are deprecated in favor of tools and supplying tools will result in + /// tool_calls that must be resolved via the tool role rather than a function_call resolved + /// by a function role message. + /// + Function, +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Chat/ChatTokenUsage.cs b/.dotnet/src/Custom/Chat/ChatTokenUsage.cs new file mode 100644 index 000000000..699af8453 --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatTokenUsage.cs @@ -0,0 +1,21 @@ +namespace OpenAI.Chat; + +/// +/// Represents computed token consumption statistics for a chat completion request. +/// +public class ChatTokenUsage +{ + /// + public long InputTokens { get; } + /// + public long OutputTokens { get; } + /// + public long TotalTokens { get; } + + internal ChatTokenUsage(Internal.Models.CompletionUsage internalUsage) + { + InputTokens = internalUsage.PromptTokens; + OutputTokens = internalUsage.CompletionTokens; + TotalTokens = internalUsage.TotalTokens; + } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Chat/ChatToolCall.Serialization.cs b/.dotnet/src/Custom/Chat/ChatToolCall.Serialization.cs new file mode 100644 index 000000000..eff6eec3c --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatToolCall.Serialization.cs @@ -0,0 +1,38 @@ +using System; +using System.ClientModel.Internal; + +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Text.Json; + +namespace OpenAI.Chat; + +public abstract partial class ChatToolCall : IJsonModel +{ + ChatToolCall IJsonModel.Create(ref Utf8JsonReader reader, ModelReaderWriterOptions options) + { + throw new NotImplementedException(); + } + + ChatToolCall IPersistableModel.Create(BinaryData data, ModelReaderWriterOptions options) + { + throw new NotImplementedException(); + } + + string IPersistableModel.GetFormatFromOptions(ModelReaderWriterOptions options) => "J"; + + void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) + { + writer.WriteStartObject(); + writer.WriteString("id"u8, Id); + WriteDerivedAdditions(writer, options); + writer.WriteEndObject(); + } + + BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) + { + throw new NotImplementedException(); + } + + internal abstract void WriteDerivedAdditions(Utf8JsonWriter writer, ModelReaderWriterOptions options); +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Chat/ChatToolCall.cs b/.dotnet/src/Custom/Chat/ChatToolCall.cs new file mode 100644 index 000000000..9203f4b01 --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatToolCall.cs @@ -0,0 +1,15 @@ +namespace OpenAI.Chat; + +/// +/// A base representation of an item in an assistant role response's tool_calls that specifies +/// parameterized resolution against a previously defined tool that is needed for the model to continue the logical +/// conversation. +/// +public abstract partial class ChatToolCall +{ + /// + /// A unique identifier associated with the tool call, used in a subsequent to + /// resolve the tool call and continue the logical conversation. + /// + public required string Id { get; set; } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Chat/ChatToolConstraint.cs b/.dotnet/src/Custom/Chat/ChatToolConstraint.cs new file mode 100644 index 000000000..15622b5be --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatToolConstraint.cs @@ -0,0 +1,87 @@ +using System; + +namespace OpenAI.Chat; + +/// +/// Represents tool_choice, the desired manner in which the model should use the tools defined in a +/// chat completion request. +/// +public readonly struct ChatToolConstraint : IEquatable +{ + private enum ToolConstraintKind + { + Predefined, + Function, + } + + private readonly ToolConstraintKind _constraintKind; + private readonly BinaryData _serializableData; + + /// + /// Creates a new instance of which requests that the model restricts its behavior + /// to calling the specified tool. + /// + /// The definition of the tool that the model should call. + /// + /// tool_choice uses the name of a tool of the function type as the correlation field, so + /// instantiating a new instance of with the desired name is + /// sufficient if the matching instance is not available. + /// + public ChatToolConstraint(ChatToolDefinition toolDefinition) + { + if (toolDefinition is ChatFunctionToolDefinition functionToolDefinition) + { + _constraintKind = ToolConstraintKind.Function; + _serializableData = BinaryData.FromObjectAsJson(new + { + type = "function", + function = new + { + name = functionToolDefinition.Name, + } + }); + } + else + { + throw new ArgumentException( + $"Unsupported {nameof(toolDefinition)} type for 'tool_choice' constraint: {toolDefinition.GetType()}"); + } + } + + internal ChatToolConstraint(string predefinedLabel) + { + _constraintKind = ToolConstraintKind.Predefined; + _serializableData = BinaryData.FromString($@"""{predefinedLabel}"""); + } + + /// + /// auto specifies that the model should freely call any combination of the provided tools, including + /// the option to not invoke any tools and issue an ordinary response. + /// + public static ChatToolConstraint Auto { get; } = new("auto"); + /// + /// none specifies that the model should not invoke any of the provided tools and instead force an + /// ordinary assistant response. Note that provided tool definitions may still influence the behavior of + /// chat completions even when tools are not called. + /// + public static ChatToolConstraint None { get; } = new("none"); + /// + public static bool operator ==(ChatToolConstraint left, ChatToolConstraint right) + => left._serializableData?.ToString() == right._serializableData?.ToString(); + /// + public static bool operator !=(ChatToolConstraint left, ChatToolConstraint right) + => left._serializableData?.ToString() != right._serializableData?.ToString(); + /// + public bool Equals(ChatToolConstraint other) + => (_serializableData == null && other._serializableData == null) + || (_serializableData.ToString().Equals(other._serializableData.ToString())); + /// + public override string ToString() => _serializableData?.ToString(); + /// + public override bool Equals(object obj) + => obj is ChatToolConstraint constraint && constraint.Equals(this); + /// + public override int GetHashCode() => $"{_serializableData?.ToString()}".GetHashCode(); + + internal BinaryData GetBinaryData() => _serializableData; +} diff --git a/.dotnet/src/Custom/Chat/ChatToolDefinition.cs b/.dotnet/src/Custom/Chat/ChatToolDefinition.cs new file mode 100644 index 000000000..d116ac460 --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatToolDefinition.cs @@ -0,0 +1,11 @@ +namespace OpenAI.Chat; + +/// +/// A base representation of a tool supplied to a chat completion request. Tools inform the model about additional, +/// caller-provided behaviors that can be invoked to provide prompt enrichment or custom actions. +/// +/// +/// Chat completion currently supports function tools via . +/// +public abstract class ChatToolDefinition +{ } diff --git a/.dotnet/src/Custom/Chat/StreamingChatUpdate.cs b/.dotnet/src/Custom/Chat/StreamingChatUpdate.cs new file mode 100644 index 000000000..c1540897b --- /dev/null +++ b/.dotnet/src/Custom/Chat/StreamingChatUpdate.cs @@ -0,0 +1,336 @@ +namespace OpenAI.Chat; + +using System; +using System.Collections.Generic; +using System.Text.Json; + +/// +/// Represents an incremental item of new data in a streaming response to a chat completion request. +/// +public partial class StreamingChatUpdate +{ + /// + /// Gets a unique identifier associated with this streamed Chat Completions response. + /// + /// + /// + /// Corresponds to $.id in the underlying REST schema. + /// + /// When using Azure OpenAI, note that the values of and may not be + /// populated until the first containing role, content, or + /// function information. + /// + public string Id { get; } + + /// + /// Gets the first timestamp associated with generation activity for this completions response, + /// represented as seconds since the beginning of the Unix epoch of 00:00 on 1 Jan 1970. + /// + /// + /// + /// Corresponds to $.created in the underlying REST schema. + /// + /// When using Azure OpenAI, note that the values of and may not be + /// populated until the first containing role, content, or + /// function information. + /// + public DateTimeOffset? Created { get; } + + /// + /// Gets the associated with this update. + /// + /// + /// + /// Corresponds to e.g. $.choices[0].delta.role in the underlying REST schema. + /// + /// assignment typically occurs in a single update across a streamed Chat Completions + /// choice and the value should be considered to be persist for all subsequent updates without a + /// that bear the same . + /// + public ChatRole? Role { get; } + + /// + /// Gets the content fragment associated with this update. + /// + /// + /// + /// Corresponds to e.g. $.choices[0].delta.content in the underlying REST schema. + /// + /// Each update contains only a small number of tokens. When presenting or reconstituting a full, streamed + /// response, all values for the same should be + /// combined. + /// + public string ContentUpdate { get; } + + /// + /// Gets the name of a function to be called. + /// + /// + /// Corresponds to e.g. $.choices[0].delta.function_call.name in the underlying REST schema. + /// + public string FunctionName { get; } + + /// + /// Gets a function arguments fragment associated with this update. + /// + /// + /// + /// Corresponds to e.g. $.choices[0].delta.function_call.arguments in the underlying REST schema. + /// + /// + /// + /// Each update contains only a small number of tokens. When presenting or reconstituting a full, streamed + /// arguments body, all values for the same + /// should be combined. + /// + /// + /// + /// As is the case for non-streaming , the content provided for function + /// arguments is not guaranteed to be well-formed JSON or to contain expected data. Callers should validate + /// function arguments before using them. + /// + /// + public string FunctionArgumentsUpdate { get; } + + /// + /// An incremental update payload for a tool call that is part of this response. + /// + /// + /// + /// Corresponds to e.g. $.choices[0].delta.tool_calls[0].index in the REST API schema. + /// + /// + /// To differentiate between parallel streaming tool calls within a single streaming choice, use the value of the + /// property. + /// + /// + /// Please note is the base class. According to the scenario, a derived class + /// of the base class might need to be assigned here, or this property needs to be casted to one of the possible + /// derived classes. + /// The available derived classes include: . + /// + /// + public StreamingToolCallUpdate ToolCallUpdate { get; } + + /// + /// Gets the associated with this update. + /// + /// + /// + /// Corresponds to e.g. $.choices[0].finish_reason in the underlying REST schema. + /// + /// + /// assignment typically appears in the final streamed update message associated + /// with a choice. + /// + /// + public ChatFinishReason? FinishReason { get; } + + /// + /// Gets the choice index associated with this streamed update. + /// + /// + /// + /// Corresponds to e.g. $.choices[0].index in the underlying REST schema. + /// + /// + /// Unless a value greater than 1 was provided as the choiceCount to + /// , + /// only one choice will be generated. In that case, this value will always be 0 and may not need to be considered. + /// + /// + /// When a value greater than 1 to that choiceCount is provided, this index represents + /// which logical choice the information is associated with. In the event + /// that a single underlying server-sent event contains multiple choices, multiple instances of + /// will be created. + /// + /// + public int? ChoiceIndex { get; } + + /// + public string SystemFingerprint { get; } + + /// + /// The log probability information for choices in the chat completion response, as requested via + /// . + /// + public ChatLogProbabilityCollection LogProbabilities { get; } + + internal StreamingChatUpdate( + string id, + DateTimeOffset created, + string systemFingerprint = null, + int? choiceIndex = null, + ChatRole? role = null, + string contentUpdate = null, + ChatFinishReason? finishReason = null, + string functionName = null, + string functionArgumentsUpdate = null, + StreamingToolCallUpdate toolCallUpdate = null, + ChatLogProbabilityCollection logProbabilities = null) + { + Id = id; + Created = created; + SystemFingerprint = systemFingerprint; + ChoiceIndex = choiceIndex; + Role = role; + ContentUpdate = contentUpdate; + FinishReason = finishReason; + FunctionName = functionName; + FunctionArgumentsUpdate = functionArgumentsUpdate; + ToolCallUpdate = toolCallUpdate; + LogProbabilities = logProbabilities; + } + + internal static List DeserializeStreamingChatUpdates(JsonElement element) + { + List results = []; + if (element.ValueKind == JsonValueKind.Null) + { + return results; + } + string id = default; + DateTimeOffset created = default; + string systemFingerprint = null; + foreach (JsonProperty property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetString(); + continue; + } + if (property.NameEquals("created"u8)) + { + created = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); + continue; + } + if (property.NameEquals("system_fingerprint")) + { + systemFingerprint = property.Value.GetString(); + continue; + } + if (property.NameEquals("choices"u8)) + { + foreach (JsonElement choiceElement in property.Value.EnumerateArray()) + { + ChatRole? role = null; + string contentUpdate = null; + string functionName = null; + string functionArgumentsUpdate = null; + int choiceIndex = 0; + ChatFinishReason? finishReason = null; + List toolCallUpdates = []; + ChatLogProbabilityCollection logProbabilities = null; + + foreach (JsonProperty choiceProperty in choiceElement.EnumerateObject()) + { + if (choiceProperty.NameEquals("index"u8)) + { + choiceIndex = choiceProperty.Value.GetInt32(); + continue; + } + if (choiceProperty.NameEquals("finish_reason"u8)) + { + if (choiceProperty.Value.ValueKind == JsonValueKind.Null) + { + finishReason = null; + continue; + } + finishReason = choiceProperty.Value.GetString() switch + { + "stop" => ChatFinishReason.Stopped, + "length" => ChatFinishReason.Length, + "tool_calls" => ChatFinishReason.ToolCalls, + "function_call" => ChatFinishReason.FunctionCall, + "content_filter" => ChatFinishReason.ContentFilter, + _ => throw new ArgumentException(nameof(finishReason)), + }; + continue; + } + if (choiceProperty.NameEquals("delta"u8)) + { + foreach (JsonProperty deltaProperty in choiceProperty.Value.EnumerateObject()) + { + if (deltaProperty.NameEquals("role"u8)) + { + role = deltaProperty.Value.GetString() switch + { + "system" => ChatRole.System, + "user" => ChatRole.User, + "assistant" => ChatRole.Assistant, + "tool" => ChatRole.Tool, + "function" => ChatRole.Function, + _ => throw new ArgumentException(nameof(role)), + }; + continue; + } + if (deltaProperty.NameEquals("content"u8)) + { + contentUpdate = deltaProperty.Value.GetString(); + continue; + } + if (deltaProperty.NameEquals("function_call"u8)) + { + foreach (JsonProperty functionProperty in deltaProperty.Value.EnumerateObject()) + { + if (functionProperty.NameEquals("name"u8)) + { + functionName = functionProperty.Value.GetString(); + continue; + } + if (functionProperty.NameEquals("arguments"u8)) + { + functionArgumentsUpdate = functionProperty.Value.GetString(); + } + } + } + if (deltaProperty.NameEquals("tool_calls")) + { + foreach (JsonElement toolCallElement in deltaProperty.Value.EnumerateArray()) + { + toolCallUpdates.Add( + StreamingToolCallUpdate.DeserializeStreamingToolCallUpdate(toolCallElement)); + } + } + } + } + if (choiceProperty.NameEquals("logprobs"u8)) + { + Internal.Models.CreateChatCompletionResponseChoiceLogprobs internalLogprobs + = Internal.Models.CreateChatCompletionResponseChoiceLogprobs.DeserializeCreateChatCompletionResponseChoiceLogprobs( + choiceProperty.Value); + logProbabilities = ChatLogProbabilityCollection.FromInternalData(internalLogprobs); + } + } + // In the unlikely event that more than one tool call arrives on a single chunk, we'll generate + // separate updates just like for choices. Adding a "null" if empty lets us avoid a separate loop. + if (toolCallUpdates.Count == 0) + { + toolCallUpdates.Add(null); + } + foreach (StreamingToolCallUpdate toolCallUpdate in toolCallUpdates) + { + results.Add(new StreamingChatUpdate( + id, + created, + systemFingerprint, + choiceIndex, + role, + contentUpdate, + finishReason, + functionName, + functionArgumentsUpdate, + toolCallUpdate, + logProbabilities)); + } + } + continue; + } + } + if (results.Count == 0) + { + results.Add(new StreamingChatUpdate(id, created, systemFingerprint)); + } + return results; + } +} diff --git a/.dotnet/src/Custom/Chat/StreamingFunctionToolCallUpdate.cs b/.dotnet/src/Custom/Chat/StreamingFunctionToolCallUpdate.cs new file mode 100644 index 000000000..bbae5e5c4 --- /dev/null +++ b/.dotnet/src/Custom/Chat/StreamingFunctionToolCallUpdate.cs @@ -0,0 +1,90 @@ +namespace OpenAI.Chat; +using System.Text.Json; + +/// +/// Represents an incremental update to a streaming function tool call that is part of a streaming chat completions +/// choice. +/// +public partial class StreamingFunctionToolCallUpdate : StreamingToolCallUpdate +{ + /// + /// The name of the function requested by the tool call. + /// + /// + /// + /// Corresponds to e.g. $.choices[0].delta.tool_calls[0].function.name in the REST API schema. + /// + /// + /// For a streaming function tool call, this name will appear in a single streaming update payload, typically the + /// first. Use the property to differentiate between multiple, + /// parallel tool calls when streaming. + /// + /// + public string Name { get; } + + /// + /// The next new segment of the function arguments for the function tool called by a streaming tool call. + /// These must be accumulated for the complete contents of the function arguments. + /// + /// + /// + /// Corresponds to e.g. $.choices[0].delta.tool_calls[0].function.arguments in the REST API schema. + /// + /// Note that the model does not always generate valid JSON and may hallucinate parameters + /// not defined by your function schema. Validate the arguments in your code before calling + /// your function. + /// + public string ArgumentsUpdate { get; } + + internal StreamingFunctionToolCallUpdate( + string id, + int toolCallIndex, + string functionName, + string functionArgumentsUpdate) + : base("function", id, toolCallIndex) + { + Name = functionName; + ArgumentsUpdate = functionArgumentsUpdate; + } + + internal static StreamingFunctionToolCallUpdate DeserializeStreamingFunctionToolCallUpdate(JsonElement element) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + + string id = null; + int toolCallIndex = 0; + string functionName = null; + string functionArgumentsUpdate = null; + + foreach (JsonProperty property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetString(); + } + if (property.NameEquals("index"u8)) + { + toolCallIndex = property.Value.GetInt32(); + } + if (property.NameEquals("function"u8)) + { + foreach (JsonProperty functionProperty in property.Value.EnumerateObject()) + { + if (functionProperty.NameEquals("name"u8)) + { + functionName = functionProperty.Value.GetString(); + } + if (functionProperty.NameEquals("arguments"u8)) + { + functionArgumentsUpdate = functionProperty.Value.GetString(); + } + } + } + } + + return new StreamingFunctionToolCallUpdate(id, toolCallIndex, functionName, functionArgumentsUpdate); + } +} diff --git a/.dotnet/src/Custom/Chat/StreamingToolCallUpdate.cs b/.dotnet/src/Custom/Chat/StreamingToolCallUpdate.cs new file mode 100644 index 000000000..ce9fc9b56 --- /dev/null +++ b/.dotnet/src/Custom/Chat/StreamingToolCallUpdate.cs @@ -0,0 +1,97 @@ +namespace OpenAI.Chat; +using System.Text.Json; + +/// +/// A base representation of an incremental update to a streaming tool call that is part of a streaming chat completion +/// request. +/// +/// +/// +/// This type encapsulates the payload located in e.g. $.choices[0].delta.tool_calls[] in the REST API schema. +/// +/// +/// To differentiate between parallel streaming tool calls within a single streaming choice, use the value of the +/// property. +/// +/// +/// is the streaming, base class counterpart to . +/// Currently, chat completion supports function tools and the derived +/// type will provide required information about the matching function +/// tool call. +/// +/// +public abstract partial class StreamingToolCallUpdate +{ + /// + /// Gets the ID associated with with the streaming tool call. + /// + /// + /// + /// Corresponds to e.g. $.choices[0].delta.tool_calls[0].id in the REST API schema. + /// + /// + /// This value appears once for each streaming tool call, typically on the first update message for each + /// . Callers should retain the value when it arrives to accumulate the complete tool + /// call information. + /// + /// + /// Tool call IDs must be provided in instances that respond to tool calls. + /// + /// + public string Id { get; } + + /// + /// Gets the tool call index associated with this . + /// + /// + /// + /// Corresponds to e.g. $.choices[0].delta.tool_calls[0].index in the REST API schema. + /// + /// + /// This value appears on every streaming tool call update. When multiple tool calls occur within the same + /// streaming chat choice, this index specifies which tool call that this update contains new information for. + /// + /// + public int ToolCallIndex { get; } + + internal string Type { get; } + + internal StreamingToolCallUpdate(string type, string id, int toolCallIndex) + { + Type = type; + Id = id; + ToolCallIndex = toolCallIndex; + } + + internal static StreamingToolCallUpdate DeserializeStreamingToolCallUpdate(JsonElement element) + { + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + foreach (JsonProperty property in element.EnumerateObject()) + { + // CUSTOM CODE NOTE: + // "type" is superficially the JSON discriminator for possible tool call categories, but it does not + // appear on every streamed delta message. To account for this without maintaining state, we instead + // allow the deserialization to infer the type based on the presence of the named/typed key. This is + // consistent across all existing patterns of the form: + // { + // "type": "" + // "": { ... } + // } + if (property.NameEquals("type"u8)) + { + if (property.Value.GetString() == "function") + { + return StreamingFunctionToolCallUpdate.DeserializeStreamingFunctionToolCallUpdate(element); + } + } + else if (property.NameEquals("function"u8)) + { + return StreamingFunctionToolCallUpdate.DeserializeStreamingFunctionToolCallUpdate(element); + } + } + return null; + } +} diff --git a/.dotnet/src/Custom/Embeddings/Embedding.cs b/.dotnet/src/Custom/Embeddings/Embedding.cs new file mode 100644 index 000000000..9b206204d --- /dev/null +++ b/.dotnet/src/Custom/Embeddings/Embedding.cs @@ -0,0 +1,44 @@ +using System; + +namespace OpenAI.Embeddings; + +/// +/// Represents an embedding vector returned by embedding endpoint. +/// +public partial class Embedding +{ + /// + /// The embedding vector, which is a list of floats. + /// + public ReadOnlyMemory Vector { get; } + /// + public long Index { get; } + /// + public string Model { get; } + /// + public EmbeddingTokenUsage Usage { get; } + + internal Embedding(ReadOnlyMemory vector, long index, EmbeddingTokenUsage usage) + { + Vector = vector; + Index = index; + Usage = usage; + } + + internal Embedding( + Internal.Models.CreateEmbeddingResponse internalResponse, + long internalDataIndex, + EmbeddingTokenUsage usage = null) + { + Internal.Models.Embedding dataItem = internalResponse.Data[(int)internalDataIndex]; + string dataItemBase64 = dataItem.EmbeddingProperty.ToString(); + dataItemBase64 = dataItemBase64.Substring(1, dataItemBase64.Length - 2); + byte[] bytes = Convert.FromBase64String(dataItemBase64); + float[] vector = new float[bytes.Length / sizeof(float)]; + Buffer.BlockCopy(bytes, 0, vector, 0, bytes.Length); + Vector = new ReadOnlyMemory(vector); + Index = dataItem.Index; + Usage = usage ?? new(internalResponse.Usage); + Model = internalResponse.Model; + } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Embeddings/EmbeddingClient.cs b/.dotnet/src/Custom/Embeddings/EmbeddingClient.cs new file mode 100644 index 000000000..8a94c33d9 --- /dev/null +++ b/.dotnet/src/Custom/Embeddings/EmbeddingClient.cs @@ -0,0 +1,121 @@ +using OpenAI.Internal.Models; +using System; +using System.ClientModel; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.ComponentModel; +using System.Threading; +using System.Threading.Tasks; + +namespace OpenAI.Embeddings; + +/// The service client for the OpenAI Embeddings endpoint. +public partial class EmbeddingClient +{ + private OpenAIClientConnector _clientConnector; + private Internal.Embeddings Shim => _clientConnector.InternalClient.GetEmbeddingsClient(); + + public EmbeddingClient(Uri endpoint, string model, ApiKeyCredential credential, OpenAIClientOptions options = null) + { + _clientConnector = new(model, endpoint, credential, options); + } + + public EmbeddingClient(Uri endpoint, string model, OpenAIClientOptions options = null) + : this(endpoint, model, credential: null, options) + { } + + public EmbeddingClient(string model, ApiKeyCredential credential, OpenAIClientOptions options = null) + : this(endpoint: null, model, credential, options) + { } + + public EmbeddingClient(string model, OpenAIClientOptions options = null) + : this(endpoint: null, model, credential: null, options) + { } + + public virtual ClientResult GenerateEmbedding(string input, EmbeddingOptions options = null) + { + Internal.Models.CreateEmbeddingRequest request = CreateInternalRequest(input, options); + ClientResult response = Shim.CreateEmbedding(request); + Embedding embeddingResult = new(response.Value, internalDataIndex: 0); + return ClientResult.FromValue(embeddingResult, response.GetRawResponse()); + } + + public virtual async Task> GenerateEmbeddingAsync(string input, EmbeddingOptions options = null) + { + Internal.Models.CreateEmbeddingRequest request = CreateInternalRequest(input, options); + ClientResult response = await Shim.CreateEmbeddingAsync(request); + Embedding embeddingResult = new(response.Value, internalDataIndex: 0); + return ClientResult.FromValue(embeddingResult, response.GetRawResponse()); + } + + public virtual ClientResult GenerateEmbedding(IEnumerable input, EmbeddingOptions options = null) + { + Internal.Models.CreateEmbeddingRequest request = CreateInternalRequest(input, options); + ClientResult response = Shim.CreateEmbedding(request); + Embedding embeddingResult = new(response.Value, internalDataIndex: 0); + return ClientResult.FromValue(embeddingResult, response.GetRawResponse()); + } + + public virtual async Task> GenerateEmbeddingAsync(IEnumerable input, EmbeddingOptions options = null) + { + Internal.Models.CreateEmbeddingRequest request = CreateInternalRequest(input, options); + ClientResult response = await Shim.CreateEmbeddingAsync(request); + Embedding embeddingResult = new(response.Value, internalDataIndex: 0); + return ClientResult.FromValue(embeddingResult, response.GetRawResponse()); + } + + public virtual ClientResult GenerateEmbeddings(IEnumerable inputs, EmbeddingOptions options = null) + { + Internal.Models.CreateEmbeddingRequest request = CreateInternalRequest(inputs, options); + ClientResult response = Shim.CreateEmbedding(request); + EmbeddingCollection resultCollection = EmbeddingCollection.CreateFromInternalResponse(response.Value); + return ClientResult.FromValue(resultCollection, response.GetRawResponse()); + } + + public virtual async Task> GenerateEmbeddingsAsync(IEnumerable inputs, EmbeddingOptions options = null) + { + Internal.Models.CreateEmbeddingRequest request = CreateInternalRequest(inputs, options); + ClientResult response = await Shim.CreateEmbeddingAsync(request); + EmbeddingCollection resultCollection = EmbeddingCollection.CreateFromInternalResponse(response.Value); + return ClientResult.FromValue(resultCollection, response.GetRawResponse()); + } + + public virtual ClientResult GenerateEmbeddings(IEnumerable> inputs, EmbeddingOptions options = null) + { + Internal.Models.CreateEmbeddingRequest request = CreateInternalRequest(inputs, options); + ClientResult response = Shim.CreateEmbedding(request); + EmbeddingCollection resultCollection = EmbeddingCollection.CreateFromInternalResponse(response.Value); + return ClientResult.FromValue(resultCollection, response.GetRawResponse()); + } + + public virtual async Task> GenerateEmbeddingsAsync(IEnumerable> inputs, EmbeddingOptions options = null) + { + Internal.Models.CreateEmbeddingRequest request = CreateInternalRequest(inputs, options); + ClientResult response = await Shim.CreateEmbeddingAsync(request); + EmbeddingCollection resultCollection = EmbeddingCollection.CreateFromInternalResponse(response.Value); + return ClientResult.FromValue(resultCollection, response.GetRawResponse()); + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult GenerateEmbeddings(BinaryContent content, RequestOptions context = null) + => Shim.CreateEmbedding(content, context); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task GenerateEmbeddingsAsync(BinaryContent content, RequestOptions context = null) + => Shim.CreateEmbeddingAsync(content, context); + + private Internal.Models.CreateEmbeddingRequest CreateInternalRequest(object inputObject, EmbeddingOptions options) + { + options ??= new(); + return new Internal.Models.CreateEmbeddingRequest( + BinaryData.FromObjectAsJson(inputObject), + new(_clientConnector.Model), + Internal.Models.CreateEmbeddingRequestEncodingFormat.Base64, + options?.Dimensions, + options?.User, + serializedAdditionalRawData: null); + } +} diff --git a/.dotnet/src/Custom/Embeddings/EmbeddingCollection.cs b/.dotnet/src/Custom/Embeddings/EmbeddingCollection.cs new file mode 100644 index 000000000..b87076584 --- /dev/null +++ b/.dotnet/src/Custom/Embeddings/EmbeddingCollection.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace OpenAI.Embeddings; + +public class EmbeddingCollection : ReadOnlyCollection +{ + internal EmbeddingCollection(IList list) : base(list) { } + internal static EmbeddingCollection CreateFromInternalResponse(Internal.Models.CreateEmbeddingResponse response) + { + EmbeddingTokenUsage usage = new(response.Usage); + List items = []; + for (int i = 0; i < response.Data.Count; i++) + { + items.Add(new(response, i, usage)); + } + return new EmbeddingCollection(items); + } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Embeddings/EmbeddingOptions.cs b/.dotnet/src/Custom/Embeddings/EmbeddingOptions.cs new file mode 100644 index 000000000..e16fcec55 --- /dev/null +++ b/.dotnet/src/Custom/Embeddings/EmbeddingOptions.cs @@ -0,0 +1,8 @@ +namespace OpenAI.Embeddings; + +public class EmbeddingOptions +{ + public string User { get; set; } + + public long? Dimensions { get; set; } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Embeddings/EmbeddingTokenUsage.cs b/.dotnet/src/Custom/Embeddings/EmbeddingTokenUsage.cs new file mode 100644 index 000000000..4fad06102 --- /dev/null +++ b/.dotnet/src/Custom/Embeddings/EmbeddingTokenUsage.cs @@ -0,0 +1,16 @@ +namespace OpenAI.Embeddings; + +public partial class EmbeddingTokenUsage +{ + private Internal.Models.EmbeddingUsage _internalUsage; + + /// + public long InputTokens => _internalUsage.PromptTokens; + /// + public long TotalTokens => _internalUsage.TotalTokens; + + internal EmbeddingTokenUsage(Internal.Models.EmbeddingUsage internalUsage) + { + _internalUsage = internalUsage; + } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Files/FileClient.cs b/.dotnet/src/Custom/Files/FileClient.cs new file mode 100644 index 000000000..4f2c6e3b1 --- /dev/null +++ b/.dotnet/src/Custom/Files/FileClient.cs @@ -0,0 +1,352 @@ +using System; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.ComponentModel; +using System.Runtime.InteropServices.ComTypes; +using System.Text; +using System.Threading.Tasks; + +namespace OpenAI.Files; + +/// +/// The service client for OpenAI file operations. +/// +public partial class FileClient +{ + private OpenAIClientConnector _clientConnector; + private Internal.Files Shim => _clientConnector.InternalClient.GetFilesClient(); + + /// + /// Initializes a new instance of , used for file operation requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The connection endpoint to use. + /// The API key used to authenticate with the service endpoint. + /// Additional options to customize the client. + public FileClient(Uri endpoint, ApiKeyCredential credential, OpenAIClientOptions options = null) + { + _clientConnector = new("none", endpoint, credential, options); + } + + /// + /// Initializes a new instance of , used for file operation requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The connection endpoint to use. + /// Additional options to customize the client. + public FileClient(Uri endpoint, OpenAIClientOptions options = null) + : this(endpoint, credential: null, options) + { } + + /// + /// Initializes a new instance of , used for file operation requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The API key used to authenticate with the service endpoint. + /// Additional options to customize the client. + public FileClient(ApiKeyCredential credential, OpenAIClientOptions options = null) + : this(endpoint: null, credential, options) + { } + + /// + /// Initializes a new instance of , used for file operation requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// Additional options to customize the client. + public FileClient(OpenAIClientOptions options = null) + : this(endpoint: null, credential: null, options) + { } + + public virtual ClientResult UploadFile(BinaryData file, string filename, OpenAIFilePurpose purpose) + { + if (file is null) throw new ArgumentNullException(nameof(file)); + if (string.IsNullOrWhiteSpace(filename)) throw new ArgumentException(nameof(filename)); + + PipelineMessage uploadMessage = CreateInternalUploadMessage(file, filename, purpose); + Shim.Pipeline.Send(uploadMessage); + return GetUploadResultFromResponse(uploadMessage.Response); + } + + public virtual async Task> UploadFileAsync(BinaryData file, string filename, OpenAIFilePurpose purpose) + { + if (file is null) throw new ArgumentNullException(nameof(file)); + if (string.IsNullOrWhiteSpace(filename)) throw new ArgumentException(nameof(filename)); + + PipelineMessage uploadMessage = CreateInternalUploadMessage(file, filename, purpose); + await Shim.Pipeline.SendAsync(uploadMessage); + return GetUploadResultFromResponse(uploadMessage.Response); + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult UploadFile(BinaryContent requestBody, RequestOptions context) + { + return Shim.CreateFile(requestBody, context); + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task UploadFileAsync(BinaryContent requestBody, RequestOptions context) + { + return Shim.CreateFileAsync(requestBody, context); + } + + public virtual ClientResult GetFileInfo(string fileId) + { + ClientResult internalResult = Shim.RetrieveFile(fileId); + return ClientResult.FromValue(new OpenAIFileInfo(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual async Task> GetFileInfoAsync(string fileId) + { + ClientResult internalResult = await Shim.RetrieveFileAsync(fileId); + return ClientResult.FromValue(new OpenAIFileInfo(internalResult.Value), internalResult.GetRawResponse()); + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult GetFileInfo(string fileId, RequestOptions context) + { + return Shim.RetrieveFile(fileId, context); + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task GetFileInfoAsync(string fileId, RequestOptions context) + { + return Shim.RetrieveFileAsync(fileId, context); + } + + public virtual ClientResult GetFileInfoList(OpenAIFilePurpose? purpose = null) + { + Internal.Models.OpenAIFilePurpose? internalPurpose = ToInternalFilePurpose(purpose); + string internalPurposeText = null; + if (internalPurpose != null) + { + internalPurposeText = internalPurpose.ToString(); + } + ClientResult result = Shim.GetFiles(internalPurposeText); + List infoItems = []; + foreach (Internal.Models.OpenAIFile internalFile in result.Value.Data) + { + infoItems.Add(new(internalFile)); + } + return ClientResult.FromValue(new OpenAIFileInfoCollection(infoItems), result.GetRawResponse()); + } + + public virtual async Task> GetFileInfoListAsync(OpenAIFilePurpose? purpose = null) + { + Internal.Models.OpenAIFilePurpose? internalPurpose = ToInternalFilePurpose(purpose); + string internalPurposeText = null; + if (internalPurpose != null) + { + internalPurposeText = internalPurpose.ToString(); + } + ClientResult result = await Shim.GetFilesAsync(internalPurposeText).ConfigureAwait(false); + List infoItems = []; + foreach (Internal.Models.OpenAIFile internalFile in result.Value.Data) + { + infoItems.Add(new(internalFile)); + } + return ClientResult.FromValue(new OpenAIFileInfoCollection(infoItems), result.GetRawResponse()); + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult GetFileInfoList(string purpose, RequestOptions context) + { + return Shim.GetFiles(purpose, context); + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task GetFileInfoListAsync(string purpose, RequestOptions context) + { + return Shim.GetFilesAsync(purpose, context); + } + + public virtual ClientResult DownloadFile(string fileId) + { + PipelineMessage message = Shim.Pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "GET"; + UriBuilder uriBuilder = new(_clientConnector.Endpoint.AbsoluteUri); + StringBuilder path = new(); + path.Append($"/files/{fileId}/content"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("content-type", "multipart/form-data"); + Shim.Pipeline.Send(message); + + if (message.Response.IsError) + { + throw new ClientResultException(message.Response); + } + + return ClientResult.FromValue(message.Response.Content, message.Response); + } + + public virtual async Task> DownloadFileAsync(string fileId) + { + PipelineMessage message = Shim.Pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "GET"; + UriBuilder uriBuilder = new(_clientConnector.Endpoint.AbsoluteUri); + StringBuilder path = new(); + path.Append($"/files/{fileId}/content"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("content-type", "multipart/form-data"); + + await Shim.Pipeline.SendAsync(message); + + if (message.Response.IsError) + { + throw new ClientResultException(message.Response); + } + + return ClientResult.FromValue(message.Response.Content, message.Response); + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult DownloadFile(string fileId, RequestOptions context) + { + return Shim.DownloadFile(fileId, context); + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task DownloadFileAsync(string fileId, RequestOptions context) + { + return Shim.DownloadFileAsync(fileId, context); + } + + public virtual void DeleteFile(string fileId) + { + _ = Shim.DeleteFile(fileId); + } + + public virtual async Task DeleteFileAsync(string fileId) + { + _ = Shim.DeleteFileAsync(fileId); + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult DeleteFile(string fileId, RequestOptions context) + { + return Shim.DeleteFile(fileId, context); + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult DeleteFileAsync(string fileId, RequestOptions context) + { + return Shim.DeleteFile(fileId, context); + } + + internal PipelineMessage CreateInternalUploadMessage(BinaryData fileData, string filename, OpenAIFilePurpose purpose) + { + MultipartFormDataContent content = new(); + content.Add(BinaryContent.Create(fileData), + name: "file", + fileName: filename, + headers: []); + content.Add(MultipartContent.Create( + BinaryData.FromString(purpose switch + { + OpenAIFilePurpose.FineTuning => "fine-tune", + OpenAIFilePurpose.Assistants => "assistants", + _ => throw new ArgumentException($"Unsupported purpose for file upload: {purpose}"), + })), + name: "\"purpose\"", + headers: []); + + PipelineMessage message = Shim.Pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_clientConnector.Endpoint.AbsoluteUri); + StringBuilder path = new(); + path.Append("/files"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); + request.Content = content; + + content.ApplyToRequest(request); + + return message; + } + + internal ClientResult GetUploadResultFromResponse(PipelineResponse response) + { + if (response.IsError) + { + throw new ClientResultException(response); + } + + Internal.Models.OpenAIFile internalFile = Internal.Models.OpenAIFile.FromResponse(response); + OpenAIFileInfo fileInfo = new(internalFile); + return ClientResult.FromValue(fileInfo, response); + } + + internal static Internal.Models.OpenAIFilePurpose? ToInternalFilePurpose(OpenAIFilePurpose? purpose) + { + if (purpose == null) + { + return null; + } + return purpose switch + { + OpenAIFilePurpose.FineTuning => Internal.Models.OpenAIFilePurpose.FineTune, + OpenAIFilePurpose.FineTuningResults => Internal.Models.OpenAIFilePurpose.FineTuneResults, + OpenAIFilePurpose.Assistants => Internal.Models.OpenAIFilePurpose.Assistants, + OpenAIFilePurpose.AssistantOutputs => Internal.Models.OpenAIFilePurpose.AssistantsOutput, + _ => throw new ArgumentException($"Unsupported file purpose: {purpose}"), + }; + } + private static PipelineMessageClassifier _responseErrorClassifier200; + private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); + +} diff --git a/.dotnet/src/Custom/Files/OpenAIFileInfo.cs b/.dotnet/src/Custom/Files/OpenAIFileInfo.cs new file mode 100644 index 000000000..04d76a036 --- /dev/null +++ b/.dotnet/src/Custom/Files/OpenAIFileInfo.cs @@ -0,0 +1,36 @@ +using System; + +namespace OpenAI.Files; + +public partial class OpenAIFileInfo +{ + public string Id { get; } + public OpenAIFilePurpose Purpose { get; } + public string Filename { get; } + public long Size { get; } + public DateTimeOffset CreatedAt { get; } + + internal OpenAIFileInfo(Internal.Models.OpenAIFile internalFile) + { + Id = internalFile.Id; + Purpose = internalFile.Purpose.ToString() switch + { + "fine-tune" => OpenAIFilePurpose.FineTuning, + "fine-tune-result" => OpenAIFilePurpose.FineTuningResults, + "assistants" => OpenAIFilePurpose.Assistants, + "assistants_output" => OpenAIFilePurpose.AssistantOutputs, + _ => throw new ArgumentException(nameof(internalFile)), + }; + Filename = internalFile.Filename; + Size = internalFile.Bytes; + CreatedAt = internalFile.CreatedAt; + } +} + +public enum OpenAIFilePurpose +{ + FineTuning, + FineTuningResults, + Assistants, + AssistantOutputs, +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Files/OpenAIFileInfoCollection.cs b/.dotnet/src/Custom/Files/OpenAIFileInfoCollection.cs new file mode 100644 index 000000000..3c40e56a5 --- /dev/null +++ b/.dotnet/src/Custom/Files/OpenAIFileInfoCollection.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace OpenAI.Files; + +public partial class OpenAIFileInfoCollection : ReadOnlyCollection +{ + internal OpenAIFileInfoCollection(IList list) : base(list) + { + } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Images/GeneratedImage.cs b/.dotnet/src/Custom/Images/GeneratedImage.cs new file mode 100644 index 000000000..807268544 --- /dev/null +++ b/.dotnet/src/Custom/Images/GeneratedImage.cs @@ -0,0 +1,48 @@ +using System; + +namespace OpenAI.Images; + +/// +/// Represents the result data for an image generation request. +/// +public class GeneratedImage +{ + /// + /// The binary image data received from the response, provided when + /// is set to . + /// + /// + /// This property is mutually exclusive with and will be null when the other + /// is present. + /// + public BinaryData ImageBytes { get; } + /// + /// A temporary internet location for an image, provided by default or when + /// is set to . + /// + /// + /// This property is mutually exclusive with and will be null when the other + /// is present. + /// + public Uri ImageUri { get; } + /// + /// The final, revised prompt that was used to generate the result image, populated if the model performed any + /// such revisions to the prompt. + /// + /// + /// Revisions are automatically performed to enrich image prompts and improve output quality and consistency. + /// + public string RevisedPrompt { get; } + /// + /// The timestamp at which the result image was generated. + /// + public DateTimeOffset CreatedAt { get; } + + internal GeneratedImage(Internal.Models.ImagesResponse internalResponse, long internalDataIndex) + { + CreatedAt = internalResponse.Created; + ImageBytes = internalResponse.Data[(int)internalDataIndex].B64Json; + RevisedPrompt = internalResponse.Data[(int)internalDataIndex].RevisedPrompt; + ImageUri = internalResponse.Data[(int)internalDataIndex].Url; + } +} diff --git a/.dotnet/src/Custom/Images/ImageClient.cs b/.dotnet/src/Custom/Images/ImageClient.cs new file mode 100644 index 000000000..24f8ae4fd --- /dev/null +++ b/.dotnet/src/Custom/Images/ImageClient.cs @@ -0,0 +1,245 @@ +using System; +using System.ClientModel; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.ComponentModel; +using System.Threading; +using System.Threading.Tasks; + +namespace OpenAI.Images; + +/// The service client for OpenAI image operations. +public partial class ImageClient +{ + private OpenAIClientConnector _clientConnector; + private Internal.Images Shim => _clientConnector.InternalClient.GetImagesClient(); + + /// + /// Initializes a new instance of , used for image operation requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The connection endpoint to use. + /// The model name for image operations that the client should use. + /// The API key used to authenticate with the service endpoint. + /// Additional options to customize the client. + public ImageClient(Uri endpoint, string model, ApiKeyCredential credential, OpenAIClientOptions options = null) + { + _clientConnector = new(model, endpoint, credential, options); + } + + /// + /// Initializes a new instance of , used for image operation requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The connection endpoint to use. + /// The model name for image operations that the client should use. + /// Additional options to customize the client. + public ImageClient(Uri endpoint, string model, OpenAIClientOptions options = null) + : this(endpoint, model, credential: null, options) + { } + + /// + /// Initializes a new instance of , used for image operation requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The model name for image operations that the client should use. + /// The API key used to authenticate with the service endpoint. + /// Additional options to customize the client. + public ImageClient(string model, ApiKeyCredential credential, OpenAIClientOptions options = null) + : this(endpoint: null, model, credential, options) + { } + + /// + /// Initializes a new instance of , used for image operation requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The model name for image operations that the client should use. + /// Additional options to customize the client. + public ImageClient(string model, OpenAIClientOptions options = null) + : this(endpoint: null, model, credential: null, options) + { } + + /// + /// Generates a single image for a provided prompt. + /// + /// The description and instructions for the image. + /// Additional options for the image generation request. + /// The cancellation token for the operation. + /// A result for a single image generation. + public virtual ClientResult GenerateImage(string prompt, ImageGenerationOptions options = null) + { + ClientResult multiResult = GenerateImages(prompt, imageCount: null, options); + return ClientResult.FromValue(multiResult.Value[0], multiResult.GetRawResponse()); + } + + /// + /// Generates a single image for a provided prompt. + /// + /// The description and instructions for the image. + /// Additional options for the image generation request. + /// The cancellation token for the operation. + /// A result for a single image generation. + public virtual async Task> GenerateImageAsync(string prompt, ImageGenerationOptions options = null) + { + ClientResult multiResult = await GenerateImagesAsync(prompt, imageCount: null, options).ConfigureAwait(false); + return ClientResult.FromValue(multiResult.Value[0], multiResult.GetRawResponse()); + } + + /// + /// Generates a collection of image alternatives for a provided prompt. + /// + /// The description and instructions for the image. + /// + /// The number of alternative images to generate for the prompt. + /// + /// Additional options for the image generation request. + /// The cancellation token for the operation. + /// A result for a single image generation. + public virtual ClientResult GenerateImages( + string prompt, + int? imageCount = null, + ImageGenerationOptions options = null) + { + Internal.Models.CreateImageRequest request = CreateInternalRequest(prompt, imageCount, options); + ClientResult response = Shim.CreateImage(request); + List ImageGenerations = []; + for (int i = 0; i < response.Value.Data.Count; i++) + { + ImageGenerations.Add(new(response.Value, i)); + } + return ClientResult.FromValue(new ImageGenerationCollection(ImageGenerations), response.GetRawResponse()); + } + + /// + /// Generates a collection of image alternatives for a provided prompt. + /// + /// The description and instructions for the image. + /// + /// The number of alternative images to generate for the prompt. + /// + /// Additional options for the image generation request. + /// The cancellation token for the operation. + /// A result for a single image generation. + public virtual async Task> GenerateImagesAsync( + string prompt, + int? imageCount = null, + ImageGenerationOptions options = null) + { + Internal.Models.CreateImageRequest request = CreateInternalRequest(prompt, imageCount, options); + ClientResult response = await Shim.CreateImageAsync(request).ConfigureAwait(false); + List ImageGenerations = []; + for (int i = 0; i < response.Value.Data.Count; i++) + { + ImageGenerations.Add(new(response.Value, i)); + } + return ClientResult.FromValue(new ImageGenerationCollection(ImageGenerations), response.GetRawResponse()); + } + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult GenerateImage(BinaryContent content, RequestOptions context = null) + => Shim.CreateImage(content, context); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task GenerateImageAsync(BinaryContent content, RequestOptions context = null) + => Shim.CreateImageAsync(content, context); + + private Internal.Models.CreateImageRequest CreateInternalRequest( + string prompt, + int? imageCount = null, + ImageGenerationOptions options = null) + { + options ??= new(); + Internal.Models.CreateImageRequestQuality? internalQuality = null; + if (options.Quality != null) + { + internalQuality = options.Quality switch + { + ImageQuality.Standard => Internal.Models.CreateImageRequestQuality.Standard, + ImageQuality.High => Internal.Models.CreateImageRequestQuality.Hd, + _ => throw new ArgumentException(nameof(options.Quality)), + }; + } + Internal.Models.CreateImageRequestResponseFormat? internalFormat = null; + if (options.ResponseFormat != null) + { + internalFormat = options.ResponseFormat switch + { + ImageResponseFormat.Bytes => Internal.Models.CreateImageRequestResponseFormat.B64Json, + ImageResponseFormat.Uri => Internal.Models.CreateImageRequestResponseFormat.Url, + _ => throw new ArgumentException(nameof(options.ResponseFormat)), + }; + } + Internal.Models.CreateImageRequestSize? internalSize = null; + if (options.Size != null) + { + internalSize = options.Size switch + { + ImageSize.Size1024x1024 => Internal.Models.CreateImageRequestSize._1024x1024, + ImageSize.Size1024x1792 => Internal.Models.CreateImageRequestSize._1024x1792, + ImageSize.Size1792x1024 => Internal.Models.CreateImageRequestSize._1792x1024, + ImageSize.Size256x256 => Internal.Models.CreateImageRequestSize._256x256, + ImageSize.Size512x512 => Internal.Models.CreateImageRequestSize._512x512, + _ => throw new ArgumentException(nameof(options.Size)), + }; + } + Internal.Models.CreateImageRequestStyle? internalStyle = null; + if (options.Style != null) + { + internalStyle = options.Style switch + { + ImageStyle.Vivid => Internal.Models.CreateImageRequestStyle.Vivid, + ImageStyle.Natural => Internal.Models.CreateImageRequestStyle.Natural, + _ => throw new ArgumentException(nameof(options.Style)), + }; + } + return new Internal.Models.CreateImageRequest( + prompt, + _clientConnector.Model, + imageCount, + quality: internalQuality, + responseFormat: internalFormat, + size: internalSize, + style: internalStyle, + options.User, + serializedAdditionalRawData: null); + } +} diff --git a/.dotnet/src/Custom/Images/ImageGenerationCollection.cs b/.dotnet/src/Custom/Images/ImageGenerationCollection.cs new file mode 100644 index 000000000..7774309b5 --- /dev/null +++ b/.dotnet/src/Custom/Images/ImageGenerationCollection.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace OpenAI.Images; + +/// +/// Represents an image generation response payload that contains information for multiple generated images. +/// +public class ImageGenerationCollection : ReadOnlyCollection +{ + internal ImageGenerationCollection(IList list) : base(list) { } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Images/ImageGenerationOptions.cs b/.dotnet/src/Custom/Images/ImageGenerationOptions.cs new file mode 100644 index 000000000..37cdb95af --- /dev/null +++ b/.dotnet/src/Custom/Images/ImageGenerationOptions.cs @@ -0,0 +1,75 @@ +namespace OpenAI.Images; + +/// +/// Represents additional options available to control the behavior of an image generation operation. +/// +public partial class ImageGenerationOptions +{ + /// + /// Specifies the quality level of the image that will be generated. This setting is only available when using + /// the dall-e-3 model. + /// + /// + /// hd - - Finer details, greater consistency, slower, more intensive. + /// + /// + /// standard - - The default quality level that's faster and less + /// intensive but may also be less detailed and consistent than hd. + /// + /// + /// + public ImageQuality? Quality { get; set; } + /// + /// Specifies the desired output representation of the generated image. + /// + /// + /// url - - Default, provides a temporary internet location that + /// the generated image can be retrieved from. + /// + /// + /// b64_json - - Provides the full image data on the response, + /// encoded in the result as a base64 string. This offers the fastest round trip time but can drastically + /// increase the size of response payloads. + /// + /// + /// + public ImageResponseFormat? ResponseFormat { get; set; } + /// + /// Specifies the dimensions of the generated image. Larger images take longer to create. + /// + /// Available for dall-e-2: + /// + /// 1024x1024 - - default + /// 256x256 - - small + /// 512x512 - - medium + /// + /// + /// + /// Available for dall-e-3: + /// + /// 1024x1024 - - default + /// 1024x1792 - - extra tall + /// 1792x1024 - - extra wide + /// + /// + /// + public ImageSize? Size { get; set; } + /// + /// The style kind to guide the generation of the image. + /// + /// + /// vivid - - default, a style that tends towards more realistic, + /// dramatic images. + /// + /// + /// natural - - a more subdued style with less tendency towards + /// realism and striking imagery. + /// + /// + /// + public ImageStyle? Style { get; set; } + /// + /// An optional identifier for the end user that can help OpenAI monitor for and detect abuse. + /// + public string User { get; set; } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Images/ImageQuality.cs b/.dotnet/src/Custom/Images/ImageQuality.cs new file mode 100644 index 000000000..41f13b0ff --- /dev/null +++ b/.dotnet/src/Custom/Images/ImageQuality.cs @@ -0,0 +1,24 @@ +namespace OpenAI.Images; + +/// +/// A representation of the quality setting for image operations that controls the level of work that the model will +/// perform. +/// +/// +/// Available qualities consist of: +/// +/// - standard - The default setting that balances speed, detail, and consistecy. +/// - hd - Better consistency and finer details, but may be slower. +/// +/// +public enum ImageQuality +{ + /// + /// The hd image quality that provides finer details and greater consistency but may be slower. + /// + High, + /// + /// The standard image quality that provides a balanced mix of detailing, consistency, and speed. + /// + Standard, +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Images/ImageResponseFormat.cs b/.dotnet/src/Custom/Images/ImageResponseFormat.cs new file mode 100644 index 000000000..8403482c5 --- /dev/null +++ b/.dotnet/src/Custom/Images/ImageResponseFormat.cs @@ -0,0 +1,32 @@ +using System; + +namespace OpenAI.Images; + +/// +/// Represents the available output methods for generated images. +/// +/// +/// url - - Default, provides a temporary internet location that +/// the generated image can be retrieved from. +/// +/// +/// b64_json - - Provides the full image data on the response, +/// encoded in the result as a base64 string. This offers the fastest round trip time but can drastically +/// increase the size of response payloads. +/// +/// +/// +public enum ImageResponseFormat +{ + /// + /// Instructs the request to return image data directly on the response, encoded as a base64 string in the response + /// JSON. This minimizes availability time but drastically increases the size of responses, required bandwidth, and + /// immediate memory needs. This is equivalent to b64_json in the REST API. + /// + Bytes, + /// + /// The default setting that instructs the request to return a temporary internet location from which the image can + /// be retrieved. + /// + Uri, +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Images/ImageSize.cs b/.dotnet/src/Custom/Images/ImageSize.cs new file mode 100644 index 000000000..e92dbf99d --- /dev/null +++ b/.dotnet/src/Custom/Images/ImageSize.cs @@ -0,0 +1,43 @@ +namespace OpenAI.Images; + +/// +/// Represents the available output dimensions for generated images. +/// +public enum ImageSize +{ + /// + /// A square image with 1024 pixels of both width and height. + /// + /// Supported and default for both dall-e-2 and dall-e-3 models. + /// + /// + Size1024x1024, + /// + /// An extra tall image, 1024 pixels wide by 1792 pixels high. + /// + /// Supported only for the dall-e-3 model. + /// + /// + Size1024x1792, + /// + /// An extra wide image, 1792 pixels wide by 1024 pixels high. + /// + /// Supported only for the dall-e-3 model. + /// + /// + Size1792x1024, + /// + /// A small, square image with 256 pixels of both width and height. + /// + /// Supported only for the older dall-e-2 model. + /// + /// + Size256x256, + /// + /// A medium-small, square image with 512 pixels of both width and height. + /// + /// Supported only for the older dall-e-2 model. + /// + /// + Size512x512, +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Images/ImageStyle.cs b/.dotnet/src/Custom/Images/ImageStyle.cs new file mode 100644 index 000000000..30616eccd --- /dev/null +++ b/.dotnet/src/Custom/Images/ImageStyle.cs @@ -0,0 +1,18 @@ +namespace OpenAI.Images; + +/// +/// The style of the generated images. Must be one of vivid or natural. Vivid causes the model to lean towards +/// generating hyper-real and dramatic images. Natural causes the model to produce more natural, less hyper-real +/// looking images. This param is only supported for dall-e-3. +/// +public enum ImageStyle +{ + /// + /// The vivid style, with which the model will tend towards hyper-realistic, dramatic imagery. + /// + Vivid, + /// + /// The natural style, with which the model will not tend towards hyper-realistic, dramatic imagery. + /// + Natural, +} \ No newline at end of file diff --git a/.dotnet/src/Custom/LegacyCompletions/LegacyCompletionClient.cs b/.dotnet/src/Custom/LegacyCompletions/LegacyCompletionClient.cs new file mode 100644 index 000000000..1b9393daa --- /dev/null +++ b/.dotnet/src/Custom/LegacyCompletions/LegacyCompletionClient.cs @@ -0,0 +1,106 @@ +using System; +using System.ClientModel; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.ComponentModel; +using System.Threading.Tasks; + +namespace OpenAI.LegacyCompletions; + +/// +/// The basic, protocol-level service client for OpenAI legacy completion operations. +/// +/// Note: pre-chat completions are a legacy feature. New solutions should consider the use of chat +/// completions or assistants, instead. +/// +/// +public partial class LegacyCompletionClient +{ + private OpenAIClientConnector _clientConnector; + private Internal.Completions Shim => _clientConnector.InternalClient.GetCompletionsClient(); + + /// + /// Initializes a new instance of , used for legacy completion requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The connection endpoint to use. + /// The API key used to authenticate with the service endpoint. + /// Additional options to customize the client. + public LegacyCompletionClient(Uri endpoint, ApiKeyCredential credential, OpenAIClientOptions options = null) + { + _clientConnector = new("protocol", endpoint, credential, options); + } + + /// + /// Initializes a new instance of , used for legacy completion operation requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The connection endpoint to use. + /// Additional options to customize the client. + public LegacyCompletionClient(Uri endpoint, OpenAIClientOptions options = null) + : this(endpoint, credential: null, options) + { } + + /// + /// Initializes a new instance of , used for legacy completion operation requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The API key used to authenticate with the service endpoint. + /// Additional options to customize the client. + public LegacyCompletionClient(ApiKeyCredential credential, OpenAIClientOptions options = null) + : this(endpoint: null, credential, options) + { } + + /// + /// Initializes a new instance of , used for legacy completion operation requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// Additional options to customize the client. + public LegacyCompletionClient(OpenAIClientOptions options = null) + : this(endpoint: null, credential: null, options) + { } + + /// + public virtual ClientResult GenerateLegacyCompletions(BinaryContent content, RequestOptions context = null) + => Shim.CreateCompletion(content, context); + + /// + public virtual Task GenerateLegacyCompletionsAsync(BinaryContent content, RequestOptions context = null) + => Shim.CreateCompletionAsync(content, context); +} diff --git a/.dotnet/src/Custom/Models/ModelDetailCollection.cs b/.dotnet/src/Custom/Models/ModelDetailCollection.cs new file mode 100644 index 000000000..8e89d769e --- /dev/null +++ b/.dotnet/src/Custom/Models/ModelDetailCollection.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace OpenAI.ModelManagement; + +/// +/// Represents a collection of entries for available models. +/// +public partial class ModelDetailCollection : ReadOnlyCollection +{ + internal ModelDetailCollection(IList list) : base(list) + {} +} diff --git a/.dotnet/src/Custom/Models/ModelDetails.cs b/.dotnet/src/Custom/Models/ModelDetails.cs new file mode 100644 index 000000000..30d9ec8b5 --- /dev/null +++ b/.dotnet/src/Custom/Models/ModelDetails.cs @@ -0,0 +1,29 @@ +using System; + +namespace OpenAI.ModelManagement; + +/// +/// Represents information about a single available model entry. +/// +public partial class ModelDetails +{ + /// + /// The ID of the model as used when calling the service. An example is 'gpt-3.5-turbo'. + /// + public string Id { get; } + /// + /// The timestamp when the current model entry became available. + /// + public DateTimeOffset CreatedAt { get; } + /// + /// The name of the organization that owns the model. + /// + public string OwnerOrganization { get; } + + internal ModelDetails(Internal.Models.Model internalModel) + { + Id = internalModel.Id; + CreatedAt = internalModel.Created; + OwnerOrganization = internalModel.OwnedBy; + } +} diff --git a/.dotnet/src/Custom/Models/ModelManagementClient.cs b/.dotnet/src/Custom/Models/ModelManagementClient.cs new file mode 100644 index 000000000..88a3c805c --- /dev/null +++ b/.dotnet/src/Custom/Models/ModelManagementClient.cs @@ -0,0 +1,197 @@ +using OpenAI.ClientShared.Internal; +using System; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.ComponentModel; +using System.Threading.Tasks; + +namespace OpenAI.ModelManagement; + +/// +/// The service client for OpenAI model operations. +/// +public partial class ModelManagementClient +{ + private OpenAIClientConnector _clientConnector; + private Internal.ModelsOps Shim => _clientConnector.InternalClient.GetModelsOpsClient(); + private Internal.FineTuning FineTuningShim + => _clientConnector.InternalClient.GetFineTuningClient(); + + /// + /// Initializes a new instance of , used for model operation requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The connection endpoint to use. + /// The API key used to authenticate with the service endpoint. + /// Additional options to customize the client. + public ModelManagementClient(Uri endpoint, ApiKeyCredential credential, OpenAIClientOptions options = null) + { + _clientConnector = new("none", endpoint, credential, options); + } + + /// + /// Initializes a new instance of , used for model operation requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The connection endpoint to use. + /// Additional options to customize the client. + public ModelManagementClient(Uri endpoint, OpenAIClientOptions options = null) + : this(endpoint, credential: null, options) + { } + + /// + /// Initializes a new instance of , used for model operation requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The API key used to authenticate with the service endpoint. + /// Additional options to customize the client. + public ModelManagementClient(ApiKeyCredential credential, OpenAIClientOptions options = null) + : this(endpoint: null, credential, options) + { } + + /// + /// Initializes a new instance of , used for model operation requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// Additional options to customize the client. + public ModelManagementClient(OpenAIClientOptions options = null) + : this(endpoint: null, credential: null, options) + { } + + public virtual ClientResult GetModelInfo(string modelId) + { + ClientResult internalResult = Shim.Retrieve(modelId); + return ClientResult.FromValue(new ModelDetails(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual async Task> GetModelInfoAsync( + string modelId) + { + ClientResult internalResult = await Shim.RetrieveAsync(modelId).ConfigureAwait(false); + return ClientResult.FromValue(new ModelDetails(internalResult.Value), internalResult.GetRawResponse()); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult GetModelInfo(string modelId, RequestOptions context) + { + return Shim.Retrieve(modelId, context); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task GetModelInfoAsync(string modelId, RequestOptions context) + { + return Shim.RetrieveAsync(modelId, context); + } + + public virtual ClientResult GetModels() + { + ClientResult internalResult = Shim.GetModels(); + OptionalList modelEntries = []; + foreach (Internal.Models.Model internalModel in internalResult.Value.Data) + { + modelEntries.Add(new(internalModel)); + } + return ClientResult.FromValue(new ModelDetailCollection(modelEntries), internalResult.GetRawResponse()); + } + + public virtual async Task> GetModelsAsync() + { + ClientResult internalResult + = await Shim.GetModelsAsync().ConfigureAwait(false); + OptionalList modelEntries = []; + foreach (Internal.Models.Model internalModel in internalResult.Value.Data) + { + modelEntries.Add(new(internalModel)); + } + return ClientResult.FromValue(new ModelDetailCollection(modelEntries), internalResult.GetRawResponse()); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult GetModels(RequestOptions context) => Shim.GetModels(context); + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task GetModelsAsync(RequestOptions context) => Shim.GetModelsAsync(context); + + public virtual ClientResult DeleteModel(string modelId) + { + ClientResult internalResult = Shim.Delete(modelId); + return ClientResult.FromValue(internalResult.Value.Deleted, internalResult.GetRawResponse()); + } + + public virtual async Task> DeleteModelAsync(string modelId) + { + ClientResult internalResult + = await Shim.DeleteAsync(modelId).ConfigureAwait(false); + return ClientResult.FromValue(internalResult.Value.Deleted, internalResult.GetRawResponse()); + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult DeleteModel(string modelId, RequestOptions context) => Shim.Delete(modelId, context); + + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual Task DeleteModelAsync(string modelId, RequestOptions context) => Shim.DeleteAsync(modelId, context); + + public virtual ClientResult CreateFineTuningJob(BinaryContent content, RequestOptions context = null) + => FineTuningShim.CreateFineTuningJob(content, context); + + public virtual Task CreateFineTuningJobAsync(BinaryContent content, RequestOptions context = null) + => FineTuningShim.CreateFineTuningJobAsync(content, context); + + public virtual ClientResult GetFineTuningJob(string jobId, RequestOptions context) => FineTuningShim.RetrieveFineTuningJob(jobId, context); + + public virtual Task GetFineTuningJobAsync(string jobId, RequestOptions context) + => FineTuningShim.RetrieveFineTuningJobAsync(jobId, context); + + public virtual ClientResult GetFineTuningJobs(string previousJobId, int? maxResults, RequestOptions context) + => FineTuningShim.GetPaginatedFineTuningJobs(previousJobId, maxResults, context); + + public virtual Task GetFineTuningJobsAsync(int? maxResults, string previousJobId, RequestOptions context) + => FineTuningShim.GetPaginatedFineTuningJobsAsync(previousJobId, maxResults, context); + + public virtual ClientResult GetFineTuningJobEvents(string jobId, int? maxResults, string previousJobId, RequestOptions context) + => FineTuningShim.GetFineTuningEvents(jobId, previousJobId, maxResults, context); + + public virtual Task GetFineTuningJobEventsAsync(string jobId, int? maxResults, string previousJobId, RequestOptions context) + => FineTuningShim.GetFineTuningEventsAsync(jobId, previousJobId, maxResults, context); + + public virtual ClientResult CancelFineTuningJob(string jobId, RequestOptions context) => FineTuningShim.CancelFineTuningJob(jobId, context); + + public virtual Task CancelFineTuningJobAsync(string jobId, RequestOptions context) + => FineTuningShim.CancelFineTuningJobAsync(jobId, context); +} diff --git a/.dotnet/src/Custom/Moderations/ModerationClient.cs b/.dotnet/src/Custom/Moderations/ModerationClient.cs new file mode 100644 index 000000000..28590087c --- /dev/null +++ b/.dotnet/src/Custom/Moderations/ModerationClient.cs @@ -0,0 +1,106 @@ +using System; +using System.ClientModel; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.ComponentModel; +using System.Threading; +using System.Threading.Tasks; + +namespace OpenAI.Moderations; + +/// +/// The service client for OpenAI moderation operations. +/// +public partial class ModerationClient +{ + private OpenAIClientConnector _clientConnector; + private Internal.Moderations Shim => _clientConnector.InternalClient.GetModerationsClient(); + + /// + /// Initializes a new instance of , used for moderation operation requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The connection endpoint to use. + /// The API key used to authenticate with the service endpoint. + /// Additional options to customize the client. + public ModerationClient(Uri endpoint, ApiKeyCredential credential, OpenAIClientOptions options = null) + { + _clientConnector = new("none", endpoint, credential, options); + } + + /// + /// Initializes a new instance of , used for moderation operation requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The connection endpoint to use. + /// Additional options to customize the client. + public ModerationClient(Uri endpoint, OpenAIClientOptions options = null) + : this(endpoint, credential: null, options) + { } + + /// + /// Initializes a new instance of , used for moderation operation requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The API key used to authenticate with the service endpoint. + /// Additional options to customize the client. + public ModerationClient(ApiKeyCredential credential, OpenAIClientOptions options = null) + : this(endpoint: null, credential, options) + { } + + /// + /// Initializes a new instance of , used for moderation operation requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// Additional options to customize the client. + public ModerationClient(OpenAIClientOptions options = null) + : this(endpoint: null, credential: null, options) + { } + + public virtual ClientResult ClassifyText(BinaryContent content, RequestOptions context = null) + { + return Shim.CreateModeration(content, context); + } + + public virtual Task ClassifyTextAsync(BinaryContent content, RequestOptions context = null) + { + return Shim.CreateModerationAsync(content, context); + } + +} diff --git a/.dotnet/src/Custom/OpenAIClient.cs b/.dotnet/src/Custom/OpenAIClient.cs new file mode 100644 index 000000000..b94c3bf93 --- /dev/null +++ b/.dotnet/src/Custom/OpenAIClient.cs @@ -0,0 +1,191 @@ +using OpenAI.Assistants; +using OpenAI.Audio; +using OpenAI.Chat; +using OpenAI.Embeddings; +using OpenAI.Files; +using OpenAI.Images; +using OpenAI.LegacyCompletions; +using OpenAI.ModelManagement; +using OpenAI.Moderations; +using System; +using System.ClientModel; + +namespace OpenAI; + +/// +/// A top-level client factory that enables convenient creation of scenario-specific sub-clients while reusing shared +/// configuration details like endpoint, authentication, and pipeline customization. +/// +public partial class OpenAIClient +{ + private readonly Uri _cachedEndpoint = null; + private readonly ApiKeyCredential _cachedCredential = null; + private readonly OpenAIClientOptions _cachedOptions = null; + + /// + /// Creates a new instance of will store common client configuration details to permit + /// easy reuse and propagation to multiple, scenario-specific subclients. + /// + /// + /// This client does not provide any model functionality directly and is purely a helper to facilitate the creation + /// of the scenario-specific subclients like . + /// + /// An explicitly defined endpoint that all clients created by this should use. + /// An explicitly defined credential that all clients created by this should use. + /// A common client options definition that all clients created by this should use. + public OpenAIClient(Uri endpoint, ApiKeyCredential credential, OpenAIClientOptions clientOptions = null) + { + _cachedEndpoint = endpoint; + _cachedCredential = credential; + _cachedOptions = clientOptions; + } + + /// + /// Creates a new instance of will store common client configuration details to permit + /// easy reuse and propagation to multiple, scenario-specific subclients. + /// + /// + /// This client does not provide any model functionality directly and is purely a helper to facilitate the creation + /// of the scenario-specific subclients like . + /// + /// An explicitly defined endpoint that all clients created by this should use. + /// A common client options definition that all clients created by this should use. + public OpenAIClient(Uri endpoint, OpenAIClientOptions clientOptions = null) + : this(endpoint, credential: null, clientOptions) + { } + + /// + /// Creates a new instance of will store common client configuration details to permit + /// easy reuse and propagation to multiple, scenario-specific subclients. + /// + /// + /// This client does not provide any model functionality directly and is purely a helper to facilitate the creation + /// of the scenario-specific subclients like . + /// + /// An explicitly defined credential that all clients created by this should use. + /// A common client options definition that all clients created by this should use. + public OpenAIClient(ApiKeyCredential credential, OpenAIClientOptions clientOptions = null) + : this(endpoint: null, credential, clientOptions) + { } + + /// + /// Creates a new instance of will store common client configuration details to permit + /// easy reuse and propagation to multiple, scenario-specific subclients. + /// + /// + /// This client does not provide any model functionality directly and is purely a helper to facilitate the creation + /// of the scenario-specific subclients like . + /// + /// A common client options definition that all clients created by this should use. + public OpenAIClient(OpenAIClientOptions clientOptions) + : this(endpoint: null, credential: null, clientOptions) + { } + + /// + /// Gets a new instance of that reuses the client configuration details provided to + /// the instance. + /// + /// + /// This method is functionally equivalent to using the constructor directly with + /// the same configuration details. + /// + /// A new . + public AssistantClient GetAssistantClient() + => new AssistantClient(_cachedEndpoint, _cachedCredential, _cachedOptions); + + /// + /// Gets a new instance of that reuses the client configuration details provided to + /// the instance. + /// + /// + /// This method is functionally equivalent to using the constructor directly with + /// the same configuration details. + /// + /// A new . + public AudioClient GetAudioClient(string model) + => new AudioClient(_cachedEndpoint, model, _cachedCredential, _cachedOptions); + + /// + /// Gets a new instance of that reuses the client configuration details provided to + /// the instance. + /// + /// + /// This method is functionally equivalent to using the constructor directly with + /// the same configuration details. + /// + /// A new . + public ChatClient GetChatClient(string model) + => new ChatClient(_cachedEndpoint, model, _cachedCredential, _cachedOptions); + + /// + /// Gets a new instance of that reuses the client configuration details provided to + /// the instance. + /// + /// + /// This method is functionally equivalent to using the constructor directly with + /// the same configuration details. + /// + /// A new . + public EmbeddingClient GetEmbeddingClient(string model) + => new EmbeddingClient(_cachedEndpoint, model, _cachedCredential, _cachedOptions); + + /// + /// Gets a new instance of that reuses the client configuration details provided to + /// the instance. + /// + /// + /// This method is functionally equivalent to using the constructor directly with + /// the same configuration details. + /// + /// A new . + public FileClient GetFileClient() + => new FileClient(_cachedEndpoint, _cachedCredential, _cachedOptions); + + /// + /// Gets a new instance of that reuses the client configuration details provided to + /// the instance. + /// + /// + /// This method is functionally equivalent to using the constructor directly with + /// the same configuration details. + /// + /// A new . + public ImageClient GetImageClient(string model) + => new ImageClient(_cachedEndpoint, model, _cachedCredential, _cachedOptions); + + /// + /// Gets a new instance of that reuses the client configuration details provided to + /// the instance. + /// + /// + /// This method is functionally equivalent to using the constructor directly with + /// the same configuration details. + /// + /// A new . + public LegacyCompletionClient GetLegacyCompletionClient() + => new LegacyCompletionClient(_cachedEndpoint, _cachedCredential, _cachedOptions); + + /// + /// Gets a new instance of that reuses the client configuration details provided to + /// the instance. + /// + /// + /// This method is functionally equivalent to using the constructor directly with + /// the same configuration details. + /// + /// A new . + public ModelManagementClient GetModelManagementClient() + => new ModelManagementClient(_cachedEndpoint, _cachedCredential, _cachedOptions); + + /// + /// Gets a new instance of that reuses the client configuration details provided to + /// the instance. + /// + /// + /// This method is functionally equivalent to using the constructor directly with + /// the same configuration details. + /// + /// A new . + public ModerationClient GetModerationClient() + => new ModerationClient(_cachedEndpoint, _cachedCredential, _cachedOptions); +} diff --git a/.dotnet/src/Custom/OpenAIClientConnector.cs b/.dotnet/src/Custom/OpenAIClientConnector.cs new file mode 100644 index 000000000..348d5f48b --- /dev/null +++ b/.dotnet/src/Custom/OpenAIClientConnector.cs @@ -0,0 +1,33 @@ +using System; +using System.ClientModel; +using System.ClientModel.Internal; + + +namespace OpenAI; + +// This internal type facilitates composition rather than inheritance for scenario clients. + +internal partial class OpenAIClientConnector +{ + private static readonly string s_OpenAIEndpointEnvironmentVariable = "OPENAI_ENDPOINT"; + private static readonly string s_OpenAIApiKeyEnvironmentVariable = "OPENAI_API_KEY"; + private static readonly string s_defaultOpenAIV1Endpoint = "https://api.openai.com/v1"; + + internal Internal.OpenAIClient InternalClient { get; } + internal string Model { get; } + internal Uri Endpoint { get; } + + internal OpenAIClientConnector( + string model, + Uri endpoint = null, + ApiKeyCredential credential = null, + OpenAIClientOptions options = null) + { + if (model is null) throw new ArgumentNullException(nameof(model)); + Model = model; + Endpoint ??= new(Environment.GetEnvironmentVariable(s_OpenAIEndpointEnvironmentVariable) ?? s_defaultOpenAIV1Endpoint); + credential ??= new(Environment.GetEnvironmentVariable(s_OpenAIApiKeyEnvironmentVariable) ?? string.Empty); + options ??= new(); + InternalClient = new(Endpoint, credential, options.InternalOptions); + } +} diff --git a/.dotnet/src/Custom/OpenAIClientOptions.cs b/.dotnet/src/Custom/OpenAIClientOptions.cs new file mode 100644 index 000000000..69eb0b2d6 --- /dev/null +++ b/.dotnet/src/Custom/OpenAIClientOptions.cs @@ -0,0 +1,32 @@ +using System.ClientModel; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Threading; + +namespace OpenAI; + +/// +/// Client-level options for the OpenAI service. +/// +public partial class OpenAIClientOptions : RequestOptions +{ + // Note: this type currently proxies RequestOptions properties manually via the matching internal type. This is a + // temporary extra step pending richer integration with code generation. + + internal Internal.OpenAIClientOptions InternalOptions { get; } + + public new void AddPolicy(PipelinePolicy policy, PipelinePosition position) + { + InternalOptions.AddPolicy(policy, position); + } + + public OpenAIClientOptions() + : this(internalOptions: null) + { } + + internal OpenAIClientOptions(Internal.OpenAIClientOptions internalOptions = null) + { + internalOptions ??= new(); + InternalOptions = internalOptions; + } +} diff --git a/.dotnet/src/Generated/OpenAIClient.cs b/.dotnet/src/Generated/OpenAIClient.cs index abe16ec58..014c7aada 100644 --- a/.dotnet/src/Generated/OpenAIClient.cs +++ b/.dotnet/src/Generated/OpenAIClient.cs @@ -51,96 +51,96 @@ public OpenAIClient(Uri endpoint, ApiKeyCredential credential, OpenAIClientOptio _endpoint = endpoint; } - private Audio _cachedAudio; - private Assistants _cachedAssistants; - private Chat _cachedChat; - private Completions _cachedCompletions; - private Embeddings _cachedEmbeddings; - private Files _cachedFiles; - private FineTuning _cachedFineTuning; - private Images _cachedImages; - private Messages _cachedMessages; - private ModelsOps _cachedModelsOps; - private Moderations _cachedModerations; - private Runs _cachedRuns; - private Threads _cachedThreads; + private OpenAI.Internal.Audio _cachedAudio; + private OpenAI.Internal.Assistants _cachedAssistants; + private OpenAI.Internal.Chat _cachedChat; + private OpenAI.Internal.Completions _cachedCompletions; + private OpenAI.Internal.Embeddings _cachedEmbeddings; + private OpenAI.Internal.Files _cachedFiles; + private OpenAI.Internal.FineTuning _cachedFineTuning; + private OpenAI.Internal.Images _cachedImages; + private OpenAI.Internal.Messages _cachedMessages; + private OpenAI.Internal.ModelsOps _cachedModelsOps; + private OpenAI.Internal.Moderations _cachedModerations; + private OpenAI.Internal.Runs _cachedRuns; + private OpenAI.Internal.Threads _cachedThreads; /// Initializes a new instance of Audio. - public virtual Audio GetAudioClient() + public virtual OpenAI.Internal.Audio GetAudioClient() { - return Volatile.Read(ref _cachedAudio) ?? Interlocked.CompareExchange(ref _cachedAudio, new Audio(_pipeline, _credential, _endpoint), null) ?? _cachedAudio; + return Volatile.Read(ref _cachedAudio) ?? Interlocked.CompareExchange(ref _cachedAudio, new OpenAI.Internal.Audio(_pipeline, _credential, _endpoint), null) ?? _cachedAudio; } /// Initializes a new instance of Assistants. - public virtual Assistants GetAssistantsClient() + public virtual OpenAI.Internal.Assistants GetAssistantsClient() { - return Volatile.Read(ref _cachedAssistants) ?? Interlocked.CompareExchange(ref _cachedAssistants, new Assistants(_pipeline, _credential, _endpoint), null) ?? _cachedAssistants; + return Volatile.Read(ref _cachedAssistants) ?? Interlocked.CompareExchange(ref _cachedAssistants, new OpenAI.Internal.Assistants(_pipeline, _credential, _endpoint), null) ?? _cachedAssistants; } /// Initializes a new instance of Chat. - public virtual Chat GetChatClient() + public virtual OpenAI.Internal.Chat GetChatClient() { - return Volatile.Read(ref _cachedChat) ?? Interlocked.CompareExchange(ref _cachedChat, new Chat(_pipeline, _credential, _endpoint), null) ?? _cachedChat; + return Volatile.Read(ref _cachedChat) ?? Interlocked.CompareExchange(ref _cachedChat, new OpenAI.Internal.Chat(_pipeline, _credential, _endpoint), null) ?? _cachedChat; } /// Initializes a new instance of Completions. - public virtual Completions GetCompletionsClient() + public virtual OpenAI.Internal.Completions GetCompletionsClient() { - return Volatile.Read(ref _cachedCompletions) ?? Interlocked.CompareExchange(ref _cachedCompletions, new Completions(_pipeline, _credential, _endpoint), null) ?? _cachedCompletions; + return Volatile.Read(ref _cachedCompletions) ?? Interlocked.CompareExchange(ref _cachedCompletions, new OpenAI.Internal.Completions(_pipeline, _credential, _endpoint), null) ?? _cachedCompletions; } /// Initializes a new instance of Embeddings. - public virtual Embeddings GetEmbeddingsClient() + public virtual OpenAI.Internal.Embeddings GetEmbeddingsClient() { - return Volatile.Read(ref _cachedEmbeddings) ?? Interlocked.CompareExchange(ref _cachedEmbeddings, new Embeddings(_pipeline, _credential, _endpoint), null) ?? _cachedEmbeddings; + return Volatile.Read(ref _cachedEmbeddings) ?? Interlocked.CompareExchange(ref _cachedEmbeddings, new OpenAI.Internal.Embeddings(_pipeline, _credential, _endpoint), null) ?? _cachedEmbeddings; } /// Initializes a new instance of Files. - public virtual Files GetFilesClient() + public virtual OpenAI.Internal.Files GetFilesClient() { - return Volatile.Read(ref _cachedFiles) ?? Interlocked.CompareExchange(ref _cachedFiles, new Files(_pipeline, _credential, _endpoint), null) ?? _cachedFiles; + return Volatile.Read(ref _cachedFiles) ?? Interlocked.CompareExchange(ref _cachedFiles, new OpenAI.Internal.Files(_pipeline, _credential, _endpoint), null) ?? _cachedFiles; } /// Initializes a new instance of FineTuning. - public virtual FineTuning GetFineTuningClient() + public virtual OpenAI.Internal.FineTuning GetFineTuningClient() { - return Volatile.Read(ref _cachedFineTuning) ?? Interlocked.CompareExchange(ref _cachedFineTuning, new FineTuning(_pipeline, _credential, _endpoint), null) ?? _cachedFineTuning; + return Volatile.Read(ref _cachedFineTuning) ?? Interlocked.CompareExchange(ref _cachedFineTuning, new OpenAI.Internal.FineTuning(_pipeline, _credential, _endpoint), null) ?? _cachedFineTuning; } /// Initializes a new instance of Images. - public virtual Images GetImagesClient() + public virtual OpenAI.Internal.Images GetImagesClient() { - return Volatile.Read(ref _cachedImages) ?? Interlocked.CompareExchange(ref _cachedImages, new Images(_pipeline, _credential, _endpoint), null) ?? _cachedImages; + return Volatile.Read(ref _cachedImages) ?? Interlocked.CompareExchange(ref _cachedImages, new OpenAI.Internal.Images(_pipeline, _credential, _endpoint), null) ?? _cachedImages; } /// Initializes a new instance of Messages. - public virtual Messages GetMessagesClient() + public virtual OpenAI.Internal.Messages GetMessagesClient() { - return Volatile.Read(ref _cachedMessages) ?? Interlocked.CompareExchange(ref _cachedMessages, new Messages(_pipeline, _credential, _endpoint), null) ?? _cachedMessages; + return Volatile.Read(ref _cachedMessages) ?? Interlocked.CompareExchange(ref _cachedMessages, new OpenAI.Internal.Messages(_pipeline, _credential, _endpoint), null) ?? _cachedMessages; } /// Initializes a new instance of ModelsOps. - public virtual ModelsOps GetModelsOpsClient() + public virtual OpenAI.Internal.ModelsOps GetModelsOpsClient() { - return Volatile.Read(ref _cachedModelsOps) ?? Interlocked.CompareExchange(ref _cachedModelsOps, new ModelsOps(_pipeline, _credential, _endpoint), null) ?? _cachedModelsOps; + return Volatile.Read(ref _cachedModelsOps) ?? Interlocked.CompareExchange(ref _cachedModelsOps, new OpenAI.Internal.ModelsOps(_pipeline, _credential, _endpoint), null) ?? _cachedModelsOps; } /// Initializes a new instance of Moderations. - public virtual Moderations GetModerationsClient() + public virtual OpenAI.Internal.Moderations GetModerationsClient() { - return Volatile.Read(ref _cachedModerations) ?? Interlocked.CompareExchange(ref _cachedModerations, new Moderations(_pipeline, _credential, _endpoint), null) ?? _cachedModerations; + return Volatile.Read(ref _cachedModerations) ?? Interlocked.CompareExchange(ref _cachedModerations, new OpenAI.Internal.Moderations(_pipeline, _credential, _endpoint), null) ?? _cachedModerations; } /// Initializes a new instance of Runs. - public virtual Runs GetRunsClient() + public virtual OpenAI.Internal.Runs GetRunsClient() { - return Volatile.Read(ref _cachedRuns) ?? Interlocked.CompareExchange(ref _cachedRuns, new Runs(_pipeline, _credential, _endpoint), null) ?? _cachedRuns; + return Volatile.Read(ref _cachedRuns) ?? Interlocked.CompareExchange(ref _cachedRuns, new OpenAI.Internal.Runs(_pipeline, _credential, _endpoint), null) ?? _cachedRuns; } /// Initializes a new instance of Threads. - public virtual Threads GetThreadsClient() + public virtual OpenAI.Internal.Threads GetThreadsClient() { - return Volatile.Read(ref _cachedThreads) ?? Interlocked.CompareExchange(ref _cachedThreads, new Threads(_pipeline, _credential, _endpoint), null) ?? _cachedThreads; + return Volatile.Read(ref _cachedThreads) ?? Interlocked.CompareExchange(ref _cachedThreads, new OpenAI.Internal.Threads(_pipeline, _credential, _endpoint), null) ?? _cachedThreads; } } } diff --git a/.dotnet/src/Generated/OpenAIModelFactory.cs b/.dotnet/src/Generated/OpenAIModelFactory.cs index ad51183cf..f01f31690 100644 --- a/.dotnet/src/Generated/OpenAIModelFactory.cs +++ b/.dotnet/src/Generated/OpenAIModelFactory.cs @@ -9,546 +9,6 @@ namespace OpenAI.Internal.Models /// Model factory for models. internal static partial class OpenAIModelFactory { - /// Initializes a new instance of . - /// One of the available [TTS models](/docs/models/tts): `tts-1` or `tts-1-hd`. - /// The text to generate audio for. The maximum length is 4096 characters. - /// - /// The voice to use when generating the audio. Supported voices are `alloy`, `echo`, `fable`, - /// `onyx`, `nova`, and `shimmer`. Previews of the voices are available in the - /// [Text to speech guide](/docs/guides/text-to-speech/voice-options). - /// - /// The format to audio in. Supported formats are `mp3`, `opus`, `aac`, and `flac`. - /// The speed of the generated audio. Select a value from `0.25` to `4.0`. `1.0` is the default. - /// A new instance for mocking. - public static CreateSpeechRequest CreateSpeechRequest(CreateSpeechRequestModel model = default, string input = null, CreateSpeechRequestVoice voice = default, CreateSpeechRequestResponseFormat? responseFormat = null, double? speed = null) - { - return new CreateSpeechRequest(model, input, voice, responseFormat, speed, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// - /// The audio file object (not file name) to transcribe, in one of these formats: flac, mp3, mp4, - /// mpeg, mpga, m4a, ogg, wav, or webm. - /// - /// ID of the model to use. Only `whisper-1` is currently available. - /// - /// The language of the input audio. Supplying the input language in - /// [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) format will improve accuracy - /// and latency. - /// - /// - /// An optional text to guide the model's style or continue a previous audio segment. The - /// [prompt](/docs/guides/speech-to-text/prompting) should match the audio language. - /// - /// - /// The format of the transcript output, in one of these options: json, text, srt, verbose_json, or - /// vtt. - /// - /// - /// The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more - /// random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, - /// the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to - /// automatically increase the temperature until certain thresholds are hit. - /// - /// A new instance for mocking. - public static CreateTranscriptionRequest CreateTranscriptionRequest(BinaryData file = null, CreateTranscriptionRequestModel model = default, string language = null, string prompt = null, CreateTranscriptionRequestResponseFormat? responseFormat = null, double? temperature = null) - { - return new CreateTranscriptionRequest(file, model, language, prompt, responseFormat, temperature, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// The transcribed text for the provided audio data. - /// The label that describes which operation type generated the accompanying response data. - /// The spoken language that was detected in the audio data. - /// The total duration of the audio processed to produce accompanying transcription information. - /// - /// A collection of information about the timing, probabilities, and other detail of each processed - /// audio segment. - /// - /// A new instance for mocking. - public static CreateTranscriptionResponse CreateTranscriptionResponse(string text = null, CreateTranscriptionResponseTask? task = null, string language = null, TimeSpan? duration = null, IEnumerable segments = null) - { - segments ??= new List(); - - return new CreateTranscriptionResponse(text, task, language, duration, segments?.ToList(), serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// The zero-based index of this segment. - /// - /// The seek position associated with the processing of this audio segment. Seek positions are - /// expressed as hundredths of seconds. The model may process several segments from a single seek - /// position, so while the seek position will never represent a later time than the segment's - /// start, the segment's start may represent a significantly later time than the segment's - /// associated seek position. - /// - /// The time at which this segment started relative to the beginning of the audio. - /// The time at which this segment ended relative to the beginning of the audio. - /// The text that was part of this audio segment. - /// The token IDs matching the text in this audio segment. - /// The temperature score associated with this audio segment. - /// The average log probability associated with this audio segment. - /// The compression ratio of this audio segment. - /// The probability of no speech detection within this audio segment. - /// A new instance for mocking. - public static AudioSegment AudioSegment(long id = default, long seek = default, TimeSpan start = default, TimeSpan end = default, string text = null, IEnumerable tokens = null, double temperature = default, double avgLogprob = default, double compressionRatio = default, double noSpeechProb = default) - { - tokens ??= new List(); - - return new AudioSegment(id, seek, start, end, text, tokens?.ToList(), temperature, avgLogprob, compressionRatio, noSpeechProb, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// - /// The audio file object (not file name) to translate, in one of these formats: flac, mp3, mp4, - /// mpeg, mpga, m4a, ogg, wav, or webm. - /// - /// ID of the model to use. Only `whisper-1` is currently available. - /// - /// An optional text to guide the model's style or continue a previous audio segment. The - /// [prompt](/docs/guides/speech-to-text/prompting) should match the audio language. - /// - /// - /// The format of the transcript output, in one of these options: json, text, srt, verbose_json, or - /// vtt. - /// - /// - /// The sampling temperature, between 0 and 1. Higher values like 0.8 will make the output more - /// random, while lower values like 0.2 will make it more focused and deterministic. If set to 0, - /// the model will use [log probability](https://en.wikipedia.org/wiki/Log_probability) to - /// automatically increase the temperature until certain thresholds are hit. - /// - /// A new instance for mocking. - public static CreateTranslationRequest CreateTranslationRequest(BinaryData file = null, CreateTranslationRequestModel model = default, string prompt = null, CreateTranslationRequestResponseFormat? responseFormat = null, double? temperature = null) - { - return new CreateTranslationRequest(file, model, prompt, responseFormat, temperature, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// The translated text for the provided audio data. - /// The label that describes which operation type generated the accompanying response data. - /// The spoken language that was detected in the audio data. - /// The total duration of the audio processed to produce accompanying translation information. - /// - /// A collection of information about the timing, probabilities, and other detail of each processed - /// audio segment. - /// - /// A new instance for mocking. - public static CreateTranslationResponse CreateTranslationResponse(string text = null, CreateTranslationResponseTask? task = null, string language = null, TimeSpan? duration = null, IEnumerable segments = null) - { - segments ??= new List(); - - return new CreateTranslationResponse(text, task, language, duration, segments?.ToList(), serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// - /// ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to - /// see all of your available models, or see our [Model overview](/docs/models/overview) for - /// descriptions of them. - /// - /// The name of the assistant. The maximum length is 256 characters. - /// The description of the assistant. The maximum length is 512 characters. - /// The system instructions that the assistant uses. The maximum length is 32768 characters. - /// - /// A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. - /// Tools can be of types `code_interpreter`, `retrieval`, or `function`. - /// - /// - /// A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a - /// maximum of 20 files attached to the assistant. Files are ordered by their creation date in - /// ascending order. - /// - /// - /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing - /// additional information about the object in a structured format. Keys can be a maximum of 64 - /// characters long and values can be a maxium of 512 characters long. - /// - /// A new instance for mocking. - public static CreateAssistantRequest CreateAssistantRequest(string model = null, string name = null, string description = null, string instructions = null, IEnumerable tools = null, IEnumerable fileIds = null, IDictionary metadata = null) - { - tools ??= new List(); - fileIds ??= new List(); - metadata ??= new Dictionary(); - - return new CreateAssistantRequest(model, name, description, instructions, tools?.ToList(), fileIds?.ToList(), metadata, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// The identifier, which can be referenced in API endpoints. - /// The object type, which is always `assistant`. - /// The Unix timestamp (in seconds) for when the assistant was created. - /// The name of the assistant. The maximum length is 256 characters. - /// The description of the assistant. The maximum length is 512 characters. - /// - /// ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to - /// see all of your available models, or see our [Model overview](/docs/models/overview) for - /// descriptions of them. - /// - /// The system instructions that the assistant uses. The maximum length is 32768 characters. - /// - /// A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. - /// Tools can be of types `code_interpreter`, `retrieval`, or `function`. - /// - /// - /// A list of [file](/docs/api-reference/files) IDs attached to this assistant. There can be a - /// maximum of 20 files attached to the assistant. Files are ordered by their creation date in - /// ascending order. - /// - /// - /// Set of 16 key-value pairs that can be attached to an object. This can be useful for storing - /// additional information about the object in a structured format. Keys can be a maximum of 64 - /// characters long and values can be a maxium of 512 characters long. - /// - /// A new instance for mocking. - public static AssistantObject AssistantObject(string id = null, AssistantObjectObject @object = default, DateTimeOffset createdAt = default, string name = null, string description = null, string model = null, string instructions = null, IEnumerable tools = null, IEnumerable fileIds = null, IReadOnlyDictionary metadata = null) - { - tools ??= new List(); - fileIds ??= new List(); - metadata ??= new Dictionary(); - - return new AssistantObject(id, @object, createdAt, name, description, model, instructions, tools?.ToList(), fileIds?.ToList(), metadata, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// - /// - /// - /// - /// - /// A new instance for mocking. - public static ListAssistantsResponse ListAssistantsResponse(ListAssistantsResponseObject @object = default, IEnumerable data = null, string firstId = null, string lastId = null, bool hasMore = default) - { - data ??= new List(); - - return new ListAssistantsResponse(@object, data?.ToList(), firstId, lastId, hasMore, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// - /// - /// - /// A new instance for mocking. - public static DeleteAssistantResponse DeleteAssistantResponse(string id = null, bool deleted = default, DeleteAssistantResponseObject @object = default) - { - return new DeleteAssistantResponse(id, deleted, @object, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// The identifier, which can be referenced in API endpoints. - /// The object type, which is always `assistant.file`. - /// The Unix timestamp (in seconds) for when the assistant file was created. - /// The assistant ID that the file is attached to. - /// A new instance for mocking. - public static AssistantFileObject AssistantFileObject(string id = null, AssistantFileObjectObject @object = default, DateTimeOffset createdAt = default, string assistantId = null) - { - return new AssistantFileObject(id, @object, createdAt, assistantId, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// - /// - /// - /// - /// - /// A new instance for mocking. - public static ListAssistantFilesResponse ListAssistantFilesResponse(ListAssistantFilesResponseObject @object = default, IEnumerable data = null, string firstId = null, string lastId = null, bool hasMore = default) - { - data ??= new List(); - - return new ListAssistantFilesResponse(@object, data?.ToList(), firstId, lastId, hasMore, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// - /// - /// - /// A new instance for mocking. - public static DeleteAssistantFileResponse DeleteAssistantFileResponse(string id = null, bool deleted = default, DeleteAssistantFileResponseObject @object = default) - { - return new DeleteAssistantFileResponse(id, deleted, @object, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// - /// A list of messages comprising the conversation so far. - /// [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_format_inputs_to_ChatGPT_models.ipynb). - /// - /// - /// ID of the model to use. See the [model endpoint compatibility](/docs/models/model-endpoint-compatibility) - /// table for details on which models work with the Chat API. - /// - /// - /// Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing - /// frequency in the text so far, decreasing the model's likelihood to repeat the same line - /// verbatim. - /// - /// [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) - /// - /// - /// Modify the likelihood of specified tokens appearing in the completion. - /// - /// Accepts a JSON object that maps tokens (specified by their token ID in the tokenizer) to an - /// associated bias value from -100 to 100. Mathematically, the bias is added to the logits - /// generated by the model prior to sampling. The exact effect will vary per model, but values - /// between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 - /// should result in a ban or exclusive selection of the relevant token. - /// - /// - /// Whether to return log probabilities of the output tokens or not. If true, returns the log - /// probabilities of each output token returned in the `content` of `message`. This option is - /// currently not available on the `gpt-4-vision-preview` model. - /// - /// - /// An integer between 0 and 5 specifying the number of most likely tokens to return at each token - /// position, each with an associated log probability. `logprobs` must be set to `true` if this - /// parameter is used. - /// - /// - /// The maximum number of [tokens](/tokenizer) that can be generated in the chat completion. - /// - /// The total length of input tokens and generated tokens is limited by the model's context length. - /// [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) - /// for counting tokens. - /// - /// - /// How many chat completion choices to generate for each input message. Note that you will be - /// charged based on the number of generated tokens across all of the choices. Keep `n` as `1` to - /// minimize costs. - /// - /// - /// Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear - /// in the text so far, increasing the model's likelihood to talk about new topics. - /// - /// [See more information about frequency and presence penalties.](/docs/guides/gpt/parameter-details) - /// - /// - /// An object specifying the format that the model must output. Compatible with - /// [GPT-4 Turbo](/docs/models/gpt-4-and-gpt-4-turbo) and `gpt-3.5-turbo-1106`. - /// - /// 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. - /// - /// - /// This feature is in Beta. - /// - /// If specified, our system will make a best effort to sample deterministically, such that - /// repeated requests with the same `seed` and parameters should return the same result. - /// - /// Determinism is not guaranteed, and you should refer to the `system_fingerprint` response - /// parameter to monitor changes in the backend. - /// - /// Up to 4 sequences where the API will stop generating further tokens. - /// - /// If set, partial message deltas will be sent, like in ChatGPT. Tokens will be sent as data-only - /// [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format) - /// as they become available, with the stream terminated by a `data: [DONE]` message. - /// [Example Python code](https://cookbook.openai.com/examples/how_to_stream_completions). - /// - /// - /// What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output - /// more random, while lower values like 0.2 will make it more focused and deterministic. - /// - /// We generally recommend altering this or `top_p` but not both. - /// - /// - /// An alternative to sampling with temperature, called nucleus sampling, where the model considers - /// the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising - /// the top 10% probability mass are considered. - /// - /// We generally recommend altering this or `temperature` but not both. - /// - /// - /// A list of tools the model may call. Currently, only functions are supported as a tool. Use this - /// to provide a list of functions the model may generate JSON inputs for. - /// - /// - /// - /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect - /// abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). - /// - /// - /// Deprecated in favor of `tool_choice`. - /// - /// Controls which (if any) function is called by the model. `none` means the model will not call a - /// function and instead generates a message. `auto` means the model can pick between generating a - /// message or calling a function. Specifying a particular function via `{"name": "my_function"}` - /// forces the model to call that function. - /// - /// `none` is the default when no functions are present. `auto` is the default if functions are - /// present. - /// - /// - /// Deprecated in favor of `tools`. - /// - /// A list of functions the model may generate JSON inputs for. - /// - /// A new instance for mocking. - public static CreateChatCompletionRequest CreateChatCompletionRequest(IEnumerable messages = null, CreateChatCompletionRequestModel model = default, double? frequencyPenalty = null, IDictionary logitBias = null, bool? logprobs = null, long? topLogprobs = null, long? maxTokens = null, long? n = null, double? presencePenalty = null, CreateChatCompletionRequestResponseFormat responseFormat = null, long? seed = null, BinaryData stop = null, bool? stream = null, double? temperature = null, double? topP = null, IEnumerable tools = null, BinaryData toolChoice = null, string user = null, BinaryData functionCall = null, IEnumerable functions = null) - { - messages ??= new List(); - logitBias ??= new Dictionary(); - tools ??= new List(); - functions ??= new List(); - - return new CreateChatCompletionRequest(messages?.ToList(), model, frequencyPenalty, logitBias, logprobs, topLogprobs, maxTokens, n, presencePenalty, responseFormat, seed, stop, stream, temperature, topP, tools?.ToList(), toolChoice, user, functionCall, functions?.ToList(), serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// The ID of the tool call. - /// The type of the tool. Currently, only `function` is supported. - /// The function that the model called. - /// A new instance for mocking. - public static ChatCompletionMessageToolCall ChatCompletionMessageToolCall(string id = null, ChatCompletionMessageToolCallType type = default, ChatCompletionMessageToolCallFunction function = null) - { - return new ChatCompletionMessageToolCall(id, type, function, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// The type of the tool. Currently, only `function` is supported. - /// - /// A new instance for mocking. - public static ChatCompletionTool ChatCompletionTool(ChatCompletionToolType type = default, FunctionObject function = null) - { - return new ChatCompletionTool(type, function, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// - /// A description of what the function does, used by the model to choose when and how to call the - /// function. - /// - /// - /// The name of the function to be called. Must be a-z, A-Z, 0-9, or contain underscores and - /// dashes, with a maximum length of 64. - /// - /// - /// A new instance for mocking. - public static ChatCompletionFunctions ChatCompletionFunctions(string description = null, string name = null, FunctionParameters parameters = null) - { - return new ChatCompletionFunctions(description, name, parameters, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// A unique identifier for the chat completion. - /// A list of chat completion choices. Can be more than one if `n` is greater than 1. - /// The Unix timestamp (in seconds) of when the chat completion was created. - /// The model used for the chat completion. - /// - /// 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. - /// - /// The object type, which is always `chat.completion`. - /// - /// A new instance for mocking. - public static CreateChatCompletionResponse CreateChatCompletionResponse(string id = null, IEnumerable choices = null, DateTimeOffset created = default, string model = null, string systemFingerprint = null, CreateChatCompletionResponseObject @object = default, CompletionUsage usage = null) - { - choices ??= new List(); - - return new CreateChatCompletionResponse(id, choices?.ToList(), created, model, systemFingerprint, @object, usage, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// - /// The reason the model stopped generating tokens. This will be `stop` if the model hit a - /// natural stop point or a provided stop sequence, `length` if the maximum number of tokens - /// specified in the request was reached, `content_filter` if content was omitted due to a flag - /// from our content filters, `tool_calls` if the model called a tool, or `function_call` - /// (deprecated) if the model called a function. - /// - /// The index of the choice in the list of choices. - /// - /// Log probability information for the choice. - /// A new instance for mocking. - public static CreateChatCompletionResponseChoice CreateChatCompletionResponseChoice(CreateChatCompletionResponseChoiceFinishReason finishReason = default, long index = default, ChatCompletionResponseMessage message = null, CreateChatCompletionResponseChoiceLogprobs logprobs = null) - { - return new CreateChatCompletionResponseChoice(finishReason, index, message, logprobs, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// The contents of the message. - /// - /// The role of the author of this message. - /// Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model. - /// A new instance for mocking. - public static ChatCompletionResponseMessage ChatCompletionResponseMessage(string content = null, IEnumerable toolCalls = null, ChatCompletionResponseMessageRole role = default, ChatCompletionResponseMessageFunctionCall functionCall = null) - { - toolCalls ??= new List(); - - return new ChatCompletionResponseMessage(content, toolCalls?.ToList(), role, functionCall, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// - /// The arguments to call the function with, as generated by the model in JSON format. Note that - /// the model does not always generate valid JSON, and may hallucinate parameters not defined by - /// your function schema. Validate the arguments in your code before calling your function. - /// - /// The name of the function to call. - /// A new instance for mocking. - public static ChatCompletionResponseMessageFunctionCall ChatCompletionResponseMessageFunctionCall(string arguments = null, string name = null) - { - return new ChatCompletionResponseMessageFunctionCall(arguments, name, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// - /// A new instance for mocking. - public static CreateChatCompletionResponseChoiceLogprobs CreateChatCompletionResponseChoiceLogprobs(IEnumerable content = null) - { - content ??= new List(); - - return new CreateChatCompletionResponseChoiceLogprobs(content?.ToList(), serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// The token. - /// The log probability of this token. - /// - /// A list of integers representing the UTF-8 bytes representation of the token. Useful in - /// instances where characters are represented by multiple tokens and their byte representations - /// must be combined to generate the correct text representation. Can be `null` if there is no - /// bytes representation for the token. - /// - /// - /// List of the most likely tokens and their log probability, at this token position. In rare - /// cases, there may be fewer than the number of requested `top_logprobs` returned. - /// - /// A new instance for mocking. - public static ChatCompletionTokenLogprob ChatCompletionTokenLogprob(string token = null, double logprob = default, IEnumerable bytes = null, IEnumerable topLogprobs = null) - { - bytes ??= new List(); - topLogprobs ??= new List(); - - return new ChatCompletionTokenLogprob(token, logprob, bytes?.ToList(), topLogprobs?.ToList(), serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// The token. - /// The log probability of this token. - /// - /// A list of integers representing the UTF-8 bytes representation of the token. Useful in - /// instances where characters are represented by multiple tokens and their byte representations - /// must be combined to generate the correct text representation. Can be `null` if there is no - /// bytes representation for the token. - /// - /// A new instance for mocking. - public static ChatCompletionTokenLogprobTopLogprob ChatCompletionTokenLogprobTopLogprob(string token = null, double logprob = default, IEnumerable bytes = null) - { - bytes ??= new List(); - - return new ChatCompletionTokenLogprobTopLogprob(token, logprob, bytes?.ToList(), serializedAdditionalRawData: null); - } - /// Initializes a new instance of . /// Number of tokens in the prompt. /// Number of tokens in the generated completion. @@ -724,118 +184,6 @@ public static CreateCompletionResponseChoiceLogprobs CreateCompletionResponseCho return new CreateCompletionResponseChoiceLogprobs(tokens?.ToList(), tokenLogprobs?.ToList(), topLogprobs?.ToList(), textOffset?.ToList(), serializedAdditionalRawData: null); } - /// Initializes a new instance of . - /// - /// Input text to embed, encoded as a string or array of tokens. To embed multiple inputs in a - /// single request, pass an array of strings or array of token arrays. Each input must not exceed - /// the max input tokens for the model (8191 tokens for `text-embedding-ada-002`) and cannot be an - /// empty string. - /// [Example Python code](https://github.com/openai/openai-cookbook/blob/main/examples/How_to_count_tokens_with_tiktoken.ipynb) - /// for counting tokens. - /// - /// - /// ID of the model to use. You can use the [List models](/docs/api-reference/models/list) API to - /// see all of your available models, or see our [Model overview](/docs/models/overview) for - /// descriptions of them. - /// - /// - /// The format to return the embeddings in. Can be either `float` or - /// [`base64`](https://pypi.org/project/pybase64/). - /// - /// - /// The number of dimensions the resulting output embeddings should have. Only supported in - /// `text-embedding-3` and later models. - /// - /// - /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect - /// abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). - /// - /// A new instance for mocking. - public static CreateEmbeddingRequest CreateEmbeddingRequest(BinaryData input = null, CreateEmbeddingRequestModel model = default, CreateEmbeddingRequestEncodingFormat? encodingFormat = null, long? dimensions = null, string user = null) - { - return new CreateEmbeddingRequest(input, model, encodingFormat, dimensions, user, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// The list of embeddings generated by the model. - /// The name of the model used to generate the embedding. - /// The object type, which is always "list". - /// The usage information for the request. - /// A new instance for mocking. - public static CreateEmbeddingResponse CreateEmbeddingResponse(IEnumerable data = null, string model = null, CreateEmbeddingResponseObject @object = default, EmbeddingUsage usage = null) - { - data ??= new List(); - - return new CreateEmbeddingResponse(data?.ToList(), model, @object, usage, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// The index of the embedding in the list of embeddings. - /// - /// The embedding vector, which is a list of floats. The length of vector depends on the model as - /// listed in the [embedding guide](/docs/guides/embeddings). - /// - /// The object type, which is always "embedding". - /// A new instance for mocking. - public static Embedding Embedding(long index = default, BinaryData embeddingProperty = null, EmbeddingObject @object = default) - { - return new Embedding(index, embeddingProperty, @object, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// The number of tokens used by the prompt. - /// The total number of tokens used by the request. - /// A new instance for mocking. - public static EmbeddingUsage EmbeddingUsage(long promptTokens = default, long totalTokens = default) - { - return new EmbeddingUsage(promptTokens, totalTokens, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// The file identifier, which can be referenced in the API endpoints. - /// The size of the file, in bytes. - /// The Unix timestamp (in seconds) for when the file was created. - /// The name of the file. - /// The object type, which is always "file". - /// - /// The intended purpose of the file. Supported values are `fine-tune`, `fine-tune-results`, - /// `assistants`, and `assistants_output`. - /// - /// - /// Deprecated. The current status of the file, which can be either `uploaded`, `processed`, or - /// `error`. - /// - /// - /// Deprecated. For details on why a fine-tuning training file failed validation, see the `error` - /// field on `fine_tuning.job`. - /// - /// A new instance for mocking. - public static OpenAIFile OpenAIFile(string id = null, long bytes = default, DateTimeOffset createdAt = default, string filename = null, OpenAIFileObject @object = default, OpenAIFilePurpose purpose = default, OpenAIFileStatus status = default, string statusDetails = null) - { - return new OpenAIFile(id, bytes, createdAt, filename, @object, purpose, status, statusDetails, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// - /// - /// A new instance for mocking. - public static ListFilesResponse ListFilesResponse(IEnumerable data = null, ListFilesResponseObject @object = default) - { - data ??= new List(); - - return new ListFilesResponse(data?.ToList(), @object, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// - /// - /// - /// A new instance for mocking. - public static DeleteFileResponse DeleteFileResponse(string id = null, DeleteFileResponseObject @object = default, bool deleted = default) - { - return new DeleteFileResponse(id, @object, deleted, serializedAdditionalRawData: null); - } - /// Initializes a new instance of . /// /// The ID of an uploaded file that contains training data. @@ -988,105 +336,6 @@ public static FineTuningJobEvent FineTuningJobEvent(string id = null, string @ob return new FineTuningJobEvent(id, @object, createdAt, level, message, serializedAdditionalRawData: null); } - /// Initializes a new instance of . - /// - /// A text description of the desired image(s). The maximum length is 1000 characters for - /// `dall-e-2` and 4000 characters for `dall-e-3`. - /// - /// The model to use for image generation. - /// - /// The number of images to generate. Must be between 1 and 10. For `dall-e-3`, only `n=1` is - /// supported. - /// - /// - /// The quality of the image that will be generated. `hd` creates images with finer details and - /// greater consistency across the image. This param is only supported for `dall-e-3`. - /// - /// The format in which the generated images are returned. Must be one of `url` or `b64_json`. - /// - /// 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. - /// - /// - /// The style of the generated images. Must be one of `vivid` or `natural`. Vivid causes the model - /// to lean towards generating hyper-real and dramatic images. Natural causes the model to produce - /// more natural, less hyper-real looking images. This param is only supported for `dall-e-3`. - /// - /// - /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect - /// abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). - /// - /// A new instance for mocking. - public static CreateImageRequest CreateImageRequest(string prompt = null, CreateImageRequestModel? model = null, long? n = null, CreateImageRequestQuality? quality = null, CreateImageRequestResponseFormat? responseFormat = null, CreateImageRequestSize? size = null, CreateImageRequestStyle? style = null, string user = null) - { - return new CreateImageRequest(prompt, model, n, quality, responseFormat, size, style, user, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// - /// - /// A new instance for mocking. - public static ImagesResponse ImagesResponse(DateTimeOffset created = default, IEnumerable data = null) - { - data ??= new List(); - - return new ImagesResponse(created, data?.ToList(), serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// The base64-encoded JSON of the generated image, if `response_format` is `b64_json`. - /// The URL of the generated image, if `response_format` is `url` (default). - /// The prompt that was used to generate the image, if there was any revision to the prompt. - /// A new instance for mocking. - public static Image Image(BinaryData b64Json = null, Uri url = null, string revisedPrompt = null) - { - return new Image(b64Json, url, revisedPrompt, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// - /// The image to edit. Must be a valid PNG file, less than 4MB, and square. If mask is not - /// provided, image must have transparency, which will be used as the mask. - /// - /// A text description of the desired image(s). The maximum length is 1000 characters. - /// - /// An additional image whose fully transparent areas (e.g. where alpha is zero) indicate where - /// `image` should be edited. Must be a valid PNG file, less than 4MB, and have the same dimensions - /// as `image`. - /// - /// The model to use for image generation. Only `dall-e-2` is supported at this time. - /// The number of images to generate. Must be between 1 and 10. - /// The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`. - /// The format in which the generated images are returned. Must be one of `url` or `b64_json`. - /// - /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect - /// abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). - /// - /// A new instance for mocking. - public static CreateImageEditRequest CreateImageEditRequest(BinaryData image = null, string prompt = null, BinaryData mask = null, CreateImageEditRequestModel? model = null, long? n = null, CreateImageEditRequestSize? size = null, CreateImageEditRequestResponseFormat? responseFormat = null, string user = null) - { - return new CreateImageEditRequest(image, prompt, mask, model, n, size, responseFormat, user, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// - /// The image to use as the basis for the variation(s). Must be a valid PNG file, less than 4MB, - /// and square. - /// - /// The model to use for image generation. Only `dall-e-2` is supported at this time. - /// The number of images to generate. Must be between 1 and 10. - /// The format in which the generated images are returned. Must be one of `url` or `b64_json`. - /// The size of the generated images. Must be one of `256x256`, `512x512`, or `1024x1024`. - /// - /// A unique identifier representing your end-user, which can help OpenAI to monitor and detect - /// abuse. [Learn more](/docs/guides/safety-best-practices/end-user-ids). - /// - /// A new instance for mocking. - public static CreateImageVariationRequest CreateImageVariationRequest(BinaryData image = null, CreateImageVariationRequestModel? model = null, long? n = null, CreateImageVariationRequestResponseFormat? responseFormat = null, CreateImageVariationRequestSize? size = null, string user = null) - { - return new CreateImageVariationRequest(image, model, n, responseFormat, size, user, serializedAdditionalRawData: null); - } - /// Initializes a new instance of . /// The role of the entity that is creating the message. Currently only `user` is supported. /// The content of the message. @@ -1215,99 +464,6 @@ public static DeleteModelResponse DeleteModelResponse(string id = null, bool del return new DeleteModelResponse(id, deleted, @object, serializedAdditionalRawData: null); } - /// Initializes a new instance of . - /// The input text to classify. - /// - /// Two content moderations models are available: `text-moderation-stable` and - /// `text-moderation-latest`. The default is `text-moderation-latest` which will be automatically - /// upgraded over time. This ensures you are always using our most accurate model. If you use - /// `text-moderation-stable`, we will provide advanced notice before updating the model. Accuracy - /// of `text-moderation-stable` may be slightly lower than for `text-moderation-latest`. - /// - /// A new instance for mocking. - public static CreateModerationRequest CreateModerationRequest(BinaryData input = null, CreateModerationRequestModel? model = null) - { - return new CreateModerationRequest(input, model, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// The unique identifier for the moderation request. - /// The model used to generate the moderation results. - /// A list of moderation objects. - /// A new instance for mocking. - public static CreateModerationResponse CreateModerationResponse(string id = null, string model = null, IEnumerable results = null) - { - results ??= new List(); - - return new CreateModerationResponse(id, model, results?.ToList(), serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// Whether the content violates [OpenAI's usage policies](/policies/usage-policies). - /// A list of the categories, and whether they are flagged or not. - /// A list of the categories along with their scores as predicted by model. - /// A new instance for mocking. - public static CreateModerationResponseResult CreateModerationResponseResult(bool flagged = default, CreateModerationResponseResultCategories categories = null, CreateModerationResponseResultCategoryScores categoryScores = null) - { - return new CreateModerationResponseResult(flagged, categories, categoryScores, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// - /// Content that expresses, incites, or promotes hate based on race, gender, ethnicity, - /// religion, nationality, sexual orientation, disability status, or caste. Hateful content - /// aimed at non-protected groups (e.g., chess players) is harrassment. - /// - /// - /// Hateful content that also includes violence or serious harm towards the targeted group - /// based on race, gender, ethnicity, religion, nationality, sexual orientation, disability - /// status, or caste. - /// - /// Content that expresses, incites, or promotes harassing language towards any target. - /// Harassment content that also includes violence or serious harm towards any target. - /// - /// Content that promotes, encourages, or depicts acts of self-harm, such as suicide, cutting, - /// and eating disorders. - /// - /// - /// Content where the speaker expresses that they are engaging or intend to engage in acts of - /// self-harm, such as suicide, cutting, and eating disorders. - /// - /// - /// Content that encourages performing acts of self-harm, such as suicide, cutting, and eating - /// disorders, or that gives instructions or advice on how to commit such acts. - /// - /// - /// Content meant to arouse sexual excitement, such as the description of sexual activity, or - /// that promotes sexual services (excluding sex education and wellness). - /// - /// Sexual content that includes an individual who is under 18 years old. - /// Content that depicts death, violence, or physical injury. - /// Content that depicts death, violence, or physical injury in graphic detail. - /// A new instance for mocking. - public static CreateModerationResponseResultCategories CreateModerationResponseResultCategories(bool hate = default, bool hateThreatening = default, bool harassment = default, bool harassmentThreatening = default, bool selfHarm = default, bool selfHarmIntent = default, bool selfHarmInstructions = default, bool sexual = default, bool sexualMinors = default, bool violence = default, bool violenceGraphic = default) - { - return new CreateModerationResponseResultCategories(hate, hateThreatening, harassment, harassmentThreatening, selfHarm, selfHarmIntent, selfHarmInstructions, sexual, sexualMinors, violence, violenceGraphic, serializedAdditionalRawData: null); - } - - /// Initializes a new instance of . - /// The score for the category 'hate'. - /// The score for the category 'hate/threatening'. - /// The score for the category 'harassment'. - /// The score for the category 'harassment/threatening'. - /// The score for the category 'self-harm'. - /// The score for the category 'self-harm/intent'. - /// The score for the category 'self-harm/instructive'. - /// The score for the category 'sexual'. - /// The score for the category 'sexual/minors'. - /// The score for the category 'violence'. - /// The score for the category 'violence/graphic'. - /// A new instance for mocking. - public static CreateModerationResponseResultCategoryScores CreateModerationResponseResultCategoryScores(double hate = default, double hateThreatening = default, double harassment = default, double harassmentThreatening = default, double selfHarm = default, double selfHarmIntent = default, double selfHarmInstructions = default, double sexual = default, double sexualMinors = default, double violence = default, double violenceGraphic = default) - { - return new CreateModerationResponseResultCategoryScores(hate, hateThreatening, harassment, harassmentThreatening, selfHarm, selfHarmIntent, selfHarmInstructions, sexual, sexualMinors, violence, violenceGraphic, serializedAdditionalRawData: null); - } - /// Initializes a new instance of . /// The ID of the [assistant](/docs/api-reference/assistants) to use to execute this run. /// If no thread is provided, an empty thread will be created. diff --git a/.dotnet/src/OpenAI.csproj b/.dotnet/src/OpenAI.csproj index e03a4dc1e..b473b4e63 100644 --- a/.dotnet/src/OpenAI.csproj +++ b/.dotnet/src/OpenAI.csproj @@ -11,6 +11,6 @@ - + diff --git a/.dotnet/src/Polyfill/System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute.cs b/.dotnet/src/Polyfill/System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute.cs new file mode 100644 index 000000000..26cd00bce --- /dev/null +++ b/.dotnet/src/Polyfill/System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute.cs @@ -0,0 +1,8 @@ +#if !NET7_0_OR_GREATER + +namespace System.Diagnostics.CodeAnalysis; + +[AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)] +internal sealed class SetsRequiredMembersAttribute : Attribute { } + +#endif // !NET7_0_OR_GREATER diff --git a/.dotnet/src/Polyfill/System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute.cs b/.dotnet/src/Polyfill/System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute.cs new file mode 100644 index 000000000..1b9abe47c --- /dev/null +++ b/.dotnet/src/Polyfill/System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute.cs @@ -0,0 +1,15 @@ +#if !NET7_0_OR_GREATER + +namespace System.Runtime.CompilerServices; + +[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = false)] +internal sealed class CompilerFeatureRequiredAttribute(string featureName) : Attribute +{ + public string FeatureName { get; } = featureName; + public bool IsOptional { get; init; } + + public const string RefStructs = nameof(RefStructs); + public const string RequiredMembers = nameof(RequiredMembers); +} + +#endif // !NET7_0_OR_GREATER diff --git a/.dotnet/src/Polyfill/System.Runtime.CompilerServices.IsExternalInit.cs b/.dotnet/src/Polyfill/System.Runtime.CompilerServices.IsExternalInit.cs new file mode 100644 index 000000000..f4b6d744f --- /dev/null +++ b/.dotnet/src/Polyfill/System.Runtime.CompilerServices.IsExternalInit.cs @@ -0,0 +1,9 @@ +#if !NET5_0_OR_GREATER + +using System.ComponentModel; +namespace System.Runtime.CompilerServices; + +[EditorBrowsable(EditorBrowsableState.Never)] +internal static class IsExternalInit { } + +#endif // !NET5_0_OR_GREATER diff --git a/.dotnet/src/Polyfill/System.Runtime.CompilerServices.RequiredMemberAttribute.cs b/.dotnet/src/Polyfill/System.Runtime.CompilerServices.RequiredMemberAttribute.cs new file mode 100644 index 000000000..216d76910 --- /dev/null +++ b/.dotnet/src/Polyfill/System.Runtime.CompilerServices.RequiredMemberAttribute.cs @@ -0,0 +1,8 @@ +#if !NET7_0_OR_GREATER + +namespace System.Runtime.CompilerServices; + +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)] +internal sealed class RequiredMemberAttribute : Attribute { } + +#endif // !NET7_0_OR_GREATER diff --git a/.dotnet/src/Utility/GenericActionPipelinePolicy.cs b/.dotnet/src/Utility/GenericActionPipelinePolicy.cs new file mode 100644 index 000000000..41ccef5ec --- /dev/null +++ b/.dotnet/src/Utility/GenericActionPipelinePolicy.cs @@ -0,0 +1,35 @@ +using System; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace OpenAI; + +internal partial class GenericActionPipelinePolicy : PipelinePolicy +{ + private Action _processMessageAction; + + public GenericActionPipelinePolicy(Action processMessageAction) + { + _processMessageAction = processMessageAction; + } + + public override void Process(PipelineMessage message, IReadOnlyList pipeline, int currentIndex) + { + _processMessageAction(message); + if (currentIndex < pipeline.Count - 1) + { + pipeline[currentIndex + 1].Process(message, pipeline, currentIndex + 1); + } + } + + public override async ValueTask ProcessAsync(PipelineMessage message, IReadOnlyList pipeline, int currentIndex) + { + _processMessageAction(message); + if (currentIndex < pipeline.Count - 1) + { + await pipeline[currentIndex + 1].ProcessAsync(message, pipeline, currentIndex + 1); + } + } +} \ No newline at end of file diff --git a/.dotnet/src/Utility/SseAsyncEnumerator.cs b/.dotnet/src/Utility/SseAsyncEnumerator.cs new file mode 100644 index 000000000..743a1bedd --- /dev/null +++ b/.dotnet/src/Utility/SseAsyncEnumerator.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.CompilerServices; +using System.Text.Json; +using System.Threading; + +namespace OpenAI; + +internal static class SseAsyncEnumerator +{ + internal static async IAsyncEnumerable EnumerateFromSseStream( + Stream stream, + Func> multiElementDeserializer, + [EnumeratorCancellation] CancellationToken cancellationToken = default) + { + try + { + using SseReader sseReader = new(stream); + while (!cancellationToken.IsCancellationRequested) + { + SseLine? sseEvent = await sseReader.TryReadSingleFieldEventAsync().ConfigureAwait(false); + if (sseEvent is not null) + { + ReadOnlyMemory name = sseEvent.Value.FieldName; + if (!name.Span.SequenceEqual("data".AsSpan())) + { + throw new InvalidDataException(); + } + ReadOnlyMemory value = sseEvent.Value.FieldValue; + if (value.Span.SequenceEqual("[DONE]".AsSpan())) + { + break; + } + using JsonDocument sseMessageJson = JsonDocument.Parse(value); + IEnumerable newItems = multiElementDeserializer.Invoke(sseMessageJson.RootElement); + foreach (T item in newItems) + { + yield return item; + } + } + } + } + finally + { + // Always dispose the stream immediately once enumeration is complete for any reason + stream.Dispose(); + } + } + + internal static IAsyncEnumerable EnumerateFromSseStream( + Stream stream, + Func elementDeserializer, + CancellationToken cancellationToken = default) + => EnumerateFromSseStream( + stream, + (element) => new T[] { elementDeserializer.Invoke(element) }, + cancellationToken); +} \ No newline at end of file diff --git a/.dotnet/src/Utility/SseLine.cs b/.dotnet/src/Utility/SseLine.cs new file mode 100644 index 000000000..4d82315f9 --- /dev/null +++ b/.dotnet/src/Utility/SseLine.cs @@ -0,0 +1,29 @@ +using System; + +namespace OpenAI; + +// SSE specification: https://html.spec.whatwg.org/multipage/server-sent-events.html#parsing-an-event-stream +internal readonly struct SseLine +{ + private readonly string _original; + private readonly int _colonIndex; + private readonly int _valueIndex; + + public static SseLine Empty { get; } = new SseLine(string.Empty, 0, false); + + internal SseLine(string original, int colonIndex, bool hasSpaceAfterColon) + { + _original = original; + _colonIndex = colonIndex; + _valueIndex = colonIndex + (hasSpaceAfterColon ? 2 : 1); + } + + public bool IsEmpty => _original.Length == 0; + public bool IsComment => !IsEmpty && _original[0] == ':'; + + // TODO: we should not expose UTF16 publicly + public ReadOnlyMemory FieldName => _original.AsMemory(0, _colonIndex); + public ReadOnlyMemory FieldValue => _original.AsMemory(_valueIndex); + + public override string ToString() => _original; +} \ No newline at end of file diff --git a/.dotnet/src/Utility/SseReader.cs b/.dotnet/src/Utility/SseReader.cs new file mode 100644 index 000000000..cf0301408 --- /dev/null +++ b/.dotnet/src/Utility/SseReader.cs @@ -0,0 +1,118 @@ +using System; +using System.ClientModel; +using System.ClientModel.Internal; +using System.IO; +using System.Threading.Tasks; + +namespace OpenAI; + +internal sealed class SseReader : IDisposable + { + private readonly Stream _stream; + private readonly StreamReader _reader; + private bool _disposedValue; + + public SseReader(Stream stream) + { + _stream = stream; + _reader = new StreamReader(stream); + } + + public SseLine? TryReadSingleFieldEvent() + { + while (true) + { + SseLine? line = TryReadLine(); + if (line == null) + return null; + if (line.Value.IsEmpty) + throw new InvalidDataException("event expected."); + SseLine? empty = TryReadLine(); + if (empty != null && !empty.Value.IsEmpty) + throw new NotSupportedException("Multi-filed events not supported."); + if (!line.Value.IsComment) + return line; // skip comment lines + } + } + + // TODO: we should support cancellation tokens, but StreamReader does not in NS2 + public async Task TryReadSingleFieldEventAsync() + { + while (true) + { + SseLine? line = await TryReadLineAsync().ConfigureAwait(false); + if (line == null) + return null; + if (line.Value.IsEmpty) + throw new InvalidDataException("event expected."); + SseLine? empty = await TryReadLineAsync().ConfigureAwait(false); + if (empty != null && !empty.Value.IsEmpty) + throw new NotSupportedException("Multi-filed events not supported."); + if (!line.Value.IsComment) + return line; // skip comment lines + } + } + + public SseLine? TryReadLine() + { + string lineText = _reader.ReadLine(); + if (lineText == null) + return null; + if (lineText.Length == 0) + return SseLine.Empty; + if (TryParseLine(lineText, out SseLine line)) + return line; + return null; + } + + // TODO: we should support cancellation tokens, but StreamReader does not in NS2 + public async Task TryReadLineAsync() + { + string lineText = await _reader.ReadLineAsync().ConfigureAwait(false); + if (lineText == null) + return null; + if (lineText.Length == 0) + return SseLine.Empty; + if (TryParseLine(lineText, out SseLine line)) + return line; + return null; + } + + private static bool TryParseLine(string lineText, out SseLine line) + { + if (lineText.Length == 0) + { + line = default; + return false; + } + + ReadOnlySpan lineSpan = lineText.AsSpan(); + int colonIndex = lineSpan.IndexOf(':'); + ReadOnlySpan fieldValue = lineSpan.Slice(colonIndex + 1); + + bool hasSpace = false; + if (fieldValue.Length > 0 && fieldValue[0] == ' ') + hasSpace = true; + line = new SseLine(lineText, colonIndex, hasSpace); + return true; + } + + private void Dispose(bool disposing) + { + if (!_disposedValue) + { + if (disposing) + { + _reader.Dispose(); + _stream.Dispose(); + } + + _disposedValue = true; + } + } + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + } \ No newline at end of file diff --git a/.dotnet/src/Utility/StreamingResult.cs b/.dotnet/src/Utility/StreamingResult.cs new file mode 100644 index 000000000..a1b6ff538 --- /dev/null +++ b/.dotnet/src/Utility/StreamingResult.cs @@ -0,0 +1,95 @@ +using System.ClientModel; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Threading; +using System.Collections.Generic; +using System; + +namespace OpenAI; + +/// +/// Represents an operation response with streaming content that can be deserialized and enumerated while the response +/// is still being received. +/// +/// The data type representative of distinct, streamable items. +public class StreamingClientResult + : IDisposable + , IAsyncEnumerable +{ + private ClientResult _rawResult { get; } + private IAsyncEnumerable _asyncEnumerableSource { get; } + private bool _disposedValue { get; set; } + + private StreamingClientResult() { } + + private StreamingClientResult( + ClientResult rawResult, + Func> asyncEnumerableProcessor) + { + _rawResult = rawResult; + _asyncEnumerableSource = asyncEnumerableProcessor.Invoke(rawResult); + } + + /// + /// Creates a new instance of using the provided underlying HTTP response. The + /// provided function will be used to resolve the response into an asynchronous enumeration of streamed response + /// items. + /// + /// The HTTP response. + /// + /// The function that will resolve the provided response into an IAsyncEnumerable. + /// + /// + /// A new instance of that will be capable of asynchronous enumeration of + /// items from the HTTP response. + /// + internal static StreamingClientResult CreateFromResponse( + ClientResult result, + Func> asyncEnumerableProcessor) + { + return new(result, asyncEnumerableProcessor); + } + + /// + /// Gets the underlying instance that this may enumerate + /// over. + /// + /// The instance attached to this . + public PipelineResponse GetRawResponse() => _rawResult.GetRawResponse(); + + /// + /// Gets the asynchronously enumerable collection of distinct, streamable items in the response. + /// + /// + /// The return value of this method may be used with the "await foreach" statement. + /// + /// As explicitly implements , callers may + /// enumerate a instance directly instead of calling this method. + /// + /// + /// + public IAsyncEnumerable EnumerateValues() => this; + + /// + public void Dispose() + { + Dispose(disposing: true); + GC.SuppressFinalize(this); + } + + /// + protected virtual void Dispose(bool disposing) + { + if (!_disposedValue) + { + if (disposing) + { + _rawResult?.GetRawResponse()?.Dispose(); + } + _disposedValue = true; + } + } + + IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) + => _asyncEnumerableSource.GetAsyncEnumerator(cancellationToken); +} \ No newline at end of file diff --git a/.dotnet/src/Utility/System.ClientModel.MultipartContent.cs b/.dotnet/src/Utility/System.ClientModel.MultipartContent.cs new file mode 100644 index 000000000..6342d7552 --- /dev/null +++ b/.dotnet/src/Utility/System.ClientModel.MultipartContent.cs @@ -0,0 +1,367 @@ + + +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace System.ClientModel; + +// Placeholder implementation adapted from: +// https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/core/Azure.Core/src/Shared/Multipart/MultipartContent.cs + +internal partial class MultipartContent : BinaryContent +{ + #region Fields + + private const string CrLf = "\r\n"; + private const string ColonSP = ": "; + + private static readonly int s_crlfLength = GetEncodedLength(CrLf); + private static readonly int s_dashDashLength = GetEncodedLength("--"); + private static readonly int s_colonSpaceLength = GetEncodedLength(ColonSP); + + private readonly List _nestedContent; + private readonly string _subtype; + private readonly string _boundary; + internal readonly Dictionary _headers; + + #endregion Fields + + #region Construction + + public MultipartContent() + : this("mixed", GetDefaultBoundary()) + { } + + public MultipartContent(string subtype) + : this(subtype, GetDefaultBoundary()) + { } + + /// + /// Initializes a new instance of the class. + /// + /// The multipart sub type. + /// The boundary string for the multipart form data content. + public MultipartContent(string subtype, string boundary) + { + ValidateBoundary(boundary); + _subtype = subtype; + + // see https://www.ietf.org/rfc/rfc1521.txt page 29. + _boundary = boundary.Contains(":") ? $"\"{boundary}\"" : boundary; + _headers = new Dictionary + { + ["content-type"] = $"multipart/{_subtype}; boundary={_boundary}" + }; + + _nestedContent = new List(); + } + + private static void ValidateBoundary(string boundary) + { + // NameValueHeaderValue is too restrictive for boundary. + // Instead validate it ourselves and then quote it. + if (string.IsNullOrWhiteSpace(boundary)) throw new ArgumentException(nameof(boundary)); + + // cspell:disable + // RFC 2046 Section 5.1.1 + // boundary := 0*69 bcharsnospace + // bchars := bcharsnospace / " " + // bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" / "+" / "_" / "," / "-" / "." / "/" / ":" / "=" / "?" + // cspell:enable + if (boundary.Length > 70) + { + throw new ArgumentOutOfRangeException(nameof(boundary), boundary, $"The field cannot be longer than {70} characters."); + } + // Cannot end with space. + if (boundary.EndsWith(" ", StringComparison.InvariantCultureIgnoreCase)) + { + throw new ArgumentException($"The format of value '{boundary}' is invalid.", nameof(boundary)); + } + + const string AllowedMarks = @"'()+_,-./:=? "; + + foreach (char ch in boundary) + { + if (('0' <= ch && ch <= '9') || // Digit. + ('a' <= ch && ch <= 'z') || // alpha. + ('A' <= ch && ch <= 'Z') || // ALPHA. + AllowedMarks.Contains(char.ToString(ch))) // Marks. + { + // Valid. + } + else + { + throw new ArgumentException($"The format of value '{boundary}' is invalid.", nameof(boundary)); + } + } + } + + private static string GetDefaultBoundary() + { + return Guid.NewGuid().ToString(); + } + + /// + /// Add content type header to the request. + /// + /// The request. + public void ApplyToRequest(PipelineRequest request) + { + request.Headers.Set("content-type", $"multipart/{_subtype}; boundary={_boundary}"); + request.Content = this; + } + + /// + /// Add HTTP content to a collection of RequestContent objects that + /// get serialized to multipart/form-data MIME type. + /// + /// The Request content to add to the collection. + public virtual void Add(BinaryContent content) + { + if (content is null) throw new ArgumentNullException(nameof(content)); + AddInternal(content, null); + } + + /// + /// Add HTTP content to a collection of RequestContent objects that + /// get serialized to multipart/form-data MIME type. + /// + /// The Request content to add to the collection. + /// The headers to add to the collection. + public virtual void Add(BinaryContent content, Dictionary headers) + { + if (content is null) throw new ArgumentNullException(nameof(content)); + if (headers is null) throw new ArgumentNullException(nameof(headers)); + + AddInternal(content, headers); + } + + private void AddInternal(BinaryContent content, Dictionary headers) + { + headers ??= []; + _nestedContent.Add(new MultipartRequestContent(content, headers)); + } + + #endregion Construction + + #region Dispose + + /// + /// Frees resources held by the object. + /// + public override void Dispose() + { + foreach (MultipartRequestContent content in _nestedContent) + { + content.RequestContent.Dispose(); + } + _nestedContent.Clear(); + } + + #endregion Dispose + + #region Serialization + + // for-each content + // write "--" + boundary + // for-each content header + // write header: header-value + // write content.WriteTo[Async] + // write "--" + boundary + "--" + // Can't be canceled directly by the user. If the overall request is canceled + // then the stream will be closed an exception thrown. + /// + /// + /// + /// + /// + /// + public override void WriteTo(Stream stream, CancellationToken cancellationToken) + { + if (stream is null) throw new ArgumentNullException(nameof(stream)); + + try + { + // Write start boundary. + EncodeStringToStream(stream, "--" + _boundary + CrLf); + + // Write each nested content. + var output = new StringBuilder(); + for (int contentIndex = 0; contentIndex < _nestedContent.Count; contentIndex++) + { + // Write divider, headers, and content. + BinaryContent content = _nestedContent[contentIndex].RequestContent; + Dictionary headers = _nestedContent[contentIndex].Headers; + EncodeStringToStream(stream, SerializeHeadersToString(output, contentIndex, headers)); + content.WriteTo(stream, cancellationToken); + } + + // Write footer boundary. + EncodeStringToStream(stream, CrLf + "--" + _boundary + "--" + CrLf); + } + catch (Exception) + { + throw; + } + } + + // for-each content + // write "--" + boundary + // for-each content header + // write header: header-value + // write content.WriteTo[Async] + // write "--" + boundary + "--" + // Can't be canceled directly by the user. If the overall request is canceled + // then the stream will be closed an exception thrown. + /// + /// + /// + /// + /// + /// + public override Task WriteToAsync(Stream stream, CancellationToken cancellation) => + SerializeToStreamAsync(stream, cancellation); + + private async Task SerializeToStreamAsync(Stream stream, CancellationToken cancellationToken) + { + if (stream is null) throw new ArgumentNullException(nameof(stream)); + try + { + // Write start boundary. + await EncodeStringToStreamAsync(stream, "--" + _boundary + CrLf, cancellationToken).ConfigureAwait(false); + + // Write each nested content. + var output = new StringBuilder(); + for (int contentIndex = 0; contentIndex < _nestedContent.Count; contentIndex++) + { + // Write divider, headers, and content. + BinaryContent content = _nestedContent[contentIndex].RequestContent; + Dictionary headers = _nestedContent[contentIndex].Headers; + await EncodeStringToStreamAsync(stream, SerializeHeadersToString(output, contentIndex, headers), cancellationToken).ConfigureAwait(false); + await content.WriteToAsync(stream, cancellationToken).ConfigureAwait(false); + } + + // Write footer boundary. + await EncodeStringToStreamAsync(stream, CrLf + "--" + _boundary + "--" + CrLf, cancellationToken).ConfigureAwait(false); + } + catch (Exception) + { + throw; + } + } + + private string SerializeHeadersToString(StringBuilder scratch, int contentIndex, Dictionary headers) + { + scratch.Clear(); + + // Add divider. + if (contentIndex != 0) // Write divider for all but the first content. + { + scratch.Append(CrLf + "--"); // const strings + scratch.Append(_boundary); + scratch.Append(CrLf); + } + + // Add headers. + foreach (KeyValuePair header in headers) + { + scratch.Append(header.Key); + scratch.Append(": "); + scratch.Append(header.Value); + scratch.Append(CrLf); + } + + // Extra CRLF to end headers (even if there are no headers). + scratch.Append(CrLf); + + return scratch.ToString(); + } + + private static void EncodeStringToStream(Stream stream, string input) + { + byte[] buffer = Encoding.Default.GetBytes(input); + stream.Write(buffer, 0, buffer.Length); + } + + private static Task EncodeStringToStreamAsync(Stream stream, string input, CancellationToken cancellationToken) + { + byte[] buffer = Encoding.Default.GetBytes(input); + return stream.WriteAsync(buffer, 0, buffer.Length, cancellationToken); + } + + /// + /// Attempts to compute the length of the underlying content, if available. + /// + /// The length of the underlying data. + public override bool TryComputeLength(out long length) + { + int boundaryLength = GetEncodedLength(_boundary); + + long currentLength = 0; + long internalBoundaryLength = s_crlfLength + s_dashDashLength + boundaryLength + s_crlfLength; + + // Start Boundary. + currentLength += s_dashDashLength + boundaryLength + s_crlfLength; + + bool first = true; + foreach (MultipartRequestContent content in _nestedContent) + { + if (first) + { + first = false; // First boundary already written. + } + else + { + // Internal Boundary. + currentLength += internalBoundaryLength; + } + + // Headers. + foreach (KeyValuePair headerPair in content.Headers) + { + currentLength += GetEncodedLength(headerPair.Key) + s_colonSpaceLength; + currentLength += GetEncodedLength(headerPair.Value); + currentLength += s_crlfLength; + } + + currentLength += s_crlfLength; + + // Content. + if (!content.RequestContent.TryComputeLength(out long tempContentLength)) + { + length = 0; + return false; + } + currentLength += tempContentLength; + } + + // Terminating boundary. + currentLength += s_crlfLength + s_dashDashLength + boundaryLength + s_dashDashLength + s_crlfLength; + + length = currentLength; + return true; + } + + private static int GetEncodedLength(string input) + { + return Encoding.Default.GetByteCount(input); + } + + #endregion Serialization + + private class MultipartRequestContent + { + public readonly BinaryContent RequestContent; + public Dictionary Headers; + + public MultipartRequestContent(BinaryContent content, Dictionary headers) + { + RequestContent = content; + Headers = headers; + } + } +} \ No newline at end of file diff --git a/.dotnet/src/Utility/System.ClientModel.MultipartFormDataContent.cs b/.dotnet/src/Utility/System.ClientModel.MultipartFormDataContent.cs new file mode 100644 index 000000000..9faceac1c --- /dev/null +++ b/.dotnet/src/Utility/System.ClientModel.MultipartFormDataContent.cs @@ -0,0 +1,117 @@ +using System.Collections.Generic; + +namespace System.ClientModel; + +// Placeholder implementation adapted from: +// https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/core/Azure.Core/src/Shared/Multipart/MultipartFormDataContent.cs + +internal partial class MultipartFormDataContent : MultipartContent +{ + // Copyright (c) Microsoft Corporation. All rights reserved. + // Licensed under the MIT License. + +#nullable disable + + #region Fields + + private const string FormData = "form-data"; + + #endregion Fields + + #region Construction + + /// + /// Initializes a new instance of the class. + /// + public MultipartFormDataContent() : base(FormData) + { } + + /// + /// Initializes a new instance of the class. + /// + /// The boundary string for the multipart form data content. + public MultipartFormDataContent(string boundary) : base(FormData, boundary) + { } + + #endregion Construction + + /// + /// Add HTTP content to a collection of RequestContent objects that + /// get serialized to multipart/form-data MIME type. + /// + /// The Request content to add to the collection. + public override void Add(BinaryContent content) + { + if (content is null) throw new ArgumentNullException(nameof(content)); + AddInternal(content, null, null, null); + } + + /// + /// Add HTTP content to a collection of RequestContent objects that + /// get serialized to multipart/form-data MIME type. + /// + /// The Request content to add to the collection. + /// The headers to add to the collection. + public override void Add(BinaryContent content, Dictionary headers) + { + if (content is null) throw new ArgumentNullException(nameof(content)); + if (headers is null) throw new ArgumentNullException(nameof(headers)); + + AddInternal(content, headers, null, null); + } + + /// + /// Add HTTP content to a collection of RequestContent objects that + /// get serialized to multipart/form-data MIME type. + /// + /// The Request content to add to the collection. + /// The name for the request content to add. + /// The headers to add to the collection. + public void Add(BinaryContent content, string name, Dictionary headers) + { + if (content is null) throw new ArgumentNullException(nameof(content)); + if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException(nameof(name)); + + AddInternal(content, headers, name, null); + } + + /// + /// Add HTTP content to a collection of RequestContent objects that + /// get serialized to multipart/form-data MIME type. + /// + /// The Request content to add to the collection. + /// The name for the request content to add. + /// The file name for the request content to add to the collection. + /// The headers to add to the collection. + public void Add(BinaryContent content, string name, string fileName, Dictionary headers) + { + if (content is null) throw new ArgumentNullException(nameof(content)); + if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException(nameof(name)); + if (string.IsNullOrWhiteSpace(fileName)) throw new ArgumentException(nameof(fileName)); + + AddInternal(content, headers, name, fileName); + } + + private void AddInternal(BinaryContent content, Dictionary headers, string name, string fileName) + { + headers ??= []; + + if (!headers.ContainsKey("Content-Disposition")) + { + var value = FormData; + + if (name != null) + { + value = value + "; name=" + name; + } + if (fileName != null) + { + value = value + "; filename=" + fileName; + } + + headers.Add("Content-Disposition", value); + } + + base.Add(content, headers); + } +} \ No newline at end of file diff --git a/.dotnet/tests/Generated/Tests/AssistantsTests.cs b/.dotnet/tests/Generated/Tests/AssistantsTests.cs deleted file mode 100644 index dde077712..000000000 --- a/.dotnet/tests/Generated/Tests/AssistantsTests.cs +++ /dev/null @@ -1,22 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel; -using NUnit.Framework; -using OpenAI; - -namespace OpenAI.Tests -{ - public partial class AssistantsTests - { - [Test] - public void SmokeTest() - { - ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - Assistants client = new OpenAIClient(credential).GetAssistantsClient(); - Assert.IsNotNull(client); - } - } -} diff --git a/.dotnet/tests/Generated/Tests/AudioTests.cs b/.dotnet/tests/Generated/Tests/AudioTests.cs deleted file mode 100644 index f14a6f69d..000000000 --- a/.dotnet/tests/Generated/Tests/AudioTests.cs +++ /dev/null @@ -1,22 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel; -using NUnit.Framework; -using OpenAI; - -namespace OpenAI.Tests -{ - public partial class AudioTests - { - [Test] - public void SmokeTest() - { - ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - Audio client = new OpenAIClient(credential).GetAudioClient(); - Assert.IsNotNull(client); - } - } -} diff --git a/.dotnet/tests/Generated/Tests/ChatTests.cs b/.dotnet/tests/Generated/Tests/ChatTests.cs deleted file mode 100644 index b1ac76e65..000000000 --- a/.dotnet/tests/Generated/Tests/ChatTests.cs +++ /dev/null @@ -1,22 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel; -using NUnit.Framework; -using OpenAI; - -namespace OpenAI.Tests -{ - public partial class ChatTests - { - [Test] - public void SmokeTest() - { - ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - Chat client = new OpenAIClient(credential).GetChatClient(); - Assert.IsNotNull(client); - } - } -} diff --git a/.dotnet/tests/Generated/Tests/CompletionsTests.cs b/.dotnet/tests/Generated/Tests/CompletionsTests.cs deleted file mode 100644 index 59958da6b..000000000 --- a/.dotnet/tests/Generated/Tests/CompletionsTests.cs +++ /dev/null @@ -1,22 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel; -using NUnit.Framework; -using OpenAI; - -namespace OpenAI.Tests -{ - public partial class CompletionsTests - { - [Test] - public void SmokeTest() - { - ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - Completions client = new OpenAIClient(credential).GetCompletionsClient(); - Assert.IsNotNull(client); - } - } -} diff --git a/.dotnet/tests/Generated/Tests/EmbeddingsTests.cs b/.dotnet/tests/Generated/Tests/EmbeddingsTests.cs deleted file mode 100644 index b4e115c86..000000000 --- a/.dotnet/tests/Generated/Tests/EmbeddingsTests.cs +++ /dev/null @@ -1,22 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel; -using NUnit.Framework; -using OpenAI; - -namespace OpenAI.Tests -{ - public partial class EmbeddingsTests - { - [Test] - public void SmokeTest() - { - ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - Embeddings client = new OpenAIClient(credential).GetEmbeddingsClient(); - Assert.IsNotNull(client); - } - } -} diff --git a/.dotnet/tests/Generated/Tests/FilesTests.cs b/.dotnet/tests/Generated/Tests/FilesTests.cs deleted file mode 100644 index 64ebbed83..000000000 --- a/.dotnet/tests/Generated/Tests/FilesTests.cs +++ /dev/null @@ -1,22 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel; -using NUnit.Framework; -using OpenAI; - -namespace OpenAI.Tests -{ - public partial class FilesTests - { - [Test] - public void SmokeTest() - { - ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - Files client = new OpenAIClient(credential).GetFilesClient(); - Assert.IsNotNull(client); - } - } -} diff --git a/.dotnet/tests/Generated/Tests/FineTuningTests.cs b/.dotnet/tests/Generated/Tests/FineTuningTests.cs deleted file mode 100644 index 324b4d458..000000000 --- a/.dotnet/tests/Generated/Tests/FineTuningTests.cs +++ /dev/null @@ -1,22 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel; -using NUnit.Framework; -using OpenAI; - -namespace OpenAI.Tests -{ - public partial class FineTuningTests - { - [Test] - public void SmokeTest() - { - ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - FineTuning client = new OpenAIClient(credential).GetFineTuningClient(); - Assert.IsNotNull(client); - } - } -} diff --git a/.dotnet/tests/Generated/Tests/ImagesTests.cs b/.dotnet/tests/Generated/Tests/ImagesTests.cs deleted file mode 100644 index 96b7146de..000000000 --- a/.dotnet/tests/Generated/Tests/ImagesTests.cs +++ /dev/null @@ -1,22 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel; -using NUnit.Framework; -using OpenAI; - -namespace OpenAI.Tests -{ - public partial class ImagesTests - { - [Test] - public void SmokeTest() - { - ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - Images client = new OpenAIClient(credential).GetImagesClient(); - Assert.IsNotNull(client); - } - } -} diff --git a/.dotnet/tests/Generated/Tests/MessagesTests.cs b/.dotnet/tests/Generated/Tests/MessagesTests.cs deleted file mode 100644 index 89933cb52..000000000 --- a/.dotnet/tests/Generated/Tests/MessagesTests.cs +++ /dev/null @@ -1,22 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel; -using NUnit.Framework; -using OpenAI; - -namespace OpenAI.Tests -{ - public partial class MessagesTests - { - [Test] - public void SmokeTest() - { - ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - Messages client = new OpenAIClient(credential).GetMessagesClient(); - Assert.IsNotNull(client); - } - } -} diff --git a/.dotnet/tests/Generated/Tests/ModelsOpsTests.cs b/.dotnet/tests/Generated/Tests/ModelsOpsTests.cs deleted file mode 100644 index 3ac25fa3d..000000000 --- a/.dotnet/tests/Generated/Tests/ModelsOpsTests.cs +++ /dev/null @@ -1,22 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel; -using NUnit.Framework; -using OpenAI; - -namespace OpenAI.Tests -{ - public partial class ModelsOpsTests - { - [Test] - public void SmokeTest() - { - ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - ModelsOps client = new OpenAIClient(credential).GetModelsOpsClient(); - Assert.IsNotNull(client); - } - } -} diff --git a/.dotnet/tests/Generated/Tests/ModerationsTests.cs b/.dotnet/tests/Generated/Tests/ModerationsTests.cs deleted file mode 100644 index 0413ef684..000000000 --- a/.dotnet/tests/Generated/Tests/ModerationsTests.cs +++ /dev/null @@ -1,22 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel; -using NUnit.Framework; -using OpenAI; - -namespace OpenAI.Tests -{ - public partial class ModerationsTests - { - [Test] - public void SmokeTest() - { - ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - Moderations client = new OpenAIClient(credential).GetModerationsClient(); - Assert.IsNotNull(client); - } - } -} diff --git a/.dotnet/tests/Generated/Tests/RunsTests.cs b/.dotnet/tests/Generated/Tests/RunsTests.cs deleted file mode 100644 index 8bc6927a9..000000000 --- a/.dotnet/tests/Generated/Tests/RunsTests.cs +++ /dev/null @@ -1,22 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel; -using NUnit.Framework; -using OpenAI; - -namespace OpenAI.Tests -{ - public partial class RunsTests - { - [Test] - public void SmokeTest() - { - ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - Runs client = new OpenAIClient(credential).GetRunsClient(); - Assert.IsNotNull(client); - } - } -} diff --git a/.dotnet/tests/Generated/Tests/ThreadsTests.cs b/.dotnet/tests/Generated/Tests/ThreadsTests.cs deleted file mode 100644 index e7f4583af..000000000 --- a/.dotnet/tests/Generated/Tests/ThreadsTests.cs +++ /dev/null @@ -1,22 +0,0 @@ -// - -#nullable disable - -using System; -using System.ClientModel; -using NUnit.Framework; -using OpenAI; - -namespace OpenAI.Tests -{ - public partial class ThreadsTests - { - [Test] - public void SmokeTest() - { - ApiKeyCredential credential = new ApiKeyCredential(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - Threads client = new OpenAIClient(credential).GetThreadsClient(); - Assert.IsNotNull(client); - } - } -} diff --git a/.dotnet/tests/OpenAI.Tests.csproj b/.dotnet/tests/OpenAI.Tests.csproj index e590c0e52..694b63bba 100644 --- a/.dotnet/tests/OpenAI.Tests.csproj +++ b/.dotnet/tests/OpenAI.Tests.csproj @@ -10,6 +10,7 @@ + diff --git a/.dotnet/tests/Samples/AssistantsSamples.cs b/.dotnet/tests/Samples/AssistantsSamples.cs new file mode 100644 index 000000000..1b59fc41c --- /dev/null +++ b/.dotnet/tests/Samples/AssistantsSamples.cs @@ -0,0 +1,167 @@ +using NUnit.Framework; +using OpenAI.Assistants; +using OpenAI.Files; +using System; +using System.IO; +using System.Threading; + +namespace OpenAI.Tests.Examples; + +public partial class AssistantExamples +{ + [Test] + [Ignore("Compilation validation only")] + public void ListAllAssistants() + { + AssistantClient client = new(); + string latestId = null; + bool continueQuery = true; + int count = 0; + + while (continueQuery) + { + var assistantList = client.GetAssistants(previousAssistantId: latestId).Value; + foreach (Assistant assistant in assistantList) + { + Console.WriteLine($"[{count,3}] {assistant.Id} {assistant.CreatedAt:s} {assistant.Name}"); + latestId = assistant.Id; + count++; + } + continueQuery = assistantList.HasMore; + } + } + + [Test] + [Ignore("Compilation validation only")] + public void CreateClients() + { + OpenAIClient openAIClient = new(""); + FileClient fileClient = openAIClient.GetFileClient(); + AssistantClient assistantClient = openAIClient.GetAssistantClient(); + } + + [Test] + [Ignore("Compilation validation only")] + public void SimpleRetrievalAugmentedGeneration() + { + OpenAIClient openAIClient = new(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + FileClient fileClient = openAIClient.GetFileClient(); + AssistantClient assistantClient = openAIClient.GetAssistantClient(); + + // First, let's contrive a document we'll use retrieval with and upload it. + BinaryData document = BinaryData.FromString(""" + { + "description": "This document contains the sale history data for Contoso products.", + "sales": [ + { + "month": "January", + "by_product": { + "113043": 15, + "113045": 12, + "113049": 2 + } + }, + { + "month": "February", + "by_product": { + "113045": 22 + } + }, + { + "month": "March", + "by_product": { + "113045": 16, + "113055": 5 + } + } + ] + } + """); + + OpenAIFileInfo openAIFileInfo = fileClient.UploadFile(document, "test-rag-file-delete-me.json", OpenAIFilePurpose.Assistants); + + // Now, we'll create a client intended to help with that data + AssistantCreationOptions assistantOptions = new() + { + Name = "Example: Contoso sales RAG", + Instructions = + "You are an assistant that looks up sales data and helps visualize the information based" + + " on user queries. When asked to generate a graph, chart, or other visualization, use" + + " the code interpreter tool to do so.", + FileIds = { openAIFileInfo.Id }, + Tools = + { + new RetrievalToolDefinition(), + new CodeInterpreterToolDefinition(), + }, + Metadata = { ["test_key_delete_me"] = "true" }, + }; + + Assistant assistant = assistantClient.CreateAssistant("gpt-4-1106-preview", assistantOptions); + + // Now we'll create a thread with a user query about the data already associated with the assistant, then run it + ThreadCreationOptions threadOptions = new() + { + Messages = + { + new ThreadInitializationMessage( + MessageRole.User, + "How well did product 113045 sell in February? Graph its trend over time."), + } + }; + + ThreadRun threadRun = assistantClient.CreateThreadAndRun(assistant.Id, threadOptions); + + // Check back to see when the run is done + do + { + Thread.Sleep(TimeSpan.FromSeconds(1)); + threadRun = assistantClient.GetRun(threadRun.ThreadId, threadRun.Id); + } while (threadRun.Status == RunStatus.Queued || threadRun.Status == RunStatus.InProgress); + + // Finally, we'll print out the full history for the thread that includes the augmented generation + ListQueryPage messages = assistantClient.GetMessages(threadRun.ThreadId); + + for (int i = messages.Count - 1; i >= 0; i--) + { + ThreadMessage message = messages[i]; + + Console.WriteLine($"[{message.Role.ToString().ToUpper()}]:"); + foreach (MessageContent contentItem in message.ContentItems) + { + if (contentItem is MessageTextContent textContent) + { + Console.WriteLine($"{textContent.Text}"); + + if (textContent.Annotations.Count > 0) + { + Console.WriteLine(); + } + + // Include annotations, if any. + foreach (TextContentAnnotation annotation in textContent.Annotations) + { + if (annotation is TextContentFileCitationAnnotation citationAnnotation) + { + Console.WriteLine($"* File citation, file ID: {citationAnnotation.FileId}"); + } + else if (annotation is TextContentFilePathAnnotation pathAnnotation) + { + Console.WriteLine($"* File path, file ID: {pathAnnotation.FileId}"); + } + } + } + else if (contentItem is MessageImageFileContent imageFileContent) + { + OpenAIFileInfo imageInfo = fileClient.GetFileInfo(imageFileContent.FileId); + BinaryData imageBytes = fileClient.DownloadFile(imageFileContent.FileId); + using FileStream stream = File.OpenWrite($"{ imageInfo.Filename }.png"); + imageBytes.ToStream().CopyTo(stream); + + Console.WriteLine($""); + } + } + Console.WriteLine(); + } + } +} diff --git a/.dotnet/tests/Samples/Chat/ChatSamples.cs b/.dotnet/tests/Samples/Chat/ChatSamples.cs new file mode 100644 index 000000000..f08824304 --- /dev/null +++ b/.dotnet/tests/Samples/Chat/ChatSamples.cs @@ -0,0 +1,128 @@ +using NUnit.Framework; +using OpenAI.Audio; +using OpenAI.Chat; +using System; +using System.ClientModel; +using System.Text.Json; +using System.Threading.Tasks; + +namespace OpenAI.Tests.Examples; + +public partial class ChatSamples +{ + [Test] + [Ignore("Compilation validation only")] + public void CreateChatClient() + { + ChatClient client = new("gpt-3.5-turbo", ""); + } + + [Test] + [Ignore("Compilation validation only")] + public void CreateClients() + { + OpenAIClient client = new(""); + AudioClient ttsClient = client.GetAudioClient("tts-1"); + AudioClient whisperClient = client.GetAudioClient("whisper-1"); + } + + [Test] + [Ignore("Compilation validation only")] + public void HelloWorldChat() + { + ChatClient client = new("gpt-3.5-turbo", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + ChatCompletion chatCompletion = client.CompleteChat("How does AI work? Explain it in simple terms."); + + Console.WriteLine($"[ASSISTANT]:"); + Console.WriteLine($"{ chatCompletion.Content }"); + } + + [Test] + [Ignore("Compilation validation only")] + public void HelloWorldChatProtocol() + { + ChatClient client = new("gpt-3.5-turbo", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + BinaryData input = BinaryData.FromString(""" + { + "model": "gpt-3.5-turbo", + "messages": [ + { + "role": "user", + "content": "How does AI work? Explain it in simple terms." + } + ] + } + """); + + ClientResult result = client.CompleteChat(BinaryContent.Create(input)); + BinaryData output = result.GetRawResponse().Content; + + using JsonDocument outputAsJson = JsonDocument.Parse(output.ToString()); + string message = outputAsJson.RootElement + .GetProperty("choices")[0] + .GetProperty("message") + .GetProperty("content") + .GetString(); + + Console.WriteLine($"[ASSISTANT]:"); + Console.WriteLine($"{ message }"); + } + + + [Test] + [Ignore("Compilation validation only")] + public async void HelloWorldChatAsync() + { + ChatClient client = new("gpt-3.5-turbo", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + ChatCompletion chatCompletion = await client.CompleteChatAsync("How does AI work? Explain it in simple terms."); + + Console.WriteLine($"[ASSISTANT]: {chatCompletion.Content}"); + } + + [Test] + [Ignore("Compilation validation only")] + public async Task HelloWorldStreamingChat() + { + ChatClient client = new("gpt-3.5-turbo", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + StreamingClientResult result = + client.CompleteChatStreaming("How does AI work? Explain it in simple terms."); + + Console.WriteLine("[ASSISTANT]: "); + + await foreach (StreamingChatUpdate chatUpdate in result) + { + Console.Write(chatUpdate.ContentUpdate); + } + } + + [Test] + [Ignore("Compilation validation only")] + public void ChatWithImage(Uri imageUri = null) + { + ChatClient client = new("gpt-4-vision-preview", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + ChatCompletion chatCompletion = client.CompleteChat( + [ + new ChatRequestUserMessage( + "Describe this image for me", + ChatMessageContent.CreateImage(imageUri)), + ]); + } + + [Test] + [Ignore("Compilation validation only")] + public void ChatWithTools() + { + ChatClient client = new("gpt-3.5-turbo", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + ChatFunctionToolDefinition getSecretWordTool = new() + { + Name = "get_secret_word", + Description = "gets the arbitrary secret word from the caller" + }; + } +} diff --git a/.dotnet/tests/Samples/Chat/Sample_FunctionCalling.cs b/.dotnet/tests/Samples/Chat/Sample_FunctionCalling.cs new file mode 100644 index 000000000..be14c9d76 --- /dev/null +++ b/.dotnet/tests/Samples/Chat/Sample_FunctionCalling.cs @@ -0,0 +1,148 @@ +using NUnit.Framework; +using OpenAI.Chat; +using System; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Tests.Examples; + +public partial class Samples_FunctionCalling +{ + #region + private static string GetCurrentWeather(string location, string unit = "celsius") + { + // Call the weather API here. + return "31 celsius"; + } + + private const string GetCurrentWeatherFunctionName = "get_current_weather"; + + private static readonly ChatFunctionToolDefinition getCurrentWeatherFunction = new() + { + Name = GetCurrentWeatherFunctionName, + Description = "Get the current weather in a given location", + Parameters = BinaryData.FromString(""" + { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state, e.g. Boston, MA" + }, + "unit": { + "type": "string", + "enum": [ "celsius", "fahrenheit" ], + "description": "The temperature unit to use. Infer this from the specified location." + } + }, + "required": [ "location" ] + } + """), + }; + #endregion + + [Test] + [Ignore("Compilation validation only")] + public void ChatWithFunctionCalling() + { + ChatClient client = new("gpt-3.5-turbo", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + #region + List messages = + [ + new ChatRequestSystemMessage( + "Don't make assumptions about what values to plug into functions." + + " Ask for clarification if a user request is ambiguous."), + new ChatRequestUserMessage("What's the weather like in San Francisco?"), + ]; + + ChatCompletionOptions options = new() + { + Tools = { getCurrentWeatherFunction }, + }; + + ChatCompletion chatCompletion = client.CompleteChat(messages, options); + #endregion + + #region + if (chatCompletion.FinishReason == ChatFinishReason.ToolCalls) + { + // First, add the assistant message with tool calls to the conversation history. + messages.Add(new ChatRequestAssistantMessage(chatCompletion)); + + // Then, add a new tool message for each tool call that is resolved. + foreach (ChatToolCall toolCall in chatCompletion.ToolCalls) + { + ChatFunctionToolCall functionToolCall = toolCall as ChatFunctionToolCall; + + switch (functionToolCall?.Name) + { + case GetCurrentWeatherFunctionName: + { + // The arguments that the model wants to use to call the function are specified as a + // stringified JSON object based on the schema defined in the tool definition. Note that + // the model may hallucinate arguments too. Consequently, it is important to do the + // appropriate parsing and validation before calling the function. + using JsonDocument argumentsJson = JsonDocument.Parse(functionToolCall.Arguments); + bool hasLocation = argumentsJson.RootElement.TryGetProperty("location", out JsonElement location); + bool hasUnit = argumentsJson.RootElement.TryGetProperty("unit", out JsonElement unit); + + if (!hasLocation) + { + throw new ArgumentNullException(nameof(location), "The location argument is required."); + } + + string toolResult = GetCurrentWeather(location.GetString(), hasUnit ? unit.GetString() : null); + messages.Add(new ChatRequestToolMessage(toolCall.Id, toolResult)); + break; + } + + default: + { + // Handle other or unexpected calls. + throw new NotImplementedException(); + } + } + } + + // Finally, make a new request to chat completions to let the assistant summarize the tool results + // and add the resulting message to the conversation history to keep it organized all in one place. + ChatCompletion chatCompletionAfterToolMessages = client.CompleteChat(messages, options); + messages.Add(new ChatRequestAssistantMessage(chatCompletionAfterToolMessages)); + } + #endregion + + #region + foreach (ChatRequestMessage requestMessage in messages) + { + switch (requestMessage) + { + case ChatRequestSystemMessage systemMessage: + Console.WriteLine($"[SYSTEM]:"); + Console.WriteLine($"{systemMessage.Content.Span[0].ToText()}"); + Console.WriteLine(); + break; + + case ChatRequestUserMessage userMessage: + Console.WriteLine($"[USER]:"); + Console.WriteLine($"{userMessage.Content.Span[0].ToText()}"); + Console.WriteLine(); + break; + + case ChatRequestAssistantMessage assistantMessage when assistantMessage.Content.Span[0].ToText() is not null: + Console.WriteLine($"[ASSISTANT]:"); + Console.WriteLine($"{assistantMessage.Content.Span[0].ToText()}"); + Console.WriteLine(); + break; + + case ChatRequestToolMessage: + // Do not print any tool messages; let the assistant summarize the tool results instead. + break; + + default: + break; + } + } + #endregion + } +} diff --git a/.dotnet/tests/Samples/CombinationSamples.cs b/.dotnet/tests/Samples/CombinationSamples.cs new file mode 100644 index 000000000..1fa848ed6 --- /dev/null +++ b/.dotnet/tests/Samples/CombinationSamples.cs @@ -0,0 +1,150 @@ +using NUnit.Framework; +using OpenAI.Audio; +using OpenAI.Chat; +using OpenAI.Images; +using System; +using System.ClientModel; +using System.IO; +using System.Threading.Tasks; + +namespace OpenAI.Tests.Examples; + +public partial class CombinationSamples +{ + [Test] + [Ignore("Compilation validation")] + public void AlpacaArtAssessor() + { + // First, we create an image using dall-e-3: + ImageClient imageClient = new("dall-e-3"); + ClientResult imageResult = imageClient.GenerateImage( + "a majestic alpaca on a mountain ridge, backed by an expansive blue sky accented with sparse clouds", + new() + { + Style = ImageStyle.Vivid, + Quality = ImageQuality.High, + Size = ImageSize.Size1792x1024, + }); + GeneratedImage imageGeneration = imageResult.Value; + Console.WriteLine($"Majestic alpaca available at:\n{imageGeneration.ImageUri.AbsoluteUri}"); + + // Now, we'll ask a cranky art critic to evaluate the image using gpt-4-vision-preview: + ChatClient chatClient = new("gpt-4-vision-preview"); + ClientResult chatResult = chatClient.CompleteChat( + [ + new ChatRequestSystemMessage("Assume the role of a cranky art critic. When asked to describe or " + + "evaluate imagery, focus on criticizing elements of subject, composition, and other details."), + new ChatRequestUserMessage( + "describe the following image in a few sentences", + ChatMessageContent.CreateImage(imageGeneration.ImageUri)), + ], + new ChatCompletionOptions() + { + MaxTokens = 2048, + }); + string chatResponseText = chatResult.Value.Content; + Console.WriteLine($"Art critique of majestic alpaca:\n{chatResponseText}"); + + // Finally, we'll get some text-to-speech for that critical evaluation using tts-1-hd: + AudioClient audioClient = new("tts-1-hd"); + ClientResult ttsResult = audioClient.GenerateSpeechFromText( + text: chatResponseText, + TextToSpeechVoice.Fable, + new TextToSpeechOptions() + { + SpeedMultiplier = 0.9f, + ResponseFormat = AudioDataFormat.Opus, + }); + FileInfo ttsFileInfo = new($"{chatResult.Value.Id}.opus"); + using (FileStream ttsFileStream = ttsFileInfo.Create()) + using (BinaryWriter ttsFileWriter = new(ttsFileStream)) + { + ttsFileWriter.Write(ttsResult.Value); + } + Console.WriteLine($"Alpaca evaluation audio available at:\n{new Uri(ttsFileInfo.FullName).AbsoluteUri}"); + } + + [Test] + [Ignore("Compilation validation")] + public async Task CuriousCreatureCreator() + { + // First, we'll use gpt-4 to have a creative helper imagine a twist on a household pet + ChatClient creativeWriterClient = new("gpt-4"); + ClientResult creativeWriterResult = creativeWriterClient.CompleteChat( + [ + new ChatRequestSystemMessage("You're a creative helper that specializes in brainstorming designs for concepts that fuse ordinary, mundane items with a fantastical touch. In particular, you can provide good one-paragraph descriptions of concept images."), + new ChatRequestUserMessage("Imagine a household pet. Now add in a subtle touch of magic or 'different'. What do you imagine? Provide a one-paragraph description of a picture of this new creature, focusing on the details of the imagery such that it'd be suitable for creating a picture."), + ], + new ChatCompletionOptions() + { + MaxTokens = 2048, + }); + string description = creativeWriterResult.Value.Content; + Console.WriteLine($"Creative helper's creature description:\n{description}"); + + // Asynchronously, in parallel to the next steps, we'll get the creative description in the voice of Onyx + AudioClient ttsClient = new("tts-1-hd"); + Task> imageDescriptionAudioTask = ttsClient.GenerateSpeechFromTextAsync( + description, + TextToSpeechVoice.Onyx, + new TextToSpeechOptions() + { + SpeedMultiplier = 1.1f, + ResponseFormat = AudioDataFormat.Opus, + }); + _ = Task.Run(async () => + { + ClientResult audioResult = await imageDescriptionAudioTask; + FileInfo audioFileInfo = new FileInfo($"{creativeWriterResult.Value.Id}-description.opus"); + using FileStream fileStream = audioFileInfo.Create(); + using BinaryWriter fileWriter = new(fileStream); + fileWriter.Write(audioResult.Value); + Console.WriteLine($"Spoken description available at:\n{new Uri(audioFileInfo.FullName).AbsoluteUri}"); + }); + + // Meanwhile, we'll use dall-e-3 to generate a rendition of our LLM artist's vision + ImageClient imageGenerationClient = new("dall-e-3"); + ClientResult imageGenerationResult = await imageGenerationClient.GenerateImageAsync( + description, + new ImageGenerationOptions() + { + Size = ImageSize.Size1792x1024, + Quality = ImageQuality.High, + }); + Uri imageLocation = imageGenerationResult.Value.ImageUri; + Console.WriteLine($"Creature image available at:\n{imageLocation.AbsoluteUri}"); + + // Now, we'll use gpt-4-vision-preview to get a hopelessly taken assessment from a usually exigent art connoisseur + ChatClient imageCriticClient = new("gpt-4-vision-preview"); + ClientResult criticalAppraisalResult = await imageCriticClient.CompleteChatAsync( + [ + new ChatRequestSystemMessage("Assume the role of an art critic. Although usually cranky and occasionally even referred to as a 'curmudgeon', you're somehow entirely smitten with the subject presented to you and, despite your best efforts, can't help but lavish praise when you're asked to appraise a provided image."), + new ChatRequestUserMessage( + "Evaluate this image for me. What is it, and what do you think of it?", + ChatMessageContent.CreateImage(imageLocation)), + ], + new ChatCompletionOptions() + { + MaxTokens = 2048, + }); + string appraisal = criticalAppraisalResult.Value.Content; + Console.WriteLine($"Critic's appraisal:\n{appraisal}"); + + // Finally, we'll get that art expert's laudations in the voice of Fable + ClientResult appraisalAudioResult = await ttsClient.GenerateSpeechFromTextAsync( + appraisal, + TextToSpeechVoice.Fable, + new TextToSpeechOptions() + { + ResponseFormat = AudioDataFormat.Opus, + SpeedMultiplier = 0.9f, + }); + FileInfo criticAudioFileInfo = new($"{criticalAppraisalResult.Value.Id}-appraisal.opus"); + using (FileStream criticStream = criticAudioFileInfo.Create()) + using (BinaryWriter criticFileWriter = new(criticStream)) + { + criticFileWriter.Write(appraisalAudioResult.Value); + } + Console.WriteLine($"Critical appraisal available at:\n{new Uri(criticAudioFileInfo.FullName).AbsoluteUri}"); + } +} diff --git a/.dotnet/tests/Samples/EmbeddingSamples.cs b/.dotnet/tests/Samples/EmbeddingSamples.cs new file mode 100644 index 000000000..7e2c8e61a --- /dev/null +++ b/.dotnet/tests/Samples/EmbeddingSamples.cs @@ -0,0 +1,95 @@ +using NUnit.Framework; +using OpenAI.Embeddings; +using System; +using System.ClientModel; +using System.Collections.Generic; + +namespace OpenAI.Tests.Examples; + +public partial class EmbeddingSamples +{ + [Test] + [Ignore("Compilation validation only")] + public void CreateEmbeddingClient() + { + EmbeddingClient client = new("text-embedding-3-small", new ApiKeyCredential("")); + } + + [Test] + [Ignore("Compilation validation only")] + public void SimpleEmbedding() + { + EmbeddingClient client = new("text-embedding-3-small", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + string description = + "Best hotel in town if you like luxury hotels. They have an amazing infinity pool, a spa," + + " and a really helpful concierge. The location is perfect -- right downtown, close to all " + + " the tourist attractions. We highly recommend this hotel."; + + Embedding embedding = client.GenerateEmbedding(description); + ReadOnlyMemory vector = embedding.Vector; + + Console.WriteLine($"Dimension: { vector.Length }"); + Console.WriteLine($"Floats: "); + for (int i = 0; i < vector.Length; i++) + { + Console.WriteLine($" [{i}] = { vector.Span[i] }"); + } + } + + [Test] + [Ignore("Compilation validation only")] + public void SimpleEmbeddingWithOptions() + { + EmbeddingClient client = new("text-embedding-3-small", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + string description = + "Best hotel in town if you like luxury hotels. They have an amazing infinity pool, a spa," + + " and a really helpful concierge. The location is perfect -- right downtown, close to all " + + " the tourist attractions. We highly recommend this hotel."; + + EmbeddingOptions options = new() { Dimensions = 512 }; + + Embedding embedding = client.GenerateEmbedding(description, options); + ReadOnlyMemory vector = embedding.Vector; + + Console.WriteLine($"Dimension: {vector.Length}"); + Console.WriteLine($"Floats: "); + for (int i = 0; i < vector.Length; i++) + { + Console.WriteLine($" [{i}] = {vector.Span[i]}"); + } + } + + [Test] + [Ignore("Compilation validation only")] + public void ComplexEmbedding() + { + EmbeddingClient client = new("text-embedding-3-small", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + string category = "Luxury"; + string description = + "Best hotel in town if you like luxury hotels. They have an amazing infinity pool, a spa," + + " and a really helpful concierge. The location is perfect -- right downtown, close to all " + + " the tourist attractions. We highly recommend this hotel."; + List inputs = [category, description]; + + EmbeddingOptions options = new() { Dimensions = 512 }; + + EmbeddingCollection collection = client.GenerateEmbeddings(inputs, options); + + foreach (Embedding embedding in collection) + { + ReadOnlyMemory vector = embedding.Vector; + + Console.WriteLine($"Dimension: {vector.Length}"); + Console.WriteLine($"Floats: "); + for (int i = 0; i < vector.Length; i++) + { + Console.WriteLine($" [{i}] = { vector.Span[i] }"); + } + + Console.WriteLine(); + } + } +} diff --git a/.dotnet/tests/Samples/ImageSamples.cs b/.dotnet/tests/Samples/ImageSamples.cs new file mode 100644 index 000000000..bad3fe58b --- /dev/null +++ b/.dotnet/tests/Samples/ImageSamples.cs @@ -0,0 +1,46 @@ +using NUnit.Framework; +using OpenAI.Images; +using System; +using System.IO; + +namespace OpenAI.Tests.Examples +{ + public partial class ImageSamples + { + [Test] + [Ignore("Compilation validation only")] + public void CreateImageClient() + { + ImageClient client = new("dall-e-3", ""); + } + + [Test] + [Ignore("Compilation validation only")] + public void SimpleImage() + { + ImageClient client = new("dall-e-3", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + string prompt = "The concept for a living room that blends Scandinavian simplicity with Japanese minimalism for" + + " a serene and cozy atmosphere. It's a space that invites relaxation and mindfulness, with natural light" + + " and fresh air. Using neutral tones, including colors like white, beige, gray, and black, that create a" + + " sense of harmony. Featuring sleek wood furniture with clean lines and subtle curves to add warmth and" + + " elegance. Plants and flowers in ceramic pots adding color and life to a space. They can serve as focal" + + " points, creating a connection with nature. Soft textiles and cushions in organic fabrics adding comfort" + + " and softness to a space. They can serve as accents, adding contrast and texture."; + + ImageGenerationOptions options = new() + { + Quality = ImageQuality.High, + Size = ImageSize.Size1792x1024, + Style = ImageStyle.Vivid, + ResponseFormat = ImageResponseFormat.Bytes + }; + + GeneratedImage image = client.GenerateImage(prompt, options); + BinaryData bytes = image.ImageBytes; + + using FileStream stream = File.OpenWrite($"{ Guid.NewGuid() }.png"); + bytes.ToStream().CopyTo(stream); + } + } +} diff --git a/.dotnet/tests/TestScenarios/AssistantTests.cs b/.dotnet/tests/TestScenarios/AssistantTests.cs new file mode 100644 index 000000000..aea1c3614 --- /dev/null +++ b/.dotnet/tests/TestScenarios/AssistantTests.cs @@ -0,0 +1,161 @@ +using NUnit.Framework; +using OpenAI.Assistants; +using System; +using System.ClientModel; +using System.Threading.Tasks; +using static OpenAI.Tests.TestHelpers; + +namespace OpenAI.Tests.Assistants; + +public partial class AssistantTests +{ + [Test] + public void ListingAssistantsWorks() + { + AssistantClient client = new(); + ClientResult> result = client.GetAssistants(); + Assert.That(result.Value, Is.Not.Null.Or.Empty); + } + + [Test] + public void CreatingAndDeletingAssistantsWorks() + { + AssistantClient client = GetTestClient(TestScenario.Assistants); + ClientResult result = client.CreateAssistant("gpt-3.5-turbo"); + Assert.That(result.Value, Is.Not.Null); + Assert.That(result.Value.Id, Is.Not.Null.Or.Empty); + ClientResult deletionResult = client.DeleteAssistant(result.Value.Id); + Assert.That(deletionResult.Value, Is.True); + } + + [Test] + public async Task AddingMessagesWorks() + { + AssistantClient client = new(); + ClientResult threadResult = await client.CreateThreadAsync(new ThreadCreationOptions() + { + Messages = + { + new(MessageRole.User, "this is an initial message on the thread"), + "this is another one done an easier way" + }, + Metadata = + { + ["test_key"] = "test_value", + [s_cleanupMetadataKey] = "true", + } + }); + ClientResult> messagesResult = await client.GetMessagesAsync(threadResult.Value.Id); + Assert.That(messagesResult.Value?.Count, Is.EqualTo(2)); + ThreadMessage latestMessage = messagesResult.Value[0]; + ThreadMessage oldestMessage = messagesResult.Value[1]; + Assert.That(latestMessage.Role, Is.EqualTo(MessageRole.User)); + Assert.That(latestMessage.ContentItems, Is.Not.Null.Or.Empty); + MessageTextContent textContent = latestMessage.ContentItems[0] as MessageTextContent; + Assert.That(textContent, Is.Not.Null); + Assert.That(textContent.Text, Is.Not.Null.Or.Empty); + Assert.That(textContent.Text, Contains.Substring("easier way")); + } + + [Test] + public async Task BasicFunctionToolWorks() + { + AssistantClient client = GetTestClient(); + ClientResult assistantResult = await client.CreateAssistantAsync( + "gpt-3.5-turbo", + new AssistantCreationOptions() + { + Tools = + { + new FunctionToolDefinition() + { + Name = "get_favorite_food_for_day_of_week", + Description = "gets the user's favorite food for a given day of the week, like Tuesday", + Parameters = BinaryData.FromObjectAsJson(new + { + type = "object", + properties = new + { + day_of_week = new + { + type = "string", + description = "a day of the week, like Tuesday or Saturday", + } + } + }), + }, + }, + Metadata = + { + [s_cleanupMetadataKey] = "true", + } + }); + Assert.That(assistantResult.Value.DefaultTools, Is.Not.Null.Or.Empty); + FunctionToolDefinition functionTool = assistantResult.Value.DefaultTools[0] as FunctionToolDefinition; + Assert.That(functionTool, Is.Not.Null); + Assert.That(functionTool.Parameters, Is.Not.Null); + + ClientResult threadResult = await client.CreateThreadAsync( + new ThreadCreationOptions() + { + Messages = + { + "what should I eat on Thursday?", + }, + Metadata = + { + [s_cleanupMetadataKey ] = "true", + } + }); + ClientResult runResult = await client.CreateRunAsync(threadResult.Value.Id, assistantResult.Value.Id); + Assert.That(runResult.Value.Id, Is.Not.Null.Or.Empty); + do + { + await Task.Delay(500); + runResult = await client.GetRunAsync(threadResult.Value.Id, runResult.Value.Id); + } while (runResult.Value.Status == RunStatus.Queued || runResult.Value.Status == RunStatus.InProgress); + Assert.That(runResult.Value.Status, Is.EqualTo(RunStatus.RequiresAction)); + Assert.That(runResult.Value.RequiredActions?.Count, Is.EqualTo(1)); + RequiredFunctionToolCall requiredFunctionToolCall = runResult.Value.RequiredActions[0] as RequiredFunctionToolCall; + Assert.That(requiredFunctionToolCall, Is.Not.Null); + _ = await client.SubmitToolOutputsAsync(threadResult.Value.Id, runResult.Value.Id, + [ + new ToolOutput(requiredFunctionToolCall, "tacos"), + ]); + runResult = await client.GetRunAsync(threadResult.Value.Id, runResult.Value.Id); + Assert.That(runResult.Value.Status, Is.Not.EqualTo(RunStatus.RequiresAction)); + } + + private async Task CreateCommonTestAssistantAsync() + { + AssistantClient client = new(); + ClientResult newAssistantResult = await client.CreateAssistantAsync("gpt-3.5-turbo", new() + { + Name = s_testAssistantName, + Metadata = + { + ["test_id"] = "test_id_goes_here", + [s_cleanupMetadataKey] = "true", + }, + }); + return newAssistantResult.Value; + } + + private async Task DeleteRecentTestThings() + { + AssistantClient client = new(); + foreach(Assistant assistant in client.GetAssistants().Value) + { + if (assistant.Name == s_testAssistantName + || assistant.Metadata?.ContainsKey(s_cleanupMetadataKey) == true) + { + _ = await client.DeleteAssistantAsync(assistant.Id); + } + } + } + + private static AssistantClient GetTestClient() => GetTestClient(TestScenario.Assistants); + + private static readonly string s_testAssistantName = $".NET SDK Test Assistant - Please Delete Me"; + private static readonly string s_cleanupMetadataKey = $"test_metadata_cleanup_eligible"; +} diff --git a/.dotnet/tests/TestScenarios/ChatClientTests.cs b/.dotnet/tests/TestScenarios/ChatClientTests.cs new file mode 100644 index 000000000..81cf59c5c --- /dev/null +++ b/.dotnet/tests/TestScenarios/ChatClientTests.cs @@ -0,0 +1,89 @@ +using NUnit.Framework; +using OpenAI.Chat; +using System; +using System.ClientModel; +using System.Diagnostics; +using System.Linq; +using System.Net; +using System.Threading.Tasks; +using static OpenAI.Tests.TestHelpers; + +namespace OpenAI.Tests.Chat; + +public partial class ChatClientTests +{ + [Test] + public void HelloWorldChat() + { + ChatClient client = GetTestClient(TestScenario.Chat); // new("gpt-3.5-turbo"); + Assert.That(client, Is.InstanceOf()); + ClientResult result = client.CompleteChat("Hello, world!"); + Assert.That(result, Is.InstanceOf>()); + Assert.That(result.Value.Content?.ContentKind, Is.EqualTo(ChatMessageContentKind.Text)); + Assert.That(result.Value.Content.ToText().Length, Is.GreaterThan(0)); + } + + [Test] + public void HelloWorldWithTopLevelClient() + { + OpenAIClient client = new(credential: new(Environment.GetEnvironmentVariable("OPENAI_API_KEY"))); + ChatClient chatClient = client.GetChatClient("gpt-3.5-turbo"); + ClientResult result = chatClient.CompleteChat("Hello, world!"); + Assert.That(result, Is.InstanceOf>()); + Assert.That(result.Value.Content.ToString().Length, Is.GreaterThan(0)); + } + [Test] + public void MultiMessageChat() + { + ChatClient client = new("gpt-3.5-turbo"); + ClientResult result = client.CompleteChat( + [ + new ChatRequestSystemMessage("You are a helpful assistant. You always talk like a pirate."), + new ChatRequestUserMessage("Hello, assistant! Can you help me train my parrot?"), + ]); + Assert.That(new string[] { "aye", "arr", "hearty" }.Any(pirateWord => result.Value.Content.ToString().ToLowerInvariant().Contains(pirateWord))); + } + + [Test] + public async Task StreamingChat() + { + ChatClient client = new("gpt-3.5-turbo"); + + TimeSpan? firstTokenReceiptTime = null; + TimeSpan? latestTokenReceiptTime = null; + Stopwatch stopwatch = Stopwatch.StartNew(); + + StreamingClientResult streamingResult + = client.CompleteChatStreaming("What are the best pizza toppings? Give me a breakdown on the reasons."); + Assert.That(streamingResult, Is.InstanceOf>()); + int updateCount = 0; + + await foreach (StreamingChatUpdate chatUpdate in streamingResult) + { + firstTokenReceiptTime ??= stopwatch.Elapsed; + latestTokenReceiptTime = stopwatch.Elapsed; + Console.WriteLine(stopwatch.Elapsed.TotalMilliseconds); + updateCount++; + } + Assert.That(updateCount, Is.GreaterThan(1)); + Assert.That(latestTokenReceiptTime - firstTokenReceiptTime > TimeSpan.FromMilliseconds(500)); + } + + [Test] + public void AuthFailure() + { + ChatClient client = new("gpt-3.5-turbo", new ApiKeyCredential("not-a-real-key")); + Exception caughtException = null; + try + { + _ = client.CompleteChat("Uh oh, this isn't going to work with that key"); + } + catch (Exception ex) + { + caughtException = ex; + } + var clientResultException = caughtException as ClientResultException; + Assert.That(clientResultException, Is.Not.Null); + Assert.That(clientResultException.Status, Is.EqualTo((int)HttpStatusCode.Unauthorized)); + } +} diff --git a/.dotnet/tests/TestScenarios/ChatToolConstraints.cs b/.dotnet/tests/TestScenarios/ChatToolConstraints.cs new file mode 100644 index 000000000..c6b20d28f --- /dev/null +++ b/.dotnet/tests/TestScenarios/ChatToolConstraints.cs @@ -0,0 +1,70 @@ +using NUnit.Framework; +using OpenAI.Chat; +using System; +using System.ClientModel; + +namespace OpenAI.Tests.Chat; + +public partial class ChatToolConstraintTests +{ + [Test] + public void BasicTypeManipulationWorks() + { + Assert.That(ChatToolConstraint.Auto.ToString(), Is.EqualTo("\"auto\"")); + Assert.That(ChatToolConstraint.None.ToString(), Is.EqualTo("\"none\"")); + Assert.That(ChatToolConstraint.Auto, Is.Not.EqualTo(ChatToolConstraint.None)); + + ChatFunctionToolDefinition functionTool = new() + { + Name = "test_function_tool", + Description = "description isn't applicable", + }; + + ChatToolConstraint constraintFromDefinition = new(functionTool); + Assert.That(constraintFromDefinition.ToString(), Is.EqualTo(@$"{{""type"":""function"",""function"":{{""name"":""{functionTool.Name}""}}}}")); + + ChatToolConstraint otherConstraint = new(new ChatFunctionToolDefinition("test_function_tool")); + Assert.That(constraintFromDefinition, Is.EqualTo(otherConstraint)); + Assert.That(otherConstraint, Is.Not.EqualTo(ChatToolConstraint.Auto)); + } + + [Test] + public void ConstraintsWork() + { + ChatClient client = new("gpt-3.5-turbo"); + ChatCompletionOptions options = new() + { + Tools = { s_numberForWordTool }, + }; + + foreach (var (constraint, reason) in new (ChatToolConstraint?, ChatFinishReason)[] + { + (null, ChatFinishReason.ToolCalls), + (ChatToolConstraint.None, ChatFinishReason.Stopped), + (new ChatToolConstraint(s_numberForWordTool), ChatFinishReason.Stopped), + (ChatToolConstraint.Auto, ChatFinishReason.ToolCalls), + }) + { + options.ToolConstraint = constraint; + ClientResult result = client.CompleteChat("What's the number for the word 'banana'?", options); + Assert.That(result.Value.FinishReason, Is.EqualTo(reason)); + } + } + + private static ChatFunctionToolDefinition s_numberForWordTool = new() + { + Name = "get_number_for_word", + Description = "gets an arbitrary number assigned to a given word", + Parameters = BinaryData.FromObjectAsJson(new + { + type = "object", + properties = new + { + word = new + { + type = "string" + } + } + }), + }; +} diff --git a/.dotnet/tests/TestScenarios/ChatToolTests.cs b/.dotnet/tests/TestScenarios/ChatToolTests.cs new file mode 100644 index 000000000..a59d789b3 --- /dev/null +++ b/.dotnet/tests/TestScenarios/ChatToolTests.cs @@ -0,0 +1,90 @@ +using NUnit.Framework; +using OpenAI.Chat; +using System; +using System.ClientModel; +using System.Collections.Generic; +using System.Text.Json; +using System.Text.Json.Nodes; +using static OpenAI.Tests.TestHelpers; + +namespace OpenAI.Tests.Chat; + +public partial class ChatToolTests +{ + [Test] + public void NoParameterToolWorks() + { + ChatClient client = new("gpt-3.5-turbo"); + ChatFunctionToolDefinition getFavoriteColorTool = new() + { + Name = "get_favorite_color", + Description = "gets the favorite color of the caller", + }; + ChatCompletionOptions options = new() + { + Tools = { getFavoriteColorTool }, + }; + ClientResult result = client.CompleteChat("What's my favorite color?", options); + Assert.That(result.Value.FinishReason, Is.EqualTo(ChatFinishReason.ToolCalls)); + Assert.That(result.Value.ToolCalls.Count, Is.EqualTo(1)); + var functionToolCall = result.Value.ToolCalls[0] as ChatFunctionToolCall; + var toolCallArguments = BinaryData.FromString(functionToolCall.Arguments).ToObjectFromJson>(); + Assert.That(functionToolCall, Is.Not.Null); + Assert.That(functionToolCall.Name, Is.EqualTo(getFavoriteColorTool.Name)); + Assert.That(functionToolCall.Id, Is.Not.Null.Or.Empty); + Assert.That(toolCallArguments.Count, Is.EqualTo(0)); + + result = client.CompleteChat( + [ + new ChatRequestUserMessage("What's my favorite color?"), + new ChatRequestAssistantMessage(result.Value), + new ChatRequestToolMessage(functionToolCall.Id, "green"), + ]); + Assert.That(result.Value.FinishReason, Is.EqualTo(ChatFinishReason.Stopped)); + Assert.That(result.Value.Content.ToString().ToLowerInvariant(), Contains.Substring("green")); + } + + [Test] + public void ParametersWork() + { + ChatClient client = GetTestClient(TestScenario.Chat); + ChatFunctionToolDefinition favoriteColorForMonthTool = new() + { + Name = "get_favorite_color_for_month", + Description = "gets the caller's favorite color for a given month", + Parameters = BinaryData.FromString(""" + { + "type": "object", + "properties": { + "month_name": { + "type": "string", + "description": "the name of a calendar month, e.g. February or October." + } + }, + "required": [ "month_name" ] + } + """), + }; + ChatCompletionOptions options = new() + { + Tools = { favoriteColorForMonthTool }, + }; + List messages = + [ + new ChatRequestUserMessage("What's my favorite color in February?"), + ]; + ClientResult result = client.CompleteChat(messages, options); + Assert.That(result.Value.FinishReason, Is.EqualTo(ChatFinishReason.ToolCalls)); + Assert.That(result.Value.ToolCalls?.Count, Is.EqualTo(1)); + var functionToolCall = result.Value.ToolCalls[0] as ChatFunctionToolCall; + Assert.That(functionToolCall.Name, Is.EqualTo(favoriteColorForMonthTool.Name)); + JsonObject argumentsJson = JsonSerializer.Deserialize(functionToolCall.Arguments); + Assert.That(argumentsJson.Count, Is.EqualTo(1)); + Assert.That(argumentsJson.ContainsKey("month_name")); + Assert.That(argumentsJson["month_name"].ToString().ToLowerInvariant(), Is.EqualTo("february")); + messages.Add(new ChatRequestAssistantMessage(result.Value)); + messages.Add(new ChatRequestToolMessage(functionToolCall.Id, "chartreuse")); + result = client.CompleteChat(messages, options); + Assert.That(result.Value.Content.ToString().ToLowerInvariant(), Contains.Substring("chartreuse")); + } +} diff --git a/.dotnet/tests/TestScenarios/ChatWithVision.cs b/.dotnet/tests/TestScenarios/ChatWithVision.cs new file mode 100644 index 000000000..4b37ea727 --- /dev/null +++ b/.dotnet/tests/TestScenarios/ChatWithVision.cs @@ -0,0 +1,33 @@ +using NUnit.Framework; +using OpenAI.Chat; +using System; +using System.ClientModel; +using System.IO; +using System.Net.Mime; +using static OpenAI.Tests.TestHelpers; + +namespace OpenAI.Tests.Chat; + +public partial class ChatWithVision +{ + [Test] + public void DescribeAnImage() + { + var stopSignPath = Path.Combine("data", "stop_sign.png"); + var stopSignData = BinaryData.FromBytes(File.ReadAllBytes(stopSignPath)); + + ChatClient client = GetTestClient(TestScenario.VisionChat); + + ClientResult result = client.CompleteChat( + [ + new ChatRequestUserMessage( + "Describe this image for me", + ChatMessageContent.CreateImage(stopSignData, "image/png")), + ], new ChatCompletionOptions() + { + MaxTokens = 2048, + }); + Console.WriteLine(result.Value.Content); + Assert.That(result.Value.Content.ToString().ToLowerInvariant(), Contains.Substring("stop")); + } +} diff --git a/.dotnet/tests/TestScenarios/EmbeddingClientTests.cs b/.dotnet/tests/TestScenarios/EmbeddingClientTests.cs new file mode 100644 index 000000000..0915e1711 --- /dev/null +++ b/.dotnet/tests/TestScenarios/EmbeddingClientTests.cs @@ -0,0 +1,52 @@ +using NUnit.Framework; +using OpenAI.Embeddings; +using System.ClientModel; +using System.Collections.Generic; + +namespace OpenAI.Tests.Embeddings; + +public partial class EmbeddingClientTests +{ + [Test] + public void OneEmbedding() + { + EmbeddingClient client = new("text-embedding-ada-002"); + ClientResult response = client.GenerateEmbedding("hello, world"); + Assert.That(response.Value, Is.Not.Null); + Assert.That(response.Value.Index, Is.EqualTo(0)); + Assert.That(response.Value.Usage, Is.Not.Null); + Assert.That(response.Value.Usage.TotalTokens, Is.GreaterThan(0)); + Assert.That(response.Value.Vector, Is.Not.Null.Or.Empty); + Assert.That(response.Value.Model, Contains.Substring("ada")); + float[] array = response.Value.Vector.ToArray(); + Assert.That(array.Length > 100); + } + + [Test] + public void SeveralEmbeddings() + { + EmbeddingClient client = new("text-embedding-3-small"); + List prompts = + [ + "Hello, world!", + "This is a test.", + "Goodbye!" + ]; + EmbeddingOptions options = new() + { + Dimensions = 456, + }; + ClientResult response = client.GenerateEmbeddings(prompts, options); + Assert.That(response.Value, Is.Not.Null); + Assert.That(response.Value.Count, Is.EqualTo(3)); + for (int i = 0; i < response.Value.Count; i++) + { + Assert.That(response.Value[i].Index, Is.EqualTo(i)); + Assert.That(response.Value[i].Usage, Is.Not.Null); + Assert.That(response.Value[i].Usage.TotalTokens, Is.GreaterThan(0)); + Assert.That(response.Value[i].Vector, Is.Not.Null.Or.Empty); + float[] array = response.Value[i].Vector.ToArray(); + Assert.That(array.Length, Is.GreaterThan(100)); + } + } +} diff --git a/.dotnet/tests/TestScenarios/FileClientTests.cs b/.dotnet/tests/TestScenarios/FileClientTests.cs new file mode 100644 index 000000000..3010dc941 --- /dev/null +++ b/.dotnet/tests/TestScenarios/FileClientTests.cs @@ -0,0 +1,43 @@ +using NUnit.Framework; +using OpenAI.Files; +using System; +using System.ClientModel; +using static OpenAI.Tests.TestHelpers; + +namespace OpenAI.Tests.Files; + +public partial class FileClientTests +{ + [Test] + public void ListFilesWorks() + { + FileClient client = new(); + ClientResult result = client.GetFileInfoList(); + Assert.That(result.Value.Count, Is.GreaterThan(0)); + Console.WriteLine(result.Value.Count); + ClientResult assistantsResult = client.GetFileInfoList(OpenAIFilePurpose.Assistants); + Assert.That(assistantsResult.Value.Count, Is.GreaterThan(0)); + Assert.That(assistantsResult.Value.Count, Is.LessThan(result.Value.Count)); + Console.WriteLine(assistantsResult.Value.Count); + } + + [Test] + public void UploadFileWorks() + { + FileClient client = GetTestClient(); + BinaryData uploadData = BinaryData.FromString("hello, this is a text file, please delete me"); + ClientResult uploadResult = client.UploadFile(uploadData, "test-file-delete-me.txt", OpenAIFilePurpose.Assistants); + } + + [Test] + public void DownloadAndInfoWork() + { + FileClient client = GetTestClient(); + ClientResult fileInfoResult = client.GetFileInfo("file-S7roYWamZqfMK9D979HU4q6m"); + Assert.That(fileInfoResult.Value, Is.Not.Null); + ClientResult downloadResult = client.DownloadFile("file-S7roYWamZqfMK9D979HU4q6m"); + Assert.That(downloadResult.Value, Is.Not.Null); + } + + private static FileClient GetTestClient() => GetTestClient(TestScenario.Files); +} \ No newline at end of file diff --git a/.dotnet/tests/TestScenarios/ImageGenerationTests.cs b/.dotnet/tests/TestScenarios/ImageGenerationTests.cs new file mode 100644 index 000000000..1d8d3304c --- /dev/null +++ b/.dotnet/tests/TestScenarios/ImageGenerationTests.cs @@ -0,0 +1,36 @@ +using NUnit.Framework; +using OpenAI.Images; +using System; +using System.ClientModel; +using static OpenAI.Tests.TestHelpers; + +namespace OpenAI.Tests.Images; + +public partial class ImageGenerationTests +{ + [Test] + public void BasicGenerationWorks() + { + ImageClient client = new("dall-e-3"); + ClientResult result = client.GenerateImage("an isolated stop sign"); + Assert.That(result, Is.InstanceOf>()); + Assert.That(result.Value.ImageUri, Is.Not.Null); + Console.WriteLine(result.Value.ImageUri.AbsoluteUri); + Assert.That(result.Value.ImageBytes, Is.Null); + Assert.That(result.Value.CreatedAt, Is.GreaterThan(new DateTimeOffset(new DateTime(year: 2020, month: 1, day: 1)))); + } + + [Test] + public void GenerationWithOptionsWorks() + { + ImageClient client = GetTestClient(); + ClientResult result = client.GenerateImage("an isolated stop sign", new ImageGenerationOptions() + { + Quality = ImageQuality.Standard, + Style = ImageStyle.Natural, + }); + Assert.That(result.Value.ImageUri, Is.Not.Null); + } + + private static ImageClient GetTestClient() => GetTestClient(TestScenario.Images); +} diff --git a/.dotnet/tests/TestScenarios/LegacyCompletions.cs b/.dotnet/tests/TestScenarios/LegacyCompletions.cs new file mode 100644 index 000000000..6f5deddc1 --- /dev/null +++ b/.dotnet/tests/TestScenarios/LegacyCompletions.cs @@ -0,0 +1,32 @@ +using NUnit.Framework; +using OpenAI.LegacyCompletions; +using System; +using System.ClientModel; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Text.Json; +using System.Text.Json.Nodes; + +namespace OpenAI.Tests.LegacyCompletions; + +public partial class LegacyCompletionTests +{ + [Test] + public void BasicValidationWorks() + { + LegacyCompletionClient client = new(); + BinaryData requestData = BinaryData.FromObjectAsJson(new + { + model = "gpt-3.5-turbo-instruct", + prompt = "hello world", + max_tokens = 256, + temperature = 0, + }); + BinaryContent content = BinaryContent.Create(requestData); + ClientResult result = client.GenerateLegacyCompletions(content); + Assert.That(result, Is.Not.Null); + JsonObject responseObject = JsonSerializer.Deserialize(result.GetRawResponse().Content.ToString()); + string text = responseObject["choices"].AsArray()[0].AsObject()["text"].ToString(); + Assert.That(text, Is.Not.Null.Or.Empty); + } +} diff --git a/.dotnet/tests/TestScenarios/ModelClientTests.cs b/.dotnet/tests/TestScenarios/ModelClientTests.cs new file mode 100644 index 000000000..2e668006a --- /dev/null +++ b/.dotnet/tests/TestScenarios/ModelClientTests.cs @@ -0,0 +1,28 @@ +using NUnit.Framework; +using OpenAI.ModelManagement; +using System.ClientModel; +using System.Linq; +using System.Threading.Tasks; + +namespace OpenAI.Tests.Models; + +public partial class ModelManagementClientTests +{ + [Test] + public async Task CanListModels() + { + ModelManagementClient client = new(); + ClientResult result = await client.GetModelsAsync(); + Assert.That(result.Value, Is.Not.Null.Or.Empty); + Assert.That(result.Value.Any(modelInfo => modelInfo.Id.ToLowerInvariant().Contains("whisper"))); + } + + [Test] + public async Task CanRetrieveModelInfo() + { + ModelManagementClient client = new(); + ClientResult result = await client.GetModelInfoAsync("gpt-3.5-turbo"); + Assert.That(result.Value, Is.Not.Null); + Assert.That(result.Value.OwnerOrganization.ToLowerInvariant(), Contains.Substring("openai")); + } +} diff --git a/.dotnet/tests/TestScenarios/TextToSpeechTests.cs b/.dotnet/tests/TestScenarios/TextToSpeechTests.cs new file mode 100644 index 000000000..c880ff864 --- /dev/null +++ b/.dotnet/tests/TestScenarios/TextToSpeechTests.cs @@ -0,0 +1,35 @@ +using NUnit.Framework; +using OpenAI.Audio; +using System; +using System.ClientModel; + +namespace OpenAI.Tests.Audio; + +public partial class TextToSpeechTests +{ + [Test] + public void BasicTTSWorks() + { + AudioClient client = new("tts-1"); + ClientResult result = client.GenerateSpeechFromText("hello, world, this is a test", TextToSpeechVoice.Shimmer); + Assert.That(result.Value, Is.Not.Null); + } + + [Test] + [TestCase(null)] + [TestCase(AudioDataFormat.Mp3)] + [TestCase(AudioDataFormat.Aac)] + [TestCase(AudioDataFormat.Opus)] + [TestCase(AudioDataFormat.Flac)] + public void OutputFormatWorks(AudioDataFormat? responseFormat) + { + AudioClient client = new("tts-1"); + TextToSpeechOptions options = new(); + if (responseFormat != null) + { + options.ResponseFormat = responseFormat; + } + ClientResult result = client.GenerateSpeechFromText("Hello, world!", TextToSpeechVoice.Alloy, options); + Assert.That(result.Value, Is.Not.Null); + } +} diff --git a/.dotnet/tests/TestScenarios/TranscriptionTests.cs b/.dotnet/tests/TestScenarios/TranscriptionTests.cs new file mode 100644 index 000000000..64813c2c3 --- /dev/null +++ b/.dotnet/tests/TestScenarios/TranscriptionTests.cs @@ -0,0 +1,43 @@ +using NUnit.Framework; +using OpenAI.Audio; +using System; +using System.ClientModel; +using System.IO; +using static OpenAI.Tests.TestHelpers; + +namespace OpenAI.Tests.Audio; + +public partial class TranscriptionTests +{ + [Test] + public void BasicTranscriptionWorks() + { + AudioClient client = GetTestClient(); + using FileStream inputStream = File.OpenRead(Path.Combine("data", "hello_world.m4a")); + BinaryData inputData = BinaryData.FromStream(inputStream); + ClientResult transcriptionResult = client.TranscribeAudio(inputData, "hello_world.m4a"); + Assert.That(transcriptionResult.Value, Is.Not.Null); + Assert.That(transcriptionResult.Value.Text.ToLowerInvariant(), Contains.Substring("hello")); + } + + [Test] + public void WordTimestampsWork() + { + AudioClient client = GetTestClient(); + using FileStream inputStream = File.OpenRead(Path.Combine("data", "hello_world.m4a")); + BinaryData inputData = BinaryData.FromStream(inputStream); + ClientResult transcriptionResult = client.TranscribeAudio(inputData, "hello_world.m4a", new AudioTranscriptionOptions() + { + EnableWordTimestamps = true, + EnableSegmentTimestamps = true, + ResponseFormat = AudioTranscriptionFormat.Detailed, + }); + Assert.That(transcriptionResult.Value, Is.Not.Null); + // Assert.That(transcriptionResult.Value.Segments, Is.Null); + // Assert.That(transcriptionResult.Value.Words, Is.Not.Null.Or.Empty); + // Assert.That(transcriptionResult.Value.Words[1].Word, Contains.Substring("world")); + // Assert.That(transcriptionResult.Value.Words[1].Start, Is.GreaterThan(TimeSpan.FromMilliseconds(0))); + // Assert.That(transcriptionResult.Value.Words[1].End, Is.GreaterThan(TimeSpan.FromMilliseconds(0))); + } + private static AudioClient GetTestClient() => GetTestClient(TestScenario.Transcription); +} diff --git a/.dotnet/tests/TestScenarios/TranslationTests.cs b/.dotnet/tests/TestScenarios/TranslationTests.cs new file mode 100644 index 000000000..e3310bd0d --- /dev/null +++ b/.dotnet/tests/TestScenarios/TranslationTests.cs @@ -0,0 +1,24 @@ +using NUnit.Framework; +using OpenAI.Audio; +using System; +using System.ClientModel; +using System.IO; +using static OpenAI.Tests.TestHelpers; + +namespace OpenAI.Tests.Audio; + +public partial class TranslationTests +{ + [Test] + public void BasicTranslationWorks() + { + AudioClient client = GetTestClient(); + using FileStream inputStream = File.OpenRead(Path.Combine("data", "hola_mundo.m4a")); + BinaryData inputData = BinaryData.FromStream(inputStream); + ClientResult translationResult = client.TranslateAudio(inputData, "hola_mundo.m4a"); + Assert.That(translationResult.Value, Is.Not.Null); + // Assert.That(translationResult.Value.Text.ToLowerInvariant(), Contains.Substring("hello")); + } + + private static AudioClient GetTestClient() => GetTestClient(TestScenario.Transcription); +} diff --git a/.dotnet/tests/Utility/TestHelpers.cs b/.dotnet/tests/Utility/TestHelpers.cs new file mode 100644 index 000000000..a9ec4198b --- /dev/null +++ b/.dotnet/tests/Utility/TestHelpers.cs @@ -0,0 +1,77 @@ +using OpenAI.Assistants; +using OpenAI.Audio; +using OpenAI.Chat; +using OpenAI.Files; +using OpenAI.Images; +using System; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.IO; + +namespace OpenAI.Tests; + +internal static class TestHelpers +{ + public enum TestScenario + { + Assistants, + TextToSpeech, + Chat, + VisionChat, + Files, + Embeddings, + FineTuning, + Images, + Transcription, + Models, + LegacyCompletions, + Moderations, + } + + public static T GetTestClient(TestScenario scenario, string overrideModel = null, bool throwOnError = true) + { + OpenAIClientOptions options = new(); + options.AddPolicy(GetDumpPolicy(), PipelinePosition.PerTry); + options.ErrorOptions = throwOnError ? ClientErrorBehaviors.Default : ClientErrorBehaviors.NoThrow; + object clientObject = scenario switch + { + TestScenario.Chat => new ChatClient(overrideModel ?? "gpt-3.5-turbo", options), + TestScenario.VisionChat => new ChatClient(overrideModel ?? "gpt-4-vision-preview", options), + TestScenario.Assistants => new AssistantClient(options), + TestScenario.Images => new ImageClient(overrideModel ?? "dall-e-3", options), + TestScenario.Files => new FileClient(options), + TestScenario.Transcription => new AudioClient(overrideModel ?? "whisper-1", options), + _ => throw new NotImplementedException(), + }; + return (T)clientObject; + } + + private static PipelinePolicy GetDumpPolicy() + { + return new TestPipelinePolicy((message) => + { + if (message.Request?.Uri != null) + { + Console.WriteLine($"--- Request URI: ---"); + Console.WriteLine(message.Request.Uri.AbsoluteUri); + } + if (message.Request?.Content != null) + { + Console.WriteLine($"--- Begin request content ---"); + using MemoryStream stream = new(); + message.Request.Content.WriteTo(stream, default); + stream.Position = 0; + using StreamReader reader = new(stream); + Console.WriteLine(reader.ReadToEnd()); + Console.WriteLine("--- End of request content ---"); + } + if (message.Response != null) + { + Console.WriteLine("--- Begin response content ---"); + Console.WriteLine(message.Response.Content?.ToString()); + Console.WriteLine("--- End of response content ---"); + } + }); + } +} \ No newline at end of file diff --git a/.dotnet/tests/Utility/TestPipelinePolicy.cs b/.dotnet/tests/Utility/TestPipelinePolicy.cs new file mode 100644 index 000000000..688c407ed --- /dev/null +++ b/.dotnet/tests/Utility/TestPipelinePolicy.cs @@ -0,0 +1,35 @@ +using System; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace OpenAI.Tests; + +internal partial class TestPipelinePolicy : PipelinePolicy +{ + private Action _processMessageAction; + + public TestPipelinePolicy(Action processMessageAction) + { + _processMessageAction = processMessageAction; + } + + public override void Process(PipelineMessage message, IReadOnlyList pipeline, int currentIndex) + { + _processMessageAction(message); + if (currentIndex < pipeline.Count - 1) + { + pipeline[currentIndex + 1].Process(message, pipeline, currentIndex + 1); + } + } + + public override async ValueTask ProcessAsync(PipelineMessage message, IReadOnlyList pipeline, int currentIndex) + { + _processMessageAction(message); + if (currentIndex < pipeline.Count - 1) + { + await pipeline[currentIndex + 1].ProcessAsync(message, pipeline, currentIndex + 1); + } + } +} \ No newline at end of file diff --git a/.dotnet/tests/data/hello_world.m4a b/.dotnet/tests/data/hello_world.m4a new file mode 100644 index 0000000000000000000000000000000000000000..ed8e09c8f0c53d942f888a85d78800657b2f962a GIT binary patch literal 79968 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 literal 0 HcmV?d00001 diff --git a/.dotnet/tests/data/hola_mundo.m4a b/.dotnet/tests/data/hola_mundo.m4a new file mode 100644 index 0000000000000000000000000000000000000000..7bc01b755379aa13d424ac61492bdeb9514fa584 GIT binary patch literal 202099 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 z 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 literal 0 HcmV?d00001 diff --git a/.dotnet/tests/data/stop_sign.png b/.dotnet/tests/data/stop_sign.png new file mode 100644 index 0000000000000000000000000000000000000000..002b3ae1aa1967d4cfd490481f67deff52d92279 GIT binary patch literal 2125 zcmV-T2(tHyP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vG#Hvj-3HvuzPpLzfQ2jWRYK~#8N-CJ91 zOj{V9hbA-AQkRG0CN~v4o z(VJ78i*uZF^mM9o*)yFhX4YBX+H39Evu4k9rk(qjeA#RE`v0}o|Lx1H+cpsjQwH$K zZ2s9+Uhe3%TAent+1YD0yL!xK>9JVclpf9jo5kYg^ileIEtUX1f3<>|H7-!FX)w;jNn7BUXifF zLEO7`socF=rTD#bCvorCL6nvjmCemW*}k19+qS9Px|Jwfwh(3WW|d7%MA@{7C>u8t zrLmFG)zCoPd-vj|Wg^f!A-^JM!M}XTf=4MO#H_(EA{yZXVxhUAlu zx;j;a%1VgvD{ppY@Q>9x0hQoCIO292HlPrw7lHmm{l=R=JoHIC^78R06uq*D$75JwA=0sMArqkwB3P|M6XBBxo_0%%DR@E0f(5DwqehXQ zva&yTSgE1UWcm?>pl@D`!3#QSYtt9uFA+Q)oJ0l&3=1wMI%;ZE5k`-O2p@Tv#;}=8 z0=I7QGs$6}IaBjVMF4^RsZ%vSK>$Yx z@XbhoFB2y+qf`N(p$LF0lnzAu(h-1!!YEdD87IEn6RGy>C;(WA_2T7PViJL;G?HFhdV$Ops6Xw0Kv*|ty-ly%h3CR znCCZwY=?P88CYOJo)N_3mPi2Pxz?@YzoHQJ35s**2ZV6tuo$5?!0e9<&%uM5vkaTn z8snd;07megJ)1Dkd-5d9OD2Hm_Ua+(6BOqlKoG-Ttjg#Od>1b=BN;3o!OGP6g4q%P z?LuD01n7kTbm%J!AjZ;0aIIMrV{62e1)x1L8Oa3jU%A5ak_q5kxsv~iLewWH&fyLS z;CV-b^#))v3^qTQtvkSf{W{A_BtYNz@g&^W$A3kkuTzwbBLwhc2#f_vy#a_f?qI;+ zLiPjmB|swR>l9_&e9?s><jhGtvVuLge8p$nf8|5#yh#0N=X1c}^7AXoWl@ zxK^)bd6~Qe+}O#5jZ8*HGSC+{g4~l#RR9dajNmD1Xqj4|Au%fUnFtV+KcEQsvUrzu>+yPF!bdm{Biqr(K zRa7{b0Q>jH8I>}l0$8o@uuKGC#Y8qNMdIa-i%$OmBW!&T3x%2p35K_&LM#D_eg@V> znE*hH2-Vebj-@~rJbmFK9TU6&*3HE{J?7Qq0*aX|c=~tGew$3=c*yaT2QWL?T&tHgS!Si*@zpd6P9?H;xjmOw_%0yVW zFs{NvA`8B~ou#qKn};xbU< Date: Wed, 28 Feb 2024 18:30:16 -0800 Subject: [PATCH 19/50] Add samples and README (#3) --- .dotnet/README.md | 538 ++++++++++++++++++ .../src/Custom/Assistants/AssistantClient.cs | 64 +-- .dotnet/src/Custom/Files/OpenAIFileInfo.cs | 2 +- .../Models/OpenAIFile.Serialization.cs | 18 +- .dotnet/src/Generated/Models/OpenAIFile.cs | 6 +- .../Models/RunObject.Serialization.cs | 36 +- .dotnet/src/Generated/Models/RunObject.cs | 6 +- .dotnet/src/Generated/OpenAIModelFactory.cs | 2 +- .../Sample01_RetrievalAugmentedGeneration.cs | 137 +++++ ...ple01_RetrievalAugmentedGenerationAsync.cs | 137 +++++ .../Sample02_ListAssistantsWithPagination.cs | 35 ++ ...ple02_ListAssistantsWithPaginationAsync.cs | 36 ++ .../Assistants/Sample03_FunctionCalling.cs | 199 +++++++ .dotnet/tests/Samples/AssistantsSamples.cs | 167 ------ .dotnet/tests/Samples/Chat/ChatSamples.cs | 128 ----- .../tests/Samples/Chat/Sample01_SimpleChat.cs | 21 + .../Samples/Chat/Sample01_SimpleChatAsync.cs | 22 + .../Chat/Sample02_StreamingChatAsync.cs | 26 + .../Samples/Chat/Sample03_FunctionCalling.cs | 148 +++++ .../Chat/Sample03_FunctionCallingAsync.cs | 116 ++++ .../tests/Samples/Chat/Sample04_Protocol.cs | 43 ++ .../Samples/Chat/Sample04_ProtocolAsync.cs | 44 ++ .../Samples/Chat/Sample05_ChatWithVision.cs | 25 + .../Chat/Sample05_ChatWithVisionAsync.cs | 26 + .../Chat/Sample06_ComplexFunctionCalling.cs | 197 +++++++ .../Samples/Chat/Sample_FunctionCalling.cs | 148 ----- .dotnet/tests/Samples/ClientSamples.cs | 53 ++ .dotnet/tests/Samples/CombinationSamples.cs | 227 ++++---- .dotnet/tests/Samples/EmbeddingSamples.cs | 95 ---- .../Embeddings/Sample01_SimpleEmbedding.cs | 31 + .../Sample01_SimpleEmbeddingAsync.cs | 32 ++ .../Sample02_EmbeddingWithOptions.cs | 33 ++ .../Sample02_EmbeddingWithOptionsAsync.cs | 34 ++ .../Embeddings/Sample03_MultipleEmbeddings.cs | 40 ++ .../Sample03_MultipleEmbeddingsAsync.cs | 41 ++ .../Sample01_SimpleImage.cs} | 13 +- .../Images/Sample01_SimpleImageAsync.cs | 40 ++ files/models.tsp | 2 +- runs/models.tsp | 2 +- 39 files changed, 2254 insertions(+), 716 deletions(-) create mode 100644 .dotnet/README.md create mode 100644 .dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGeneration.cs create mode 100644 .dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGenerationAsync.cs create mode 100644 .dotnet/tests/Samples/Assistants/Sample02_ListAssistantsWithPagination.cs create mode 100644 .dotnet/tests/Samples/Assistants/Sample02_ListAssistantsWithPaginationAsync.cs create mode 100644 .dotnet/tests/Samples/Assistants/Sample03_FunctionCalling.cs delete mode 100644 .dotnet/tests/Samples/AssistantsSamples.cs delete mode 100644 .dotnet/tests/Samples/Chat/ChatSamples.cs create mode 100644 .dotnet/tests/Samples/Chat/Sample01_SimpleChat.cs create mode 100644 .dotnet/tests/Samples/Chat/Sample01_SimpleChatAsync.cs create mode 100644 .dotnet/tests/Samples/Chat/Sample02_StreamingChatAsync.cs create mode 100644 .dotnet/tests/Samples/Chat/Sample03_FunctionCalling.cs create mode 100644 .dotnet/tests/Samples/Chat/Sample03_FunctionCallingAsync.cs create mode 100644 .dotnet/tests/Samples/Chat/Sample04_Protocol.cs create mode 100644 .dotnet/tests/Samples/Chat/Sample04_ProtocolAsync.cs create mode 100644 .dotnet/tests/Samples/Chat/Sample05_ChatWithVision.cs create mode 100644 .dotnet/tests/Samples/Chat/Sample05_ChatWithVisionAsync.cs create mode 100644 .dotnet/tests/Samples/Chat/Sample06_ComplexFunctionCalling.cs delete mode 100644 .dotnet/tests/Samples/Chat/Sample_FunctionCalling.cs create mode 100644 .dotnet/tests/Samples/ClientSamples.cs delete mode 100644 .dotnet/tests/Samples/EmbeddingSamples.cs create mode 100644 .dotnet/tests/Samples/Embeddings/Sample01_SimpleEmbedding.cs create mode 100644 .dotnet/tests/Samples/Embeddings/Sample01_SimpleEmbeddingAsync.cs create mode 100644 .dotnet/tests/Samples/Embeddings/Sample02_EmbeddingWithOptions.cs create mode 100644 .dotnet/tests/Samples/Embeddings/Sample02_EmbeddingWithOptionsAsync.cs create mode 100644 .dotnet/tests/Samples/Embeddings/Sample03_MultipleEmbeddings.cs create mode 100644 .dotnet/tests/Samples/Embeddings/Sample03_MultipleEmbeddingsAsync.cs rename .dotnet/tests/Samples/{ImageSamples.cs => Images/Sample01_SimpleImage.cs} (81%) create mode 100644 .dotnet/tests/Samples/Images/Sample01_SimpleImageAsync.cs diff --git a/.dotnet/README.md b/.dotnet/README.md new file mode 100644 index 000000000..3d2ea9844 --- /dev/null +++ b/.dotnet/README.md @@ -0,0 +1,538 @@ +# OpenAI client library for .NET + +The OpenAI client library for .NET provides convenient access to the OpenAI REST API from .NET applications. + +## Getting started + +### Prerequisites + +To call the OpenAI REST API, you will need an API key. To obtain one, first [create a new OpenAI account](https://platform.openai.com/signup) or [log in](https://platform.openai.com/login). Next, navigate to the [API key page](https://platform.openai.com/account/api-keys) and select "Create new secret key", optionally naming the key. Make sure to save your API key somewhere safe and do not share it with anyone. + +### Install the NuGet package + +Add the client library to your .NET project with [NuGet](https://www.nuget.org/): + +```cli +dotnet add package OpenAI.OpenAI --prerelease +``` + +Note that the code samples included below were written using [.NET 8](https://dotnet.microsoft.com/download/dotnet/8.0). + +## Using the client library + +For convenience, the client library is organized by feature area into nine different namespaces, each with a corresponding client class: + +| Namespace | Client class | +| ----------------------------|--------------------------| +| `OpenAI.Assistants` | `AssistantsClient` | +| `OpenAI.Audio` | `AudioClient` | +| `OpenAI.Chat` | `ChatClient` | +| `OpenAI.Embeddings` | `EmbeddingClient` | +| `OpenAI.Files` | `FileClient` | +| `OpenAI.Images` | `ImageClient` | +| `OpenAI.LegacyCompletions` | `LegacyCompletionClient` | +| `OpenAI.ModelManagement` | `ModelManagementClient` | +| `OpenAI.Moderations` | `ModerationsClient` | + +To use chat completions, for example, start by adding the corresponding `using` statement and create an instance of the `ChatClient` by specifying both: + +1. The name of the OpenAI model that the client will use in its API calls (e.g., `"gpt-3.5-turbo"`) +2. The API key that the client will use to authenticate + +Then, call its `CompleteChat` method by passing the user message that you would like to generate completions for: + +```csharp +using OpenAI.Chat; + +ChatClient client = new("gpt-3.5-turbo", ""); + +ChatCompletion chatCompletion = client.CompleteChat("How does AI work? Explain it in simple terms."); + +Console.WriteLine($"[ASSISTANT]:"); +Console.WriteLine($"{ chatCompletion.Content }"); +``` + +For illustrative purposes, the code above prints the `Content` property of the resulting `ChatCompletion` object, yielding something like this: + +```text +[ASSISTANT]: +AI, or artificial intelligence, is a technology that allows machines to mimic human behaviors and intelligence. +It works by using algorithms and data to make decisions and perform tasks. These algorithms are designed to analyze +data, recognize patterns, and learn from past experiences to make predictions and solve problems. AI can be trained +to perform specific tasks, such as recognizing images or translating languages, by using vast amounts of data to +make accurate decisions. Essentially, AI works by processing data and using it to make informed decisions and solve +problems, much like a human brain would. +``` + +### Making async API calls + +Note that every client method that performs a synchronous API call has an asynchronous variant in the same client class. For instance, the asynchronous variant of the `ChatClient`'s `CompleteChat` method is the `ChatClient`'s `CompleteChatAsync` method. If you wanted to re-write the sample above as async code, all that you would need to do is modify the client method call like this: + +```csharp +ChatCompletion chatCompletion = await client.CompleteChatAsync("How does AI work? Explain it in simple terms."); +``` + +### Using the `OpenAIClient` class + +In addition to the nine namespaces mentioned above, there is also the parent `OpenAI` namespace itself: + +```csharp +using OpenAI; +``` + +This namespace contains the `OpenAIClient` class, which offers certain conveniences when you need to work with multiple clients. More specifically, you can use an instance of this class to create instances of the other clients that would share the same HTTP pipeline. + +You can create an `OpenAIClient` by specifying the API key that all clients will use for authentication: + +```csharp +OpenAIClient client = new(""); +``` + +Next, to create an instance of an `AudioClient`, for example, you can call the `OpenAIClient`'s `GetAudioClient` method by passing the OpenAI model that the `AudioClient` will use in its API calls. If necessary, you can create additional clients of the same type to target different models. + +```csharp +AudioClient ttsClient = client.GetAudioClient("tts-1"); +AudioClient whisperClient = client.GetAudioClient("whisper-1"); +``` + +## How to use chat completions with streaming + +When you request a chat completion, the default behavior is for the server to generate it in its entirety before sending it back in a single response. Consequently, long chat completions can require waiting for several seconds before hearing back from the server. To mitigate this, the OpenAI REST API supports the ability to stream partial results back as they are being generated, allowing you to start processing the beginning of the completion before it is finished. + +The client library offers a convenient approach to working with streaming chat completions. If you wanted to re-write the sample from the previous section using streaming, rather than calling the `ChatClient`'s `CompleteChat` method, you would call its `CompleteChatStreaming` method instead: + +```csharp +StreamingClientResult result = + client.CompleteChatStreaming("How does AI work? Explain it in simple terms."); +``` + +Notice that the returned value is a `StreamingClientResult` object, which can be iterated on to receive the streaming updates as they arrive: + +```csharp +Console.WriteLine("[ASSISTANT]: "); + +await foreach (StreamingChatUpdate chatUpdate in result) +{ + Console.Write(chatUpdate.ContentUpdate); +} +``` + +## How to use chat completions with function calling + +In this sample, you have a function that lets you query the weather in a given location (e.g., by making an API call to some third-party weather service or similar). For illustrative purposes, consider a function like this one: + +```csharp +private static string GetCurrentWeather(string location, string unit = "celsius") +{ + // Call the weather API here. + return "31 celsius"; +} +``` + +You want chat completions to be able to call this function if the model deems it necessary to have this information in order to respond to a user request. + +Start by creating a `ChatFunctionToolDefinition` that describes your function: + +```csharp +private const string GetCurrentWeatherFunctionName = "get_current_weather"; + +private static readonly ChatFunctionToolDefinition getCurrentWeatherFunction = new() +{ + Name = GetCurrentWeatherFunctionName, + Description = "Get the current weather in a given location", + Parameters = BinaryData.FromString(""" + { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state, e.g. Boston, MA" + }, + "unit": { + "type": "string", + "enum": [ "celsius", "fahrenheit" ], + "description": "The temperature unit to use. Infer this from the specified location." + } + }, + "required": [ "location" ] + } + """), +}; +``` + +As part of calling the `ChatClient`'s `CompleteChat` method, create a `ChatCompletionsOptions` instance, set its `Tools` property to include your `ChatFunctionToolDefinition`, and pass it as a parameter along with the request messages: + +```csharp +List messages = +[ + new ChatRequestSystemMessage( + "Don't make assumptions about what values to plug into functions." + + " Ask for clarification if a user request is ambiguous."), + new ChatRequestUserMessage("What's the weather like in San Francisco?"), +]; + +ChatCompletionOptions options = new() +{ + Tools = { getCurrentWeatherFunction }, +}; + +ChatCompletion chatCompletion = client.CompleteChat(messages, options); +``` + +If the resulting `ChatCompletion` has a `FinishReason` property equal to `ChatFinishReason.ToolCalls`, it means that the model has determined that one or more tools must be called before the assistant can respond appropriately. + +```csharp +if (chatCompletion.FinishReason == ChatFinishReason.ToolCalls) +{ + // First, add the assistant message with tool calls to the conversation history. + messages.Add(new ChatRequestAssistantMessage(chatCompletion)); + + // Then, add a new tool message for each tool call that is resolved. + foreach (ChatToolCall toolCall in chatCompletion.ToolCalls) + { + ChatFunctionToolCall functionToolCall = toolCall as ChatFunctionToolCall; + + switch (functionToolCall?.Name) + { + case GetCurrentWeatherFunctionName: + { + // The arguments that the model wants to use to call the function are specified as a + // stringified JSON object based on the schema defined in the tool definition. Note that + // the model may hallucinate arguments too. Consequently, it is important to do the + // appropriate parsing and validation before calling the function. + using JsonDocument argumentsJson = JsonDocument.Parse(functionToolCall.Arguments); + bool hasLocation = argumentsJson.RootElement.TryGetProperty("location", out JsonElement location); + bool hasUnit = argumentsJson.RootElement.TryGetProperty("unit", out JsonElement unit); + + if (!hasLocation) + { + throw new ArgumentNullException(nameof(location), "The location argument is required."); + } + + string toolResult = GetCurrentWeather(location.GetString(), hasUnit ? unit.GetString() : null); + messages.Add(new ChatRequestToolMessage(toolCall.Id, toolResult)); + break; + } + + default: + { + // Handle other or unexpected calls. + throw new NotImplementedException(); + } + } + } + + // Finally, make a new request to chat completions to let the assistant summarize the tool results + // and add the resulting message to the conversation history to keep it organized all in one place. + ChatCompletion chatCompletionAfterToolMessages = client.CompleteChat(messages, options); + messages.Add(new ChatRequestAssistantMessage(chatCompletionAfterToolMessages)); +} +``` + +## How to get text embeddings + +In this sample, you want to create a trip-planning website that allows customers to write a prompt describing the kind of hotel that they are looking for and then offers hotel recommendations that closely match this description. To achieve this, it is possible to use text embeddings to measure the relatedness of text strings. In summary, you can get embeddings of the hotel descriptions, store them in a vector database, and use them to build a search index that you can query using the embedding of a given customer's prompt. + +To get a text embedding, start by adding the corresponding `using` statement: + +```csharp +using OpenAI.Embeddings; +``` + +Next, instantiate the `EmbeddingClient` and call its `GenerateEmbedding` method by passing the text input as a parameter: + +```csharp +EmbeddingClient client = new("text-embedding-3-small", ""); + +string description = + "Best hotel in town if you like luxury hotels. They have an amazing infinity pool, a spa," + + " and a really helpful concierge. The location is perfect -- right downtown, close to all " + + " the tourist attractions. We highly recommend this hotel."; + +Embedding embedding = client.GenerateEmbedding(description); +ReadOnlyMemory vector = embedding.Vector; +``` + +Notice that the resulting embedding is a list (also called a vector) of floating point numbers represented as an instance of `ReadOnlyMemory`. By default, the length of the embedding vector will be 1536 when using the `text-embedding-3-small` model or 3072 when using the `text-embedding-3-large` model. Generally, larger embeddings perform better, but using them also tends to cost more in terms of compute, memory, and storage. You can reduce the dimensions of the embedding by creating an instance of the `EmbeddingOptions` class, setting the `Dimensions` property, and passing it as a parameter in your call to the `GenerateEmbedding` method: + +```csharp +EmbeddingOptions options = new() { Dimensions = 512 }; + +Embedding embedding = client.GenerateEmbedding(description, options); +``` + +## How to generate images + +In this sample, you want to build an app to help interior designers prototype new ideas based on the latest design trends. As part of the creative process, an interior designer can use this app to generate images for inspiration simply by describing the scene in their head as a prompt. As expected, high-quality, strikingly dramatic images with finer details deliver the best results for this application. + +To generate an image, start by adding the corresponding `using` statement: + +```csharp +using OpenAI.Images; +``` + +Next, instantiate the `ImageClient`: + +```csharp +ImageClient client = new("dall-e-3", ""); +``` + +To tailor the image generation to your specific needs, create an instance of the `ImageGenerationOptions` class and set the `Quality`, `Size`, and `Style` properties accordingly. Note that you can also set the `ResponseFormat` property of `ImageGenerationOptions` to `ImageResponseFormat.Bytes` in order to receive the resulting PNG as `BinaryData` if this is convenient for your use case. + +```csharp +string prompt = "The concept for a living room that blends Scandinavian simplicity with Japanese minimalism for" + + " a serene and cozy atmosphere. It's a space that invites relaxation and mindfulness, with natural light" + + " and fresh air. Using neutral tones, including colors like white, beige, gray, and black, that create a" + + " sense of harmony. Featuring sleek wood furniture with clean lines and subtle curves to add warmth and" + + " elegance. Plants and flowers in ceramic pots adding color and life to a space. They can serve as focal" + + " points, creating a connection with nature. Soft textiles and cushions in organic fabrics adding comfort" + + " and softness to a space. They can serve as accents, adding contrast and texture."; + +ImageGenerationOptions options = new() +{ + Quality = ImageQuality.High, + Size = ImageSize.Size1792x1024, + Style = ImageStyle.Vivid, + ResponseFormat = ImageResponseFormat.Bytes +}; +``` + +Finally, call the `ImageClient`'s `GenerateImage` method by passing the prompt and the `ImageGenerationOptions` instance as parameters: + +```csharp +GeneratedImage image = client.GenerateImage(prompt, options); +BinaryData bytes = image.ImageBytes; +``` + +For illustrative purposes, you could save the generated image to local storage: + +```csharp +using FileStream stream = File.OpenWrite($"{ Guid.NewGuid() }.png"); +bytes.ToStream().CopyTo(stream); +``` + +## How to use assistants with retrieval augmented generation (RAG) + +In this sample, you have a JSON document with the monthly sales information of different products, and you want to build an assistant capable of analyzing it and answering questions about it. + +Start by adding the following `using` statements: + +```csharp +using OpenAI; +using OpenAI.Assistants; +using OpenAI.Files; +``` + +Create an instance of the `OpenAIClient` class and use it to instantiate a `FileClient` and an `AssistantClient`: + +```csharp +OpenAIClient openAIClient = new(""); +FileClient fileClient = openAIClient.GetFileClient(); +AssistantClient assistantClient = openAIClient.GetAssistantClient(); +``` + +Here is an example of what the JSON document might look like: + +```csharp +BinaryData document = BinaryData.FromString(""" + { + "description": "This document contains the sale history data for Contoso products.", + "sales": [ + { + "month": "January", + "by_product": { + "113043": 15, + "113045": 12, + "113049": 2 + } + }, + { + "month": "February", + "by_product": { + "113045": 22 + } + }, + { + "month": "March", + "by_product": { + "113045": 16, + "113055": 5 + } + } + ] + } + """); +``` + +Upload this document to OpenAI using the `FileClient`'s `UploadFile` method: + +```csharp +OpenAIFileInfo openAIFileInfo = fileClient.UploadFile(document, "MonthlySales.json", OpenAIFilePurpose.Assistants); +``` + +Create an instance of the `AssistantCreationOptions` class and use it to define the assistant that you want to build. Make sure to include: + +1. The ID of the JSON document that you just uploaded in the `FileIds` property +2. An instance of the `RetrievalToolDefinition` class in the `Tools` property + +Optionally, you can also include an instance of the `CodeInterpreterToolDefinition` class in the `Tools` property and instruct the assistant via the `Instructions` property to use it to generate data visualizations when prompted. + +```csharp +AssistantCreationOptions assistantOptions = new() +{ + Name = "Example: Contoso sales RAG", + Instructions = + "You are an assistant that looks up sales data and helps visualize the information based" + + " on user queries. When asked to generate a graph, chart, or other visualization, use" + + " the code interpreter tool to do so.", + FileIds = { openAIFileInfo.Id }, + Tools = + { + new RetrievalToolDefinition(), + new CodeInterpreterToolDefinition(), + } +}; +``` + +Now, create the assistant using the `AssistantClient`'s `CreateAssistant` method: + +```csharp +Assistant assistant = assistantClient.CreateAssistant("gpt-4-1106-preview", assistantOptions); +``` + +Next, create a new thread. For illustrative purposes, you could include an initial user message asking about the sales information of a given product and then use the `AssistantClient`'s `CreateThreadAndRun` method to get it started: + +```csharp +ThreadCreationOptions threadOptions = new() +{ + Messages = + { + new ThreadInitializationMessage( + MessageRole.User, + "How well did product 113045 sell in February? Graph its trend over time."), + } +}; + +ThreadRun threadRun = assistantClient.CreateThreadAndRun(assistant.Id, threadOptions); +``` + +Poll the status of the run until it is no longer queued or in progress: + +```csharp +do +{ + Thread.Sleep(TimeSpan.FromSeconds(1)); + threadRun = assistantClient.GetRun(threadRun.ThreadId, threadRun.Id); +} while (threadRun.Status == RunStatus.Queued || threadRun.Status == RunStatus.InProgress); +``` + +If everything went well, the terminal status of the run will be `RunStatus.CompletedSuccessfully`. + +Finally, you can use the `AssistantClient`'s `GetMessages` method to retrieve the messages associated with this thread, which now include the responses from the assistant to the initial user message: + +```csharp +ListQueryPage messages = assistantClient.GetMessages(threadRun.ThreadId); +``` + +For illustrative purposes, you could print the messages to the console and also save any images produced by the assistant to local storage: + +```csharp +for (int i = messages.Count - 1; i >= 0; i--) +{ + ThreadMessage message = messages[i]; + + Console.WriteLine($"[{message.Role.ToString().ToUpper()}]:"); + foreach (MessageContent contentItem in message.ContentItems) + { + if (contentItem is MessageTextContent textContent) + { + Console.WriteLine($"{textContent.Text}"); + + if (textContent.Annotations.Count > 0) + { + Console.WriteLine(); + } + + // Include annotations, if any. + foreach (TextContentAnnotation annotation in textContent.Annotations) + { + if (annotation is TextContentFileCitationAnnotation citationAnnotation) + { + Console.WriteLine($"* File citation, file ID: {citationAnnotation.FileId}"); + } + else if (annotation is TextContentFilePathAnnotation pathAnnotation) + { + Console.WriteLine($"* File path, file ID: {pathAnnotation.FileId}"); + } + } + } + else if (contentItem is MessageImageFileContent imageFileContent) + { + OpenAIFileInfo imageInfo = fileClient.GetFileInfo(imageFileContent.FileId); + BinaryData imageBytes = fileClient.DownloadFile(imageFileContent.FileId); + using FileStream stream = File.OpenWrite($"{ imageInfo.Filename }.png"); + imageBytes.ToStream().CopyTo(stream); + + Console.WriteLine($"<{ imageInfo.Filename }.png>"); + } + } + Console.WriteLine(); +} +``` + +And it would yield something like this: + +```text +[USER]: +How well did product 113045 sell in February? Graph its trend over time. + +[ASSISTANT]: + +Product 113045 sold 22 units in February. Here is the trend graph showing its sales over the months of +January, February, and March. +``` + +## Advanced scenarios + +### Using protocol methods + +The client library includes model types—convenience classes that map to the request and response bodies of the REST API. The client methods that receive and return model types can be called here _convenience methods_. In addition to these, the clients also expose overloads of these methods that mirror the request and response bodies directly. Those methods are called here _protocol methods_, as they provide more direct access to the REST protocol. + +For example, to use the protocol method variant of the `ChatClient`'s `CompleteChat` method, pass the request body as a `BinaryContent` object: + +```csharp +BinaryData input = BinaryData.FromString(""" + { + "model": "gpt-3.5-turbo", + "messages": [ + { + "role": "user", + "content": "How does AI work? Explain it in simple terms." + } + ] + } + """); + +ClientResult result = client.CompleteChat(BinaryContent.Create(input)); +BinaryData output = result.GetRawResponse().Content; + +using JsonDocument outputAsJson = JsonDocument.Parse(output.ToString()); +string message = outputAsJson.RootElement + .GetProperty("choices")[0] + .GetProperty("message") + .GetProperty("content") + .GetString(); +``` + +Notice how you can then call the resulting `ClientResult`'s `GetRawResponse` method and retrieve the response body as `BinaryData` via the `PipelineResponse`'s `Content` property. + +### Automatically retrying errors + +By default, the client classes will automatically retry the following errors up to three additional times using exponential backoff: + +- 408 Request Timeout +- 429 Too Many Requests +- 500 Internal Server Error +- 502 Bad Gateway +- 503 Service Unavailable +- 504 Gateway Timeout diff --git a/.dotnet/src/Custom/Assistants/AssistantClient.cs b/.dotnet/src/Custom/Assistants/AssistantClient.cs index 72f33f119..b2f02a1aa 100644 --- a/.dotnet/src/Custom/Assistants/AssistantClient.cs +++ b/.dotnet/src/Custom/Assistants/AssistantClient.cs @@ -1,15 +1,9 @@ +using OpenAI.ClientShared.Internal; using System; -using System.ClientModel; -using System.ClientModel.Internal; - using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; -using System.Threading; using System.Threading.Tasks; -using OpenAI.Internal; -using System.Text.Json; -using OpenAI.ClientShared.Internal; namespace OpenAI.Assistants; @@ -530,13 +524,13 @@ Internal.Models.CreateThreadAndRunRequest request return ClientResult.FromValue(new ThreadRun(internalResult.Value), internalResult.GetRawResponse()); } - public virtual ClientResult GetRun(string threadId, string runId) + public virtual ClientResult GetRun(string threadId, string runId) { ClientResult internalResult = RunShim.GetRun(threadId, runId); return ClientResult.FromValue(new ThreadRun(internalResult.Value), internalResult.GetRawResponse()); } - public virtual async Task> GetRunAsync(string threadId, string runId) + public virtual async Task> GetRunAsync(string threadId, string runId) { ClientResult internalResult = await RunShim.GetRunAsync(threadId, runId).ConfigureAwait(false); @@ -575,14 +569,14 @@ public virtual Task>> GetRunsAsync( return GetListQueryPageAsync(internalFunc); } - public virtual ClientResult ModifyRun(string threadId, string runId, RunModificationOptions options) + public virtual ClientResult ModifyRun(string threadId, string runId, RunModificationOptions options) { Internal.Models.ModifyRunRequest request = new(options.Metadata, serializedAdditionalRawData: null); ClientResult internalResult = RunShim.ModifyRun(threadId, runId, request); return ClientResult.FromValue(new ThreadRun(internalResult.Value), internalResult.GetRawResponse()); } - public virtual async Task> ModifyRunAsync(string threadId, string runId, RunModificationOptions options) + public virtual async Task> ModifyRunAsync(string threadId, string runId, RunModificationOptions options) { Internal.Models.ModifyRunRequest request = new(options.Metadata, serializedAdditionalRawData: null); ClientResult internalResult @@ -590,45 +584,45 @@ public virtual async Task> ModifyRunAsync(string threadI return ClientResult.FromValue(new ThreadRun(internalResult.Value), internalResult.GetRawResponse()); } - public virtual ClientResult CancelRun(string threadId, string runId) + public virtual ClientResult CancelRun(string threadId, string runId) { ClientResult internalResult = RunShim.CancelRun(threadId, runId); return ClientResult.FromValue(true, internalResult.GetRawResponse()); } - public virtual async Task> CancelRunAsync(string threadId, string runId) + public virtual async Task> CancelRunAsync(string threadId, string runId) { ClientResult internalResult = await RunShim.CancelRunAsync(threadId, runId); return ClientResult.FromValue(true, internalResult.GetRawResponse()); } - public virtual ClientResult SubmitToolOutputs(string threadId, string runId, IEnumerable toolOutputs) + public virtual ClientResult SubmitToolOutputs(string threadId, string runId, IEnumerable toolOutputs) { - BinaryContent content = BinaryContent.Create(BinaryData.FromObjectAsJson(new - { - tool_outputs = toolOutputs - }, - new JsonSerializerOptions() - { - PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower - })); - ClientResult internalResult = RunShim.SubmitToolOuputsToRun(threadId, runId, content, default); - return ClientResult.FromValue(true, internalResult.GetRawResponse()); + List requestToolOutputs = []; + + foreach (ToolOutput toolOutput in toolOutputs) + { + requestToolOutputs.Add(new(toolOutput.Id, toolOutput.Output, null)); + } + + Internal.Models.SubmitToolOutputsRunRequest request = new(requestToolOutputs, null); + ClientResult internalResult = RunShim.SubmitToolOuputsToRun(threadId, runId, request); + return ClientResult.FromValue(new ThreadRun(internalResult.Value), internalResult.GetRawResponse()); } - public virtual async Task> SubmitToolOutputsAsync(string threadId, string runId, IEnumerable toolOutputs) + public virtual async Task> SubmitToolOutputsAsync(string threadId, string runId, IEnumerable toolOutputs) { - BinaryContent content = BinaryContent.Create(BinaryData.FromObjectAsJson(new - { - tool_outputs = toolOutputs - }, - new JsonSerializerOptions() - { - PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower - })); - ClientResult internalResult - = await RunShim.SubmitToolOuputsToRunAsync(threadId, runId, content, default).ConfigureAwait(false); + List requestToolOutputs = []; + + foreach (ToolOutput toolOutput in toolOutputs) + { + requestToolOutputs.Add(new(toolOutput.Id, toolOutput.Output, null)); + } + + Internal.Models.SubmitToolOutputsRunRequest request = new(requestToolOutputs, null); + ClientResult internalResult + = await RunShim.SubmitToolOuputsToRunAsync(threadId, runId, request).ConfigureAwait(false); return ClientResult.FromValue(true, internalResult.GetRawResponse()); } diff --git a/.dotnet/src/Custom/Files/OpenAIFileInfo.cs b/.dotnet/src/Custom/Files/OpenAIFileInfo.cs index 04d76a036..26988b297 100644 --- a/.dotnet/src/Custom/Files/OpenAIFileInfo.cs +++ b/.dotnet/src/Custom/Files/OpenAIFileInfo.cs @@ -7,7 +7,7 @@ public partial class OpenAIFileInfo public string Id { get; } public OpenAIFilePurpose Purpose { get; } public string Filename { get; } - public long Size { get; } + public long? Size { get; } public DateTimeOffset CreatedAt { get; } internal OpenAIFileInfo(Internal.Models.OpenAIFile internalFile) diff --git a/.dotnet/src/Generated/Models/OpenAIFile.Serialization.cs b/.dotnet/src/Generated/Models/OpenAIFile.Serialization.cs index 98890a027..8243b7143 100644 --- a/.dotnet/src/Generated/Models/OpenAIFile.Serialization.cs +++ b/.dotnet/src/Generated/Models/OpenAIFile.Serialization.cs @@ -21,8 +21,15 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOption writer.WriteStartObject(); writer.WritePropertyName("id"u8); writer.WriteStringValue(Id); - writer.WritePropertyName("bytes"u8); - writer.WriteNumberValue(Bytes); + if (Bytes != null) + { + writer.WritePropertyName("bytes"u8); + writer.WriteNumberValue(Bytes.Value); + } + else + { + writer.WriteNull("bytes"); + } writer.WritePropertyName("created_at"u8); writer.WriteNumberValue(CreatedAt, "U"); writer.WritePropertyName("filename"u8); @@ -77,7 +84,7 @@ internal static OpenAIFile DeserializeOpenAIFile(JsonElement element, ModelReade return null; } string id = default; - long bytes = default; + long? bytes = default; DateTimeOffset createdAt = default; string filename = default; OpenAIFileObject @object = default; @@ -95,6 +102,11 @@ internal static OpenAIFile DeserializeOpenAIFile(JsonElement element, ModelReade } if (property.NameEquals("bytes"u8)) { + if (property.Value.ValueKind == JsonValueKind.Null) + { + bytes = null; + continue; + } bytes = property.Value.GetInt64(); continue; } diff --git a/.dotnet/src/Generated/Models/OpenAIFile.cs b/.dotnet/src/Generated/Models/OpenAIFile.cs index 99f8e94ad..697be44f8 100644 --- a/.dotnet/src/Generated/Models/OpenAIFile.cs +++ b/.dotnet/src/Generated/Models/OpenAIFile.cs @@ -55,7 +55,7 @@ internal partial class OpenAIFile /// `error`. /// /// or is null. - internal OpenAIFile(string id, long bytes, DateTimeOffset createdAt, string filename, OpenAIFilePurpose purpose, OpenAIFileStatus status) + internal OpenAIFile(string id, long? bytes, DateTimeOffset createdAt, string filename, OpenAIFilePurpose purpose, OpenAIFileStatus status) { if (id is null) throw new ArgumentNullException(nameof(id)); if (filename is null) throw new ArgumentNullException(nameof(filename)); @@ -87,7 +87,7 @@ internal OpenAIFile(string id, long bytes, DateTimeOffset createdAt, string file /// field on `fine_tuning.job`. /// /// Keeps track of any properties unknown to the library. - internal OpenAIFile(string id, long bytes, DateTimeOffset createdAt, string filename, OpenAIFileObject @object, OpenAIFilePurpose purpose, OpenAIFileStatus status, string statusDetails, IDictionary serializedAdditionalRawData) + internal OpenAIFile(string id, long? bytes, DateTimeOffset createdAt, string filename, OpenAIFileObject @object, OpenAIFilePurpose purpose, OpenAIFileStatus status, string statusDetails, IDictionary serializedAdditionalRawData) { Id = id; Bytes = bytes; @@ -108,7 +108,7 @@ internal OpenAIFile() /// The file identifier, which can be referenced in the API endpoints. public string Id { get; } /// The size of the file, in bytes. - public long Bytes { get; } + public long? Bytes { get; } /// The Unix timestamp (in seconds) for when the file was created. public DateTimeOffset CreatedAt { get; } /// The name of the file. diff --git a/.dotnet/src/Generated/Models/RunObject.Serialization.cs b/.dotnet/src/Generated/Models/RunObject.Serialization.cs index 07fa205c1..70aa2431b 100644 --- a/.dotnet/src/Generated/Models/RunObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunObject.Serialization.cs @@ -49,8 +49,15 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions { writer.WriteNull("last_error"); } - writer.WritePropertyName("expires_at"u8); - writer.WriteNumberValue(ExpiresAt, "U"); + if (ExpiresAt != null) + { + writer.WritePropertyName("expires_at"u8); + writer.WriteStringValue(ExpiresAt.Value, "O"); + } + else + { + writer.WriteNull("expires_at"); + } if (StartedAt != null) { writer.WritePropertyName("started_at"u8); @@ -187,7 +194,7 @@ internal static RunObject DeserializeRunObject(JsonElement element, ModelReaderW RunObjectStatus status = default; RunObjectRequiredAction requiredAction = default; RunObjectLastError lastError = default; - DateTimeOffset expiresAt = default; + DateTimeOffset? expiresAt = default; DateTimeOffset? startedAt = default; DateTimeOffset? cancelledAt = default; DateTimeOffset? failedAt = default; @@ -254,6 +261,13 @@ internal static RunObject DeserializeRunObject(JsonElement element, ModelReaderW } if (property.NameEquals("expires_at"u8)) { + if (property.Value.ValueKind == JsonValueKind.Null) + { + expiresAt = null; + continue; + } + // BUG: https://github.com/Azure/autorest.csharp/issues/4296 + // expiresAt = property.Value.GetDateTimeOffset("O"); expiresAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); continue; } @@ -264,7 +278,9 @@ internal static RunObject DeserializeRunObject(JsonElement element, ModelReaderW startedAt = null; continue; } - startedAt = property.Value.GetDateTimeOffset("O"); + // BUG: https://github.com/Azure/autorest.csharp/issues/4296 + // startedAt = property.Value.GetDateTimeOffset("O"); + startedAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); continue; } if (property.NameEquals("cancelled_at"u8)) @@ -274,7 +290,9 @@ internal static RunObject DeserializeRunObject(JsonElement element, ModelReaderW cancelledAt = null; continue; } - cancelledAt = property.Value.GetDateTimeOffset("O"); + // BUG: https://github.com/Azure/autorest.csharp/issues/4296 + // cancelledAt = property.Value.GetDateTimeOffset("O"); + cancelledAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); continue; } if (property.NameEquals("failed_at"u8)) @@ -284,7 +302,9 @@ internal static RunObject DeserializeRunObject(JsonElement element, ModelReaderW failedAt = null; continue; } - failedAt = property.Value.GetDateTimeOffset("O"); + // BUG: https://github.com/Azure/autorest.csharp/issues/4296 + // failedAt = property.Value.GetDateTimeOffset("O"); + failedAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); continue; } if (property.NameEquals("completed_at"u8)) @@ -294,7 +314,9 @@ internal static RunObject DeserializeRunObject(JsonElement element, ModelReaderW completedAt = null; continue; } - completedAt = property.Value.GetDateTimeOffset("O"); + // BUG: https://github.com/Azure/autorest.csharp/issues/4296 + // completedAt = property.Value.GetDateTimeOffset("O"); + completedAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); continue; } if (property.NameEquals("model"u8)) diff --git a/.dotnet/src/Generated/Models/RunObject.cs b/.dotnet/src/Generated/Models/RunObject.cs index 282cac58a..680ffe5ea 100644 --- a/.dotnet/src/Generated/Models/RunObject.cs +++ b/.dotnet/src/Generated/Models/RunObject.cs @@ -78,7 +78,7 @@ internal partial class RunObject /// /// /// , , , , , or is null. - internal RunObject(string id, DateTimeOffset createdAt, string threadId, string assistantId, RunObjectStatus status, RunObjectRequiredAction requiredAction, RunObjectLastError lastError, DateTimeOffset expiresAt, DateTimeOffset? startedAt, DateTimeOffset? cancelledAt, DateTimeOffset? failedAt, DateTimeOffset? completedAt, string model, string instructions, IEnumerable tools, IEnumerable fileIds, IReadOnlyDictionary metadata, RunCompletionUsage usage) + internal RunObject(string id, DateTimeOffset createdAt, string threadId, string assistantId, RunObjectStatus status, RunObjectRequiredAction requiredAction, RunObjectLastError lastError, DateTimeOffset? expiresAt, DateTimeOffset? startedAt, DateTimeOffset? cancelledAt, DateTimeOffset? failedAt, DateTimeOffset? completedAt, string model, string instructions, IEnumerable tools, IEnumerable fileIds, IReadOnlyDictionary metadata, RunCompletionUsage usage) { if (id is null) throw new ArgumentNullException(nameof(id)); if (threadId is null) throw new ArgumentNullException(nameof(threadId)); @@ -145,7 +145,7 @@ internal RunObject(string id, DateTimeOffset createdAt, string threadId, string /// /// /// Keeps track of any properties unknown to the library. - internal RunObject(string id, RunObjectObject @object, DateTimeOffset createdAt, string threadId, string assistantId, RunObjectStatus status, RunObjectRequiredAction requiredAction, RunObjectLastError lastError, DateTimeOffset expiresAt, DateTimeOffset? startedAt, DateTimeOffset? cancelledAt, DateTimeOffset? failedAt, DateTimeOffset? completedAt, string model, string instructions, IReadOnlyList tools, IReadOnlyList fileIds, IReadOnlyDictionary metadata, RunCompletionUsage usage, IDictionary serializedAdditionalRawData) + internal RunObject(string id, RunObjectObject @object, DateTimeOffset createdAt, string threadId, string assistantId, RunObjectStatus status, RunObjectRequiredAction requiredAction, RunObjectLastError lastError, DateTimeOffset? expiresAt, DateTimeOffset? startedAt, DateTimeOffset? cancelledAt, DateTimeOffset? failedAt, DateTimeOffset? completedAt, string model, string instructions, IReadOnlyList tools, IReadOnlyList fileIds, IReadOnlyDictionary metadata, RunCompletionUsage usage, IDictionary serializedAdditionalRawData) { Id = id; Object = @object; @@ -201,7 +201,7 @@ internal RunObject() /// The last error associated with this run. Will be `null` if there are no errors. public RunObjectLastError LastError { get; } /// The Unix timestamp (in seconds) for when the run will expire. - public DateTimeOffset ExpiresAt { get; } + public DateTimeOffset? ExpiresAt { get; } /// The Unix timestamp (in seconds) for when the run was started. public DateTimeOffset? StartedAt { get; } /// The Unix timestamp (in seconds) for when the run was cancelled. diff --git a/.dotnet/src/Generated/OpenAIModelFactory.cs b/.dotnet/src/Generated/OpenAIModelFactory.cs index f01f31690..7f65feaf5 100644 --- a/.dotnet/src/Generated/OpenAIModelFactory.cs +++ b/.dotnet/src/Generated/OpenAIModelFactory.cs @@ -531,7 +531,7 @@ public static CreateThreadAndRunRequest CreateThreadAndRunRequest(string assista /// /// /// A new instance for mocking. - public static RunObject RunObject(string id = null, RunObjectObject @object = default, DateTimeOffset createdAt = default, string threadId = null, string assistantId = null, RunObjectStatus status = default, RunObjectRequiredAction requiredAction = null, RunObjectLastError lastError = null, DateTimeOffset expiresAt = default, DateTimeOffset? startedAt = null, DateTimeOffset? cancelledAt = null, DateTimeOffset? failedAt = null, DateTimeOffset? completedAt = null, string model = null, string instructions = null, IEnumerable tools = null, IEnumerable fileIds = null, IReadOnlyDictionary metadata = null, RunCompletionUsage usage = null) + public static RunObject RunObject(string id = null, RunObjectObject @object = default, DateTimeOffset createdAt = default, string threadId = null, string assistantId = null, RunObjectStatus status = default, RunObjectRequiredAction requiredAction = null, RunObjectLastError lastError = null, DateTimeOffset? expiresAt = null, DateTimeOffset? startedAt = null, DateTimeOffset? cancelledAt = null, DateTimeOffset? failedAt = null, DateTimeOffset? completedAt = null, string model = null, string instructions = null, IEnumerable tools = null, IEnumerable fileIds = null, IReadOnlyDictionary metadata = null, RunCompletionUsage usage = null) { tools ??= new List(); fileIds ??= new List(); diff --git a/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGeneration.cs b/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGeneration.cs new file mode 100644 index 000000000..7d0bf174c --- /dev/null +++ b/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGeneration.cs @@ -0,0 +1,137 @@ +using NUnit.Framework; +using OpenAI.Assistants; +using OpenAI.Files; +using System; +using System.IO; +using System.Threading; + +namespace OpenAI.Samples +{ + public partial class AssistantSamples + { + [Test] + // [Ignore("Compilation validation only")] + public void Sample01_RetrievalAugmentedGeneration() + { + OpenAIClient openAIClient = new(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + FileClient fileClient = openAIClient.GetFileClient(); + AssistantClient assistantClient = openAIClient.GetAssistantClient(); + + // First, let's contrive a document we'll use retrieval with and upload it. + BinaryData document = BinaryData.FromString(""" + { + "description": "This document contains the sale history data for Contoso products.", + "sales": [ + { + "month": "January", + "by_product": { + "113043": 15, + "113045": 12, + "113049": 2 + } + }, + { + "month": "February", + "by_product": { + "113045": 22 + } + }, + { + "month": "March", + "by_product": { + "113045": 16, + "113055": 5 + } + } + ] + } + """); + + OpenAIFileInfo openAIFileInfo = fileClient.UploadFile(document, "test-rag-file-delete-me.json", OpenAIFilePurpose.Assistants); + + // Now, we'll create a client intended to help with that data + AssistantCreationOptions assistantOptions = new() + { + Name = "Example: Contoso sales RAG", + Instructions = + "You are an assistant that looks up sales data and helps visualize the information based" + + " on user queries. When asked to generate a graph, chart, or other visualization, use" + + " the code interpreter tool to do so.", + FileIds = { openAIFileInfo.Id }, + Tools = + { + new RetrievalToolDefinition(), + new CodeInterpreterToolDefinition(), + }, + Metadata = { ["test_key_delete_me"] = "true" }, + }; + + Assistant assistant = assistantClient.CreateAssistant("gpt-4-1106-preview", assistantOptions); + + // Now we'll create a thread with a user query about the data already associated with the assistant, then run it + ThreadCreationOptions threadOptions = new() + { + Messages = + { + new ThreadInitializationMessage( + MessageRole.User, + "How well did product 113045 sell in February? Graph its trend over time."), + } + }; + + ThreadRun threadRun = assistantClient.CreateThreadAndRun(assistant.Id, threadOptions); + + // Check back to see when the run is done + do + { + Thread.Sleep(TimeSpan.FromSeconds(1)); + threadRun = assistantClient.GetRun(threadRun.ThreadId, threadRun.Id); + } while (threadRun.Status == RunStatus.Queued || threadRun.Status == RunStatus.InProgress); + + // Finally, we'll print out the full history for the thread that includes the augmented generation + ListQueryPage messages = assistantClient.GetMessages(threadRun.ThreadId); + + for (int i = messages.Count - 1; i >= 0; i--) + { + ThreadMessage message = messages[i]; + + Console.WriteLine($"[{message.Role.ToString().ToUpper()}]:"); + foreach (MessageContent contentItem in message.ContentItems) + { + if (contentItem is MessageTextContent textContent) + { + Console.WriteLine($"{textContent.Text}"); + + if (textContent.Annotations.Count > 0) + { + Console.WriteLine(); + } + + // Include annotations, if any. + foreach (TextContentAnnotation annotation in textContent.Annotations) + { + if (annotation is TextContentFileCitationAnnotation citationAnnotation) + { + Console.WriteLine($"* File citation, file ID: {citationAnnotation.FileId}"); + } + else if (annotation is TextContentFilePathAnnotation pathAnnotation) + { + Console.WriteLine($"* File path, file ID: {pathAnnotation.FileId}"); + } + } + } + else if (contentItem is MessageImageFileContent imageFileContent) + { + OpenAIFileInfo imageInfo = fileClient.GetFileInfo(imageFileContent.FileId); + BinaryData imageBytes = fileClient.DownloadFile(imageFileContent.FileId); + using FileStream stream = File.OpenWrite($"{imageInfo.Filename}.png"); + imageBytes.ToStream().CopyTo(stream); + + Console.WriteLine($""); + } + } + Console.WriteLine(); + } + } + } +} diff --git a/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGenerationAsync.cs b/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGenerationAsync.cs new file mode 100644 index 000000000..4b706a8eb --- /dev/null +++ b/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGenerationAsync.cs @@ -0,0 +1,137 @@ +using NUnit.Framework; +using OpenAI.Assistants; +using OpenAI.Files; +using System; +using System.IO; +using System.Threading.Tasks; + +namespace OpenAI.Samples +{ + public partial class AssistantSamples + { + [Test] + [Ignore("Compilation validation only")] + public async Task Sample01_RetrievalAugmentedGenerationAsync() + { + OpenAIClient openAIClient = new(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + FileClient fileClient = openAIClient.GetFileClient(); + AssistantClient assistantClient = openAIClient.GetAssistantClient(); + + // First, let's contrive a document we'll use retrieval with and upload it. + BinaryData document = BinaryData.FromString(""" + { + "description": "This document contains the sale history data for Contoso products.", + "sales": [ + { + "month": "January", + "by_product": { + "113043": 15, + "113045": 12, + "113049": 2 + } + }, + { + "month": "February", + "by_product": { + "113045": 22 + } + }, + { + "month": "March", + "by_product": { + "113045": 16, + "113055": 5 + } + } + ] + } + """); + + OpenAIFileInfo openAIFileInfo = await fileClient.UploadFileAsync(document, "test-rag-file-delete-me.json", OpenAIFilePurpose.Assistants); + + // Now, we'll create a client intended to help with that data + AssistantCreationOptions assistantOptions = new() + { + Name = "Example: Contoso sales RAG", + Instructions = + "You are an assistant that looks up sales data and helps visualize the information based" + + " on user queries. When asked to generate a graph, chart, or other visualization, use" + + " the code interpreter tool to do so.", + FileIds = { openAIFileInfo.Id }, + Tools = + { + new RetrievalToolDefinition(), + new CodeInterpreterToolDefinition(), + }, + Metadata = { ["test_key_delete_me"] = "true" }, + }; + + Assistant assistant = await assistantClient.CreateAssistantAsync("gpt-4-1106-preview", assistantOptions); + + // Now we'll create a thread with a user query about the data already associated with the assistant, then run it + ThreadCreationOptions threadOptions = new() + { + Messages = + { + new ThreadInitializationMessage( + MessageRole.User, + "How well did product 113045 sell in February? Graph its trend over time."), + } + }; + + ThreadRun threadRun = await assistantClient.CreateThreadAndRunAsync(assistant.Id, threadOptions); + + // Check back to see when the run is done + do + { + await Task.Delay(TimeSpan.FromSeconds(1)); + threadRun = await assistantClient.GetRunAsync(threadRun.ThreadId, threadRun.Id); + } while (threadRun.Status == RunStatus.Queued || threadRun.Status == RunStatus.InProgress); + + // Finally, we'll print out the full history for the thread that includes the augmented generation + ListQueryPage messages = await assistantClient.GetMessagesAsync(threadRun.ThreadId); + + for (int i = messages.Count - 1; i >= 0; i--) + { + ThreadMessage message = messages[i]; + + Console.WriteLine($"[{message.Role.ToString().ToUpper()}]:"); + foreach (MessageContent contentItem in message.ContentItems) + { + if (contentItem is MessageTextContent textContent) + { + Console.WriteLine($"{textContent.Text}"); + + if (textContent.Annotations.Count > 0) + { + Console.WriteLine(); + } + + // Include annotations, if any. + foreach (TextContentAnnotation annotation in textContent.Annotations) + { + if (annotation is TextContentFileCitationAnnotation citationAnnotation) + { + Console.WriteLine($"* File citation, file ID: {citationAnnotation.FileId}"); + } + else if (annotation is TextContentFilePathAnnotation pathAnnotation) + { + Console.WriteLine($"* File path, file ID: {pathAnnotation.FileId}"); + } + } + } + else if (contentItem is MessageImageFileContent imageFileContent) + { + OpenAIFileInfo imageInfo = await fileClient.GetFileInfoAsync(imageFileContent.FileId); + BinaryData imageBytes = await fileClient.DownloadFileAsync(imageFileContent.FileId); + using FileStream stream = File.OpenWrite($"{imageInfo.Filename}.png"); + imageBytes.ToStream().CopyTo(stream); + + Console.WriteLine($""); + } + } + Console.WriteLine(); + } + } + } +} diff --git a/.dotnet/tests/Samples/Assistants/Sample02_ListAssistantsWithPagination.cs b/.dotnet/tests/Samples/Assistants/Sample02_ListAssistantsWithPagination.cs new file mode 100644 index 000000000..59f171d66 --- /dev/null +++ b/.dotnet/tests/Samples/Assistants/Sample02_ListAssistantsWithPagination.cs @@ -0,0 +1,35 @@ +using NUnit.Framework; +using OpenAI.Assistants; +using System; + +namespace OpenAI.Samples +{ + public partial class AssistantSamples + { + [Test] + [Ignore("Compilation validation only")] + public void Sample02_ListAssistantsWithPagination() + { + AssistantClient client = new(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + string latestId = null; + bool continueQuery = true; + int count = 0; + + while (continueQuery) + { + ListQueryPage pagedAssistants = client.GetAssistants(previousAssistantId: latestId); + + foreach (Assistant assistant in pagedAssistants) + { + Console.WriteLine($"[{count,3}] {assistant.Id} {assistant.CreatedAt:s} {assistant.Name}"); + + latestId = assistant.Id; + count++; + } + + continueQuery = pagedAssistants.HasMore; + } + } + } +} diff --git a/.dotnet/tests/Samples/Assistants/Sample02_ListAssistantsWithPaginationAsync.cs b/.dotnet/tests/Samples/Assistants/Sample02_ListAssistantsWithPaginationAsync.cs new file mode 100644 index 000000000..2e4f6db86 --- /dev/null +++ b/.dotnet/tests/Samples/Assistants/Sample02_ListAssistantsWithPaginationAsync.cs @@ -0,0 +1,36 @@ +using NUnit.Framework; +using OpenAI.Assistants; +using System; +using System.Threading.Tasks; + +namespace OpenAI.Samples +{ + public partial class AssistantSamples + { + [Test] + [Ignore("Compilation validation only")] + public async Task Sample02_ListAssistantsWithPaginationAsync() + { + AssistantClient client = new(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + string latestId = null; + bool continueQuery = true; + int count = 0; + + while (continueQuery) + { + ListQueryPage pagedAssistants = await client.GetAssistantsAsync(previousAssistantId: latestId); + + foreach (Assistant assistant in pagedAssistants) + { + Console.WriteLine($"[{count,3}] {assistant.Id} {assistant.CreatedAt:s} {assistant.Name}"); + + latestId = assistant.Id; + count++; + } + + continueQuery = pagedAssistants.HasMore; + } + } + } +} diff --git a/.dotnet/tests/Samples/Assistants/Sample03_FunctionCalling.cs b/.dotnet/tests/Samples/Assistants/Sample03_FunctionCalling.cs new file mode 100644 index 000000000..a276e26e7 --- /dev/null +++ b/.dotnet/tests/Samples/Assistants/Sample03_FunctionCalling.cs @@ -0,0 +1,199 @@ +using NUnit.Framework; +using OpenAI.Assistants; +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Threading; + +namespace OpenAI.Samples +{ + public partial class AssistantSamples + { + #region + private static string GetCurrentLocation() + { + // Call the location API here. + return "San Francisco"; + } + + private static string GetCurrentWeather(string location, string unit = "celsius") + { + // Call the weather API here. + return $"31 {unit}"; + } + + private const string GetCurrentLocationFunctionName = "get_current_location"; + + private const string GetCurrentWeatherFunctionName = "get_current_weather"; + + private static readonly FunctionToolDefinition getCurrentLocationFunction = new() + { + Name = GetCurrentLocationFunctionName, + Description = "Get the user's current location" + }; + + private static readonly FunctionToolDefinition getCurrentWeatherFunction = new() + { + Name = GetCurrentWeatherFunctionName, + Description = "Get the current weather in a given location", + Parameters = BinaryData.FromString(""" + { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state, e.g. Boston, MA" + }, + "unit": { + "type": "string", + "enum": [ "celsius", "fahrenheit" ], + "description": "The temperature unit to use. Infer this from the specified location." + } + }, + "required": [ "location" ] + } + """), + }; + #endregion + + [Test] + // [Ignore("Compilation validation only")] + public void Sample03_FunctionCalling() + { + AssistantClient client = new(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + #region + // Create an assistant that can call the function tools. + AssistantCreationOptions assistantOptions = new() + { + Name = "Sample: Function Calling", + Instructions = + "Don't make assumptions about what values to plug into functions." + + " Ask for clarification if a user request is ambiguous.", + Tools = { getCurrentLocationFunction, getCurrentWeatherFunction }, + Metadata = { ["test_key_delete_me"] = "true" }, + }; + + Assistant assistant = client.CreateAssistant("gpt-4-1106-preview", assistantOptions); + #endregion + + #region + // Create a thread with an initial user message and run it. + ThreadCreationOptions threadOptions = new() + { + Messages = { new ThreadInitializationMessage(MessageRole.User, "What's the weather like today?"), } + }; + + ThreadRun threadRun = client.CreateThreadAndRun(assistant.Id, threadOptions); + #endregion + + #region + // Poll the run until it is no longer queued or in progress. + while (threadRun.Status == RunStatus.Queued || threadRun.Status == RunStatus.InProgress) + { + Thread.Sleep(TimeSpan.FromSeconds(1)); + threadRun = client.GetRun(threadRun.ThreadId, threadRun.Id); + + // If the run requires action, resolve them. + if (threadRun.Status == RunStatus.RequiresAction) + { + List toolOutputs = []; + + foreach (RunRequiredAction action in threadRun.RequiredActions) + { + RequiredFunctionToolCall requiredFunctionToolCall = action as RequiredFunctionToolCall; + + switch (requiredFunctionToolCall?.Name) + { + case GetCurrentLocationFunctionName: + { + string toolResult = GetCurrentLocation(); + toolOutputs.Add(new ToolOutput(requiredFunctionToolCall.Id, toolResult)); + break; + } + + case GetCurrentWeatherFunctionName: + { + // The arguments that the model wants to use to call the function are specified as a + // stringified JSON object based on the schema defined in the tool definition. Note that + // the model may hallucinate arguments too. Consequently, it is important to do the + // appropriate parsing and validation before calling the function. + using JsonDocument argumentsJson = JsonDocument.Parse(requiredFunctionToolCall.Arguments); + bool hasLocation = argumentsJson.RootElement.TryGetProperty("location", out JsonElement location); + bool hasUnit = argumentsJson.RootElement.TryGetProperty("unit", out JsonElement unit); + + if (!hasLocation) + { + throw new ArgumentNullException(nameof(location), "The location argument is required."); + } + + string toolResult = hasUnit + ? GetCurrentWeather(location.GetString(), unit.GetString()) + : GetCurrentWeather(location.GetString()); + toolOutputs.Add(new ToolOutput(requiredFunctionToolCall.Id, toolResult)); + break; + } + + default: + { + // Handle other or unexpected calls. + throw new NotImplementedException(); + } + } + } + + // Submit the tool outputs to the assistant, which returns the run to the queued state. + threadRun = client.SubmitToolOutputs(threadRun.ThreadId, threadRun.Id, toolOutputs); + } + } + #endregion + + #region + switch (threadRun.Status) + { + case RunStatus.CompletedSuccessfully: + { + ListQueryPage messages = client.GetMessages(threadRun.ThreadId); + + for (int i = messages.Count - 1; i >= 0; i--) + { + ThreadMessage message = messages[i]; + + Console.WriteLine($"[{message.Role.ToString().ToUpper()}]:"); + foreach (MessageContent contentItem in message.ContentItems) + { + if (contentItem is MessageTextContent textContent) + { + Console.WriteLine($"{textContent.Text}"); + + if (textContent.Annotations.Count > 0) + { + Console.WriteLine(); + } + + // Include annotations, if any. + foreach (TextContentAnnotation annotation in textContent.Annotations) + { + if (annotation is TextContentFileCitationAnnotation citationAnnotation) + { + Console.WriteLine($"* File citation, file ID: {citationAnnotation.FileId}"); + } + else if (annotation is TextContentFilePathAnnotation pathAnnotation) + { + Console.WriteLine($"* File path, file ID: {pathAnnotation.FileId}"); + } + } + } + } + Console.WriteLine(); + } + break; + } + + default: + throw new NotImplementedException(threadRun.Status.ToString()); + } + #endregion + } + } +} diff --git a/.dotnet/tests/Samples/AssistantsSamples.cs b/.dotnet/tests/Samples/AssistantsSamples.cs deleted file mode 100644 index 1b59fc41c..000000000 --- a/.dotnet/tests/Samples/AssistantsSamples.cs +++ /dev/null @@ -1,167 +0,0 @@ -using NUnit.Framework; -using OpenAI.Assistants; -using OpenAI.Files; -using System; -using System.IO; -using System.Threading; - -namespace OpenAI.Tests.Examples; - -public partial class AssistantExamples -{ - [Test] - [Ignore("Compilation validation only")] - public void ListAllAssistants() - { - AssistantClient client = new(); - string latestId = null; - bool continueQuery = true; - int count = 0; - - while (continueQuery) - { - var assistantList = client.GetAssistants(previousAssistantId: latestId).Value; - foreach (Assistant assistant in assistantList) - { - Console.WriteLine($"[{count,3}] {assistant.Id} {assistant.CreatedAt:s} {assistant.Name}"); - latestId = assistant.Id; - count++; - } - continueQuery = assistantList.HasMore; - } - } - - [Test] - [Ignore("Compilation validation only")] - public void CreateClients() - { - OpenAIClient openAIClient = new(""); - FileClient fileClient = openAIClient.GetFileClient(); - AssistantClient assistantClient = openAIClient.GetAssistantClient(); - } - - [Test] - [Ignore("Compilation validation only")] - public void SimpleRetrievalAugmentedGeneration() - { - OpenAIClient openAIClient = new(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - FileClient fileClient = openAIClient.GetFileClient(); - AssistantClient assistantClient = openAIClient.GetAssistantClient(); - - // First, let's contrive a document we'll use retrieval with and upload it. - BinaryData document = BinaryData.FromString(""" - { - "description": "This document contains the sale history data for Contoso products.", - "sales": [ - { - "month": "January", - "by_product": { - "113043": 15, - "113045": 12, - "113049": 2 - } - }, - { - "month": "February", - "by_product": { - "113045": 22 - } - }, - { - "month": "March", - "by_product": { - "113045": 16, - "113055": 5 - } - } - ] - } - """); - - OpenAIFileInfo openAIFileInfo = fileClient.UploadFile(document, "test-rag-file-delete-me.json", OpenAIFilePurpose.Assistants); - - // Now, we'll create a client intended to help with that data - AssistantCreationOptions assistantOptions = new() - { - Name = "Example: Contoso sales RAG", - Instructions = - "You are an assistant that looks up sales data and helps visualize the information based" - + " on user queries. When asked to generate a graph, chart, or other visualization, use" - + " the code interpreter tool to do so.", - FileIds = { openAIFileInfo.Id }, - Tools = - { - new RetrievalToolDefinition(), - new CodeInterpreterToolDefinition(), - }, - Metadata = { ["test_key_delete_me"] = "true" }, - }; - - Assistant assistant = assistantClient.CreateAssistant("gpt-4-1106-preview", assistantOptions); - - // Now we'll create a thread with a user query about the data already associated with the assistant, then run it - ThreadCreationOptions threadOptions = new() - { - Messages = - { - new ThreadInitializationMessage( - MessageRole.User, - "How well did product 113045 sell in February? Graph its trend over time."), - } - }; - - ThreadRun threadRun = assistantClient.CreateThreadAndRun(assistant.Id, threadOptions); - - // Check back to see when the run is done - do - { - Thread.Sleep(TimeSpan.FromSeconds(1)); - threadRun = assistantClient.GetRun(threadRun.ThreadId, threadRun.Id); - } while (threadRun.Status == RunStatus.Queued || threadRun.Status == RunStatus.InProgress); - - // Finally, we'll print out the full history for the thread that includes the augmented generation - ListQueryPage messages = assistantClient.GetMessages(threadRun.ThreadId); - - for (int i = messages.Count - 1; i >= 0; i--) - { - ThreadMessage message = messages[i]; - - Console.WriteLine($"[{message.Role.ToString().ToUpper()}]:"); - foreach (MessageContent contentItem in message.ContentItems) - { - if (contentItem is MessageTextContent textContent) - { - Console.WriteLine($"{textContent.Text}"); - - if (textContent.Annotations.Count > 0) - { - Console.WriteLine(); - } - - // Include annotations, if any. - foreach (TextContentAnnotation annotation in textContent.Annotations) - { - if (annotation is TextContentFileCitationAnnotation citationAnnotation) - { - Console.WriteLine($"* File citation, file ID: {citationAnnotation.FileId}"); - } - else if (annotation is TextContentFilePathAnnotation pathAnnotation) - { - Console.WriteLine($"* File path, file ID: {pathAnnotation.FileId}"); - } - } - } - else if (contentItem is MessageImageFileContent imageFileContent) - { - OpenAIFileInfo imageInfo = fileClient.GetFileInfo(imageFileContent.FileId); - BinaryData imageBytes = fileClient.DownloadFile(imageFileContent.FileId); - using FileStream stream = File.OpenWrite($"{ imageInfo.Filename }.png"); - imageBytes.ToStream().CopyTo(stream); - - Console.WriteLine($""); - } - } - Console.WriteLine(); - } - } -} diff --git a/.dotnet/tests/Samples/Chat/ChatSamples.cs b/.dotnet/tests/Samples/Chat/ChatSamples.cs deleted file mode 100644 index f08824304..000000000 --- a/.dotnet/tests/Samples/Chat/ChatSamples.cs +++ /dev/null @@ -1,128 +0,0 @@ -using NUnit.Framework; -using OpenAI.Audio; -using OpenAI.Chat; -using System; -using System.ClientModel; -using System.Text.Json; -using System.Threading.Tasks; - -namespace OpenAI.Tests.Examples; - -public partial class ChatSamples -{ - [Test] - [Ignore("Compilation validation only")] - public void CreateChatClient() - { - ChatClient client = new("gpt-3.5-turbo", ""); - } - - [Test] - [Ignore("Compilation validation only")] - public void CreateClients() - { - OpenAIClient client = new(""); - AudioClient ttsClient = client.GetAudioClient("tts-1"); - AudioClient whisperClient = client.GetAudioClient("whisper-1"); - } - - [Test] - [Ignore("Compilation validation only")] - public void HelloWorldChat() - { - ChatClient client = new("gpt-3.5-turbo", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - - ChatCompletion chatCompletion = client.CompleteChat("How does AI work? Explain it in simple terms."); - - Console.WriteLine($"[ASSISTANT]:"); - Console.WriteLine($"{ chatCompletion.Content }"); - } - - [Test] - [Ignore("Compilation validation only")] - public void HelloWorldChatProtocol() - { - ChatClient client = new("gpt-3.5-turbo", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - - BinaryData input = BinaryData.FromString(""" - { - "model": "gpt-3.5-turbo", - "messages": [ - { - "role": "user", - "content": "How does AI work? Explain it in simple terms." - } - ] - } - """); - - ClientResult result = client.CompleteChat(BinaryContent.Create(input)); - BinaryData output = result.GetRawResponse().Content; - - using JsonDocument outputAsJson = JsonDocument.Parse(output.ToString()); - string message = outputAsJson.RootElement - .GetProperty("choices")[0] - .GetProperty("message") - .GetProperty("content") - .GetString(); - - Console.WriteLine($"[ASSISTANT]:"); - Console.WriteLine($"{ message }"); - } - - - [Test] - [Ignore("Compilation validation only")] - public async void HelloWorldChatAsync() - { - ChatClient client = new("gpt-3.5-turbo", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - - ChatCompletion chatCompletion = await client.CompleteChatAsync("How does AI work? Explain it in simple terms."); - - Console.WriteLine($"[ASSISTANT]: {chatCompletion.Content}"); - } - - [Test] - [Ignore("Compilation validation only")] - public async Task HelloWorldStreamingChat() - { - ChatClient client = new("gpt-3.5-turbo", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - - StreamingClientResult result = - client.CompleteChatStreaming("How does AI work? Explain it in simple terms."); - - Console.WriteLine("[ASSISTANT]: "); - - await foreach (StreamingChatUpdate chatUpdate in result) - { - Console.Write(chatUpdate.ContentUpdate); - } - } - - [Test] - [Ignore("Compilation validation only")] - public void ChatWithImage(Uri imageUri = null) - { - ChatClient client = new("gpt-4-vision-preview", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - - ChatCompletion chatCompletion = client.CompleteChat( - [ - new ChatRequestUserMessage( - "Describe this image for me", - ChatMessageContent.CreateImage(imageUri)), - ]); - } - - [Test] - [Ignore("Compilation validation only")] - public void ChatWithTools() - { - ChatClient client = new("gpt-3.5-turbo", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - - ChatFunctionToolDefinition getSecretWordTool = new() - { - Name = "get_secret_word", - Description = "gets the arbitrary secret word from the caller" - }; - } -} diff --git a/.dotnet/tests/Samples/Chat/Sample01_SimpleChat.cs b/.dotnet/tests/Samples/Chat/Sample01_SimpleChat.cs new file mode 100644 index 000000000..57aa7e739 --- /dev/null +++ b/.dotnet/tests/Samples/Chat/Sample01_SimpleChat.cs @@ -0,0 +1,21 @@ +using NUnit.Framework; +using OpenAI.Chat; +using System; + +namespace OpenAI.Samples +{ + public partial class ChatSamples + { + [Test] + [Ignore("Compilation validation only")] + public void Sample01_SimpleChat() + { + ChatClient client = new("gpt-3.5-turbo", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + ChatCompletion chatCompletion = client.CompleteChat("How does AI work? Explain it in simple terms."); + + Console.WriteLine($"[ASSISTANT]:"); + Console.WriteLine($"{chatCompletion.Content}"); + } + } +} diff --git a/.dotnet/tests/Samples/Chat/Sample01_SimpleChatAsync.cs b/.dotnet/tests/Samples/Chat/Sample01_SimpleChatAsync.cs new file mode 100644 index 000000000..2b3d3bc04 --- /dev/null +++ b/.dotnet/tests/Samples/Chat/Sample01_SimpleChatAsync.cs @@ -0,0 +1,22 @@ +using NUnit.Framework; +using OpenAI.Chat; +using System; +using System.Threading.Tasks; + +namespace OpenAI.Samples +{ + public partial class ChatSamples + { + [Test] + [Ignore("Compilation validation only")] + public async Task Sample01_SimpleChatAsync() + { + ChatClient client = new("gpt-3.5-turbo", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + ChatCompletion chatCompletion = await client.CompleteChatAsync("How does AI work? Explain it in simple terms."); + + Console.WriteLine($"[ASSISTANT]:"); + Console.WriteLine($"{chatCompletion.Content}"); + } + } +} diff --git a/.dotnet/tests/Samples/Chat/Sample02_StreamingChatAsync.cs b/.dotnet/tests/Samples/Chat/Sample02_StreamingChatAsync.cs new file mode 100644 index 000000000..6ce1a96f0 --- /dev/null +++ b/.dotnet/tests/Samples/Chat/Sample02_StreamingChatAsync.cs @@ -0,0 +1,26 @@ +using NUnit.Framework; +using OpenAI.Chat; +using System; +using System.Threading.Tasks; + +namespace OpenAI.Samples +{ + public partial class ChatSamples + { + [Test] + [Ignore("Compilation validation only")] + public async Task Sample02_StreamingChatAsync() + { + ChatClient client = new("gpt-3.5-turbo", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + StreamingClientResult result = + client.CompleteChatStreaming("How does AI work? Explain it in simple terms."); + + Console.WriteLine("[ASSISTANT]: "); + await foreach (StreamingChatUpdate chatUpdate in result) + { + Console.Write(chatUpdate.ContentUpdate); + } + } + } +} diff --git a/.dotnet/tests/Samples/Chat/Sample03_FunctionCalling.cs b/.dotnet/tests/Samples/Chat/Sample03_FunctionCalling.cs new file mode 100644 index 000000000..5c402b98f --- /dev/null +++ b/.dotnet/tests/Samples/Chat/Sample03_FunctionCalling.cs @@ -0,0 +1,148 @@ +using NUnit.Framework; +using OpenAI.Chat; +using System; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Samples +{ + public partial class ChatSamples + { + #region + //private static string GetCurrentWeather(string location, string unit = "celsius") + //{ + // // Call the weather API here. + // return "31 celsius"; + //} + + //private const string GetCurrentWeatherFunctionName = "get_current_weather"; + + //private static readonly ChatFunctionToolDefinition getCurrentWeatherFunction = new() + //{ + // Name = GetCurrentWeatherFunctionName, + // Description = "Get the current weather in a given location", + // Parameters = BinaryData.FromString(""" + // { + // "type": "object", + // "properties": { + // "location": { + // "type": "string", + // "description": "The city and state, e.g. Boston, MA" + // }, + // "unit": { + // "type": "string", + // "enum": [ "celsius", "fahrenheit" ], + // "description": "The temperature unit to use. Infer this from the specified location." + // } + // }, + // "required": [ "location" ] + // } + // """), + //}; + #endregion + + [Test] + [Ignore("Compilation validation only")] + public void Sample03_FunctionCalling() + { + ChatClient client = new("gpt-3.5-turbo", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + #region + List messages = [ + new ChatRequestSystemMessage( + "Don't make assumptions about what values to plug into functions." + + " Ask for clarification if a user request is ambiguous."), + new ChatRequestUserMessage("What's the weather like in San Francisco?"), + ]; + + ChatCompletionOptions options = new() + { + Tools = { getCurrentWeatherFunction }, + }; + + ChatCompletion chatCompletion = client.CompleteChat(messages, options); + #endregion + + #region + if (chatCompletion.FinishReason == ChatFinishReason.ToolCalls) + { + // First, add the assistant message with tool calls to the conversation history. + messages.Add(new ChatRequestAssistantMessage(chatCompletion)); + + // Then, add a new tool message for each tool call that is resolved. + foreach (ChatToolCall toolCall in chatCompletion.ToolCalls) + { + ChatFunctionToolCall functionToolCall = toolCall as ChatFunctionToolCall; + + switch (functionToolCall?.Name) + { + case GetCurrentWeatherFunctionName: + { + // The arguments that the model wants to use to call the function are specified as a + // stringified JSON object based on the schema defined in the tool definition. Note that + // the model may hallucinate arguments too. Consequently, it is important to do the + // appropriate parsing and validation before calling the function. + using JsonDocument argumentsJson = JsonDocument.Parse(functionToolCall.Arguments); + bool hasLocation = argumentsJson.RootElement.TryGetProperty("location", out JsonElement location); + bool hasUnit = argumentsJson.RootElement.TryGetProperty("unit", out JsonElement unit); + + if (!hasLocation) + { + throw new ArgumentNullException(nameof(location), "The location argument is required."); + } + + string toolResult = GetCurrentWeather(location.GetString(), hasUnit ? unit.GetString() : null); + messages.Add(new ChatRequestToolMessage(toolCall.Id, toolResult)); + break; + } + + default: + { + // Handle other or unexpected calls. + throw new NotImplementedException(); + } + } + } + + // Finally, make a new request to chat completions to let the assistant summarize the tool results + // and add the resulting message to the conversation history to keep it organized all in one place. + ChatCompletion chatCompletionAfterToolMessages = client.CompleteChat(messages, options); + messages.Add(new ChatRequestAssistantMessage(chatCompletionAfterToolMessages)); + } + #endregion + + #region + foreach (ChatRequestMessage requestMessage in messages) + { + switch (requestMessage) + { + case ChatRequestSystemMessage systemMessage: + Console.WriteLine($"[SYSTEM]:"); + Console.WriteLine($"{systemMessage.Content.Span[0].ToText()}"); + Console.WriteLine(); + break; + + case ChatRequestUserMessage userMessage: + Console.WriteLine($"[USER]:"); + Console.WriteLine($"{userMessage.Content.Span[0].ToText()}"); + Console.WriteLine(); + break; + + case ChatRequestAssistantMessage assistantMessage when assistantMessage.Content.Span[0].ToText() is not null: + Console.WriteLine($"[ASSISTANT]:"); + Console.WriteLine($"{assistantMessage.Content.Span[0].ToText()}"); + Console.WriteLine(); + break; + + case ChatRequestToolMessage: + // Do not print any tool messages; let the assistant summarize the tool results instead. + break; + + default: + break; + } + } + #endregion + } + } +} diff --git a/.dotnet/tests/Samples/Chat/Sample03_FunctionCallingAsync.cs b/.dotnet/tests/Samples/Chat/Sample03_FunctionCallingAsync.cs new file mode 100644 index 000000000..97fc0c3b3 --- /dev/null +++ b/.dotnet/tests/Samples/Chat/Sample03_FunctionCallingAsync.cs @@ -0,0 +1,116 @@ +using NUnit.Framework; +using OpenAI.Chat; +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Threading.Tasks; + +namespace OpenAI.Samples +{ + public partial class ChatSamples + { + [Test] + [Ignore("Compilation validation only")] + public async Task Sample03_FunctionCallingAsync() + { + ChatClient client = new("gpt-3.5-turbo", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + #region + List messages = [ + new ChatRequestSystemMessage( + "Don't make assumptions about what values to plug into functions." + + " Ask for clarification if a user request is ambiguous."), + new ChatRequestUserMessage("What's the weather like in San Francisco?"), + ]; + + ChatCompletionOptions options = new() + { + Tools = { getCurrentWeatherFunction }, + }; + + ChatCompletion chatCompletion = await client.CompleteChatAsync(messages, options); + #endregion + + #region + if (chatCompletion.FinishReason == ChatFinishReason.ToolCalls) + { + // First, add the assistant message with tool calls to the conversation history. + messages.Add(new ChatRequestAssistantMessage(chatCompletion)); + + // Then, add a new tool message for each tool call that is resolved. + foreach (ChatToolCall toolCall in chatCompletion.ToolCalls) + { + ChatFunctionToolCall functionToolCall = toolCall as ChatFunctionToolCall; + + switch (functionToolCall?.Name) + { + case GetCurrentWeatherFunctionName: + { + // The arguments that the model wants to use to call the function are specified as a + // stringified JSON object based on the schema defined in the tool definition. Note that + // the model may hallucinate arguments too. Consequently, it is important to do the + // appropriate parsing and validation before calling the function. + using JsonDocument argumentsJson = JsonDocument.Parse(functionToolCall.Arguments); + bool hasLocation = argumentsJson.RootElement.TryGetProperty("location", out JsonElement location); + bool hasUnit = argumentsJson.RootElement.TryGetProperty("unit", out JsonElement unit); + + if (!hasLocation) + { + throw new ArgumentNullException(nameof(location), "The location argument is required."); + } + + string toolResult = GetCurrentWeather(location.GetString(), hasUnit ? unit.GetString() : null); + messages.Add(new ChatRequestToolMessage(toolCall.Id, toolResult)); + break; + } + + default: + { + // Handle other or unexpected calls. + throw new NotImplementedException(); + } + } + } + + // Finally, make a new request to chat completions to let the assistant summarize the tool results + // and add the resulting message to the conversation history to keep it organized all in one place. + ChatCompletion chatCompletionAfterToolMessages = await client.CompleteChatAsync(messages, options); + messages.Add(new ChatRequestAssistantMessage(chatCompletionAfterToolMessages)); + } + #endregion + + #region + foreach (ChatRequestMessage requestMessage in messages) + { + switch (requestMessage) + { + case ChatRequestSystemMessage systemMessage: + Console.WriteLine($"[SYSTEM]:"); + Console.WriteLine($"{systemMessage.Content.Span[0].ToText()}"); + Console.WriteLine(); + break; + + case ChatRequestUserMessage userMessage: + Console.WriteLine($"[USER]:"); + Console.WriteLine($"{userMessage.Content.Span[0].ToText()}"); + Console.WriteLine(); + break; + + case ChatRequestAssistantMessage assistantMessage when assistantMessage.Content.Span[0].ToText() is not null: + Console.WriteLine($"[ASSISTANT]:"); + Console.WriteLine($"{assistantMessage.Content.Span[0].ToText()}"); + Console.WriteLine(); + break; + + case ChatRequestToolMessage: + // Do not print any tool messages; let the assistant summarize the tool results instead. + break; + + default: + break; + } + } + #endregion + } + } +} \ No newline at end of file diff --git a/.dotnet/tests/Samples/Chat/Sample04_Protocol.cs b/.dotnet/tests/Samples/Chat/Sample04_Protocol.cs new file mode 100644 index 000000000..099ddbbe7 --- /dev/null +++ b/.dotnet/tests/Samples/Chat/Sample04_Protocol.cs @@ -0,0 +1,43 @@ +using NUnit.Framework; +using OpenAI.Chat; +using System; +using System.ClientModel; +using System.Text.Json; + +namespace OpenAI.Samples +{ + public partial class ChatSamples + { + [Test] + [Ignore("Compilation validation only")] + public void Sample04_Protocol() + { + ChatClient client = new("gpt-3.5-turbo", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + BinaryData input = BinaryData.FromString(""" + { + "model": "gpt-3.5-turbo", + "messages": [ + { + "role": "user", + "content": "How does AI work? Explain it in simple terms." + } + ] + } + """); + + ClientResult result = client.CompleteChat(BinaryContent.Create(input)); + BinaryData output = result.GetRawResponse().Content; + + using JsonDocument outputAsJson = JsonDocument.Parse(output.ToString()); + string message = outputAsJson.RootElement + .GetProperty("choices")[0] + .GetProperty("message") + .GetProperty("content") + .GetString(); + + Console.WriteLine($"[ASSISTANT]:"); + Console.WriteLine($"{message}"); + } + } +} diff --git a/.dotnet/tests/Samples/Chat/Sample04_ProtocolAsync.cs b/.dotnet/tests/Samples/Chat/Sample04_ProtocolAsync.cs new file mode 100644 index 000000000..6d066ee17 --- /dev/null +++ b/.dotnet/tests/Samples/Chat/Sample04_ProtocolAsync.cs @@ -0,0 +1,44 @@ +using NUnit.Framework; +using OpenAI.Chat; +using System; +using System.ClientModel; +using System.Text.Json; +using System.Threading.Tasks; + +namespace OpenAI.Samples +{ + public partial class ChatSamples + { + [Test] + [Ignore("Compilation validation only")] + public async Task Sample04_ProtocolAsync() + { + ChatClient client = new("gpt-3.5-turbo", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + BinaryData input = BinaryData.FromString(""" + { + "model": "gpt-3.5-turbo", + "messages": [ + { + "role": "user", + "content": "How does AI work? Explain it in simple terms." + } + ] + } + """); + + ClientResult result = await client.CompleteChatAsync(BinaryContent.Create(input)); + BinaryData output = result.GetRawResponse().Content; + + using JsonDocument outputAsJson = JsonDocument.Parse(output.ToString()); + string message = outputAsJson.RootElement + .GetProperty("choices")[0] + .GetProperty("message") + .GetProperty("content") + .GetString(); + + Console.WriteLine($"[ASSISTANT]:"); + Console.WriteLine($"{message}"); + } + } +} diff --git a/.dotnet/tests/Samples/Chat/Sample05_ChatWithVision.cs b/.dotnet/tests/Samples/Chat/Sample05_ChatWithVision.cs new file mode 100644 index 000000000..c5c696166 --- /dev/null +++ b/.dotnet/tests/Samples/Chat/Sample05_ChatWithVision.cs @@ -0,0 +1,25 @@ +using NUnit.Framework; +using OpenAI.Chat; +using System; +using System.Collections.Generic; + +namespace OpenAI.Samples +{ + public partial class ChatSamples + { + [Test] + [Ignore("Compilation validation only")] + public void Sample05_ChatWithVision(Uri imageUri = null) + { + ChatClient client = new("gpt-4-vision-preview", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + List messages = [ + new ChatRequestUserMessage( + "Describe this image for me", + ChatMessageContent.CreateImage(imageUri)) + ]; + + ChatCompletion chatCompletion = client.CompleteChat(messages); + } + } +} \ No newline at end of file diff --git a/.dotnet/tests/Samples/Chat/Sample05_ChatWithVisionAsync.cs b/.dotnet/tests/Samples/Chat/Sample05_ChatWithVisionAsync.cs new file mode 100644 index 000000000..e180985d5 --- /dev/null +++ b/.dotnet/tests/Samples/Chat/Sample05_ChatWithVisionAsync.cs @@ -0,0 +1,26 @@ +using NUnit.Framework; +using OpenAI.Chat; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace OpenAI.Samples +{ + public partial class ChatSamples + { + [Test] + [Ignore("Compilation validation only")] + public async Task Sample05_ChatWithVisionAsync(Uri imageUri = null) + { + ChatClient client = new("gpt-4-vision-preview", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + List messages = [ + new ChatRequestUserMessage( + "Describe this image for me", + ChatMessageContent.CreateImage(imageUri)) + ]; + + ChatCompletion chatCompletion = await client.CompleteChatAsync(messages); + } + } +} \ No newline at end of file diff --git a/.dotnet/tests/Samples/Chat/Sample06_ComplexFunctionCalling.cs b/.dotnet/tests/Samples/Chat/Sample06_ComplexFunctionCalling.cs new file mode 100644 index 000000000..d6c75ca11 --- /dev/null +++ b/.dotnet/tests/Samples/Chat/Sample06_ComplexFunctionCalling.cs @@ -0,0 +1,197 @@ +using NUnit.Framework; +using OpenAI.Chat; +using System; +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI.Samples +{ + public partial class ChatSamples + { + #region + private static string GetCurrentLocation() + { + // Call the location API here. + return "San Francisco"; + } + + private static string GetCurrentWeather(string location, string unit = "celsius") + { + // Call the weather API here. + return $"31 {unit}"; + } + + private const string GetCurrentLocationFunctionName = "get_current_location"; + + private const string GetCurrentWeatherFunctionName = "get_current_weather"; + + private static readonly ChatFunctionToolDefinition getCurrentLocationFunction = new() + { + Name = GetCurrentLocationFunctionName, + Description = "Get the user's current location" + }; + + private static readonly ChatFunctionToolDefinition getCurrentWeatherFunction = new() + { + Name = GetCurrentWeatherFunctionName, + Description = "Get the current weather in a given location", + Parameters = BinaryData.FromString(""" + { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state, e.g. Boston, MA" + }, + "unit": { + "type": "string", + "enum": [ "celsius", "fahrenheit" ], + "description": "The temperature unit to use. Infer this from the specified location." + } + }, + "required": [ "location" ] + } + """), + }; + #endregion + + [Test] + [Ignore("Compilation validation only")] + public void Sample06_ComplexFunctionCalling() + { + ChatClient client = new("gpt-3.5-turbo", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + #region + List messages = [ + new ChatRequestSystemMessage( + "Don't make assumptions about what values to plug into functions." + + " Ask for clarification if a user request is ambiguous."), + new ChatRequestUserMessage("What's the weather like today?"), + ]; + + ChatCompletionOptions options = new() + { + Tools = { getCurrentLocationFunction, getCurrentWeatherFunction }, + }; + #endregion + + #region + bool requiresAction; + + do + { + requiresAction = false; + ChatCompletion chatCompletion = client.CompleteChat(messages, options); + + switch (chatCompletion.FinishReason) + { + case ChatFinishReason.Stopped: + { + ChatCompletion chatCompletionAfterToolMessages = client.CompleteChat(messages, options); + messages.Add(new ChatRequestAssistantMessage(chatCompletionAfterToolMessages)); + break; + } + + case ChatFinishReason.ToolCalls: + { + // First, add the assistant message with tool calls to the conversation history. + messages.Add(new ChatRequestAssistantMessage(chatCompletion)); + + // Then, add a new tool message for each tool call that is resolved. + foreach (ChatToolCall toolCall in chatCompletion.ToolCalls) + { + ChatFunctionToolCall functionToolCall = toolCall as ChatFunctionToolCall; + + switch (functionToolCall?.Name) + { + case GetCurrentLocationFunctionName: + { + string toolResult = GetCurrentLocation(); + messages.Add(new ChatRequestToolMessage(toolCall.Id, toolResult)); + break; + } + + case GetCurrentWeatherFunctionName: + { + // The arguments that the model wants to use to call the function are specified as a + // stringified JSON object based on the schema defined in the tool definition. Note that + // the model may hallucinate arguments too. Consequently, it is important to do the + // appropriate parsing and validation before calling the function. + using JsonDocument argumentsJson = JsonDocument.Parse(functionToolCall.Arguments); + bool hasLocation = argumentsJson.RootElement.TryGetProperty("location", out JsonElement location); + bool hasUnit = argumentsJson.RootElement.TryGetProperty("unit", out JsonElement unit); + + if (!hasLocation) + { + throw new ArgumentNullException(nameof(location), "The location argument is required."); + } + + string toolResult = hasUnit + ? GetCurrentWeather(location.GetString(), unit.GetString()) + : GetCurrentWeather(location.GetString()); + messages.Add(new ChatRequestToolMessage(toolCall.Id, toolResult)); + break; + } + + default: + { + // Handle other or unexpected calls. + throw new NotImplementedException(); + } + } + } + + requiresAction = true; + break; + } + + case ChatFinishReason.Length: + throw new NotImplementedException("Incomplete model output due to MaxTokens parameter or token limit exceeded."); + + case ChatFinishReason.ContentFilter: + throw new NotImplementedException("Omitted content due to a content filter flag."); + + case ChatFinishReason.FunctionCall: + throw new NotImplementedException("Deprecated in favor of tool calls."); + + default: + throw new NotImplementedException(chatCompletion.FinishReason.ToString()); + } + } while (requiresAction); + #endregion + + #region + foreach (ChatRequestMessage requestMessage in messages) + { + switch (requestMessage) + { + case ChatRequestSystemMessage systemMessage: + Console.WriteLine($"[SYSTEM]:"); + Console.WriteLine($"{systemMessage.Content.Span[0].ToText()}"); + Console.WriteLine(); + break; + + case ChatRequestUserMessage userMessage: + Console.WriteLine($"[USER]:"); + Console.WriteLine($"{userMessage.Content.Span[0].ToText()}"); + Console.WriteLine(); + break; + + case ChatRequestAssistantMessage assistantMessage when assistantMessage.Content.Span[0].ToText() is not null: + Console.WriteLine($"[ASSISTANT]:"); + Console.WriteLine($"{assistantMessage.Content.Span[0].ToText()}"); + Console.WriteLine(); + break; + + case ChatRequestToolMessage: + // Do not print any tool messages; let the assistant summarize the tool results instead. + break; + + default: + break; + } + } + #endregion + } + } +} diff --git a/.dotnet/tests/Samples/Chat/Sample_FunctionCalling.cs b/.dotnet/tests/Samples/Chat/Sample_FunctionCalling.cs deleted file mode 100644 index be14c9d76..000000000 --- a/.dotnet/tests/Samples/Chat/Sample_FunctionCalling.cs +++ /dev/null @@ -1,148 +0,0 @@ -using NUnit.Framework; -using OpenAI.Chat; -using System; -using System.Collections.Generic; -using System.Text.Json; - -namespace OpenAI.Tests.Examples; - -public partial class Samples_FunctionCalling -{ - #region - private static string GetCurrentWeather(string location, string unit = "celsius") - { - // Call the weather API here. - return "31 celsius"; - } - - private const string GetCurrentWeatherFunctionName = "get_current_weather"; - - private static readonly ChatFunctionToolDefinition getCurrentWeatherFunction = new() - { - Name = GetCurrentWeatherFunctionName, - Description = "Get the current weather in a given location", - Parameters = BinaryData.FromString(""" - { - "type": "object", - "properties": { - "location": { - "type": "string", - "description": "The city and state, e.g. Boston, MA" - }, - "unit": { - "type": "string", - "enum": [ "celsius", "fahrenheit" ], - "description": "The temperature unit to use. Infer this from the specified location." - } - }, - "required": [ "location" ] - } - """), - }; - #endregion - - [Test] - [Ignore("Compilation validation only")] - public void ChatWithFunctionCalling() - { - ChatClient client = new("gpt-3.5-turbo", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - - #region - List messages = - [ - new ChatRequestSystemMessage( - "Don't make assumptions about what values to plug into functions." - + " Ask for clarification if a user request is ambiguous."), - new ChatRequestUserMessage("What's the weather like in San Francisco?"), - ]; - - ChatCompletionOptions options = new() - { - Tools = { getCurrentWeatherFunction }, - }; - - ChatCompletion chatCompletion = client.CompleteChat(messages, options); - #endregion - - #region - if (chatCompletion.FinishReason == ChatFinishReason.ToolCalls) - { - // First, add the assistant message with tool calls to the conversation history. - messages.Add(new ChatRequestAssistantMessage(chatCompletion)); - - // Then, add a new tool message for each tool call that is resolved. - foreach (ChatToolCall toolCall in chatCompletion.ToolCalls) - { - ChatFunctionToolCall functionToolCall = toolCall as ChatFunctionToolCall; - - switch (functionToolCall?.Name) - { - case GetCurrentWeatherFunctionName: - { - // The arguments that the model wants to use to call the function are specified as a - // stringified JSON object based on the schema defined in the tool definition. Note that - // the model may hallucinate arguments too. Consequently, it is important to do the - // appropriate parsing and validation before calling the function. - using JsonDocument argumentsJson = JsonDocument.Parse(functionToolCall.Arguments); - bool hasLocation = argumentsJson.RootElement.TryGetProperty("location", out JsonElement location); - bool hasUnit = argumentsJson.RootElement.TryGetProperty("unit", out JsonElement unit); - - if (!hasLocation) - { - throw new ArgumentNullException(nameof(location), "The location argument is required."); - } - - string toolResult = GetCurrentWeather(location.GetString(), hasUnit ? unit.GetString() : null); - messages.Add(new ChatRequestToolMessage(toolCall.Id, toolResult)); - break; - } - - default: - { - // Handle other or unexpected calls. - throw new NotImplementedException(); - } - } - } - - // Finally, make a new request to chat completions to let the assistant summarize the tool results - // and add the resulting message to the conversation history to keep it organized all in one place. - ChatCompletion chatCompletionAfterToolMessages = client.CompleteChat(messages, options); - messages.Add(new ChatRequestAssistantMessage(chatCompletionAfterToolMessages)); - } - #endregion - - #region - foreach (ChatRequestMessage requestMessage in messages) - { - switch (requestMessage) - { - case ChatRequestSystemMessage systemMessage: - Console.WriteLine($"[SYSTEM]:"); - Console.WriteLine($"{systemMessage.Content.Span[0].ToText()}"); - Console.WriteLine(); - break; - - case ChatRequestUserMessage userMessage: - Console.WriteLine($"[USER]:"); - Console.WriteLine($"{userMessage.Content.Span[0].ToText()}"); - Console.WriteLine(); - break; - - case ChatRequestAssistantMessage assistantMessage when assistantMessage.Content.Span[0].ToText() is not null: - Console.WriteLine($"[ASSISTANT]:"); - Console.WriteLine($"{assistantMessage.Content.Span[0].ToText()}"); - Console.WriteLine(); - break; - - case ChatRequestToolMessage: - // Do not print any tool messages; let the assistant summarize the tool results instead. - break; - - default: - break; - } - } - #endregion - } -} diff --git a/.dotnet/tests/Samples/ClientSamples.cs b/.dotnet/tests/Samples/ClientSamples.cs new file mode 100644 index 000000000..21000a32b --- /dev/null +++ b/.dotnet/tests/Samples/ClientSamples.cs @@ -0,0 +1,53 @@ +using NUnit.Framework; +using OpenAI.Assistants; +using OpenAI.Audio; +using OpenAI.Chat; +using OpenAI.Embeddings; +using OpenAI.Files; +using OpenAI.Images; +using System.ClientModel; + +namespace OpenAI.Samples.Miscellaneous +{ + public partial class ClientSamples + { + [Test] + [Ignore("Compilation validation only")] + public void CreateAssistantAndFileClients() + { + OpenAIClient openAIClient = new(""); + FileClient fileClient = openAIClient.GetFileClient(); + AssistantClient assistantClient = openAIClient.GetAssistantClient(); + } + + [Test] + [Ignore("Compilation validation only")] + public void CreateChatClient() + { + ChatClient client = new("gpt-3.5-turbo", ""); + } + + [Test] + [Ignore("Compilation validation only")] + public void CreateEmbeddingClient() + { + EmbeddingClient client = new("text-embedding-3-small", new ApiKeyCredential("")); + } + + [Test] + [Ignore("Compilation validation only")] + public void CreateImageClient() + { + ImageClient client = new("dall-e-3", ""); + } + + [Test] + [Ignore("Compilation validation only")] + public void CreateMultipleAudioClients() + { + OpenAIClient client = new(""); + AudioClient ttsClient = client.GetAudioClient("tts-1"); + AudioClient whisperClient = client.GetAudioClient("whisper-1"); + } + } +} diff --git a/.dotnet/tests/Samples/CombinationSamples.cs b/.dotnet/tests/Samples/CombinationSamples.cs index 1fa848ed6..d105b3839 100644 --- a/.dotnet/tests/Samples/CombinationSamples.cs +++ b/.dotnet/tests/Samples/CombinationSamples.cs @@ -7,144 +7,145 @@ using System.IO; using System.Threading.Tasks; -namespace OpenAI.Tests.Examples; - -public partial class CombinationSamples +namespace OpenAI.Samples.Miscellaneous { - [Test] - [Ignore("Compilation validation")] - public void AlpacaArtAssessor() + public partial class CombinationSamples { - // First, we create an image using dall-e-3: - ImageClient imageClient = new("dall-e-3"); - ClientResult imageResult = imageClient.GenerateImage( - "a majestic alpaca on a mountain ridge, backed by an expansive blue sky accented with sparse clouds", - new() - { - Style = ImageStyle.Vivid, - Quality = ImageQuality.High, - Size = ImageSize.Size1792x1024, - }); - GeneratedImage imageGeneration = imageResult.Value; - Console.WriteLine($"Majestic alpaca available at:\n{imageGeneration.ImageUri.AbsoluteUri}"); + [Test] + [Ignore("Compilation validation")] + public void AlpacaArtAssessor() + { + // First, we create an image using dall-e-3: + ImageClient imageClient = new("dall-e-3"); + ClientResult imageResult = imageClient.GenerateImage( + "a majestic alpaca on a mountain ridge, backed by an expansive blue sky accented with sparse clouds", + new() + { + Style = ImageStyle.Vivid, + Quality = ImageQuality.High, + Size = ImageSize.Size1792x1024, + }); + GeneratedImage imageGeneration = imageResult.Value; + Console.WriteLine($"Majestic alpaca available at:\n{imageGeneration.ImageUri.AbsoluteUri}"); - // Now, we'll ask a cranky art critic to evaluate the image using gpt-4-vision-preview: - ChatClient chatClient = new("gpt-4-vision-preview"); - ClientResult chatResult = chatClient.CompleteChat( - [ - new ChatRequestSystemMessage("Assume the role of a cranky art critic. When asked to describe or " + // Now, we'll ask a cranky art critic to evaluate the image using gpt-4-vision-preview: + ChatClient chatClient = new("gpt-4-vision-preview"); + ClientResult chatResult = chatClient.CompleteChat( + [ + new ChatRequestSystemMessage("Assume the role of a cranky art critic. When asked to describe or " + "evaluate imagery, focus on criticizing elements of subject, composition, and other details."), new ChatRequestUserMessage( "describe the following image in a few sentences", ChatMessageContent.CreateImage(imageGeneration.ImageUri)), ], - new ChatCompletionOptions() - { - MaxTokens = 2048, - }); - string chatResponseText = chatResult.Value.Content; - Console.WriteLine($"Art critique of majestic alpaca:\n{chatResponseText}"); + new ChatCompletionOptions() + { + MaxTokens = 2048, + }); + string chatResponseText = chatResult.Value.Content; + Console.WriteLine($"Art critique of majestic alpaca:\n{chatResponseText}"); - // Finally, we'll get some text-to-speech for that critical evaluation using tts-1-hd: - AudioClient audioClient = new("tts-1-hd"); - ClientResult ttsResult = audioClient.GenerateSpeechFromText( - text: chatResponseText, - TextToSpeechVoice.Fable, - new TextToSpeechOptions() + // Finally, we'll get some text-to-speech for that critical evaluation using tts-1-hd: + AudioClient audioClient = new("tts-1-hd"); + ClientResult ttsResult = audioClient.GenerateSpeechFromText( + text: chatResponseText, + TextToSpeechVoice.Fable, + new TextToSpeechOptions() + { + SpeedMultiplier = 0.9f, + ResponseFormat = AudioDataFormat.Opus, + }); + FileInfo ttsFileInfo = new($"{chatResult.Value.Id}.opus"); + using (FileStream ttsFileStream = ttsFileInfo.Create()) + using (BinaryWriter ttsFileWriter = new(ttsFileStream)) { - SpeedMultiplier = 0.9f, - ResponseFormat = AudioDataFormat.Opus, - }); - FileInfo ttsFileInfo = new($"{chatResult.Value.Id}.opus"); - using (FileStream ttsFileStream = ttsFileInfo.Create()) - using (BinaryWriter ttsFileWriter = new(ttsFileStream)) - { - ttsFileWriter.Write(ttsResult.Value); + ttsFileWriter.Write(ttsResult.Value); + } + Console.WriteLine($"Alpaca evaluation audio available at:\n{new Uri(ttsFileInfo.FullName).AbsoluteUri}"); } - Console.WriteLine($"Alpaca evaluation audio available at:\n{new Uri(ttsFileInfo.FullName).AbsoluteUri}"); - } - [Test] - [Ignore("Compilation validation")] - public async Task CuriousCreatureCreator() - { - // First, we'll use gpt-4 to have a creative helper imagine a twist on a household pet - ChatClient creativeWriterClient = new("gpt-4"); - ClientResult creativeWriterResult = creativeWriterClient.CompleteChat( - [ - new ChatRequestSystemMessage("You're a creative helper that specializes in brainstorming designs for concepts that fuse ordinary, mundane items with a fantastical touch. In particular, you can provide good one-paragraph descriptions of concept images."), + [Test] + [Ignore("Compilation validation")] + public async Task CuriousCreatureCreator() + { + // First, we'll use gpt-4 to have a creative helper imagine a twist on a household pet + ChatClient creativeWriterClient = new("gpt-4"); + ClientResult creativeWriterResult = creativeWriterClient.CompleteChat( + [ + new ChatRequestSystemMessage("You're a creative helper that specializes in brainstorming designs for concepts that fuse ordinary, mundane items with a fantastical touch. In particular, you can provide good one-paragraph descriptions of concept images."), new ChatRequestUserMessage("Imagine a household pet. Now add in a subtle touch of magic or 'different'. What do you imagine? Provide a one-paragraph description of a picture of this new creature, focusing on the details of the imagery such that it'd be suitable for creating a picture."), ], - new ChatCompletionOptions() - { - MaxTokens = 2048, - }); - string description = creativeWriterResult.Value.Content; - Console.WriteLine($"Creative helper's creature description:\n{description}"); + new ChatCompletionOptions() + { + MaxTokens = 2048, + }); + string description = creativeWriterResult.Value.Content; + Console.WriteLine($"Creative helper's creature description:\n{description}"); - // Asynchronously, in parallel to the next steps, we'll get the creative description in the voice of Onyx - AudioClient ttsClient = new("tts-1-hd"); - Task> imageDescriptionAudioTask = ttsClient.GenerateSpeechFromTextAsync( - description, - TextToSpeechVoice.Onyx, - new TextToSpeechOptions() + // Asynchronously, in parallel to the next steps, we'll get the creative description in the voice of Onyx + AudioClient ttsClient = new("tts-1-hd"); + Task> imageDescriptionAudioTask = ttsClient.GenerateSpeechFromTextAsync( + description, + TextToSpeechVoice.Onyx, + new TextToSpeechOptions() + { + SpeedMultiplier = 1.1f, + ResponseFormat = AudioDataFormat.Opus, + }); + _ = Task.Run(async () => { - SpeedMultiplier = 1.1f, - ResponseFormat = AudioDataFormat.Opus, + ClientResult audioResult = await imageDescriptionAudioTask; + FileInfo audioFileInfo = new FileInfo($"{creativeWriterResult.Value.Id}-description.opus"); + using FileStream fileStream = audioFileInfo.Create(); + using BinaryWriter fileWriter = new(fileStream); + fileWriter.Write(audioResult.Value); + Console.WriteLine($"Spoken description available at:\n{new Uri(audioFileInfo.FullName).AbsoluteUri}"); }); - _ = Task.Run(async () => - { - ClientResult audioResult = await imageDescriptionAudioTask; - FileInfo audioFileInfo = new FileInfo($"{creativeWriterResult.Value.Id}-description.opus"); - using FileStream fileStream = audioFileInfo.Create(); - using BinaryWriter fileWriter = new(fileStream); - fileWriter.Write(audioResult.Value); - Console.WriteLine($"Spoken description available at:\n{new Uri(audioFileInfo.FullName).AbsoluteUri}"); - }); - // Meanwhile, we'll use dall-e-3 to generate a rendition of our LLM artist's vision - ImageClient imageGenerationClient = new("dall-e-3"); - ClientResult imageGenerationResult = await imageGenerationClient.GenerateImageAsync( - description, - new ImageGenerationOptions() - { - Size = ImageSize.Size1792x1024, - Quality = ImageQuality.High, - }); - Uri imageLocation = imageGenerationResult.Value.ImageUri; - Console.WriteLine($"Creature image available at:\n{imageLocation.AbsoluteUri}"); + // Meanwhile, we'll use dall-e-3 to generate a rendition of our LLM artist's vision + ImageClient imageGenerationClient = new("dall-e-3"); + ClientResult imageGenerationResult = await imageGenerationClient.GenerateImageAsync( + description, + new ImageGenerationOptions() + { + Size = ImageSize.Size1792x1024, + Quality = ImageQuality.High, + }); + Uri imageLocation = imageGenerationResult.Value.ImageUri; + Console.WriteLine($"Creature image available at:\n{imageLocation.AbsoluteUri}"); - // Now, we'll use gpt-4-vision-preview to get a hopelessly taken assessment from a usually exigent art connoisseur - ChatClient imageCriticClient = new("gpt-4-vision-preview"); - ClientResult criticalAppraisalResult = await imageCriticClient.CompleteChatAsync( - [ - new ChatRequestSystemMessage("Assume the role of an art critic. Although usually cranky and occasionally even referred to as a 'curmudgeon', you're somehow entirely smitten with the subject presented to you and, despite your best efforts, can't help but lavish praise when you're asked to appraise a provided image."), + // Now, we'll use gpt-4-vision-preview to get a hopelessly taken assessment from a usually exigent art connoisseur + ChatClient imageCriticClient = new("gpt-4-vision-preview"); + ClientResult criticalAppraisalResult = await imageCriticClient.CompleteChatAsync( + [ + new ChatRequestSystemMessage("Assume the role of an art critic. Although usually cranky and occasionally even referred to as a 'curmudgeon', you're somehow entirely smitten with the subject presented to you and, despite your best efforts, can't help but lavish praise when you're asked to appraise a provided image."), new ChatRequestUserMessage( "Evaluate this image for me. What is it, and what do you think of it?", ChatMessageContent.CreateImage(imageLocation)), ], - new ChatCompletionOptions() - { - MaxTokens = 2048, - }); - string appraisal = criticalAppraisalResult.Value.Content; - Console.WriteLine($"Critic's appraisal:\n{appraisal}"); + new ChatCompletionOptions() + { + MaxTokens = 2048, + }); + string appraisal = criticalAppraisalResult.Value.Content; + Console.WriteLine($"Critic's appraisal:\n{appraisal}"); - // Finally, we'll get that art expert's laudations in the voice of Fable - ClientResult appraisalAudioResult = await ttsClient.GenerateSpeechFromTextAsync( - appraisal, - TextToSpeechVoice.Fable, - new TextToSpeechOptions() + // Finally, we'll get that art expert's laudations in the voice of Fable + ClientResult appraisalAudioResult = await ttsClient.GenerateSpeechFromTextAsync( + appraisal, + TextToSpeechVoice.Fable, + new TextToSpeechOptions() + { + ResponseFormat = AudioDataFormat.Opus, + SpeedMultiplier = 0.9f, + }); + FileInfo criticAudioFileInfo = new($"{criticalAppraisalResult.Value.Id}-appraisal.opus"); + using (FileStream criticStream = criticAudioFileInfo.Create()) + using (BinaryWriter criticFileWriter = new(criticStream)) { - ResponseFormat = AudioDataFormat.Opus, - SpeedMultiplier = 0.9f, - }); - FileInfo criticAudioFileInfo = new($"{criticalAppraisalResult.Value.Id}-appraisal.opus"); - using (FileStream criticStream = criticAudioFileInfo.Create()) - using (BinaryWriter criticFileWriter = new(criticStream)) - { - criticFileWriter.Write(appraisalAudioResult.Value); + criticFileWriter.Write(appraisalAudioResult.Value); + } + Console.WriteLine($"Critical appraisal available at:\n{new Uri(criticAudioFileInfo.FullName).AbsoluteUri}"); } - Console.WriteLine($"Critical appraisal available at:\n{new Uri(criticAudioFileInfo.FullName).AbsoluteUri}"); } } diff --git a/.dotnet/tests/Samples/EmbeddingSamples.cs b/.dotnet/tests/Samples/EmbeddingSamples.cs deleted file mode 100644 index 7e2c8e61a..000000000 --- a/.dotnet/tests/Samples/EmbeddingSamples.cs +++ /dev/null @@ -1,95 +0,0 @@ -using NUnit.Framework; -using OpenAI.Embeddings; -using System; -using System.ClientModel; -using System.Collections.Generic; - -namespace OpenAI.Tests.Examples; - -public partial class EmbeddingSamples -{ - [Test] - [Ignore("Compilation validation only")] - public void CreateEmbeddingClient() - { - EmbeddingClient client = new("text-embedding-3-small", new ApiKeyCredential("")); - } - - [Test] - [Ignore("Compilation validation only")] - public void SimpleEmbedding() - { - EmbeddingClient client = new("text-embedding-3-small", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - - string description = - "Best hotel in town if you like luxury hotels. They have an amazing infinity pool, a spa," - + " and a really helpful concierge. The location is perfect -- right downtown, close to all " - + " the tourist attractions. We highly recommend this hotel."; - - Embedding embedding = client.GenerateEmbedding(description); - ReadOnlyMemory vector = embedding.Vector; - - Console.WriteLine($"Dimension: { vector.Length }"); - Console.WriteLine($"Floats: "); - for (int i = 0; i < vector.Length; i++) - { - Console.WriteLine($" [{i}] = { vector.Span[i] }"); - } - } - - [Test] - [Ignore("Compilation validation only")] - public void SimpleEmbeddingWithOptions() - { - EmbeddingClient client = new("text-embedding-3-small", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - - string description = - "Best hotel in town if you like luxury hotels. They have an amazing infinity pool, a spa," - + " and a really helpful concierge. The location is perfect -- right downtown, close to all " - + " the tourist attractions. We highly recommend this hotel."; - - EmbeddingOptions options = new() { Dimensions = 512 }; - - Embedding embedding = client.GenerateEmbedding(description, options); - ReadOnlyMemory vector = embedding.Vector; - - Console.WriteLine($"Dimension: {vector.Length}"); - Console.WriteLine($"Floats: "); - for (int i = 0; i < vector.Length; i++) - { - Console.WriteLine($" [{i}] = {vector.Span[i]}"); - } - } - - [Test] - [Ignore("Compilation validation only")] - public void ComplexEmbedding() - { - EmbeddingClient client = new("text-embedding-3-small", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - - string category = "Luxury"; - string description = - "Best hotel in town if you like luxury hotels. They have an amazing infinity pool, a spa," - + " and a really helpful concierge. The location is perfect -- right downtown, close to all " - + " the tourist attractions. We highly recommend this hotel."; - List inputs = [category, description]; - - EmbeddingOptions options = new() { Dimensions = 512 }; - - EmbeddingCollection collection = client.GenerateEmbeddings(inputs, options); - - foreach (Embedding embedding in collection) - { - ReadOnlyMemory vector = embedding.Vector; - - Console.WriteLine($"Dimension: {vector.Length}"); - Console.WriteLine($"Floats: "); - for (int i = 0; i < vector.Length; i++) - { - Console.WriteLine($" [{i}] = { vector.Span[i] }"); - } - - Console.WriteLine(); - } - } -} diff --git a/.dotnet/tests/Samples/Embeddings/Sample01_SimpleEmbedding.cs b/.dotnet/tests/Samples/Embeddings/Sample01_SimpleEmbedding.cs new file mode 100644 index 000000000..be1461097 --- /dev/null +++ b/.dotnet/tests/Samples/Embeddings/Sample01_SimpleEmbedding.cs @@ -0,0 +1,31 @@ +using NUnit.Framework; +using OpenAI.Embeddings; +using System; + +namespace OpenAI.Samples +{ + public partial class EmbeddingSamples + { + [Test] + [Ignore("Compilation validation only")] + public void Sample01_SimpleEmbedding() + { + EmbeddingClient client = new("text-embedding-3-small", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + string description = + "Best hotel in town if you like luxury hotels. They have an amazing infinity pool, a spa," + + " and a really helpful concierge. The location is perfect -- right downtown, close to all " + + " the tourist attractions. We highly recommend this hotel."; + + Embedding embedding = client.GenerateEmbedding(description); + ReadOnlyMemory vector = embedding.Vector; + + Console.WriteLine($"Dimension: {vector.Length}"); + Console.WriteLine($"Floats: "); + for (int i = 0; i < vector.Length; i++) + { + Console.WriteLine($" [{i}] = {vector.Span[i]}"); + } + } + } +} diff --git a/.dotnet/tests/Samples/Embeddings/Sample01_SimpleEmbeddingAsync.cs b/.dotnet/tests/Samples/Embeddings/Sample01_SimpleEmbeddingAsync.cs new file mode 100644 index 000000000..e2eb0653a --- /dev/null +++ b/.dotnet/tests/Samples/Embeddings/Sample01_SimpleEmbeddingAsync.cs @@ -0,0 +1,32 @@ +using NUnit.Framework; +using OpenAI.Embeddings; +using System; +using System.Threading.Tasks; + +namespace OpenAI.Samples +{ + public partial class EmbeddingSamples + { + [Test] + [Ignore("Compilation validation only")] + public async Task Sample01_SimpleEmbeddingAsync() + { + EmbeddingClient client = new("text-embedding-3-small", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + string description = + "Best hotel in town if you like luxury hotels. They have an amazing infinity pool, a spa," + + " and a really helpful concierge. The location is perfect -- right downtown, close to all " + + " the tourist attractions. We highly recommend this hotel."; + + Embedding embedding = await client.GenerateEmbeddingAsync(description); + ReadOnlyMemory vector = embedding.Vector; + + Console.WriteLine($"Dimension: {vector.Length}"); + Console.WriteLine($"Floats: "); + for (int i = 0; i < vector.Length; i++) + { + Console.WriteLine($" [{i}] = {vector.Span[i]}"); + } + } + } +} diff --git a/.dotnet/tests/Samples/Embeddings/Sample02_EmbeddingWithOptions.cs b/.dotnet/tests/Samples/Embeddings/Sample02_EmbeddingWithOptions.cs new file mode 100644 index 000000000..5872c7e91 --- /dev/null +++ b/.dotnet/tests/Samples/Embeddings/Sample02_EmbeddingWithOptions.cs @@ -0,0 +1,33 @@ +using NUnit.Framework; +using OpenAI.Embeddings; +using System; + +namespace OpenAI.Samples +{ + public partial class EmbeddingSamples + { + [Test] + [Ignore("Compilation validation only")] + public void Sample02_EmbeddingWithOptions() + { + EmbeddingClient client = new("text-embedding-3-small", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + string description = + "Best hotel in town if you like luxury hotels. They have an amazing infinity pool, a spa," + + " and a really helpful concierge. The location is perfect -- right downtown, close to all " + + " the tourist attractions. We highly recommend this hotel."; + + EmbeddingOptions options = new() { Dimensions = 512 }; + + Embedding embedding = client.GenerateEmbedding(description, options); + ReadOnlyMemory vector = embedding.Vector; + + Console.WriteLine($"Dimension: {vector.Length}"); + Console.WriteLine($"Floats: "); + for (int i = 0; i < vector.Length; i++) + { + Console.WriteLine($" [{i}] = {vector.Span[i]}"); + } + } + } +} diff --git a/.dotnet/tests/Samples/Embeddings/Sample02_EmbeddingWithOptionsAsync.cs b/.dotnet/tests/Samples/Embeddings/Sample02_EmbeddingWithOptionsAsync.cs new file mode 100644 index 000000000..a32e11646 --- /dev/null +++ b/.dotnet/tests/Samples/Embeddings/Sample02_EmbeddingWithOptionsAsync.cs @@ -0,0 +1,34 @@ +using NUnit.Framework; +using OpenAI.Embeddings; +using System; +using System.Threading.Tasks; + +namespace OpenAI.Samples +{ + public partial class EmbeddingSamples + { + [Test] + [Ignore("Compilation validation only")] + public async Task Sample02_EmbeddingWithOptionsAsync() + { + EmbeddingClient client = new("text-embedding-3-small", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + string description = + "Best hotel in town if you like luxury hotels. They have an amazing infinity pool, a spa," + + " and a really helpful concierge. The location is perfect -- right downtown, close to all " + + " the tourist attractions. We highly recommend this hotel."; + + EmbeddingOptions options = new() { Dimensions = 512 }; + + Embedding embedding = await client.GenerateEmbeddingAsync(description, options); + ReadOnlyMemory vector = embedding.Vector; + + Console.WriteLine($"Dimension: {vector.Length}"); + Console.WriteLine($"Floats: "); + for (int i = 0; i < vector.Length; i++) + { + Console.WriteLine($" [{i}] = {vector.Span[i]}"); + } + } + } +} diff --git a/.dotnet/tests/Samples/Embeddings/Sample03_MultipleEmbeddings.cs b/.dotnet/tests/Samples/Embeddings/Sample03_MultipleEmbeddings.cs new file mode 100644 index 000000000..f74a0c05f --- /dev/null +++ b/.dotnet/tests/Samples/Embeddings/Sample03_MultipleEmbeddings.cs @@ -0,0 +1,40 @@ +using NUnit.Framework; +using OpenAI.Embeddings; +using System; +using System.Collections.Generic; + +namespace OpenAI.Samples +{ + public partial class EmbeddingSamples + { + [Test] + [Ignore("Compilation validation only")] + public void Sample03_MultipleEmbeddings() + { + EmbeddingClient client = new("text-embedding-3-small", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + string category = "Luxury"; + string description = + "Best hotel in town if you like luxury hotels. They have an amazing infinity pool, a spa," + + " and a really helpful concierge. The location is perfect -- right downtown, close to all " + + " the tourist attractions. We highly recommend this hotel."; + List inputs = [category, description]; + + EmbeddingCollection collection = client.GenerateEmbeddings(inputs); + + foreach (Embedding embedding in collection) + { + ReadOnlyMemory vector = embedding.Vector; + + Console.WriteLine($"Dimension: {vector.Length}"); + Console.WriteLine($"Floats: "); + for (int i = 0; i < vector.Length; i++) + { + Console.WriteLine($" [{i}] = {vector.Span[i]}"); + } + + Console.WriteLine(); + } + } + } +} diff --git a/.dotnet/tests/Samples/Embeddings/Sample03_MultipleEmbeddingsAsync.cs b/.dotnet/tests/Samples/Embeddings/Sample03_MultipleEmbeddingsAsync.cs new file mode 100644 index 000000000..1ee87811f --- /dev/null +++ b/.dotnet/tests/Samples/Embeddings/Sample03_MultipleEmbeddingsAsync.cs @@ -0,0 +1,41 @@ +using NUnit.Framework; +using OpenAI.Embeddings; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace OpenAI.Samples +{ + public partial class EmbeddingSamples + { + [Test] + [Ignore("Compilation validation only")] + public async Task Sample03_MultipleEmbeddingsAsync() + { + EmbeddingClient client = new("text-embedding-3-small", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + string category = "Luxury"; + string description = + "Best hotel in town if you like luxury hotels. They have an amazing infinity pool, a spa," + + " and a really helpful concierge. The location is perfect -- right downtown, close to all " + + " the tourist attractions. We highly recommend this hotel."; + List inputs = [category, description]; + + EmbeddingCollection collection = await client.GenerateEmbeddingsAsync(inputs); + + foreach (Embedding embedding in collection) + { + ReadOnlyMemory vector = embedding.Vector; + + Console.WriteLine($"Dimension: {vector.Length}"); + Console.WriteLine($"Floats: "); + for (int i = 0; i < vector.Length; i++) + { + Console.WriteLine($" [{i}] = {vector.Span[i]}"); + } + + Console.WriteLine(); + } + } + } +} diff --git a/.dotnet/tests/Samples/ImageSamples.cs b/.dotnet/tests/Samples/Images/Sample01_SimpleImage.cs similarity index 81% rename from .dotnet/tests/Samples/ImageSamples.cs rename to .dotnet/tests/Samples/Images/Sample01_SimpleImage.cs index bad3fe58b..725e1cab3 100644 --- a/.dotnet/tests/Samples/ImageSamples.cs +++ b/.dotnet/tests/Samples/Images/Sample01_SimpleImage.cs @@ -3,20 +3,13 @@ using System; using System.IO; -namespace OpenAI.Tests.Examples +namespace OpenAI.Samples { public partial class ImageSamples { [Test] [Ignore("Compilation validation only")] - public void CreateImageClient() - { - ImageClient client = new("dall-e-3", ""); - } - - [Test] - [Ignore("Compilation validation only")] - public void SimpleImage() + public void Sample01_SimpleImage() { ImageClient client = new("dall-e-3", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); @@ -39,7 +32,7 @@ public void SimpleImage() GeneratedImage image = client.GenerateImage(prompt, options); BinaryData bytes = image.ImageBytes; - using FileStream stream = File.OpenWrite($"{ Guid.NewGuid() }.png"); + using FileStream stream = File.OpenWrite($"{Guid.NewGuid()}.png"); bytes.ToStream().CopyTo(stream); } } diff --git a/.dotnet/tests/Samples/Images/Sample01_SimpleImageAsync.cs b/.dotnet/tests/Samples/Images/Sample01_SimpleImageAsync.cs new file mode 100644 index 000000000..a3c55901a --- /dev/null +++ b/.dotnet/tests/Samples/Images/Sample01_SimpleImageAsync.cs @@ -0,0 +1,40 @@ +using NUnit.Framework; +using OpenAI.Images; +using System; +using System.IO; +using System.Threading.Tasks; + +namespace OpenAI.Samples +{ + public partial class ImageSamples + { + [Test] + [Ignore("Compilation validation only")] + public async Task Sample01_SimpleImageAsync() + { + ImageClient client = new("dall-e-3", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + string prompt = "The concept for a living room that blends Scandinavian simplicity with Japanese minimalism for" + + " a serene and cozy atmosphere. It's a space that invites relaxation and mindfulness, with natural light" + + " and fresh air. Using neutral tones, including colors like white, beige, gray, and black, that create a" + + " sense of harmony. Featuring sleek wood furniture with clean lines and subtle curves to add warmth and" + + " elegance. Plants and flowers in ceramic pots adding color and life to a space. They can serve as focal" + + " points, creating a connection with nature. Soft textiles and cushions in organic fabrics adding comfort" + + " and softness to a space. They can serve as accents, adding contrast and texture."; + + ImageGenerationOptions options = new() + { + Quality = ImageQuality.High, + Size = ImageSize.Size1792x1024, + Style = ImageStyle.Vivid, + ResponseFormat = ImageResponseFormat.Bytes + }; + + GeneratedImage image = await client.GenerateImageAsync(prompt, options); + BinaryData bytes = image.ImageBytes; + + using FileStream stream = File.OpenWrite($"{Guid.NewGuid()}.png"); + bytes.ToStream().CopyTo(stream); + } + } +} diff --git a/files/models.tsp b/files/models.tsp index fdd2b1f45..7cfd02a68 100644 --- a/files/models.tsp +++ b/files/models.tsp @@ -41,7 +41,7 @@ model OpenAIFile { id: string; /** The size of the file, in bytes. */ - bytes: safeint; + bytes: safeint | null; // TODO: This is not nullable in the OpenAPI spec, but it is in practice. /** The Unix timestamp (in seconds) for when the file was created. */ @encode("unixTimestamp", int32) diff --git a/runs/models.tsp b/runs/models.tsp index 42d7935ef..e29f762e0 100644 --- a/runs/models.tsp +++ b/runs/models.tsp @@ -348,7 +348,7 @@ model RunObject { /** The Unix timestamp (in seconds) for when the run will expire. */ @encode("unixTimestamp", int32) - expires_at: utcDateTime; + expires_at: utcDateTime | null; // TODO: This is not nullable in the OpenAPI spec, but it is in practice. /** The Unix timestamp (in seconds) for when the run was started. */ @encode("unixTimestamp", int32) From 6604f76c527faf7f615f611586fcb3afb693599d Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado <45773732+joseharriaga@users.noreply.github.com> Date: Wed, 28 Feb 2024 18:54:55 -0800 Subject: [PATCH 20/50] Add CONTRIBUTING guide, fix Add-Customizations.ps1 script (#4) --- .dotnet/CONTRIBUTING.md | 16 ++++++++++++++++ .dotnet/Directory.Build.props | 5 ----- .dotnet/scripts/Add-Customizations.ps1 | 13 ++++++++++++- .dotnet/tests/OpenAI.Tests.csproj | 5 ++--- tsp-output/@typespec/openapi3/openapi.yaml | 6 ++++-- 5 files changed, 34 insertions(+), 11 deletions(-) create mode 100644 .dotnet/CONTRIBUTING.md delete mode 100644 .dotnet/Directory.Build.props diff --git a/.dotnet/CONTRIBUTING.md b/.dotnet/CONTRIBUTING.md new file mode 100644 index 000000000..05eb58570 --- /dev/null +++ b/.dotnet/CONTRIBUTING.md @@ -0,0 +1,16 @@ +# CONTRIBUTING + +## How to run code generation + +1. Run the following command to install the necessary tools: + `npm install` +1. Regenerate the OpenAPI spec by running the following command: + `npx tsp compile .\openai-in-typespec\main.tsp --emit @typespec/openapi3` +1. Regenerate the library by running the following command: + `npx tsp compile .\openai-in-typespec\main.tsp --emit @azure-tools/typespec-csharp --option @azure-tools/typespec-csharp.emitter-output-dir=.\openai-in-typespec\.dotnet` +1. Run the following script: + `.\openai-in-typespec\.dotnet\scripts\Update-ClientModel.ps1` +1. Run the following script: + `.\openai-in-typespec\.dotnet\scripts\ConvertTo-Internal.ps1` +1. Run the following script: + `.\openai-in-typespec\.dotnet\scripts\Add-Customizations.ps1` diff --git a/.dotnet/Directory.Build.props b/.dotnet/Directory.Build.props deleted file mode 100644 index a95ac958c..000000000 --- a/.dotnet/Directory.Build.props +++ /dev/null @@ -1,5 +0,0 @@ - - - latest - - \ No newline at end of file diff --git a/.dotnet/scripts/Add-Customizations.ps1 b/.dotnet/scripts/Add-Customizations.ps1 index c7eb4412b..d6d8671d2 100644 --- a/.dotnet/scripts/Add-Customizations.ps1 +++ b/.dotnet/scripts/Add-Customizations.ps1 @@ -24,5 +24,16 @@ function Update-MicrosoftBclAsyncInterfacesPackage { Set-Location -Path $current } +function Set-LangVersionToLatest { + $root = Split-Path $PSScriptRoot -Parent + $filePath = Join-Path -Path $root -ChildPath "tests\OpenAI.Tests.csproj" + $xml = [xml](Get-Content -Path $filePath) + $element = $xml.CreateElement("LangVersion") + $element.InnerText = "latest" + $xml.Project.PropertyGroup.AppendChild($element) | Out-Null + $xml.Save($filePath) +} + Update-SystemTextJsonPackage -Update-MicrosoftBclAsyncInterfacesPackage \ No newline at end of file +Update-MicrosoftBclAsyncInterfacesPackage +Set-LangVersionToLatest \ No newline at end of file diff --git a/.dotnet/tests/OpenAI.Tests.csproj b/.dotnet/tests/OpenAI.Tests.csproj index 694b63bba..086eca0d7 100644 --- a/.dotnet/tests/OpenAI.Tests.csproj +++ b/.dotnet/tests/OpenAI.Tests.csproj @@ -3,12 +3,11 @@ net7.0 $(NoWarn);CS1591 + latest - - @@ -17,4 +16,4 @@ - + \ No newline at end of file diff --git a/tsp-output/@typespec/openapi3/openapi.yaml b/tsp-output/@typespec/openapi3/openapi.yaml index 10cc8f54e..bc739d4eb 100644 --- a/tsp-output/@typespec/openapi3/openapi.yaml +++ b/tsp-output/@typespec/openapi3/openapi.yaml @@ -5204,6 +5204,7 @@ components: bytes: type: integer format: int64 + nullable: true description: The size of the file, in bytes. created_at: type: integer @@ -5375,8 +5376,9 @@ components: nullable: true description: The last error associated with this run. Will be `null` if there are no errors. expires_at: - type: integer - format: unixtime + type: string + format: date-time + nullable: true description: The Unix timestamp (in seconds) for when the run will expire. started_at: type: string From 9b3a87fce4540f913ff2c9abc7ebfff98c31da28 Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado <45773732+joseharriaga@users.noreply.github.com> Date: Wed, 28 Feb 2024 20:56:07 -0800 Subject: [PATCH 21/50] Improve function calling samples (#5) - Fix issue in AssistantClient where `SubmitToolOutputsAsync` was not returning a `ThreadRun` as it should. - Add missing async sample for function calling - Clean up function calling samples to make them more genuine --- .../src/Custom/Assistants/AssistantClient.cs | 7 +- .../Sample01_RetrievalAugmentedGeneration.cs | 2 +- .../Assistants/Sample03_FunctionCalling.cs | 2 +- .../Sample03_FunctionCallingAsync.cs | 153 ++++++++++++++ .../Samples/Chat/Sample03_FunctionCalling.cs | 189 ++++++++++------- .../Chat/Sample03_FunctionCallingAsync.cs | 115 ++++++---- .../Chat/Sample06_ComplexFunctionCalling.cs | 197 ------------------ 7 files changed, 352 insertions(+), 313 deletions(-) create mode 100644 .dotnet/tests/Samples/Assistants/Sample03_FunctionCallingAsync.cs delete mode 100644 .dotnet/tests/Samples/Chat/Sample06_ComplexFunctionCalling.cs diff --git a/.dotnet/src/Custom/Assistants/AssistantClient.cs b/.dotnet/src/Custom/Assistants/AssistantClient.cs index b2f02a1aa..413a5460f 100644 --- a/.dotnet/src/Custom/Assistants/AssistantClient.cs +++ b/.dotnet/src/Custom/Assistants/AssistantClient.cs @@ -611,7 +611,7 @@ public virtual ClientResult SubmitToolOutputs(string threadId, string return ClientResult.FromValue(new ThreadRun(internalResult.Value), internalResult.GetRawResponse()); } - public virtual async Task> SubmitToolOutputsAsync(string threadId, string runId, IEnumerable toolOutputs) + public virtual async Task> SubmitToolOutputsAsync(string threadId, string runId, IEnumerable toolOutputs) { List requestToolOutputs = []; @@ -621,9 +621,8 @@ public virtual async Task> SubmitToolOutputsAsync(string thre } Internal.Models.SubmitToolOutputsRunRequest request = new(requestToolOutputs, null); - ClientResult internalResult - = await RunShim.SubmitToolOuputsToRunAsync(threadId, runId, request).ConfigureAwait(false); - return ClientResult.FromValue(true, internalResult.GetRawResponse()); + ClientResult internalResult = await RunShim.SubmitToolOuputsToRunAsync(threadId, runId, request).ConfigureAwait(false); + return ClientResult.FromValue(new ThreadRun(internalResult.Value), internalResult.GetRawResponse()); } internal static Internal.Models.CreateAssistantRequest CreateInternalCreateAssistantRequest( diff --git a/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGeneration.cs b/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGeneration.cs index 7d0bf174c..cc8431f19 100644 --- a/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGeneration.cs +++ b/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGeneration.cs @@ -10,7 +10,7 @@ namespace OpenAI.Samples public partial class AssistantSamples { [Test] - // [Ignore("Compilation validation only")] + [Ignore("Compilation validation only")] public void Sample01_RetrievalAugmentedGeneration() { OpenAIClient openAIClient = new(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); diff --git a/.dotnet/tests/Samples/Assistants/Sample03_FunctionCalling.cs b/.dotnet/tests/Samples/Assistants/Sample03_FunctionCalling.cs index a276e26e7..e989b95b2 100644 --- a/.dotnet/tests/Samples/Assistants/Sample03_FunctionCalling.cs +++ b/.dotnet/tests/Samples/Assistants/Sample03_FunctionCalling.cs @@ -57,7 +57,7 @@ private static string GetCurrentWeather(string location, string unit = "celsius" #endregion [Test] - // [Ignore("Compilation validation only")] + [Ignore("Compilation validation only")] public void Sample03_FunctionCalling() { AssistantClient client = new(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); diff --git a/.dotnet/tests/Samples/Assistants/Sample03_FunctionCallingAsync.cs b/.dotnet/tests/Samples/Assistants/Sample03_FunctionCallingAsync.cs new file mode 100644 index 000000000..44fc106b2 --- /dev/null +++ b/.dotnet/tests/Samples/Assistants/Sample03_FunctionCallingAsync.cs @@ -0,0 +1,153 @@ +using NUnit.Framework; +using OpenAI.Assistants; +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; + +namespace OpenAI.Samples +{ + public partial class AssistantSamples + { + [Test] + [Ignore("Compilation validation only")] + public async Task Sample03_FunctionCallingAsync() + { + AssistantClient client = new(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); + + #region + // Create an assistant that can call the function tools. + AssistantCreationOptions assistantOptions = new() + { + Name = "Sample: Function Calling", + Instructions = + "Don't make assumptions about what values to plug into functions." + + " Ask for clarification if a user request is ambiguous.", + Tools = { getCurrentLocationFunction, getCurrentWeatherFunction }, + Metadata = { ["test_key_delete_me"] = "true" }, + }; + + Assistant assistant = await client.CreateAssistantAsync("gpt-4-1106-preview", assistantOptions); + #endregion + + #region + // Create a thread with an initial user message and run it. + ThreadCreationOptions threadOptions = new() + { + Messages = { new ThreadInitializationMessage(MessageRole.User, "What's the weather like today?"), } + }; + + ThreadRun threadRun = await client.CreateThreadAndRunAsync(assistant.Id, threadOptions); + #endregion + + #region + // Poll the run until it is no longer queued or in progress. + while (threadRun.Status == RunStatus.Queued || threadRun.Status == RunStatus.InProgress) + { + Thread.Sleep(TimeSpan.FromSeconds(1)); + threadRun = await client.GetRunAsync(threadRun.ThreadId, threadRun.Id); + + // If the run requires action, resolve them. + if (threadRun.Status == RunStatus.RequiresAction) + { + List toolOutputs = []; + + foreach (RunRequiredAction action in threadRun.RequiredActions) + { + RequiredFunctionToolCall requiredFunctionToolCall = action as RequiredFunctionToolCall; + + switch (requiredFunctionToolCall?.Name) + { + case GetCurrentLocationFunctionName: + { + string toolResult = GetCurrentLocation(); + toolOutputs.Add(new ToolOutput(requiredFunctionToolCall.Id, toolResult)); + break; + } + + case GetCurrentWeatherFunctionName: + { + // The arguments that the model wants to use to call the function are specified as a + // stringified JSON object based on the schema defined in the tool definition. Note that + // the model may hallucinate arguments too. Consequently, it is important to do the + // appropriate parsing and validation before calling the function. + using JsonDocument argumentsJson = JsonDocument.Parse(requiredFunctionToolCall.Arguments); + bool hasLocation = argumentsJson.RootElement.TryGetProperty("location", out JsonElement location); + bool hasUnit = argumentsJson.RootElement.TryGetProperty("unit", out JsonElement unit); + + if (!hasLocation) + { + throw new ArgumentNullException(nameof(location), "The location argument is required."); + } + + string toolResult = hasUnit + ? GetCurrentWeather(location.GetString(), unit.GetString()) + : GetCurrentWeather(location.GetString()); + toolOutputs.Add(new ToolOutput(requiredFunctionToolCall.Id, toolResult)); + break; + } + + default: + { + // Handle other or unexpected calls. + throw new NotImplementedException(); + } + } + } + + // Submit the tool outputs to the assistant, which returns the run to the queued state. + threadRun = await client.SubmitToolOutputsAsync(threadRun.ThreadId, threadRun.Id, toolOutputs); + } + } + #endregion + + #region + switch (threadRun.Status) + { + case RunStatus.CompletedSuccessfully: + { + ListQueryPage messages = await client.GetMessagesAsync(threadRun.ThreadId); + + for (int i = messages.Count - 1; i >= 0; i--) + { + ThreadMessage message = messages[i]; + + Console.WriteLine($"[{message.Role.ToString().ToUpper()}]:"); + foreach (MessageContent contentItem in message.ContentItems) + { + if (contentItem is MessageTextContent textContent) + { + Console.WriteLine($"{textContent.Text}"); + + if (textContent.Annotations.Count > 0) + { + Console.WriteLine(); + } + + // Include annotations, if any. + foreach (TextContentAnnotation annotation in textContent.Annotations) + { + if (annotation is TextContentFileCitationAnnotation citationAnnotation) + { + Console.WriteLine($"* File citation, file ID: {citationAnnotation.FileId}"); + } + else if (annotation is TextContentFilePathAnnotation pathAnnotation) + { + Console.WriteLine($"* File path, file ID: {pathAnnotation.FileId}"); + } + } + } + } + Console.WriteLine(); + } + break; + } + + default: + throw new NotImplementedException(threadRun.Status.ToString()); + } + #endregion + } + } +} diff --git a/.dotnet/tests/Samples/Chat/Sample03_FunctionCalling.cs b/.dotnet/tests/Samples/Chat/Sample03_FunctionCalling.cs index 5c402b98f..3061d35bd 100644 --- a/.dotnet/tests/Samples/Chat/Sample03_FunctionCalling.cs +++ b/.dotnet/tests/Samples/Chat/Sample03_FunctionCalling.cs @@ -9,36 +9,50 @@ namespace OpenAI.Samples public partial class ChatSamples { #region - //private static string GetCurrentWeather(string location, string unit = "celsius") - //{ - // // Call the weather API here. - // return "31 celsius"; - //} - - //private const string GetCurrentWeatherFunctionName = "get_current_weather"; - - //private static readonly ChatFunctionToolDefinition getCurrentWeatherFunction = new() - //{ - // Name = GetCurrentWeatherFunctionName, - // Description = "Get the current weather in a given location", - // Parameters = BinaryData.FromString(""" - // { - // "type": "object", - // "properties": { - // "location": { - // "type": "string", - // "description": "The city and state, e.g. Boston, MA" - // }, - // "unit": { - // "type": "string", - // "enum": [ "celsius", "fahrenheit" ], - // "description": "The temperature unit to use. Infer this from the specified location." - // } - // }, - // "required": [ "location" ] - // } - // """), - //}; + private static string GetCurrentLocation() + { + // Call the location API here. + return "San Francisco"; + } + + private static string GetCurrentWeather(string location, string unit = "celsius") + { + // Call the weather API here. + return $"31 {unit}"; + } + + private const string GetCurrentLocationFunctionName = "get_current_location"; + + private const string GetCurrentWeatherFunctionName = "get_current_weather"; + + private static readonly ChatFunctionToolDefinition getCurrentLocationFunction = new() + { + Name = GetCurrentLocationFunctionName, + Description = "Get the user's current location" + }; + + private static readonly ChatFunctionToolDefinition getCurrentWeatherFunction = new() + { + Name = GetCurrentWeatherFunctionName, + Description = "Get the current weather in a given location", + Parameters = BinaryData.FromString(""" + { + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state, e.g. Boston, MA" + }, + "unit": { + "type": "string", + "enum": [ "celsius", "fahrenheit" ], + "description": "The temperature unit to use. Infer this from the specified location." + } + }, + "required": [ "location" ] + } + """), + }; #endregion [Test] @@ -52,63 +66,98 @@ public void Sample03_FunctionCalling() new ChatRequestSystemMessage( "Don't make assumptions about what values to plug into functions." + " Ask for clarification if a user request is ambiguous."), - new ChatRequestUserMessage("What's the weather like in San Francisco?"), + new ChatRequestUserMessage("What's the weather like today?"), ]; ChatCompletionOptions options = new() { - Tools = { getCurrentWeatherFunction }, + Tools = { getCurrentLocationFunction, getCurrentWeatherFunction }, }; - - ChatCompletion chatCompletion = client.CompleteChat(messages, options); #endregion #region - if (chatCompletion.FinishReason == ChatFinishReason.ToolCalls) + bool requiresAction; + + do { - // First, add the assistant message with tool calls to the conversation history. - messages.Add(new ChatRequestAssistantMessage(chatCompletion)); + requiresAction = false; + ChatCompletion chatCompletion = client.CompleteChat(messages, options); - // Then, add a new tool message for each tool call that is resolved. - foreach (ChatToolCall toolCall in chatCompletion.ToolCalls) + switch (chatCompletion.FinishReason) { - ChatFunctionToolCall functionToolCall = toolCall as ChatFunctionToolCall; - - switch (functionToolCall?.Name) - { - case GetCurrentWeatherFunctionName: + case ChatFinishReason.Stopped: + { + ChatCompletion chatCompletionAfterToolMessages = client.CompleteChat(messages, options); + messages.Add(new ChatRequestAssistantMessage(chatCompletionAfterToolMessages)); + break; + } + + case ChatFinishReason.ToolCalls: + { + // First, add the assistant message with tool calls to the conversation history. + messages.Add(new ChatRequestAssistantMessage(chatCompletion)); + + // Then, add a new tool message for each tool call that is resolved. + foreach (ChatToolCall toolCall in chatCompletion.ToolCalls) { - // The arguments that the model wants to use to call the function are specified as a - // stringified JSON object based on the schema defined in the tool definition. Note that - // the model may hallucinate arguments too. Consequently, it is important to do the - // appropriate parsing and validation before calling the function. - using JsonDocument argumentsJson = JsonDocument.Parse(functionToolCall.Arguments); - bool hasLocation = argumentsJson.RootElement.TryGetProperty("location", out JsonElement location); - bool hasUnit = argumentsJson.RootElement.TryGetProperty("unit", out JsonElement unit); - - if (!hasLocation) + ChatFunctionToolCall functionToolCall = toolCall as ChatFunctionToolCall; + + switch (functionToolCall?.Name) { - throw new ArgumentNullException(nameof(location), "The location argument is required."); + case GetCurrentLocationFunctionName: + { + string toolResult = GetCurrentLocation(); + messages.Add(new ChatRequestToolMessage(toolCall.Id, toolResult)); + break; + } + + case GetCurrentWeatherFunctionName: + { + // The arguments that the model wants to use to call the function are specified as a + // stringified JSON object based on the schema defined in the tool definition. Note that + // the model may hallucinate arguments too. Consequently, it is important to do the + // appropriate parsing and validation before calling the function. + using JsonDocument argumentsJson = JsonDocument.Parse(functionToolCall.Arguments); + bool hasLocation = argumentsJson.RootElement.TryGetProperty("location", out JsonElement location); + bool hasUnit = argumentsJson.RootElement.TryGetProperty("unit", out JsonElement unit); + + if (!hasLocation) + { + throw new ArgumentNullException(nameof(location), "The location argument is required."); + } + + string toolResult = hasUnit + ? GetCurrentWeather(location.GetString(), unit.GetString()) + : GetCurrentWeather(location.GetString()); + messages.Add(new ChatRequestToolMessage(toolCall.Id, toolResult)); + break; + } + + default: + { + // Handle other or unexpected calls. + throw new NotImplementedException(); + } } - - string toolResult = GetCurrentWeather(location.GetString(), hasUnit ? unit.GetString() : null); - messages.Add(new ChatRequestToolMessage(toolCall.Id, toolResult)); - break; } - default: - { - // Handle other or unexpected calls. - throw new NotImplementedException(); - } - } - } + requiresAction = true; + break; + } - // Finally, make a new request to chat completions to let the assistant summarize the tool results - // and add the resulting message to the conversation history to keep it organized all in one place. - ChatCompletion chatCompletionAfterToolMessages = client.CompleteChat(messages, options); - messages.Add(new ChatRequestAssistantMessage(chatCompletionAfterToolMessages)); - } + case ChatFinishReason.Length: + throw new NotImplementedException("Incomplete model output due to MaxTokens parameter or token limit exceeded."); + + case ChatFinishReason.ContentFilter: + throw new NotImplementedException("Omitted content due to a content filter flag."); + + case ChatFinishReason.FunctionCall: + throw new NotImplementedException("Deprecated in favor of tool calls."); + + default: + throw new NotImplementedException(chatCompletion.FinishReason.ToString()); + } + } while (requiresAction); #endregion #region diff --git a/.dotnet/tests/Samples/Chat/Sample03_FunctionCallingAsync.cs b/.dotnet/tests/Samples/Chat/Sample03_FunctionCallingAsync.cs index 97fc0c3b3..77f20e0d5 100644 --- a/.dotnet/tests/Samples/Chat/Sample03_FunctionCallingAsync.cs +++ b/.dotnet/tests/Samples/Chat/Sample03_FunctionCallingAsync.cs @@ -20,63 +20,98 @@ public async Task Sample03_FunctionCallingAsync() new ChatRequestSystemMessage( "Don't make assumptions about what values to plug into functions." + " Ask for clarification if a user request is ambiguous."), - new ChatRequestUserMessage("What's the weather like in San Francisco?"), + new ChatRequestUserMessage("What's the weather like today?"), ]; ChatCompletionOptions options = new() { - Tools = { getCurrentWeatherFunction }, + Tools = { getCurrentLocationFunction, getCurrentWeatherFunction }, }; - - ChatCompletion chatCompletion = await client.CompleteChatAsync(messages, options); #endregion #region - if (chatCompletion.FinishReason == ChatFinishReason.ToolCalls) + bool requiresAction; + + do { - // First, add the assistant message with tool calls to the conversation history. - messages.Add(new ChatRequestAssistantMessage(chatCompletion)); + requiresAction = false; + ChatCompletion chatCompletion = await client.CompleteChatAsync(messages, options); - // Then, add a new tool message for each tool call that is resolved. - foreach (ChatToolCall toolCall in chatCompletion.ToolCalls) + switch (chatCompletion.FinishReason) { - ChatFunctionToolCall functionToolCall = toolCall as ChatFunctionToolCall; - - switch (functionToolCall?.Name) - { - case GetCurrentWeatherFunctionName: + case ChatFinishReason.Stopped: + { + ChatCompletion chatCompletionAfterToolMessages = await client.CompleteChatAsync(messages, options); + messages.Add(new ChatRequestAssistantMessage(chatCompletionAfterToolMessages)); + break; + } + + case ChatFinishReason.ToolCalls: + { + // First, add the assistant message with tool calls to the conversation history. + messages.Add(new ChatRequestAssistantMessage(chatCompletion)); + + // Then, add a new tool message for each tool call that is resolved. + foreach (ChatToolCall toolCall in chatCompletion.ToolCalls) { - // The arguments that the model wants to use to call the function are specified as a - // stringified JSON object based on the schema defined in the tool definition. Note that - // the model may hallucinate arguments too. Consequently, it is important to do the - // appropriate parsing and validation before calling the function. - using JsonDocument argumentsJson = JsonDocument.Parse(functionToolCall.Arguments); - bool hasLocation = argumentsJson.RootElement.TryGetProperty("location", out JsonElement location); - bool hasUnit = argumentsJson.RootElement.TryGetProperty("unit", out JsonElement unit); - - if (!hasLocation) + ChatFunctionToolCall functionToolCall = toolCall as ChatFunctionToolCall; + + switch (functionToolCall?.Name) { - throw new ArgumentNullException(nameof(location), "The location argument is required."); + case GetCurrentLocationFunctionName: + { + string toolResult = GetCurrentLocation(); + messages.Add(new ChatRequestToolMessage(toolCall.Id, toolResult)); + break; + } + + case GetCurrentWeatherFunctionName: + { + // The arguments that the model wants to use to call the function are specified as a + // stringified JSON object based on the schema defined in the tool definition. Note that + // the model may hallucinate arguments too. Consequently, it is important to do the + // appropriate parsing and validation before calling the function. + using JsonDocument argumentsJson = JsonDocument.Parse(functionToolCall.Arguments); + bool hasLocation = argumentsJson.RootElement.TryGetProperty("location", out JsonElement location); + bool hasUnit = argumentsJson.RootElement.TryGetProperty("unit", out JsonElement unit); + + if (!hasLocation) + { + throw new ArgumentNullException(nameof(location), "The location argument is required."); + } + + string toolResult = hasUnit + ? GetCurrentWeather(location.GetString(), unit.GetString()) + : GetCurrentWeather(location.GetString()); + messages.Add(new ChatRequestToolMessage(toolCall.Id, toolResult)); + break; + } + + default: + { + // Handle other or unexpected calls. + throw new NotImplementedException(); + } } - - string toolResult = GetCurrentWeather(location.GetString(), hasUnit ? unit.GetString() : null); - messages.Add(new ChatRequestToolMessage(toolCall.Id, toolResult)); - break; } - default: - { - // Handle other or unexpected calls. - throw new NotImplementedException(); - } - } - } + requiresAction = true; + break; + } - // Finally, make a new request to chat completions to let the assistant summarize the tool results - // and add the resulting message to the conversation history to keep it organized all in one place. - ChatCompletion chatCompletionAfterToolMessages = await client.CompleteChatAsync(messages, options); - messages.Add(new ChatRequestAssistantMessage(chatCompletionAfterToolMessages)); - } + case ChatFinishReason.Length: + throw new NotImplementedException("Incomplete model output due to MaxTokens parameter or token limit exceeded."); + + case ChatFinishReason.ContentFilter: + throw new NotImplementedException("Omitted content due to a content filter flag."); + + case ChatFinishReason.FunctionCall: + throw new NotImplementedException("Deprecated in favor of tool calls."); + + default: + throw new NotImplementedException(chatCompletion.FinishReason.ToString()); + } + } while (requiresAction); #endregion #region diff --git a/.dotnet/tests/Samples/Chat/Sample06_ComplexFunctionCalling.cs b/.dotnet/tests/Samples/Chat/Sample06_ComplexFunctionCalling.cs deleted file mode 100644 index d6c75ca11..000000000 --- a/.dotnet/tests/Samples/Chat/Sample06_ComplexFunctionCalling.cs +++ /dev/null @@ -1,197 +0,0 @@ -using NUnit.Framework; -using OpenAI.Chat; -using System; -using System.Collections.Generic; -using System.Text.Json; - -namespace OpenAI.Samples -{ - public partial class ChatSamples - { - #region - private static string GetCurrentLocation() - { - // Call the location API here. - return "San Francisco"; - } - - private static string GetCurrentWeather(string location, string unit = "celsius") - { - // Call the weather API here. - return $"31 {unit}"; - } - - private const string GetCurrentLocationFunctionName = "get_current_location"; - - private const string GetCurrentWeatherFunctionName = "get_current_weather"; - - private static readonly ChatFunctionToolDefinition getCurrentLocationFunction = new() - { - Name = GetCurrentLocationFunctionName, - Description = "Get the user's current location" - }; - - private static readonly ChatFunctionToolDefinition getCurrentWeatherFunction = new() - { - Name = GetCurrentWeatherFunctionName, - Description = "Get the current weather in a given location", - Parameters = BinaryData.FromString(""" - { - "type": "object", - "properties": { - "location": { - "type": "string", - "description": "The city and state, e.g. Boston, MA" - }, - "unit": { - "type": "string", - "enum": [ "celsius", "fahrenheit" ], - "description": "The temperature unit to use. Infer this from the specified location." - } - }, - "required": [ "location" ] - } - """), - }; - #endregion - - [Test] - [Ignore("Compilation validation only")] - public void Sample06_ComplexFunctionCalling() - { - ChatClient client = new("gpt-3.5-turbo", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); - - #region - List messages = [ - new ChatRequestSystemMessage( - "Don't make assumptions about what values to plug into functions." - + " Ask for clarification if a user request is ambiguous."), - new ChatRequestUserMessage("What's the weather like today?"), - ]; - - ChatCompletionOptions options = new() - { - Tools = { getCurrentLocationFunction, getCurrentWeatherFunction }, - }; - #endregion - - #region - bool requiresAction; - - do - { - requiresAction = false; - ChatCompletion chatCompletion = client.CompleteChat(messages, options); - - switch (chatCompletion.FinishReason) - { - case ChatFinishReason.Stopped: - { - ChatCompletion chatCompletionAfterToolMessages = client.CompleteChat(messages, options); - messages.Add(new ChatRequestAssistantMessage(chatCompletionAfterToolMessages)); - break; - } - - case ChatFinishReason.ToolCalls: - { - // First, add the assistant message with tool calls to the conversation history. - messages.Add(new ChatRequestAssistantMessage(chatCompletion)); - - // Then, add a new tool message for each tool call that is resolved. - foreach (ChatToolCall toolCall in chatCompletion.ToolCalls) - { - ChatFunctionToolCall functionToolCall = toolCall as ChatFunctionToolCall; - - switch (functionToolCall?.Name) - { - case GetCurrentLocationFunctionName: - { - string toolResult = GetCurrentLocation(); - messages.Add(new ChatRequestToolMessage(toolCall.Id, toolResult)); - break; - } - - case GetCurrentWeatherFunctionName: - { - // The arguments that the model wants to use to call the function are specified as a - // stringified JSON object based on the schema defined in the tool definition. Note that - // the model may hallucinate arguments too. Consequently, it is important to do the - // appropriate parsing and validation before calling the function. - using JsonDocument argumentsJson = JsonDocument.Parse(functionToolCall.Arguments); - bool hasLocation = argumentsJson.RootElement.TryGetProperty("location", out JsonElement location); - bool hasUnit = argumentsJson.RootElement.TryGetProperty("unit", out JsonElement unit); - - if (!hasLocation) - { - throw new ArgumentNullException(nameof(location), "The location argument is required."); - } - - string toolResult = hasUnit - ? GetCurrentWeather(location.GetString(), unit.GetString()) - : GetCurrentWeather(location.GetString()); - messages.Add(new ChatRequestToolMessage(toolCall.Id, toolResult)); - break; - } - - default: - { - // Handle other or unexpected calls. - throw new NotImplementedException(); - } - } - } - - requiresAction = true; - break; - } - - case ChatFinishReason.Length: - throw new NotImplementedException("Incomplete model output due to MaxTokens parameter or token limit exceeded."); - - case ChatFinishReason.ContentFilter: - throw new NotImplementedException("Omitted content due to a content filter flag."); - - case ChatFinishReason.FunctionCall: - throw new NotImplementedException("Deprecated in favor of tool calls."); - - default: - throw new NotImplementedException(chatCompletion.FinishReason.ToString()); - } - } while (requiresAction); - #endregion - - #region - foreach (ChatRequestMessage requestMessage in messages) - { - switch (requestMessage) - { - case ChatRequestSystemMessage systemMessage: - Console.WriteLine($"[SYSTEM]:"); - Console.WriteLine($"{systemMessage.Content.Span[0].ToText()}"); - Console.WriteLine(); - break; - - case ChatRequestUserMessage userMessage: - Console.WriteLine($"[USER]:"); - Console.WriteLine($"{userMessage.Content.Span[0].ToText()}"); - Console.WriteLine(); - break; - - case ChatRequestAssistantMessage assistantMessage when assistantMessage.Content.Span[0].ToText() is not null: - Console.WriteLine($"[ASSISTANT]:"); - Console.WriteLine($"{assistantMessage.Content.Span[0].ToText()}"); - Console.WriteLine(); - break; - - case ChatRequestToolMessage: - // Do not print any tool messages; let the assistant summarize the tool results instead. - break; - - default: - break; - } - } - #endregion - } - } -} From 2e44859c2adf2d8c489a032883da794b3d73829d Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado <45773732+joseharriaga@users.noreply.github.com> Date: Mon, 4 Mar 2024 12:11:40 -0800 Subject: [PATCH 22/50] Refactor codegen scripts for eventual removal (#7) The objective is to eventually stop depending on these scripts and remove them entirely. With this in mind, I refactored the scripts to split them into smaller parts so that it's easier to remove them incrementally. --- .dotnet/scripts/Add-Customizations.ps1 | 21 +++++++++- .dotnet/scripts/ConvertTo-Internal.ps1 | 54 +++++++++++++++++++++----- 2 files changed, 64 insertions(+), 11 deletions(-) diff --git a/.dotnet/scripts/Add-Customizations.ps1 b/.dotnet/scripts/Add-Customizations.ps1 index d6d8671d2..30e795553 100644 --- a/.dotnet/scripts/Add-Customizations.ps1 +++ b/.dotnet/scripts/Add-Customizations.ps1 @@ -34,6 +34,25 @@ function Set-LangVersionToLatest { $xml.Save($filePath) } +function Edit-RunObjectSerialization { + $root = Split-Path $PSScriptRoot -Parent + $directory = Join-Path -Path $root -ChildPath "src\Generated\Models" + + $file = Get-ChildItem -Path $directory -Filter "RunObject.Serialization.cs" + $content = Get-Content -Path $file -Raw + + Write-Output "Editing $($file.FullName)" + + $content = $content -creplace "expiresAt = property\.Value\.GetDateTimeOffset\(`"O`"\);", "// BUG: https://github.com/Azure/autorest.csharp/issues/4296`r`n // expiresAt = property.Value.GetDateTimeOffset(`"O`");`r`n expiresAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64());" + $content = $content -creplace "startedAt = property\.Value\.GetDateTimeOffset\(`"O`"\);", "// BUG: https://github.com/Azure/autorest.csharp/issues/4296`r`n // startedAt = property.Value.GetDateTimeOffset(`"O`");`r`n startedAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64());" + $content = $content -creplace "cancelledAt = property\.Value\.GetDateTimeOffset\(`"O`"\);", "// BUG: https://github.com/Azure/autorest.csharp/issues/4296`r`n // cancelledAt = property.Value.GetDateTimeOffset(`"O`");`r`n cancelledAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64());" + $content = $content -creplace "failedAt = property\.Value\.GetDateTimeOffset\(`"O`"\);", "// BUG: https://github.com/Azure/autorest.csharp/issues/4296`r`n // failedAt = property.Value.GetDateTimeOffset(`"O`");`r`n failedAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64());" + $content = $content -creplace "completedAt = property\.Value\.GetDateTimeOffset\(`"O`"\);", "// BUG: https://github.com/Azure/autorest.csharp/issues/4296`r`n // completedAt = property.Value.GetDateTimeOffset(`"O`");`r`n completedAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64());" + + $content | Set-Content -Path $file.FullName -NoNewline +} + Update-SystemTextJsonPackage Update-MicrosoftBclAsyncInterfacesPackage -Set-LangVersionToLatest \ No newline at end of file +Set-LangVersionToLatest +Edit-RunObjectSerialization \ No newline at end of file diff --git a/.dotnet/scripts/ConvertTo-Internal.ps1 b/.dotnet/scripts/ConvertTo-Internal.ps1 index 60f66e75e..2a656ed9e 100644 --- a/.dotnet/scripts/ConvertTo-Internal.ps1 +++ b/.dotnet/scripts/ConvertTo-Internal.ps1 @@ -1,8 +1,30 @@ -function Edit-GeneratedSources { +function Edit-GeneratedOpenAIClient { $root = Split-Path $PSScriptRoot -Parent $directory = Join-Path -Path $root -ChildPath "src\Generated" - $files = Get-ChildItem -Path $($directory + "\*") -Include "*.cs" -Recurse + $file = Get-ChildItem -Path $directory -Filter "OpenAIClient.cs" + + $content = Get-Content -Path $file -Raw + + Write-Output "Editing $($file.FullName)" + + $content = $content -creplace "public partial class", "internal partial class" + $content = $content -creplace "public readonly partial struct", "internal readonly partial struct" + $content = $content -creplace "public static partial class", "internal static partial class" + $content = $content -creplace "namespace OpenAI", "namespace OpenAI.Internal" + $content = $content -creplace "using OpenAI.Models;", "using OpenAI.Internal.Models;" + $content = $content -creplace "private (OpenAI.)?(?\w+) _cached(\w+);", "private OpenAI.Internal.`${var} _cached`${var};" + $content = $content -creplace "public virtual (OpenAI.)?(?\w+) Get(\w+)Client", "public virtual OpenAI.Internal.`${var} Get`${var}Client" + $content = $content -creplace "ref _cached(\w+), new (OpenAI.)?(?\w+)", "ref _cached`${var}, new OpenAI.Internal.`${var}" + + $content | Set-Content -Path $file.FullName -NoNewline +} + +function Edit-GeneratedSubclients { + $root = Split-Path $PSScriptRoot -Parent + + $directory = Join-Path -Path $root -ChildPath "src\Generated" + $files = Get-ChildItem -Path $($directory + "\*") -Include "*.cs" -Exclude "OpenAIClient.cs" foreach ($file in $files) { $content = Get-Content -Path $file -Raw @@ -17,17 +39,27 @@ function Edit-GeneratedSources { $content | Set-Content -Path $file.FullName -NoNewline } +} - $file = Get-ChildItem -Path $directory -Filter "OpenAIClient.cs" - $content = Get-Content -Path $file -Raw +function Edit-GeneratedModels { + $root = Split-Path $PSScriptRoot -Parent - Write-Output "Editing $($file.FullName)" + $directory = Join-Path -Path $root -ChildPath "src\Generated\Models" + $files = Get-ChildItem -Path $($directory + "\*") -Include "*.cs" - $content = $content -creplace "private (OpenAI.)?(?\w+) _cached(\w+);", "private OpenAI.Internal.`${var} _cached`${var};" - $content = $content -creplace "public virtual (OpenAI.)?(?\w+) Get(\w+)Client", "public virtual OpenAI.Internal.`${var} Get`${var}Client" - $content = $content -creplace "ref _cached(\w+), new (OpenAI.)?(?\w+)", "ref _cached`${var}, new OpenAI.Internal.`${var}" + foreach ($file in $files) { + $content = Get-Content -Path $file -Raw - $content | Set-Content -Path $file.FullName -NoNewline + Write-Output "Editing $($file.FullName)" + + $content = $content -creplace "public partial class", "internal partial class" + $content = $content -creplace "public readonly partial struct", "internal readonly partial struct" + $content = $content -creplace "public static partial class", "internal static partial class" + $content = $content -creplace "namespace OpenAI", "namespace OpenAI.Internal" + $content = $content -creplace "using OpenAI.Models;", "using OpenAI.Internal.Models;" + + $content | Set-Content -Path $file.FullName -NoNewline + } } function Remove-GeneratedTests { @@ -37,5 +69,7 @@ function Remove-GeneratedTests { Remove-Item -LiteralPath $directory -Recurse -Force } -Edit-GeneratedSources +Edit-GeneratedOpenAIClient +Edit-GeneratedSubclients +Edit-GeneratedModels Remove-GeneratedTests From 36718a753b2b2b9578533c73ea58b54bc2ab2855 Mon Sep 17 00:00:00 2001 From: Travis Wilson <35748617+trrwilson@users.noreply.github.com> Date: Tue, 5 Mar 2024 12:42:03 -0800 Subject: [PATCH 23/50] fix toolcalls serialization issue (#8) --- .dotnet/src/Custom/Chat/ChatCompletion.cs | 3 ++- .../Chat/ChatRequestAssistantMessage.cs | 9 ++++--- .dotnet/src/OpenAI.csproj | 2 +- .dotnet/tests/OpenAI.Tests.csproj | 2 +- .../tests/TestScenarios/ChatClientTests.cs | 24 +++++++++++++++++++ 5 files changed, 32 insertions(+), 8 deletions(-) diff --git a/.dotnet/src/Custom/Chat/ChatCompletion.cs b/.dotnet/src/Custom/Chat/ChatCompletion.cs index 119f62e1d..121f90940 100644 --- a/.dotnet/src/Custom/Chat/ChatCompletion.cs +++ b/.dotnet/src/Custom/Chat/ChatCompletion.cs @@ -1,3 +1,4 @@ +using OpenAI.ClientShared.Internal; using System; using System.Collections.Generic; @@ -59,7 +60,7 @@ internal ChatCompletion(Internal.Models.CreateChatCompletionResponse internalRes Content = internalChoice.Message.Content; if (internalChoice.Message.ToolCalls != null) { - List toolCalls = []; + OptionalList toolCalls = []; foreach (Internal.Models.ChatCompletionMessageToolCall internalToolCall in internalChoice.Message.ToolCalls) { if (internalToolCall.Type == "function") diff --git a/.dotnet/src/Custom/Chat/ChatRequestAssistantMessage.cs b/.dotnet/src/Custom/Chat/ChatRequestAssistantMessage.cs index ecfba14c7..cfd1e794d 100644 --- a/.dotnet/src/Custom/Chat/ChatRequestAssistantMessage.cs +++ b/.dotnet/src/Custom/Chat/ChatRequestAssistantMessage.cs @@ -1,11 +1,8 @@ +using OpenAI.ClientShared.Internal; using System; -using System.ClientModel.Internal; - -using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; -using OpenAI.ClientShared.Internal; namespace OpenAI.Chat; @@ -21,13 +18,15 @@ public class ChatRequestAssistantMessage : ChatRequestMessage /// message and is used to differentiate between multiple participants of the same role. /// public string Name { get; set; } + /// /// The tool_calls furnished by the model that are needed to continue the logical conversation across chat /// completion requests. A instance corresponds to a supplied /// instance and is resolved by providing a /// that correlates via id to the item in tool_calls. /// - public IReadOnlyList ToolCalls { get; } + public IReadOnlyList ToolCalls { get; } = new OptionalList(); + /// /// Deprecated in favor of tool_calls. /// diff --git a/.dotnet/src/OpenAI.csproj b/.dotnet/src/OpenAI.csproj index b473b4e63..ed91914a5 100644 --- a/.dotnet/src/OpenAI.csproj +++ b/.dotnet/src/OpenAI.csproj @@ -10,7 +10,7 @@ - + diff --git a/.dotnet/tests/OpenAI.Tests.csproj b/.dotnet/tests/OpenAI.Tests.csproj index 086eca0d7..aaf8385b2 100644 --- a/.dotnet/tests/OpenAI.Tests.csproj +++ b/.dotnet/tests/OpenAI.Tests.csproj @@ -14,6 +14,6 @@ - + \ No newline at end of file diff --git a/.dotnet/tests/TestScenarios/ChatClientTests.cs b/.dotnet/tests/TestScenarios/ChatClientTests.cs index 81cf59c5c..4624f2703 100644 --- a/.dotnet/tests/TestScenarios/ChatClientTests.cs +++ b/.dotnet/tests/TestScenarios/ChatClientTests.cs @@ -2,6 +2,7 @@ using OpenAI.Chat; using System; using System.ClientModel; +using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net; @@ -69,6 +70,27 @@ StreamingClientResult streamingResult Assert.That(latestTokenReceiptTime - firstTokenReceiptTime > TimeSpan.FromMilliseconds(500)); } + [Test] + public void TwoTurnChat() + { + ChatClient client = GetTestClient(); + + List messages = + [ + ChatRequestMessage.CreateUserMessage("What are ten of the most common colors, including the brightest and darkest?"), + ]; + ClientResult firstResult = client.CompleteChat(messages); + Assert.That(firstResult?.Value, Is.Not.Null); + Assert.That(firstResult.Value.Content.ToString().ToLowerInvariant(), Contains.Substring("white")); + Assert.That(firstResult.Value.Content.ToString().ToLowerInvariant(), Contains.Substring("black")); + messages.Add(new ChatRequestAssistantMessage(firstResult.Value)); + messages.Add(new ChatRequestUserMessage("Which of those are considered brightest, aligning with hexadecimal rgb notation?")); + ClientResult secondResult = client.CompleteChat(messages); + Assert.That(secondResult?.Value, Is.Not.Null); + Assert.That(secondResult.Value.Content.ToString().ToLowerInvariant(), Contains.Substring("white")); + Assert.That(secondResult.Value.Content.ToString().ToLowerInvariant(), Does.Not.Contains("black")); + } + [Test] public void AuthFailure() { @@ -86,4 +108,6 @@ public void AuthFailure() Assert.That(clientResultException, Is.Not.Null); Assert.That(clientResultException.Status, Is.EqualTo((int)HttpStatusCode.Unauthorized)); } + + private static ChatClient GetTestClient(string overrideModel = null) => GetTestClient(TestScenario.Chat, overrideModel); } From 6ee5281440264000539d7a1a63e9792f6cfe9ee8 Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado <45773732+joseharriaga@users.noreply.github.com> Date: Wed, 6 Mar 2024 22:40:37 -0800 Subject: [PATCH 24/50] Update the fine-tuning TypeSpec and generated code (#9) Update the fine-tuning TypeSpec to properly match its definition as per the OpenAPI spec here: https://raw.githubusercontent.com/openai/openai-openapi/b648b7823135e6fa5148ac9a303c16fdad050da6/openapi.yaml --- .dotnet/scripts/Update-ClientModel.ps1 | 4 +- .dotnet/src/Generated/FineTuning.cs | 8 +- ...reateFineTuningJobRequest.Serialization.cs | 60 +- .../Models/CreateFineTuningJobRequest.cs | 68 +-- ...JobRequestHyperparameters.Serialization.cs | 46 +- ...eateFineTuningJobRequestHyperparameters.cs | 98 ++- .../Models/FineTuningJob.Serialization.cs | 124 ++-- .dotnet/src/Generated/Models/FineTuningJob.cs | 168 +++--- .../FineTuningJobError.Serialization.cs | 43 +- .../Generated/Models/FineTuningJobError.cs | 39 +- .../FineTuningJobEvent.Serialization.cs | 18 +- .../Generated/Models/FineTuningJobEvent.cs | 19 +- .../Models/FineTuningJobEventObject.cs | 43 ++ ...eTuningJobHyperparameters.Serialization.cs | 21 +- .../Models/FineTuningJobHyperparameters.cs | 23 +- .../Generated/Models/FineTuningJobStatus.cs | 12 +- ...neTuningJobEventsResponse.Serialization.cs | 18 +- .../Models/ListFineTuningJobEventsResponse.cs | 17 +- .../ListFineTuningJobEventsResponseObject.cs | 43 ++ ...tedFineTuningJobsResponse.Serialization.cs | 18 +- .../ListPaginatedFineTuningJobsResponse.cs | 17 +- ...stPaginatedFineTuningJobsResponseObject.cs | 43 ++ .dotnet/src/Generated/OpenAIModelFactory.cs | 118 ++-- fine-tuning/models.tsp | 464 ++++---------- fine-tuning/operations.tsp | 1 + tsp-output/@typespec/openapi3/openapi.yaml | 568 +++++------------- 26 files changed, 940 insertions(+), 1161 deletions(-) create mode 100644 .dotnet/src/Generated/Models/FineTuningJobEventObject.cs create mode 100644 .dotnet/src/Generated/Models/ListFineTuningJobEventsResponseObject.cs create mode 100644 .dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponseObject.cs diff --git a/.dotnet/scripts/Update-ClientModel.ps1 b/.dotnet/scripts/Update-ClientModel.ps1 index a833fc8b7..9a05eb4e5 100644 --- a/.dotnet/scripts/Update-ClientModel.ps1 +++ b/.dotnet/scripts/Update-ClientModel.ps1 @@ -6,13 +6,13 @@ function Update-SystemClientModelPackage { $directory = Join-Path -Path $root -ChildPath "src" Set-Location -Path $directory dotnet remove "OpenAI.csproj" package "System.ClientModel" - dotnet add "OpenAI.csproj" package "System.ClientModel" --version "1.1.0-alpha.20240227.1" --source "https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-net/nuget/v3/index.json" + dotnet add "OpenAI.csproj" package "System.ClientModel" --version "1.1.0-alpha.20240305.1" --source "https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-net/nuget/v3/index.json" # Update System.ClientModel package in OpenAI.Tests.csproj $directory = Join-Path -Path $root -ChildPath "tests" Set-Location -Path $directory dotnet remove "OpenAI.Tests.csproj" package "System.ClientModel" - dotnet add "OpenAI.Tests.csproj" package "System.ClientModel" --version "1.1.0-alpha.20240227.1" --source "https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-net/nuget/v3/index.json" + dotnet add "OpenAI.Tests.csproj" package "System.ClientModel" --version "1.1.0-alpha.20240305.1" --source "https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-net/nuget/v3/index.json" Set-Location -Path $current } diff --git a/.dotnet/src/Generated/FineTuning.cs b/.dotnet/src/Generated/FineTuning.cs index f8c408c7d..39412b46b 100644 --- a/.dotnet/src/Generated/FineTuning.cs +++ b/.dotnet/src/Generated/FineTuning.cs @@ -248,7 +248,7 @@ public virtual ClientResult GetPaginatedFineTuningJobs(string after, long? limit /// /// [Learn more about fine-tuning](/docs/guides/fine-tuning) /// - /// The to use. + /// The ID of the fine-tuning job. /// is null. /// is an empty string, and was expected to be non-empty. public virtual async Task> RetrieveFineTuningJobAsync(string fineTuningJobId) @@ -265,7 +265,7 @@ public virtual async Task> RetrieveFineTuningJobAsyn /// /// [Learn more about fine-tuning](/docs/guides/fine-tuning) /// - /// The to use. + /// The ID of the fine-tuning job. /// is null. /// is an empty string, and was expected to be non-empty. public virtual ClientResult RetrieveFineTuningJob(string fineTuningJobId) @@ -294,7 +294,7 @@ public virtual ClientResult RetrieveFineTuningJob(string fineTuni /// /// /// - /// The to use. + /// The ID of the fine-tuning job. /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. @@ -334,7 +334,7 @@ public virtual async Task RetrieveFineTuningJobAsync(string fineTu /// /// /// - /// The to use. + /// The ID of the fine-tuning job. /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// is null. /// is an empty string, and was expected to be non-empty. diff --git a/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.Serialization.cs index c03035768..a7b573d95 100644 --- a/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.Serialization.cs @@ -19,22 +19,10 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelRe } writer.WriteStartObject(); - writer.WritePropertyName("training_file"u8); - writer.WriteStringValue(TrainingFile); - if (OptionalProperty.IsDefined(ValidationFile)) - { - if (ValidationFile != null) - { - writer.WritePropertyName("validation_file"u8); - writer.WriteStringValue(ValidationFile); - } - else - { - writer.WriteNull("validation_file"); - } - } writer.WritePropertyName("model"u8); writer.WriteStringValue(Model.ToString()); + writer.WritePropertyName("training_file"u8); + writer.WriteStringValue(TrainingFile); if (OptionalProperty.IsDefined(Hyperparameters)) { writer.WritePropertyName("hyperparameters"u8); @@ -52,6 +40,18 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelRe writer.WriteNull("suffix"); } } + if (OptionalProperty.IsDefined(ValidationFile)) + { + if (ValidationFile != null) + { + writer.WritePropertyName("validation_file"u8); + writer.WriteStringValue(ValidationFile); + } + else + { + writer.WriteNull("validation_file"); + } + } if (options.Format != "W" && _serializedAdditionalRawData != null) { foreach (var item in _serializedAdditionalRawData) @@ -90,52 +90,52 @@ internal static CreateFineTuningJobRequest DeserializeCreateFineTuningJobRequest { return null; } - string trainingFile = default; - OptionalProperty validationFile = default; CreateFineTuningJobRequestModel model = default; + string trainingFile = default; OptionalProperty hyperparameters = default; OptionalProperty suffix = default; + OptionalProperty validationFile = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) { + if (property.NameEquals("model"u8)) + { + model = new CreateFineTuningJobRequestModel(property.Value.GetString()); + continue; + } if (property.NameEquals("training_file"u8)) { trainingFile = property.Value.GetString(); continue; } - if (property.NameEquals("validation_file"u8)) + if (property.NameEquals("hyperparameters"u8)) { if (property.Value.ValueKind == JsonValueKind.Null) { - validationFile = null; continue; } - validationFile = property.Value.GetString(); - continue; - } - if (property.NameEquals("model"u8)) - { - model = new CreateFineTuningJobRequestModel(property.Value.GetString()); + hyperparameters = CreateFineTuningJobRequestHyperparameters.DeserializeCreateFineTuningJobRequestHyperparameters(property.Value); continue; } - if (property.NameEquals("hyperparameters"u8)) + if (property.NameEquals("suffix"u8)) { if (property.Value.ValueKind == JsonValueKind.Null) { + suffix = null; continue; } - hyperparameters = CreateFineTuningJobRequestHyperparameters.DeserializeCreateFineTuningJobRequestHyperparameters(property.Value); + suffix = property.Value.GetString(); continue; } - if (property.NameEquals("suffix"u8)) + if (property.NameEquals("validation_file"u8)) { if (property.Value.ValueKind == JsonValueKind.Null) { - suffix = null; + validationFile = null; continue; } - suffix = property.Value.GetString(); + validationFile = property.Value.GetString(); continue; } if (options.Format != "W") @@ -144,7 +144,7 @@ internal static CreateFineTuningJobRequest DeserializeCreateFineTuningJobRequest } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateFineTuningJobRequest(trainingFile, validationFile.Value, model, hyperparameters.Value, suffix.Value, serializedAdditionalRawData); + return new CreateFineTuningJobRequest(model, trainingFile, hyperparameters.Value, suffix.Value, validationFile.Value, serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) diff --git a/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.cs b/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.cs index e4a89072b..5cf2787d4 100644 --- a/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.cs +++ b/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.cs @@ -42,6 +42,10 @@ internal partial class CreateFineTuningJobRequest private IDictionary _serializedAdditionalRawData; /// Initializes a new instance of . + /// + /// The name of the model to fine-tune. You can select one of the + /// [supported models](/docs/guides/fine-tuning/what-models-can-be-fine-tuned). + /// /// /// The ID of an uploaded file that contains training data. /// @@ -52,20 +56,20 @@ internal partial class CreateFineTuningJobRequest /// /// See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. /// - /// - /// The name of the model to fine-tune. You can select one of the - /// [supported models](/docs/guides/fine-tuning/what-models-can-be-fine-tuned). - /// /// is null. - public CreateFineTuningJobRequest(string trainingFile, CreateFineTuningJobRequestModel model) + public CreateFineTuningJobRequest(CreateFineTuningJobRequestModel model, string trainingFile) { if (trainingFile is null) throw new ArgumentNullException(nameof(trainingFile)); - TrainingFile = trainingFile; Model = model; + TrainingFile = trainingFile; } /// Initializes a new instance of . + /// + /// The name of the model to fine-tune. You can select one of the + /// [supported models](/docs/guides/fine-tuning/what-models-can-be-fine-tuned). + /// /// /// The ID of an uploaded file that contains training data. /// @@ -76,6 +80,13 @@ public CreateFineTuningJobRequest(string trainingFile, CreateFineTuningJobReques /// /// See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. /// + /// The hyperparameters used for the fine-tuning job. + /// + /// 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`. + /// /// /// The ID of an uploaded file that contains validation data. /// @@ -88,25 +99,14 @@ public CreateFineTuningJobRequest(string trainingFile, CreateFineTuningJobReques /// /// See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. /// - /// - /// The name of the model to fine-tune. You can select one of the - /// [supported models](/docs/guides/fine-tuning/what-models-can-be-fine-tuned). - /// - /// The hyperparameters used for the fine-tuning job. - /// - /// 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`. - /// /// Keeps track of any properties unknown to the library. - internal CreateFineTuningJobRequest(string trainingFile, string validationFile, CreateFineTuningJobRequestModel model, CreateFineTuningJobRequestHyperparameters hyperparameters, string suffix, IDictionary serializedAdditionalRawData) + internal CreateFineTuningJobRequest(CreateFineTuningJobRequestModel model, string trainingFile, CreateFineTuningJobRequestHyperparameters hyperparameters, string suffix, string validationFile, IDictionary serializedAdditionalRawData) { - TrainingFile = trainingFile; - ValidationFile = validationFile; Model = model; + TrainingFile = trainingFile; Hyperparameters = hyperparameters; Suffix = suffix; + ValidationFile = validationFile; _serializedAdditionalRawData = serializedAdditionalRawData; } @@ -115,6 +115,11 @@ internal CreateFineTuningJobRequest() { } + /// + /// The name of the model to fine-tune. You can select one of the + /// [supported models](/docs/guides/fine-tuning/what-models-can-be-fine-tuned). + /// + public CreateFineTuningJobRequestModel Model { get; } /// /// The ID of an uploaded file that contains training data. /// @@ -126,6 +131,15 @@ internal CreateFineTuningJobRequest() /// See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. /// public string TrainingFile { get; } + /// The hyperparameters used for the fine-tuning job. + public CreateFineTuningJobRequestHyperparameters Hyperparameters { get; set; } + /// + /// 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`. + /// + public string Suffix { get; set; } /// /// The ID of an uploaded file that contains validation data. /// @@ -139,19 +153,5 @@ internal CreateFineTuningJobRequest() /// See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. /// public string ValidationFile { get; set; } - /// - /// The name of the model to fine-tune. You can select one of the - /// [supported models](/docs/guides/fine-tuning/what-models-can-be-fine-tuned). - /// - public CreateFineTuningJobRequestModel Model { get; } - /// The hyperparameters used for the fine-tuning job. - public CreateFineTuningJobRequestHyperparameters Hyperparameters { get; set; } - /// - /// 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`. - /// - public string Suffix { get; set; } } } diff --git a/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.Serialization.cs b/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.Serialization.cs index 6cd4a835a..11f4a766b 100644 --- a/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.Serialization.cs @@ -19,6 +19,30 @@ void IJsonModel.Write(Utf8JsonWriter } writer.WriteStartObject(); + if (OptionalProperty.IsDefined(BatchSize)) + { + writer.WritePropertyName("batch_size"u8); +#if NET6_0_OR_GREATER + writer.WriteRawValue(BatchSize); +#else + using (JsonDocument document = JsonDocument.Parse(BatchSize)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } + if (OptionalProperty.IsDefined(LearningRateMultiplier)) + { + writer.WritePropertyName("learning_rate_multiplier"u8); +#if NET6_0_OR_GREATER + writer.WriteRawValue(LearningRateMultiplier); +#else + using (JsonDocument document = JsonDocument.Parse(LearningRateMultiplier)) + { + JsonSerializer.Serialize(writer, document.RootElement); + } +#endif + } if (OptionalProperty.IsDefined(NEpochs)) { writer.WritePropertyName("n_epochs"u8); @@ -69,11 +93,31 @@ internal static CreateFineTuningJobRequestHyperparameters DeserializeCreateFineT { return null; } + OptionalProperty batchSize = default; + OptionalProperty learningRateMultiplier = default; OptionalProperty nEpochs = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) { + if (property.NameEquals("batch_size"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + batchSize = BinaryData.FromString(property.Value.GetRawText()); + continue; + } + if (property.NameEquals("learning_rate_multiplier"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + learningRateMultiplier = BinaryData.FromString(property.Value.GetRawText()); + continue; + } if (property.NameEquals("n_epochs"u8)) { if (property.Value.ValueKind == JsonValueKind.Null) @@ -89,7 +133,7 @@ internal static CreateFineTuningJobRequestHyperparameters DeserializeCreateFineT } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateFineTuningJobRequestHyperparameters(nEpochs.Value, serializedAdditionalRawData); + return new CreateFineTuningJobRequestHyperparameters(batchSize.Value, learningRateMultiplier.Value, nEpochs.Value, serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) diff --git a/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.cs b/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.cs index 9c2712095..eafff5310 100644 --- a/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.cs +++ b/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.cs @@ -46,17 +46,113 @@ public CreateFineTuningJobRequestHyperparameters() } /// Initializes a new instance of . + /// + /// Number of examples in each batch. A larger batch size means that model parameters are + /// updated less frequently, but with lower variance. + /// + /// + /// Scaling factor for the learning rate. A smaller learning rate may be useful to avoid + /// overfitting. + /// /// /// The number of epochs to train the model for. An epoch refers to one full cycle through the /// training dataset. /// /// Keeps track of any properties unknown to the library. - internal CreateFineTuningJobRequestHyperparameters(BinaryData nEpochs, IDictionary serializedAdditionalRawData) + internal CreateFineTuningJobRequestHyperparameters(BinaryData batchSize, BinaryData learningRateMultiplier, BinaryData nEpochs, IDictionary serializedAdditionalRawData) { + BatchSize = batchSize; + LearningRateMultiplier = learningRateMultiplier; NEpochs = nEpochs; _serializedAdditionalRawData = serializedAdditionalRawData; } + /// + /// Number of examples in each batch. A larger batch size means that model parameters are + /// updated less frequently, but with lower variance. + /// + /// To assign an object to this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// + /// Supported types: + /// + /// + /// "auto" + /// + /// + /// + /// + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + public BinaryData BatchSize { get; set; } + /// + /// Scaling factor for the learning rate. A smaller learning rate may be useful to avoid + /// overfitting. + /// + /// To assign an object to this property use . + /// + /// + /// To assign an already formatted json string to this property use . + /// + /// + /// + /// Supported types: + /// + /// + /// "auto" + /// + /// + /// + /// + /// + /// + /// Examples: + /// + /// + /// BinaryData.FromObjectAsJson("foo") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromString("\"foo\"") + /// Creates a payload of "foo". + /// + /// + /// BinaryData.FromObjectAsJson(new { key = "value" }) + /// Creates a payload of { "key": "value" }. + /// + /// + /// BinaryData.FromString("{\"key\": \"value\"}") + /// Creates a payload of { "key": "value" }. + /// + /// + /// + /// + public BinaryData LearningRateMultiplier { get; set; } /// /// The number of epochs to train the model for. An epoch refers to one full cycle through the /// training dataset. diff --git a/.dotnet/src/Generated/Models/FineTuningJob.Serialization.cs b/.dotnet/src/Generated/Models/FineTuningJob.Serialization.cs index c8457dfdf..2c9e983f6 100644 --- a/.dotnet/src/Generated/Models/FineTuningJob.Serialization.cs +++ b/.dotnet/src/Generated/Models/FineTuningJob.Serialization.cs @@ -21,21 +21,17 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOpt writer.WriteStartObject(); writer.WritePropertyName("id"u8); writer.WriteStringValue(Id); - writer.WritePropertyName("object"u8); - writer.WriteStringValue(Object.ToString()); writer.WritePropertyName("created_at"u8); writer.WriteNumberValue(CreatedAt, "U"); - if (FinishedAt != null) + if (Error != null) { - writer.WritePropertyName("finished_at"u8); - writer.WriteStringValue(FinishedAt.Value, "O"); + writer.WritePropertyName("error"u8); + writer.WriteObjectValue(Error); } else { - writer.WriteNull("finished_at"); + writer.WriteNull("error"); } - writer.WritePropertyName("model"u8); - writer.WriteStringValue(Model); if (FineTunedModel != null) { writer.WritePropertyName("fine_tuned_model"u8); @@ -45,23 +41,23 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOpt { writer.WriteNull("fine_tuned_model"); } - writer.WritePropertyName("organization_id"u8); - writer.WriteStringValue(OrganizationId); - writer.WritePropertyName("status"u8); - writer.WriteStringValue(Status.ToString()); - writer.WritePropertyName("hyperparameters"u8); - writer.WriteObjectValue(Hyperparameters); - writer.WritePropertyName("training_file"u8); - writer.WriteStringValue(TrainingFile); - if (ValidationFile != null) + if (FinishedAt != null) { - writer.WritePropertyName("validation_file"u8); - writer.WriteStringValue(ValidationFile); + writer.WritePropertyName("finished_at"u8); + writer.WriteStringValue(FinishedAt.Value, "O"); } else { - writer.WriteNull("validation_file"); + writer.WriteNull("finished_at"); } + writer.WritePropertyName("hyperparameters"u8); + writer.WriteObjectValue(Hyperparameters); + writer.WritePropertyName("model"u8); + writer.WriteStringValue(Model); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); + writer.WritePropertyName("organization_id"u8); + writer.WriteStringValue(OrganizationId); writer.WritePropertyName("result_files"u8); writer.WriteStartArray(); foreach (var item in ResultFiles) @@ -69,6 +65,8 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOpt writer.WriteStringValue(item); } writer.WriteEndArray(); + writer.WritePropertyName("status"u8); + writer.WriteStringValue(Status.ToString()); if (TrainedTokens != null) { writer.WritePropertyName("trained_tokens"u8); @@ -78,14 +76,16 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOpt { writer.WriteNull("trained_tokens"); } - if (Error != null) + writer.WritePropertyName("training_file"u8); + writer.WriteStringValue(TrainingFile); + if (ValidationFile != null) { - writer.WritePropertyName("error"u8); - writer.WriteObjectValue(Error); + writer.WritePropertyName("validation_file"u8); + writer.WriteStringValue(ValidationFile); } else { - writer.WriteNull("error"); + writer.WriteNull("validation_file"); } if (options.Format != "W" && _serializedAdditionalRawData != null) { @@ -126,19 +126,19 @@ internal static FineTuningJob DeserializeFineTuningJob(JsonElement element, Mode return null; } string id = default; - FineTuningJobObject @object = default; DateTimeOffset createdAt = default; + FineTuningJobError error = default; + string fineTunedModel = default; DateTimeOffset? finishedAt = default; + FineTuningJobHyperparameters hyperparameters = default; string model = default; - string fineTunedModel = default; + FineTuningJobObject @object = default; string organizationId = default; + IReadOnlyList resultFiles = default; FineTuningJobStatus status = default; - FineTuningJobHyperparameters hyperparameters = default; + long? trainedTokens = default; string trainingFile = default; string validationFile = default; - IReadOnlyList resultFiles = default; - long? trainedTokens = default; - FineTuningJobError error = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -148,29 +148,19 @@ internal static FineTuningJob DeserializeFineTuningJob(JsonElement element, Mode id = property.Value.GetString(); continue; } - if (property.NameEquals("object"u8)) - { - @object = new FineTuningJobObject(property.Value.GetString()); - continue; - } if (property.NameEquals("created_at"u8)) { createdAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); continue; } - if (property.NameEquals("finished_at"u8)) + if (property.NameEquals("error"u8)) { if (property.Value.ValueKind == JsonValueKind.Null) { - finishedAt = null; + error = null; continue; } - finishedAt = property.Value.GetDateTimeOffset("O"); - continue; - } - if (property.NameEquals("model"u8)) - { - model = property.Value.GetString(); + error = FineTuningJobError.DeserializeFineTuningJobError(property.Value); continue; } if (property.NameEquals("fine_tuned_model"u8)) @@ -183,34 +173,34 @@ internal static FineTuningJob DeserializeFineTuningJob(JsonElement element, Mode fineTunedModel = property.Value.GetString(); continue; } - if (property.NameEquals("organization_id"u8)) + if (property.NameEquals("finished_at"u8)) { - organizationId = property.Value.GetString(); + if (property.Value.ValueKind == JsonValueKind.Null) + { + finishedAt = null; + continue; + } + finishedAt = property.Value.GetDateTimeOffset("O"); continue; } - if (property.NameEquals("status"u8)) + if (property.NameEquals("hyperparameters"u8)) { - status = new FineTuningJobStatus(property.Value.GetString()); + hyperparameters = FineTuningJobHyperparameters.DeserializeFineTuningJobHyperparameters(property.Value); continue; } - if (property.NameEquals("hyperparameters"u8)) + if (property.NameEquals("model"u8)) { - hyperparameters = FineTuningJobHyperparameters.DeserializeFineTuningJobHyperparameters(property.Value); + model = property.Value.GetString(); continue; } - if (property.NameEquals("training_file"u8)) + if (property.NameEquals("object"u8)) { - trainingFile = property.Value.GetString(); + @object = new FineTuningJobObject(property.Value.GetString()); continue; } - if (property.NameEquals("validation_file"u8)) + if (property.NameEquals("organization_id"u8)) { - if (property.Value.ValueKind == JsonValueKind.Null) - { - validationFile = null; - continue; - } - validationFile = property.Value.GetString(); + organizationId = property.Value.GetString(); continue; } if (property.NameEquals("result_files"u8)) @@ -223,6 +213,11 @@ internal static FineTuningJob DeserializeFineTuningJob(JsonElement element, Mode resultFiles = array; continue; } + if (property.NameEquals("status"u8)) + { + status = new FineTuningJobStatus(property.Value.GetString()); + continue; + } if (property.NameEquals("trained_tokens"u8)) { if (property.Value.ValueKind == JsonValueKind.Null) @@ -233,14 +228,19 @@ internal static FineTuningJob DeserializeFineTuningJob(JsonElement element, Mode trainedTokens = property.Value.GetInt64(); continue; } - if (property.NameEquals("error"u8)) + if (property.NameEquals("training_file"u8)) + { + trainingFile = property.Value.GetString(); + continue; + } + if (property.NameEquals("validation_file"u8)) { if (property.Value.ValueKind == JsonValueKind.Null) { - error = null; + validationFile = null; continue; } - error = FineTuningJobError.DeserializeFineTuningJobError(property.Value); + validationFile = property.Value.GetString(); continue; } if (options.Format != "W") @@ -249,7 +249,7 @@ internal static FineTuningJob DeserializeFineTuningJob(JsonElement element, Mode } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new FineTuningJob(id, @object, createdAt, finishedAt, model, fineTunedModel, organizationId, status, hyperparameters, trainingFile, validationFile, resultFiles, trainedTokens, error, serializedAdditionalRawData); + return new FineTuningJob(id, createdAt, error, fineTunedModel, finishedAt, hyperparameters, model, @object, organizationId, resultFiles, status, trainedTokens, trainingFile, validationFile, serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) diff --git a/.dotnet/src/Generated/Models/FineTuningJob.cs b/.dotnet/src/Generated/Models/FineTuningJob.cs index 52609ca25..3c69c6a1e 100644 --- a/.dotnet/src/Generated/Models/FineTuningJob.cs +++ b/.dotnet/src/Generated/Models/FineTuningJob.cs @@ -45,128 +45,128 @@ internal partial class FineTuningJob /// Initializes a new instance of . /// The object identifier, which can be referenced in the API endpoints. /// The Unix timestamp (in seconds) for when the fine-tuning job was created. - /// - /// The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be - /// null if the fine-tuning job is still running. + /// + /// For fine-tuning jobs that have `failed`, this will contain more information on the cause of the + /// failure. /// - /// The base model that is being fine-tuned. /// /// The name of the fine-tuned model that is being created. The value will be null if the /// fine-tuning job is still running. /// - /// The organization that owns the fine-tuning job. - /// - /// The current status of the fine-tuning job, which can be either `created`, `pending`, `running`, - /// `succeeded`, `failed`, or `cancelled`. + /// + /// The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be + /// null if the fine-tuning job is still running. /// /// /// The hyperparameters used for the fine-tuning job. See the /// [fine-tuning guide](/docs/guides/fine-tuning) for more details. /// - /// - /// The file ID used for training. You can retrieve the training data with the - /// [Files API](/docs/api-reference/files/retrieve-contents). - /// - /// - /// The file ID used for validation. You can retrieve the validation results with the - /// [Files API](/docs/api-reference/files/retrieve-contents). - /// + /// The base model that is being fine-tuned. + /// The organization that owns the fine-tuning job. /// /// The compiled results file ID(s) for the fine-tuning job. You can retrieve the results with the /// [Files API](/docs/api-reference/files/retrieve-contents). /// + /// + /// The current status of the fine-tuning job, which can be either `validating_files`, `queued`, + /// `running`, `succeeded`, `failed`, or `cancelled`. + /// /// - /// The total number of billable tokens processed by this fine tuning job. The value will be null + /// The total number of billable tokens processed by this fine-tuning job. The value will be null /// if the fine-tuning job is still running. /// - /// - /// For fine-tuning jobs that have `failed`, this will contain more information on the cause of the - /// failure. + /// + /// The file ID used for training. You can retrieve the training data with the + /// [Files API](/docs/api-reference/files/retrieve-contents). /// - /// , , , , or is null. - internal FineTuningJob(string id, DateTimeOffset createdAt, DateTimeOffset? finishedAt, string model, string fineTunedModel, string organizationId, FineTuningJobStatus status, FineTuningJobHyperparameters hyperparameters, string trainingFile, string validationFile, IEnumerable resultFiles, long? trainedTokens, FineTuningJobError error) + /// + /// The file ID used for validation. You can retrieve the validation results with the + /// [Files API](/docs/api-reference/files/retrieve-contents). + /// + /// , , , , or is null. + internal FineTuningJob(string id, DateTimeOffset createdAt, FineTuningJobError error, string fineTunedModel, DateTimeOffset? finishedAt, FineTuningJobHyperparameters hyperparameters, string model, string organizationId, IEnumerable resultFiles, FineTuningJobStatus status, long? trainedTokens, string trainingFile, string validationFile) { if (id is null) throw new ArgumentNullException(nameof(id)); + if (hyperparameters is null) throw new ArgumentNullException(nameof(hyperparameters)); if (model is null) throw new ArgumentNullException(nameof(model)); if (organizationId is null) throw new ArgumentNullException(nameof(organizationId)); - if (hyperparameters is null) throw new ArgumentNullException(nameof(hyperparameters)); - if (trainingFile is null) throw new ArgumentNullException(nameof(trainingFile)); if (resultFiles is null) throw new ArgumentNullException(nameof(resultFiles)); + if (trainingFile is null) throw new ArgumentNullException(nameof(trainingFile)); Id = id; CreatedAt = createdAt; + Error = error; + FineTunedModel = fineTunedModel; FinishedAt = finishedAt; + Hyperparameters = hyperparameters; Model = model; - FineTunedModel = fineTunedModel; OrganizationId = organizationId; + ResultFiles = resultFiles.ToList(); Status = status; - Hyperparameters = hyperparameters; + TrainedTokens = trainedTokens; TrainingFile = trainingFile; ValidationFile = validationFile; - ResultFiles = resultFiles.ToList(); - TrainedTokens = trainedTokens; - Error = error; } /// Initializes a new instance of . /// The object identifier, which can be referenced in the API endpoints. - /// The object type, which is always "fine_tuning.job". /// The Unix timestamp (in seconds) for when the fine-tuning job was created. - /// - /// The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be - /// null if the fine-tuning job is still running. + /// + /// For fine-tuning jobs that have `failed`, this will contain more information on the cause of the + /// failure. /// - /// The base model that is being fine-tuned. /// /// The name of the fine-tuned model that is being created. The value will be null if the /// fine-tuning job is still running. /// - /// The organization that owns the fine-tuning job. - /// - /// The current status of the fine-tuning job, which can be either `created`, `pending`, `running`, - /// `succeeded`, `failed`, or `cancelled`. + /// + /// The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be + /// null if the fine-tuning job is still running. /// /// /// The hyperparameters used for the fine-tuning job. See the /// [fine-tuning guide](/docs/guides/fine-tuning) for more details. /// - /// - /// The file ID used for training. You can retrieve the training data with the - /// [Files API](/docs/api-reference/files/retrieve-contents). - /// - /// - /// The file ID used for validation. You can retrieve the validation results with the - /// [Files API](/docs/api-reference/files/retrieve-contents). - /// + /// The base model that is being fine-tuned. + /// The object type, which is always "fine_tuning.job". + /// The organization that owns the fine-tuning job. /// /// The compiled results file ID(s) for the fine-tuning job. You can retrieve the results with the /// [Files API](/docs/api-reference/files/retrieve-contents). /// + /// + /// The current status of the fine-tuning job, which can be either `validating_files`, `queued`, + /// `running`, `succeeded`, `failed`, or `cancelled`. + /// /// - /// The total number of billable tokens processed by this fine tuning job. The value will be null + /// The total number of billable tokens processed by this fine-tuning job. The value will be null /// if the fine-tuning job is still running. /// - /// - /// For fine-tuning jobs that have `failed`, this will contain more information on the cause of the - /// failure. + /// + /// The file ID used for training. You can retrieve the training data with the + /// [Files API](/docs/api-reference/files/retrieve-contents). + /// + /// + /// The file ID used for validation. You can retrieve the validation results with the + /// [Files API](/docs/api-reference/files/retrieve-contents). /// /// Keeps track of any properties unknown to the library. - internal FineTuningJob(string id, FineTuningJobObject @object, DateTimeOffset createdAt, DateTimeOffset? finishedAt, string model, string fineTunedModel, string organizationId, FineTuningJobStatus status, FineTuningJobHyperparameters hyperparameters, string trainingFile, string validationFile, IReadOnlyList resultFiles, long? trainedTokens, FineTuningJobError error, IDictionary serializedAdditionalRawData) + internal FineTuningJob(string id, DateTimeOffset createdAt, FineTuningJobError error, string fineTunedModel, DateTimeOffset? finishedAt, FineTuningJobHyperparameters hyperparameters, string model, FineTuningJobObject @object, string organizationId, IReadOnlyList resultFiles, FineTuningJobStatus status, long? trainedTokens, string trainingFile, string validationFile, IDictionary serializedAdditionalRawData) { Id = id; - Object = @object; CreatedAt = createdAt; + Error = error; + FineTunedModel = fineTunedModel; FinishedAt = finishedAt; + Hyperparameters = hyperparameters; Model = model; - FineTunedModel = fineTunedModel; + Object = @object; OrganizationId = organizationId; + ResultFiles = resultFiles; Status = status; - Hyperparameters = hyperparameters; + TrainedTokens = trainedTokens; TrainingFile = trainingFile; ValidationFile = validationFile; - ResultFiles = resultFiles; - TrainedTokens = trainedTokens; - Error = error; _serializedAdditionalRawData = serializedAdditionalRawData; } @@ -177,59 +177,59 @@ internal FineTuningJob() /// The object identifier, which can be referenced in the API endpoints. public string Id { get; } - /// The object type, which is always "fine_tuning.job". - public FineTuningJobObject Object { get; } = FineTuningJobObject.FineTuningJob; - /// The Unix timestamp (in seconds) for when the fine-tuning job was created. public DateTimeOffset CreatedAt { get; } /// - /// The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be - /// null if the fine-tuning job is still running. + /// For fine-tuning jobs that have `failed`, this will contain more information on the cause of the + /// failure. /// - public DateTimeOffset? FinishedAt { get; } - /// The base model that is being fine-tuned. - public string Model { get; } + public FineTuningJobError Error { get; } /// /// The name of the fine-tuned model that is being created. The value will be null if the /// fine-tuning job is still running. /// public string FineTunedModel { get; } - /// The organization that owns the fine-tuning job. - public string OrganizationId { get; } /// - /// The current status of the fine-tuning job, which can be either `created`, `pending`, `running`, - /// `succeeded`, `failed`, or `cancelled`. + /// The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be + /// null if the fine-tuning job is still running. /// - public FineTuningJobStatus Status { get; } + public DateTimeOffset? FinishedAt { get; } /// /// The hyperparameters used for the fine-tuning job. See the /// [fine-tuning guide](/docs/guides/fine-tuning) for more details. /// public FineTuningJobHyperparameters Hyperparameters { get; } - /// - /// The file ID used for training. You can retrieve the training data with the - /// [Files API](/docs/api-reference/files/retrieve-contents). - /// - public string TrainingFile { get; } - /// - /// The file ID used for validation. You can retrieve the validation results with the - /// [Files API](/docs/api-reference/files/retrieve-contents). - /// - public string ValidationFile { get; } + /// The base model that is being fine-tuned. + public string Model { get; } + /// The object type, which is always "fine_tuning.job". + public FineTuningJobObject Object { get; } = FineTuningJobObject.FineTuningJob; + + /// The organization that owns the fine-tuning job. + public string OrganizationId { get; } /// /// The compiled results file ID(s) for the fine-tuning job. You can retrieve the results with the /// [Files API](/docs/api-reference/files/retrieve-contents). /// public IReadOnlyList ResultFiles { get; } /// - /// The total number of billable tokens processed by this fine tuning job. The value will be null + /// The current status of the fine-tuning job, which can be either `validating_files`, `queued`, + /// `running`, `succeeded`, `failed`, or `cancelled`. + /// + public FineTuningJobStatus Status { get; } + /// + /// The total number of billable tokens processed by this fine-tuning job. The value will be null /// if the fine-tuning job is still running. /// public long? TrainedTokens { get; } /// - /// For fine-tuning jobs that have `failed`, this will contain more information on the cause of the - /// failure. + /// The file ID used for training. You can retrieve the training data with the + /// [Files API](/docs/api-reference/files/retrieve-contents). /// - public FineTuningJobError Error { get; } + public string TrainingFile { get; } + /// + /// The file ID used for validation. You can retrieve the validation results with the + /// [Files API](/docs/api-reference/files/retrieve-contents). + /// + public string ValidationFile { get; } } } diff --git a/.dotnet/src/Generated/Models/FineTuningJobError.Serialization.cs b/.dotnet/src/Generated/Models/FineTuningJobError.Serialization.cs index fab47e3bd..7177ea5dd 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobError.Serialization.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobError.Serialization.cs @@ -19,27 +19,18 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWrit } writer.WriteStartObject(); - if (OptionalProperty.IsDefined(Message)) + writer.WritePropertyName("code"u8); + writer.WriteStringValue(Code); + writer.WritePropertyName("message"u8); + writer.WriteStringValue(Message); + if (Param != null) { - writer.WritePropertyName("message"u8); - writer.WriteStringValue(Message); + writer.WritePropertyName("param"u8); + writer.WriteStringValue(Param); } - if (OptionalProperty.IsDefined(Code)) + else { - writer.WritePropertyName("code"u8); - writer.WriteStringValue(Code); - } - if (OptionalProperty.IsDefined(Param)) - { - if (Param != null) - { - writer.WritePropertyName("param"u8); - writer.WriteStringValue(Param); - } - else - { - writer.WriteNull("param"); - } + writer.WriteNull("param"); } if (options.Format != "W" && _serializedAdditionalRawData != null) { @@ -79,21 +70,21 @@ internal static FineTuningJobError DeserializeFineTuningJobError(JsonElement ele { return null; } - OptionalProperty message = default; - OptionalProperty code = default; - OptionalProperty param = default; + string code = default; + string message = default; + string param = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) { - if (property.NameEquals("message"u8)) + if (property.NameEquals("code"u8)) { - message = property.Value.GetString(); + code = property.Value.GetString(); continue; } - if (property.NameEquals("code"u8)) + if (property.NameEquals("message"u8)) { - code = property.Value.GetString(); + message = property.Value.GetString(); continue; } if (property.NameEquals("param"u8)) @@ -112,7 +103,7 @@ internal static FineTuningJobError DeserializeFineTuningJobError(JsonElement ele } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new FineTuningJobError(message.Value, code.Value, param.Value, serializedAdditionalRawData); + return new FineTuningJobError(code, message, param, serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) diff --git a/.dotnet/src/Generated/Models/FineTuningJobError.cs b/.dotnet/src/Generated/Models/FineTuningJobError.cs index c3798392a..744c38ab4 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobError.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobError.cs @@ -1,6 +1,7 @@ // using System; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Internal.Models @@ -41,33 +42,51 @@ internal partial class FineTuningJobError private IDictionary _serializedAdditionalRawData; /// Initializes a new instance of . - internal FineTuningJobError() + /// A machine-readable error code. + /// A human-readable error message. + /// + /// The parameter that was invalid, usually `training_file` or `validation_file`. This field will + /// be null if the failure was not parameter-specific. + /// + /// or is null. + internal FineTuningJobError(string code, string message, string param) { + if (code is null) throw new ArgumentNullException(nameof(code)); + if (message is null) throw new ArgumentNullException(nameof(message)); + + Code = code; + Message = message; + Param = param; } /// Initializes a new instance of . - /// A human-readable error message. /// A machine-readable error code. + /// A human-readable error message. /// - /// The parameter that was invalid, usually `training_file` or `validation_file`. This field - /// will be null if the failure was not parameter-specific. + /// The parameter that was invalid, usually `training_file` or `validation_file`. This field will + /// be null if the failure was not parameter-specific. /// /// Keeps track of any properties unknown to the library. - internal FineTuningJobError(string message, string code, string param, IDictionary serializedAdditionalRawData) + internal FineTuningJobError(string code, string message, string param, IDictionary serializedAdditionalRawData) { - Message = message; Code = code; + Message = message; Param = param; _serializedAdditionalRawData = serializedAdditionalRawData; } - /// A human-readable error message. - public string Message { get; } + /// Initializes a new instance of for deserialization. + internal FineTuningJobError() + { + } + /// A machine-readable error code. public string Code { get; } + /// A human-readable error message. + public string Message { get; } /// - /// The parameter that was invalid, usually `training_file` or `validation_file`. This field - /// will be null if the failure was not parameter-specific. + /// The parameter that was invalid, usually `training_file` or `validation_file`. This field will + /// be null if the failure was not parameter-specific. /// public string Param { get; } } diff --git a/.dotnet/src/Generated/Models/FineTuningJobEvent.Serialization.cs b/.dotnet/src/Generated/Models/FineTuningJobEvent.Serialization.cs index 0176faabe..dad0768e9 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobEvent.Serialization.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobEvent.Serialization.cs @@ -21,14 +21,14 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWrit writer.WriteStartObject(); writer.WritePropertyName("id"u8); writer.WriteStringValue(Id); - writer.WritePropertyName("object"u8); - writer.WriteStringValue(Object); writer.WritePropertyName("created_at"u8); writer.WriteNumberValue(CreatedAt, "U"); writer.WritePropertyName("level"u8); writer.WriteStringValue(Level.ToString()); writer.WritePropertyName("message"u8); writer.WriteStringValue(Message); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); if (options.Format != "W" && _serializedAdditionalRawData != null) { foreach (var item in _serializedAdditionalRawData) @@ -68,10 +68,10 @@ internal static FineTuningJobEvent DeserializeFineTuningJobEvent(JsonElement ele return null; } string id = default; - string @object = default; DateTimeOffset createdAt = default; FineTuningJobEventLevel level = default; string message = default; + FineTuningJobEventObject @object = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -81,11 +81,6 @@ internal static FineTuningJobEvent DeserializeFineTuningJobEvent(JsonElement ele id = property.Value.GetString(); continue; } - if (property.NameEquals("object"u8)) - { - @object = property.Value.GetString(); - continue; - } if (property.NameEquals("created_at"u8)) { createdAt = DateTimeOffset.FromUnixTimeSeconds(property.Value.GetInt64()); @@ -101,13 +96,18 @@ internal static FineTuningJobEvent DeserializeFineTuningJobEvent(JsonElement ele message = property.Value.GetString(); continue; } + if (property.NameEquals("object"u8)) + { + @object = new FineTuningJobEventObject(property.Value.GetString()); + continue; + } if (options.Format != "W") { additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new FineTuningJobEvent(id, @object, createdAt, level, message, serializedAdditionalRawData); + return new FineTuningJobEvent(id, createdAt, level, message, @object, serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) diff --git a/.dotnet/src/Generated/Models/FineTuningJobEvent.cs b/.dotnet/src/Generated/Models/FineTuningJobEvent.cs index 30f900667..c73c76045 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobEvent.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobEvent.cs @@ -6,7 +6,7 @@ namespace OpenAI.Internal.Models { - /// The FineTuningJobEvent. + /// Fine-tuning job event object. internal partial class FineTuningJobEvent { /// @@ -43,19 +43,16 @@ internal partial class FineTuningJobEvent /// Initializes a new instance of . /// - /// /// /// /// - /// , or is null. - internal FineTuningJobEvent(string id, string @object, DateTimeOffset createdAt, FineTuningJobEventLevel level, string message) + /// or is null. + internal FineTuningJobEvent(string id, DateTimeOffset createdAt, FineTuningJobEventLevel level, string message) { if (id is null) throw new ArgumentNullException(nameof(id)); - if (@object is null) throw new ArgumentNullException(nameof(@object)); if (message is null) throw new ArgumentNullException(nameof(message)); Id = id; - Object = @object; CreatedAt = createdAt; Level = level; Message = message; @@ -63,18 +60,18 @@ internal FineTuningJobEvent(string id, string @object, DateTimeOffset createdAt, /// Initializes a new instance of . /// - /// /// /// /// + /// /// Keeps track of any properties unknown to the library. - internal FineTuningJobEvent(string id, string @object, DateTimeOffset createdAt, FineTuningJobEventLevel level, string message, IDictionary serializedAdditionalRawData) + internal FineTuningJobEvent(string id, DateTimeOffset createdAt, FineTuningJobEventLevel level, string message, FineTuningJobEventObject @object, IDictionary serializedAdditionalRawData) { Id = id; - Object = @object; CreatedAt = createdAt; Level = level; Message = message; + Object = @object; _serializedAdditionalRawData = serializedAdditionalRawData; } @@ -85,13 +82,13 @@ internal FineTuningJobEvent() /// Gets the id. public string Id { get; } - /// Gets the object. - public string Object { get; } /// Gets the created at. public DateTimeOffset CreatedAt { get; } /// Gets the level. public FineTuningJobEventLevel Level { get; } /// Gets the message. public string Message { get; } + /// Gets the object. + public FineTuningJobEventObject Object { get; } = FineTuningJobEventObject.FineTuningJobEvent; } } diff --git a/.dotnet/src/Generated/Models/FineTuningJobEventObject.cs b/.dotnet/src/Generated/Models/FineTuningJobEventObject.cs new file mode 100644 index 000000000..f73cd4fc1 --- /dev/null +++ b/.dotnet/src/Generated/Models/FineTuningJobEventObject.cs @@ -0,0 +1,43 @@ +// + +using System; +using System.ComponentModel; + +namespace OpenAI.Internal.Models +{ + /// The FineTuningJobEvent_object. + internal readonly partial struct FineTuningJobEventObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public FineTuningJobEventObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string FineTuningJobEventValue = "fine_tuning.job.event"; + + /// fine_tuning.job.event. + public static FineTuningJobEventObject FineTuningJobEvent { get; } = new FineTuningJobEventObject(FineTuningJobEventValue); + /// Determines if two values are the same. + public static bool operator ==(FineTuningJobEventObject left, FineTuningJobEventObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(FineTuningJobEventObject left, FineTuningJobEventObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator FineTuningJobEventObject(string value) => new FineTuningJobEventObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is FineTuningJobEventObject other && Equals(other); + /// + public bool Equals(FineTuningJobEventObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.Serialization.cs b/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.Serialization.cs index c08e0565b..67ef81085 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.Serialization.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.Serialization.cs @@ -19,18 +19,15 @@ void IJsonModel.Write(Utf8JsonWriter writer, Model } writer.WriteStartObject(); - if (OptionalProperty.IsDefined(NEpochs)) - { - writer.WritePropertyName("n_epochs"u8); + writer.WritePropertyName("n_epochs"u8); #if NET6_0_OR_GREATER writer.WriteRawValue(NEpochs); #else - using (JsonDocument document = JsonDocument.Parse(NEpochs)) - { - JsonSerializer.Serialize(writer, document.RootElement); - } -#endif + using (JsonDocument document = JsonDocument.Parse(NEpochs)) + { + JsonSerializer.Serialize(writer, document.RootElement); } +#endif if (options.Format != "W" && _serializedAdditionalRawData != null) { foreach (var item in _serializedAdditionalRawData) @@ -69,17 +66,13 @@ internal static FineTuningJobHyperparameters DeserializeFineTuningJobHyperparame { return null; } - OptionalProperty nEpochs = default; + BinaryData nEpochs = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) { if (property.NameEquals("n_epochs"u8)) { - if (property.Value.ValueKind == JsonValueKind.Null) - { - continue; - } nEpochs = BinaryData.FromString(property.Value.GetRawText()); continue; } @@ -89,7 +82,7 @@ internal static FineTuningJobHyperparameters DeserializeFineTuningJobHyperparame } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new FineTuningJobHyperparameters(nEpochs.Value, serializedAdditionalRawData); + return new FineTuningJobHyperparameters(nEpochs, serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) diff --git a/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.cs b/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.cs index 40a9d6547..b81c9c19f 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.cs @@ -1,6 +1,7 @@ // using System; +using OpenAI.ClientShared.Internal; using System.Collections.Generic; namespace OpenAI.Internal.Models @@ -41,8 +42,19 @@ internal partial class FineTuningJobHyperparameters private IDictionary _serializedAdditionalRawData; /// Initializes a new instance of . - internal FineTuningJobHyperparameters() + /// + /// The number of epochs to train the model for. An epoch refers to one full cycle through the + /// training dataset. + /// + /// "auto" decides the optimal number of epochs based on the size of the dataset. If setting the + /// number manually, we support any number between 1 and 50 epochs. + /// + /// is null. + internal FineTuningJobHyperparameters(BinaryData nEpochs) { + if (nEpochs is null) throw new ArgumentNullException(nameof(nEpochs)); + + NEpochs = nEpochs; } /// Initializes a new instance of . @@ -50,7 +62,7 @@ internal FineTuningJobHyperparameters() /// The number of epochs to train the model for. An epoch refers to one full cycle through the /// training dataset. /// - /// "Auto" decides the optimal number of epochs based on the size of the dataset. If setting the + /// "auto" decides the optimal number of epochs based on the size of the dataset. If setting the /// number manually, we support any number between 1 and 50 epochs. /// /// Keeps track of any properties unknown to the library. @@ -60,11 +72,16 @@ internal FineTuningJobHyperparameters(BinaryData nEpochs, IDictionary Initializes a new instance of for deserialization. + internal FineTuningJobHyperparameters() + { + } + /// /// The number of epochs to train the model for. An epoch refers to one full cycle through the /// training dataset. /// - /// "Auto" decides the optimal number of epochs based on the size of the dataset. If setting the + /// "auto" decides the optimal number of epochs based on the size of the dataset. If setting the /// number manually, we support any number between 1 and 50 epochs. /// /// To assign an object to this property use . diff --git a/.dotnet/src/Generated/Models/FineTuningJobStatus.cs b/.dotnet/src/Generated/Models/FineTuningJobStatus.cs index 73c350bca..660c4d469 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobStatus.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobStatus.cs @@ -17,17 +17,17 @@ public FineTuningJobStatus(string value) _value = value ?? throw new ArgumentNullException(nameof(value)); } - private const string CreatedValue = "created"; - private const string PendingValue = "pending"; + private const string ValidatingFilesValue = "validating_files"; + private const string QueuedValue = "queued"; private const string RunningValue = "running"; private const string SucceededValue = "succeeded"; private const string FailedValue = "failed"; private const string CancelledValue = "cancelled"; - /// created. - public static FineTuningJobStatus Created { get; } = new FineTuningJobStatus(CreatedValue); - /// pending. - public static FineTuningJobStatus Pending { get; } = new FineTuningJobStatus(PendingValue); + /// validating_files. + public static FineTuningJobStatus ValidatingFiles { get; } = new FineTuningJobStatus(ValidatingFilesValue); + /// queued. + public static FineTuningJobStatus Queued { get; } = new FineTuningJobStatus(QueuedValue); /// running. public static FineTuningJobStatus Running { get; } = new FineTuningJobStatus(RunningValue); /// succeeded. diff --git a/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.Serialization.cs index b2595af03..fe4b81c4b 100644 --- a/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.Serialization.cs @@ -19,8 +19,6 @@ void IJsonModel.Write(Utf8JsonWriter writer, Mo } writer.WriteStartObject(); - writer.WritePropertyName("object"u8); - writer.WriteStringValue(Object); writer.WritePropertyName("data"u8); writer.WriteStartArray(); foreach (var item in Data) @@ -28,6 +26,8 @@ void IJsonModel.Write(Utf8JsonWriter writer, Mo writer.WriteObjectValue(item); } writer.WriteEndArray(); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); if (options.Format != "W" && _serializedAdditionalRawData != null) { foreach (var item in _serializedAdditionalRawData) @@ -66,17 +66,12 @@ internal static ListFineTuningJobEventsResponse DeserializeListFineTuningJobEven { return null; } - string @object = default; IReadOnlyList data = default; + ListFineTuningJobEventsResponseObject @object = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) { - if (property.NameEquals("object"u8)) - { - @object = property.Value.GetString(); - continue; - } if (property.NameEquals("data"u8)) { List array = new List(); @@ -87,13 +82,18 @@ internal static ListFineTuningJobEventsResponse DeserializeListFineTuningJobEven data = array; continue; } + if (property.NameEquals("object"u8)) + { + @object = new ListFineTuningJobEventsResponseObject(property.Value.GetString()); + continue; + } if (options.Format != "W") { additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new ListFineTuningJobEventsResponse(@object, data, serializedAdditionalRawData); + return new ListFineTuningJobEventsResponse(data, @object, serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) diff --git a/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.cs b/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.cs index 6ff86e39b..57508a714 100644 --- a/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.cs +++ b/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.cs @@ -43,26 +43,23 @@ internal partial class ListFineTuningJobEventsResponse private IDictionary _serializedAdditionalRawData; /// Initializes a new instance of . - /// /// - /// or is null. - internal ListFineTuningJobEventsResponse(string @object, IEnumerable data) + /// is null. + internal ListFineTuningJobEventsResponse(IEnumerable data) { - if (@object is null) throw new ArgumentNullException(nameof(@object)); if (data is null) throw new ArgumentNullException(nameof(data)); - Object = @object; Data = data.ToList(); } /// Initializes a new instance of . - /// /// + /// /// Keeps track of any properties unknown to the library. - internal ListFineTuningJobEventsResponse(string @object, IReadOnlyList data, IDictionary serializedAdditionalRawData) + internal ListFineTuningJobEventsResponse(IReadOnlyList data, ListFineTuningJobEventsResponseObject @object, IDictionary serializedAdditionalRawData) { - Object = @object; Data = data; + Object = @object; _serializedAdditionalRawData = serializedAdditionalRawData; } @@ -71,9 +68,9 @@ internal ListFineTuningJobEventsResponse() { } - /// Gets the object. - public string Object { get; } /// Gets the data. public IReadOnlyList Data { get; } + /// Gets the object. + public ListFineTuningJobEventsResponseObject Object { get; } = ListFineTuningJobEventsResponseObject.List; } } diff --git a/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponseObject.cs b/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponseObject.cs new file mode 100644 index 000000000..adbb30c46 --- /dev/null +++ b/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponseObject.cs @@ -0,0 +1,43 @@ +// + +using System; +using System.ComponentModel; + +namespace OpenAI.Internal.Models +{ + /// The ListFineTuningJobEventsResponse_object. + internal readonly partial struct ListFineTuningJobEventsResponseObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public ListFineTuningJobEventsResponseObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string ListValue = "list"; + + /// list. + public static ListFineTuningJobEventsResponseObject List { get; } = new ListFineTuningJobEventsResponseObject(ListValue); + /// Determines if two values are the same. + public static bool operator ==(ListFineTuningJobEventsResponseObject left, ListFineTuningJobEventsResponseObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(ListFineTuningJobEventsResponseObject left, ListFineTuningJobEventsResponseObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator ListFineTuningJobEventsResponseObject(string value) => new ListFineTuningJobEventsResponseObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is ListFineTuningJobEventsResponseObject other && Equals(other); + /// + public bool Equals(ListFineTuningJobEventsResponseObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.Serialization.cs index c1344e078..c741d8962 100644 --- a/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.Serialization.cs @@ -19,8 +19,6 @@ void IJsonModel.Write(Utf8JsonWriter writer } writer.WriteStartObject(); - writer.WritePropertyName("object"u8); - writer.WriteStringValue(Object); writer.WritePropertyName("data"u8); writer.WriteStartArray(); foreach (var item in Data) @@ -30,6 +28,8 @@ void IJsonModel.Write(Utf8JsonWriter writer writer.WriteEndArray(); writer.WritePropertyName("has_more"u8); writer.WriteBooleanValue(HasMore); + writer.WritePropertyName("object"u8); + writer.WriteStringValue(Object.ToString()); if (options.Format != "W" && _serializedAdditionalRawData != null) { foreach (var item in _serializedAdditionalRawData) @@ -68,18 +68,13 @@ internal static ListPaginatedFineTuningJobsResponse DeserializeListPaginatedFine { return null; } - string @object = default; IReadOnlyList data = default; bool hasMore = default; + ListPaginatedFineTuningJobsResponseObject @object = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) { - if (property.NameEquals("object"u8)) - { - @object = property.Value.GetString(); - continue; - } if (property.NameEquals("data"u8)) { List array = new List(); @@ -95,13 +90,18 @@ internal static ListPaginatedFineTuningJobsResponse DeserializeListPaginatedFine hasMore = property.Value.GetBoolean(); continue; } + if (property.NameEquals("object"u8)) + { + @object = new ListPaginatedFineTuningJobsResponseObject(property.Value.GetString()); + continue; + } if (options.Format != "W") { additionalPropertiesDictionary.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new ListPaginatedFineTuningJobsResponse(@object, data, hasMore, serializedAdditionalRawData); + return new ListPaginatedFineTuningJobsResponse(data, hasMore, @object, serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) diff --git a/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.cs b/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.cs index e99c79598..ce7267ba2 100644 --- a/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.cs +++ b/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.cs @@ -43,30 +43,27 @@ internal partial class ListPaginatedFineTuningJobsResponse private IDictionary _serializedAdditionalRawData; /// Initializes a new instance of . - /// /// /// - /// or is null. - internal ListPaginatedFineTuningJobsResponse(string @object, IEnumerable data, bool hasMore) + /// is null. + internal ListPaginatedFineTuningJobsResponse(IEnumerable data, bool hasMore) { - if (@object is null) throw new ArgumentNullException(nameof(@object)); if (data is null) throw new ArgumentNullException(nameof(data)); - Object = @object; Data = data.ToList(); HasMore = hasMore; } /// Initializes a new instance of . - /// /// /// + /// /// Keeps track of any properties unknown to the library. - internal ListPaginatedFineTuningJobsResponse(string @object, IReadOnlyList data, bool hasMore, IDictionary serializedAdditionalRawData) + internal ListPaginatedFineTuningJobsResponse(IReadOnlyList data, bool hasMore, ListPaginatedFineTuningJobsResponseObject @object, IDictionary serializedAdditionalRawData) { - Object = @object; Data = data; HasMore = hasMore; + Object = @object; _serializedAdditionalRawData = serializedAdditionalRawData; } @@ -75,11 +72,11 @@ internal ListPaginatedFineTuningJobsResponse() { } - /// Gets the object. - public string Object { get; } /// Gets the data. public IReadOnlyList Data { get; } /// Gets the has more. public bool HasMore { get; } + /// Gets the object. + public ListPaginatedFineTuningJobsResponseObject Object { get; } = ListPaginatedFineTuningJobsResponseObject.List; } } diff --git a/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponseObject.cs b/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponseObject.cs new file mode 100644 index 000000000..faa11b860 --- /dev/null +++ b/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponseObject.cs @@ -0,0 +1,43 @@ +// + +using System; +using System.ComponentModel; + +namespace OpenAI.Internal.Models +{ + /// The ListPaginatedFineTuningJobsResponse_object. + internal readonly partial struct ListPaginatedFineTuningJobsResponseObject : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public ListPaginatedFineTuningJobsResponseObject(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string ListValue = "list"; + + /// list. + public static ListPaginatedFineTuningJobsResponseObject List { get; } = new ListPaginatedFineTuningJobsResponseObject(ListValue); + /// Determines if two values are the same. + public static bool operator ==(ListPaginatedFineTuningJobsResponseObject left, ListPaginatedFineTuningJobsResponseObject right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(ListPaginatedFineTuningJobsResponseObject left, ListPaginatedFineTuningJobsResponseObject right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator ListPaginatedFineTuningJobsResponseObject(string value) => new ListPaginatedFineTuningJobsResponseObject(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is ListPaginatedFineTuningJobsResponseObject other && Equals(other); + /// + public bool Equals(ListPaginatedFineTuningJobsResponseObject other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/.dotnet/src/Generated/OpenAIModelFactory.cs b/.dotnet/src/Generated/OpenAIModelFactory.cs index 7f65feaf5..cc63a0fba 100644 --- a/.dotnet/src/Generated/OpenAIModelFactory.cs +++ b/.dotnet/src/Generated/OpenAIModelFactory.cs @@ -185,6 +185,10 @@ public static CreateCompletionResponseChoiceLogprobs CreateCompletionResponseCho } /// Initializes a new instance of . + /// + /// The name of the model to fine-tune. You can select one of the + /// [supported models](/docs/guides/fine-tuning/what-models-can-be-fine-tuned). + /// /// /// The ID of an uploaded file that contains training data. /// @@ -195,6 +199,13 @@ public static CreateCompletionResponseChoiceLogprobs CreateCompletionResponseCho /// /// See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. /// + /// The hyperparameters used for the fine-tuning job. + /// + /// 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`. + /// /// /// The ID of an uploaded file that contains validation data. /// @@ -207,71 +218,73 @@ public static CreateCompletionResponseChoiceLogprobs CreateCompletionResponseCho /// /// See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. /// - /// - /// The name of the model to fine-tune. You can select one of the - /// [supported models](/docs/guides/fine-tuning/what-models-can-be-fine-tuned). - /// - /// The hyperparameters used for the fine-tuning job. - /// - /// 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`. - /// /// A new instance for mocking. - public static CreateFineTuningJobRequest CreateFineTuningJobRequest(string trainingFile = null, string validationFile = null, CreateFineTuningJobRequestModel model = default, CreateFineTuningJobRequestHyperparameters hyperparameters = null, string suffix = null) + public static CreateFineTuningJobRequest CreateFineTuningJobRequest(CreateFineTuningJobRequestModel model = default, string trainingFile = null, CreateFineTuningJobRequestHyperparameters hyperparameters = null, string suffix = null, string validationFile = null) { - return new CreateFineTuningJobRequest(trainingFile, validationFile, model, hyperparameters, suffix, serializedAdditionalRawData: null); + return new CreateFineTuningJobRequest(model, trainingFile, hyperparameters, suffix, validationFile, serializedAdditionalRawData: null); } /// Initializes a new instance of . /// The object identifier, which can be referenced in the API endpoints. - /// The object type, which is always "fine_tuning.job". /// The Unix timestamp (in seconds) for when the fine-tuning job was created. - /// - /// The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be - /// null if the fine-tuning job is still running. + /// + /// For fine-tuning jobs that have `failed`, this will contain more information on the cause of the + /// failure. /// - /// The base model that is being fine-tuned. /// /// The name of the fine-tuned model that is being created. The value will be null if the /// fine-tuning job is still running. /// - /// The organization that owns the fine-tuning job. - /// - /// The current status of the fine-tuning job, which can be either `created`, `pending`, `running`, - /// `succeeded`, `failed`, or `cancelled`. + /// + /// The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be + /// null if the fine-tuning job is still running. /// /// /// The hyperparameters used for the fine-tuning job. See the /// [fine-tuning guide](/docs/guides/fine-tuning) for more details. /// - /// - /// The file ID used for training. You can retrieve the training data with the - /// [Files API](/docs/api-reference/files/retrieve-contents). - /// - /// - /// The file ID used for validation. You can retrieve the validation results with the - /// [Files API](/docs/api-reference/files/retrieve-contents). - /// + /// The base model that is being fine-tuned. + /// The object type, which is always "fine_tuning.job". + /// The organization that owns the fine-tuning job. /// /// The compiled results file ID(s) for the fine-tuning job. You can retrieve the results with the /// [Files API](/docs/api-reference/files/retrieve-contents). /// + /// + /// The current status of the fine-tuning job, which can be either `validating_files`, `queued`, + /// `running`, `succeeded`, `failed`, or `cancelled`. + /// /// - /// The total number of billable tokens processed by this fine tuning job. The value will be null + /// The total number of billable tokens processed by this fine-tuning job. The value will be null /// if the fine-tuning job is still running. /// - /// - /// For fine-tuning jobs that have `failed`, this will contain more information on the cause of the - /// failure. + /// + /// The file ID used for training. You can retrieve the training data with the + /// [Files API](/docs/api-reference/files/retrieve-contents). + /// + /// + /// The file ID used for validation. You can retrieve the validation results with the + /// [Files API](/docs/api-reference/files/retrieve-contents). /// /// A new instance for mocking. - public static FineTuningJob FineTuningJob(string id = null, FineTuningJobObject @object = default, DateTimeOffset createdAt = default, DateTimeOffset? finishedAt = null, string model = null, string fineTunedModel = null, string organizationId = null, FineTuningJobStatus status = default, FineTuningJobHyperparameters hyperparameters = null, string trainingFile = null, string validationFile = null, IEnumerable resultFiles = null, long? trainedTokens = null, FineTuningJobError error = null) + public static FineTuningJob FineTuningJob(string id = null, DateTimeOffset createdAt = default, FineTuningJobError error = null, string fineTunedModel = null, DateTimeOffset? finishedAt = null, FineTuningJobHyperparameters hyperparameters = null, string model = null, FineTuningJobObject @object = default, string organizationId = null, IEnumerable resultFiles = null, FineTuningJobStatus status = default, long? trainedTokens = null, string trainingFile = null, string validationFile = null) { resultFiles ??= new List(); - return new FineTuningJob(id, @object, createdAt, finishedAt, model, fineTunedModel, organizationId, status, hyperparameters, trainingFile, validationFile, resultFiles?.ToList(), trainedTokens, error, serializedAdditionalRawData: null); + return new FineTuningJob(id, createdAt, error, fineTunedModel, finishedAt, hyperparameters, model, @object, organizationId, resultFiles?.ToList(), status, trainedTokens, trainingFile, validationFile, serializedAdditionalRawData: null); + } + + /// Initializes a new instance of . + /// A machine-readable error code. + /// A human-readable error message. + /// + /// The parameter that was invalid, usually `training_file` or `validation_file`. This field will + /// be null if the failure was not parameter-specific. + /// + /// A new instance for mocking. + public static FineTuningJobError FineTuningJobError(string code = null, string message = null, string param = null) + { + return new FineTuningJobError(code, message, param, serializedAdditionalRawData: null); } /// Initializes a new instance of . @@ -279,7 +292,7 @@ public static FineTuningJob FineTuningJob(string id = null, FineTuningJobObject /// The number of epochs to train the model for. An epoch refers to one full cycle through the /// training dataset. /// - /// "Auto" decides the optimal number of epochs based on the size of the dataset. If setting the + /// "auto" decides the optimal number of epochs based on the size of the dataset. If setting the /// number manually, we support any number between 1 and 50 epochs. /// /// A new instance for mocking. @@ -288,52 +301,39 @@ public static FineTuningJobHyperparameters FineTuningJobHyperparameters(BinaryDa return new FineTuningJobHyperparameters(nEpochs, serializedAdditionalRawData: null); } - /// Initializes a new instance of . - /// A human-readable error message. - /// A machine-readable error code. - /// - /// The parameter that was invalid, usually `training_file` or `validation_file`. This field - /// will be null if the failure was not parameter-specific. - /// - /// A new instance for mocking. - public static FineTuningJobError FineTuningJobError(string message = null, string code = null, string param = null) - { - return new FineTuningJobError(message, code, param, serializedAdditionalRawData: null); - } - /// Initializes a new instance of . - /// /// /// + /// /// A new instance for mocking. - public static ListPaginatedFineTuningJobsResponse ListPaginatedFineTuningJobsResponse(string @object = null, IEnumerable data = null, bool hasMore = default) + public static ListPaginatedFineTuningJobsResponse ListPaginatedFineTuningJobsResponse(IEnumerable data = null, bool hasMore = default, ListPaginatedFineTuningJobsResponseObject @object = default) { data ??= new List(); - return new ListPaginatedFineTuningJobsResponse(@object, data?.ToList(), hasMore, serializedAdditionalRawData: null); + return new ListPaginatedFineTuningJobsResponse(data?.ToList(), hasMore, @object, serializedAdditionalRawData: null); } /// Initializes a new instance of . - /// /// + /// /// A new instance for mocking. - public static ListFineTuningJobEventsResponse ListFineTuningJobEventsResponse(string @object = null, IEnumerable data = null) + public static ListFineTuningJobEventsResponse ListFineTuningJobEventsResponse(IEnumerable data = null, ListFineTuningJobEventsResponseObject @object = default) { data ??= new List(); - return new ListFineTuningJobEventsResponse(@object, data?.ToList(), serializedAdditionalRawData: null); + return new ListFineTuningJobEventsResponse(data?.ToList(), @object, serializedAdditionalRawData: null); } /// Initializes a new instance of . /// - /// /// /// /// + /// /// A new instance for mocking. - public static FineTuningJobEvent FineTuningJobEvent(string id = null, string @object = null, DateTimeOffset createdAt = default, FineTuningJobEventLevel level = default, string message = null) + public static FineTuningJobEvent FineTuningJobEvent(string id = null, DateTimeOffset createdAt = default, FineTuningJobEventLevel level = default, string message = null, FineTuningJobEventObject @object = default) { - return new FineTuningJobEvent(id, @object, createdAt, level, message, serializedAdditionalRawData: null); + return new FineTuningJobEvent(id, createdAt, level, message, @object, serializedAdditionalRawData: null); } /// Initializes a new instance of . diff --git a/fine-tuning/models.tsp b/fine-tuning/models.tsp index 9afce6d02..5fa91066e 100644 --- a/fine-tuning/models.tsp +++ b/fine-tuning/models.tsp @@ -1,419 +1,213 @@ -import "../files/models.tsp"; - using TypeSpec.OpenAPI; namespace OpenAI; -model FineTuningJob { - /** The object identifier, which can be referenced in the API endpoints. */ - id: string; - - /** The object type, which is always "fine_tuning.job". */ - object: "fine_tuning.job"; - - /** The Unix timestamp (in seconds) for when the fine-tuning job was created. */ - @encode("unixTimestamp", int32) - created_at: utcDateTime; - +model CreateFineTuningJobRequest { /** - * The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be - * null if the fine-tuning job is still running. + * The name of the model to fine-tune. You can select one of the + * [supported models](/docs/guides/fine-tuning/what-models-can-be-fine-tuned). */ - @encode("unixTimestamp", int32) - finished_at: utcDateTime | null; - - /** The base model that is being fine-tuned. */ - `model`: string; + @extension("x-oaiTypeLabel", "string") + `model`: string | "babbage-002" | "davinci-002" | "gpt-3.5-turbo"; /** - * The name of the fine-tuned model that is being created. The value will be null if the - * fine-tuning job is still running. + * The ID of an uploaded file that contains training data. + * + * See [upload file](/docs/api-reference/files/upload) for how to upload a file. + * + * Your dataset must be formatted as a JSONL file. Additionally, you must upload your file with + * the purpose `fine-tune`. + * + * See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. */ - fine_tuned_model: string | null; + training_file: string; - /** The organization that owns the fine-tuning job. */ - organization_id: string; + /** The hyperparameters used for the fine-tuning job. */ + hyperparameters?: { + /** + * Number of examples in each batch. A larger batch size means that model parameters are + * updated less frequently, but with lower variance. + */ + batch_size?: "auto" | BatchSize = "auto"; - /** - * The current status of the fine-tuning job, which can be either `created`, `pending`, `running`, - * `succeeded`, `failed`, or `cancelled`. - */ - status: - | "created" - | "pending" - | "running" - | "succeeded" - | "failed" - | "cancelled"; + /** + * Scaling factor for the learning rate. A smaller learning rate may be useful to avoid + * overfitting. + */ + learning_rate_multiplier?: "auto" | LearningRateMultiplier = "auto"; - /** - * The hyperparameters used for the fine-tuning job. See the - * [fine-tuning guide](/docs/guides/fine-tuning) for more details. - */ - hyperparameters: { /** * The number of epochs to train the model for. An epoch refers to one full cycle through the * training dataset. - * - * "Auto" decides the optimal number of epochs based on the size of the dataset. If setting the - * number manually, we support any number between 1 and 50 epochs. */ n_epochs?: "auto" | NEpochs = "auto"; }; /** - * The file ID used for training. You can retrieve the training data with the - * [Files API](/docs/api-reference/files/retrieve-contents). + * 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`. */ - training_file: string; + suffix?: SuffixString | null = null; /** - * The file ID used for validation. You can retrieve the validation results with the - * [Files API](/docs/api-reference/files/retrieve-contents). + * The ID of an uploaded file that contains validation data. + * + * If you provide this file, the data is used to generate validation metrics periodically during + * fine-tuning. These metrics can be viewed in the fine-tuning results file. The same data should + * not be present in both train and validation files. + * + * Your dataset must be formatted as a JSONL file. You must upload your file with the purpose + * `fine-tune`. + * + * See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. */ - validation_file: string | null; + validation_file?: string | null; +} - /** - * The compiled results file ID(s) for the fine-tuning job. You can retrieve the results with the - * [Files API](/docs/api-reference/files/retrieve-contents). - */ - result_files: string[]; +model ListPaginatedFineTuningJobsResponse { + data: FineTuningJob[]; - /** - * The total number of billable tokens processed by this fine tuning job. The value will be null - * if the fine-tuning job is still running. - */ - trained_tokens: safeint | null; + has_more: boolean; - /** - * For fine-tuning jobs that have `failed`, this will contain more information on the cause of the - * failure. - */ - error: { - /** A human-readable error message. */ - message?: string; // likely should be required, but spec doesn't say so. + object: "list"; +} - /** A machine-readable error code. */ - code?: string; +model ListFineTuningJobEventsResponse { + data: FineTuningJobEvent[]; - /** - * The parameter that was invalid, usually `training_file` or `validation_file`. This field - * will be null if the failure was not parameter-specific. - */ - param?: string | null; - } | null; + object: "list"; + + // TODO: The sample in the OpenAPI spec includes a `has_more` property that is not included here. } -model FineTuningEvent { - object: string; +@minValue(1) +@maxValue(50) +scalar NEpochs extends safeint; - @encode("unixTimestamp", int32) - created_at: utcDateTime; +@minValue(1) +@maxValue(256) +scalar BatchSize extends safeint; - level: string; - message: string; - data?: Record | null; - type?: "message" | "metrics"; // "default is "none"? -} +@minValueExclusive(0) +scalar LearningRateMultiplier extends float64; -/** The `FineTune` object represents a legacy fine-tune job that has been created through the API. */ -#deprecated "deprecated" -model FineTune { +@minLength(1) +@maxLength(40) +scalar SuffixString extends string; + +/* The `fine_tuning.job` object represents a fine-tuning job that has been created through the API. */ +model FineTuningJob { /** The object identifier, which can be referenced in the API endpoints. */ id: string; - /** The object type, which is always "fine-tune". */ - object: "fine-tune"; - /** The Unix timestamp (in seconds) for when the fine-tuning job was created. */ @encode("unixTimestamp", int32) created_at: utcDateTime; - /** The Unix timestamp (in seconds) for when the fine-tuning job was last updated. */ - @encode("unixTimestamp", int32) - updated_at: utcDateTime; - - /** The base model that is being fine-tuned. */ - `model`: string; - - /** The name of the fine-tuned model that is being created. */ - fine_tuned_model: string | null; - - /** The organization that owns the fine-tuning job. */ - organization_id: string; - /** - * The current status of the fine-tuning job, which can be either `created`, `running`, - * `succeeded`, `failed`, or `cancelled`. + * For fine-tuning jobs that have `failed`, this will contain more information on the cause of the + * failure. */ - status: "created" | "running" | "succeeded" | "failed" | "cancelled"; + error: { + /** A machine-readable error code. */ + code: string; - /** - * The hyperparameters used for the fine-tuning job. See the - * [fine-tuning guide](/docs/guides/legacy-fine-tuning/hyperparameters) for more details. - */ - hyperparams: { - /** - * The number of epochs to train the model for. An epoch refers to one full cycle through the - * training dataset. - */ - n_epochs: safeint; + /** A human-readable error message. */ + message: string; /** - * The batch size to use for training. The batch size is the number of training examples used to - * train a single forward and backward pass. + * The parameter that was invalid, usually `training_file` or `validation_file`. This field will + * be null if the failure was not parameter-specific. */ - batch_size: safeint; - - /** The weight to use for loss on the prompt tokens. */ - prompt_loss_weight: float64; - - /** The learning rate multiplier to use for training. */ - learning_rate_multiplier: float64; - - /** The classification metrics to compute using the validation dataset at the end of every epoch. */ - compute_classification_metrics?: boolean; - - /** The positive class to use for computing classification metrics. */ - classification_positive_class?: string; - - /** The number of classes to use for computing classification metrics. */ - classification_n_classes?: safeint; - }; - - /** The list of files used for training. */ - training_files: OpenAIFile[]; - - /** The list of files used for validation. */ - validation_files: OpenAIFile[]; - - /** The compiled results files for the fine-tuning job. */ - result_files: OpenAIFile[]; - - /** The list of events that have been observed in the lifecycle of the FineTune job. */ - events?: FineTuneEvent[]; -} - -model FineTuningJobEvent { - id: string; - object: string; - - @encode("unixTimestamp", int32) - created_at: utcDateTime; - - level: "info" | "warn" | "error"; - message: string; -} - -model FineTuneEvent { - object: string; - - @encode("unixTimestamp", int32) - created_at: utcDateTime; - - level: string; - message: string; -} + param: string | null; + } | null; -model CreateFineTuningJobRequest { /** - * The ID of an uploaded file that contains training data. - * - * See [upload file](/docs/api-reference/files/upload) for how to upload a file. - * - * Your dataset must be formatted as a JSONL file. Additionally, you must upload your file with - * the purpose `fine-tune`. - * - * See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. + * The name of the fine-tuned model that is being created. The value will be null if the + * fine-tuning job is still running. */ - training_file: string; + fine_tuned_model: string | null; /** - * The ID of an uploaded file that contains validation data. - * - * If you provide this file, the data is used to generate validation metrics periodically during - * fine-tuning. These metrics can be viewed in the fine-tuning results file. The same data should - * not be present in both train and validation files. - * - * Your dataset must be formatted as a JSONL file. You must upload your file with the purpose - * `fine-tune`. - * - * See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. + * The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be + * null if the fine-tuning job is still running. */ - validation_file?: string | null; + @encode("unixTimestamp", int32) + finished_at: utcDateTime | null; /** - * The name of the model to fine-tune. You can select one of the - * [supported models](/docs/guides/fine-tuning/what-models-can-be-fine-tuned). + * The hyperparameters used for the fine-tuning job. See the + * [fine-tuning guide](/docs/guides/fine-tuning) for more details. */ - @extension("x-oaiTypeLabel", "string") - `model`: string | "babbage-002" | "davinci-002" | "gpt-3.5-turbo"; - - /** The hyperparameters used for the fine-tuning job. */ - hyperparameters?: { + hyperparameters: { /** * The number of epochs to train the model for. An epoch refers to one full cycle through the * training dataset. + * + * "auto" decides the optimal number of epochs based on the size of the dataset. If setting the + * number manually, we support any number between 1 and 50 epochs. */ - n_epochs?: "auto" | NEpochs = "auto"; + n_epochs: "auto" | NEpochs = "auto"; }; - /** - * 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`. - */ - suffix?: SuffixString | null = null; -} - -@minValue(1) -@maxValue(50) -scalar NEpochs extends safeint; - -model ListFineTuningJobEventsResponse { - object: string; - data: FineTuningJobEvent[]; -} - -model CreateFineTuneRequest { - /** - * The ID of an uploaded file that contains training data. - * - * See [upload file](/docs/api-reference/files/upload) for how to upload a file. - * - * Your dataset must be formatted as a JSONL file, where each training example is a JSON object - * with the keys "prompt" and "completion". Additionally, you must upload your file with the - * purpose `fine-tune`. - * - * See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more - * details. - */ - training_file: string; - - /** - * The ID of an uploaded file that contains validation data. - * - * If you provide this file, the data is used to generate validation metrics periodically during - * fine-tuning. These metrics can be viewed in the - * [fine-tuning results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model). - * Your train and validation data should be mutually exclusive. - * - * Your dataset must be formatted as a JSONL file, where each validation example is a JSON object - * with the keys "prompt" and "completion". Additionally, you must upload your file with the - * purpose `fine-tune`. - * - * See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more - * details. - */ - validation_file?: string | null; - - /** - * The name of the base model to fine-tune. You can select one of "ada", "babbage", "curie", - * "davinci", or a fine-tuned model created after 2022-04-21 and before 2023-08-22. To learn more - * about these models, see the [Models](/docs/models) documentation. - */ - @extension("x-oaiTypeLabel", "string") - `model`?: string | "ada" | "babbage" | "curie" | "davinci" | null; - - /** - * The number of epochs to train the model for. An epoch refers to one full cycle through the - * training dataset. - */ - n_epochs?: safeint | null = 4; - - /** - * The batch size to use for training. The batch size is the number of training examples used to - * train a single forward and backward pass. - * - * By default, the batch size will be dynamically configured to be ~0.2% of the number of examples - * in the training set, capped at 256 - in general, we've found that larger batch sizes tend to - * work better for larger datasets. - */ - batch_size?: safeint | null = null; + /** The base model that is being fine-tuned. */ + `model`: string; - /** - * The learning rate multiplier to use for training. The fine-tuning learning rate is the original - * learning rate used for pretraining multiplied by this value. - * - * By default, the learning rate multiplier is the 0.05, 0.1, or 0.2 depending on final - * `batch_size` (larger learning rates tend to perform better with larger batch sizes). We - * recommend experimenting with values in the range 0.02 to 0.2 to see what produces the best - * results. - */ - learning_rate_multiplier?: float64 | null = null; + /** The object type, which is always "fine_tuning.job". */ + object: "fine_tuning.job"; - /** - * The weight to use for loss on the prompt tokens. This controls how much the model tries to - * learn to generate the prompt (as compared to the completion which always has a weight of 1.0), - * and can add a stabilizing effect to training when completions are short. - * - * If prompts are extremely long (relative to completions), it may make sense to reduce this - * weight so as to avoid over-prioritizing learning the prompt. - */ - prompt_loss_rate?: float64 | null = 0.01; + /** The organization that owns the fine-tuning job. */ + organization_id: string; /** - * If set, we calculate classification-specific metrics such as accuracy and F-1 score using the - * validation set at the end of every epoch. These metrics can be viewed in the - * [results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model). - * - * In order to compute classification metrics, you must provide a `validation_file`. Additionally, - * you must specify `classification_n_classes` for multiclass classification or - * `classification_positive_class` for binary classification. + * The compiled results file ID(s) for the fine-tuning job. You can retrieve the results with the + * [Files API](/docs/api-reference/files/retrieve-contents). */ - compute_classification_metrics?: boolean | null = false; + result_files: string[]; /** - * The number of classes in a classification task. - * - * This parameter is required for multiclass classification. + * The current status of the fine-tuning job, which can be either `validating_files`, `queued`, + * `running`, `succeeded`, `failed`, or `cancelled`. */ - classification_n_classes?: safeint | null = null; + status: + | "validating_files" + | "queued" + | "running" + | "succeeded" + | "failed" + | "cancelled"; /** - * The positive class in binary classification. - * - * This parameter is needed to generate precision, recall, and F1 metrics when doing binary - * classification. + * The total number of billable tokens processed by this fine-tuning job. The value will be null + * if the fine-tuning job is still running. */ - classification_positive_class?: string | null = null; + trained_tokens: safeint | null; /** - * If this is provided, we calculate F-beta scores at the specified beta values. The F-beta score - * is a generalization of F-1 score. This is only used for binary classification. - * - * With a beta of 1 (i.e. the F-1 score), precision and recall are given the same weight. A larger - * beta score puts more weight on recall and less on precision. A smaller beta score puts more - * weight on precision and less on recall. + * The file ID used for training. You can retrieve the training data with the + * [Files API](/docs/api-reference/files/retrieve-contents). */ - classification_betas?: float64[] | null = null; + training_file: string; /** - * 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 - * `ada:ft-your-org:custom-model-name-2022-02-15-04-21-04`. + * The file ID used for validation. You can retrieve the validation results with the + * [Files API](/docs/api-reference/files/retrieve-contents). */ - suffix?: SuffixString | null = null; + validation_file: string | null; } -@minLength(1) -@maxLength(40) -scalar SuffixString extends string; +/** Fine-tuning job event object */ +model FineTuningJobEvent { + id: string; -model ListFineTunesResponse { - object: string; - data: FineTune[]; -} + @encode("unixTimestamp", int32) + created_at: utcDateTime; -model ListFineTuneEventsResponse { - object: string; - data: FineTuneEvent[]; -} + level: "info" | "warn" | "error"; -model ListPaginatedFineTuningJobsResponse { - object: string; - data: FineTuningJob[]; - has_more: boolean; -} + message: string; + + object: "fine_tuning.job.event"; +} \ No newline at end of file diff --git a/fine-tuning/operations.tsp b/fine-tuning/operations.tsp index f37e90cc7..21c08b161 100644 --- a/fine-tuning/operations.tsp +++ b/fine-tuning/operations.tsp @@ -49,6 +49,7 @@ interface FineTuning { [Learn more about fine-tuning](/docs/guides/fine-tuning) """) retrieveFineTuningJob( + /** The ID of the fine-tuning job. */ @path fine_tuning_job_id: string, ): FineTuningJob | ErrorResponse; diff --git a/tsp-output/@typespec/openapi3/openapi.yaml b/tsp-output/@typespec/openapi3/openapi.yaml index bc739d4eb..69b1f6687 100644 --- a/tsp-output/@typespec/openapi3/openapi.yaml +++ b/tsp-output/@typespec/openapi3/openapi.yaml @@ -714,6 +714,7 @@ paths: - name: fine_tuning_job_id in: path required: true + description: The ID of the fine-tuning job. schema: type: string responses: @@ -1916,6 +1917,11 @@ components: type: number format: double description: The probability of no speech detection within this audio segment. + BatchSize: + type: integer + format: int64 + minimum: 1 + maximum: 256 ChatCompletionFunctionCallOption: type: object required: @@ -3135,161 +3141,24 @@ components: [Fine-tuning](/docs/api-reference/fine-tuning) and "assistants" for [Assistants](/docs/api-reference/assistants) and [Messages](/docs/api-reference/messages). This allows us to validate the format of the uploaded file is correct for fine-tuning. - CreateFineTuneRequest: + CreateFineTuningJobRequest: type: object required: + - model - training_file properties: - training_file: - type: string - description: |- - The ID of an uploaded file that contains training data. - - See [upload file](/docs/api-reference/files/upload) for how to upload a file. - - Your dataset must be formatted as a JSONL file, where each training example is a JSON object - with the keys "prompt" and "completion". Additionally, you must upload your file with the - purpose `fine-tune`. - - See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more - details. - validation_file: - type: string - nullable: true - description: |- - The ID of an uploaded file that contains validation data. - - If you provide this file, the data is used to generate validation metrics periodically during - fine-tuning. These metrics can be viewed in the - [fine-tuning results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model). - Your train and validation data should be mutually exclusive. - - Your dataset must be formatted as a JSONL file, where each validation example is a JSON object - with the keys "prompt" and "completion". Additionally, you must upload your file with the - purpose `fine-tune`. - - See the [fine-tuning guide](/docs/guides/legacy-fine-tuning/creating-training-data) for more - details. model: anyOf: - type: string - type: string enum: - - ada - - babbage - - curie - - davinci - nullable: true + - babbage-002 + - davinci-002 + - gpt-3.5-turbo description: |- - The name of the base model to fine-tune. You can select one of "ada", "babbage", "curie", - "davinci", or a fine-tuned model created after 2022-04-21 and before 2023-08-22. To learn more - about these models, see the [Models](/docs/models) documentation. + The name of the model to fine-tune. You can select one of the + [supported models](/docs/guides/fine-tuning/what-models-can-be-fine-tuned). x-oaiTypeLabel: string - n_epochs: - type: integer - format: int64 - nullable: true - description: |- - The number of epochs to train the model for. An epoch refers to one full cycle through the - training dataset. - default: 4 - batch_size: - type: integer - format: int64 - nullable: true - description: |- - The batch size to use for training. The batch size is the number of training examples used to - train a single forward and backward pass. - - By default, the batch size will be dynamically configured to be ~0.2% of the number of examples - in the training set, capped at 256 - in general, we've found that larger batch sizes tend to - work better for larger datasets. - default: null - learning_rate_multiplier: - type: number - format: double - nullable: true - description: |- - The learning rate multiplier to use for training. The fine-tuning learning rate is the original - learning rate used for pretraining multiplied by this value. - - By default, the learning rate multiplier is the 0.05, 0.1, or 0.2 depending on final - `batch_size` (larger learning rates tend to perform better with larger batch sizes). We - recommend experimenting with values in the range 0.02 to 0.2 to see what produces the best - results. - default: null - prompt_loss_rate: - type: number - format: double - nullable: true - description: |- - The weight to use for loss on the prompt tokens. This controls how much the model tries to - learn to generate the prompt (as compared to the completion which always has a weight of 1.0), - and can add a stabilizing effect to training when completions are short. - - If prompts are extremely long (relative to completions), it may make sense to reduce this - weight so as to avoid over-prioritizing learning the prompt. - default: 0.01 - compute_classification_metrics: - type: boolean - nullable: true - description: |- - If set, we calculate classification-specific metrics such as accuracy and F-1 score using the - validation set at the end of every epoch. These metrics can be viewed in the - [results file](/docs/guides/legacy-fine-tuning/analyzing-your-fine-tuned-model). - - In order to compute classification metrics, you must provide a `validation_file`. Additionally, - you must specify `classification_n_classes` for multiclass classification or - `classification_positive_class` for binary classification. - default: false - classification_n_classes: - type: integer - format: int64 - nullable: true - description: |- - The number of classes in a classification task. - - This parameter is required for multiclass classification. - default: null - classification_positive_class: - type: string - nullable: true - description: |- - The positive class in binary classification. - - This parameter is needed to generate precision, recall, and F1 metrics when doing binary - classification. - default: null - classification_betas: - type: array - items: - type: number - format: double - nullable: true - description: |- - If this is provided, we calculate F-beta scores at the specified beta values. The F-beta score - is a generalization of F-1 score. This is only used for binary classification. - - With a beta of 1 (i.e. the F-1 score), precision and recall are given the same weight. A larger - beta score puts more weight on recall and less on precision. A smaller beta score puts more - weight on precision and less on recall. - default: null - suffix: - oneOf: - - $ref: '#/components/schemas/SuffixString' - nullable: true - description: |- - 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 - `ada:ft-your-org:custom-model-name-2022-02-15-04-21-04`. - default: null - CreateFineTuningJobRequest: - type: object - required: - - training_file - - model - properties: training_file: type: string description: |- @@ -3301,35 +3170,33 @@ components: the purpose `fine-tune`. See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. - validation_file: - type: string - nullable: true - description: |- - The ID of an uploaded file that contains validation data. - - If you provide this file, the data is used to generate validation metrics periodically during - fine-tuning. These metrics can be viewed in the fine-tuning results file. The same data should - not be present in both train and validation files. - - Your dataset must be formatted as a JSONL file. You must upload your file with the purpose - `fine-tune`. - - See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. - model: - anyOf: - - type: string - - type: string - enum: - - babbage-002 - - davinci-002 - - gpt-3.5-turbo - description: |- - The name of the model to fine-tune. You can select one of the - [supported models](/docs/guides/fine-tuning/what-models-can-be-fine-tuned). - x-oaiTypeLabel: string hyperparameters: type: object properties: + batch_size: + anyOf: + - type: string + enum: + - auto + - low + - high + - $ref: '#/components/schemas/BatchSize' + description: |- + Number of examples in each batch. A larger batch size means that model parameters are + updated less frequently, but with lower variance. + default: auto + learning_rate_multiplier: + anyOf: + - type: string + enum: + - auto + - low + - high + - $ref: '#/components/schemas/LearningRateMultiplier' + description: |- + Scaling factor for the learning rate. A smaller learning rate may be useful to avoid + overfitting. + default: auto n_epochs: anyOf: - type: string @@ -3353,6 +3220,20 @@ components: For example, a `suffix` of "custom-model-name" would produce a model name like `ft:gpt-3.5-turbo:openai:custom-model-name:7p4lURel`. default: null + validation_file: + type: string + nullable: true + description: |- + The ID of an uploaded file that contains validation data. + + If you provide this file, the data is used to generate validation metrics periodically during + fine-tuning. These metrics can be viewed in the fine-tuning results file. The same data should + not be present in both train and validation files. + + Your dataset must be formatted as a JSONL file. You must upload your file with the purpose + `fine-tune`. + + See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. CreateImageEditRequestMultiPart: type: object required: @@ -4238,238 +4119,67 @@ components: properties: error: $ref: '#/components/schemas/Error' - FineTune: + FineTuningJob: type: object required: - id - - object - created_at - - updated_at - - model + - error - fine_tuned_model + - finished_at + - hyperparameters + - model + - object - organization_id - - status - - hyperparams - - training_files - - validation_files - result_files + - status + - trained_tokens + - training_file + - validation_file properties: id: type: string description: The object identifier, which can be referenced in the API endpoints. - object: - type: string - enum: - - fine-tune - - fine-tune-results - - assistants - - assistants_output - description: The object type, which is always "fine-tune". created_at: type: integer format: unixtime description: The Unix timestamp (in seconds) for when the fine-tuning job was created. - updated_at: - type: integer - format: unixtime - description: The Unix timestamp (in seconds) for when the fine-tuning job was last updated. - model: - type: string - description: The base model that is being fine-tuned. - fine_tuned_model: - type: string - nullable: true - description: The name of the fine-tuned model that is being created. - organization_id: - type: string - description: The organization that owns the fine-tuning job. - status: - type: string - enum: - - created - - pending - - running - - succeeded - - failed - - cancelled - - running - - succeeded - - failed - - cancelled - description: |- - The current status of the fine-tuning job, which can be either `created`, `running`, - `succeeded`, `failed`, or `cancelled`. - hyperparams: + error: type: object properties: - n_epochs: - type: integer - format: int64 - description: |- - The number of epochs to train the model for. An epoch refers to one full cycle through the - training dataset. - batch_size: - type: integer - format: int64 - description: |- - The batch size to use for training. The batch size is the number of training examples used to - train a single forward and backward pass. - prompt_loss_weight: - type: number - format: double - description: The weight to use for loss on the prompt tokens. - learning_rate_multiplier: - type: number - format: double - description: The learning rate multiplier to use for training. - compute_classification_metrics: - type: boolean - description: The classification metrics to compute using the validation dataset at the end of every epoch. - classification_positive_class: + code: + type: string + description: A machine-readable error code. + message: + type: string + description: A human-readable error message. + param: type: string - description: The positive class to use for computing classification metrics. - classification_n_classes: - type: integer - format: int64 - description: The number of classes to use for computing classification metrics. + nullable: true + description: |- + The parameter that was invalid, usually `training_file` or `validation_file`. This field will + be null if the failure was not parameter-specific. required: - - n_epochs - - batch_size - - prompt_loss_weight - - learning_rate_multiplier - description: |- - The hyperparameters used for the fine-tuning job. See the - [fine-tuning guide](/docs/guides/legacy-fine-tuning/hyperparameters) for more details. - training_files: - type: array - items: - $ref: '#/components/schemas/OpenAIFile' - description: The list of files used for training. - validation_files: - type: array - items: - $ref: '#/components/schemas/OpenAIFile' - description: The list of files used for validation. - result_files: - type: array - items: - $ref: '#/components/schemas/OpenAIFile' - description: The compiled results files for the fine-tuning job. - events: - type: array - items: - $ref: '#/components/schemas/FineTuneEvent' - description: The list of events that have been observed in the lifecycle of the FineTune job. - description: The `FineTune` object represents a legacy fine-tune job that has been created through the API. - deprecated: true - FineTuneEvent: - type: object - required: - - object - - created_at - - level - - message - properties: - object: - type: string - created_at: - type: integer - format: unixtime - level: - type: string - message: - type: string - FineTuningEvent: - type: object - required: - - object - - created_at - - level - - message - properties: - object: - type: string - created_at: - type: integer - format: unixtime - level: - type: string - message: - type: string - data: - type: object - additionalProperties: {} - nullable: true - type: - type: string - enum: + - code - message - - metrics - FineTuningJob: - type: object - required: - - id - - object - - created_at - - finished_at - - model - - fine_tuned_model - - organization_id - - status - - hyperparameters - - training_file - - validation_file - - result_files - - trained_tokens - - error - properties: - id: - type: string - description: The object identifier, which can be referenced in the API endpoints. - object: - type: string - enum: - - fine_tuning.job - description: The object type, which is always "fine_tuning.job". - created_at: - type: integer - format: unixtime - description: The Unix timestamp (in seconds) for when the fine-tuning job was created. - finished_at: - type: string - format: date-time + - param nullable: true description: |- - The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be - null if the fine-tuning job is still running. - model: - type: string - description: The base model that is being fine-tuned. + For fine-tuning jobs that have `failed`, this will contain more information on the cause of the + failure. fine_tuned_model: type: string nullable: true description: |- The name of the fine-tuned model that is being created. The value will be null if the fine-tuning job is still running. - organization_id: - type: string - description: The organization that owns the fine-tuning job. - status: + finished_at: type: string - enum: - - created - - pending - - running - - succeeded - - failed - - cancelled - - running - - succeeded - - failed - - cancelled + format: date-time + nullable: true description: |- - The current status of the fine-tuning job, which can be either `created`, `pending`, `running`, - `succeeded`, `failed`, or `cancelled`. + The Unix timestamp (in seconds) for when the fine-tuning job was finished. The value will be + null if the fine-tuning job is still running. hyperparameters: type: object properties: @@ -4485,23 +4195,25 @@ components: The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset. - "Auto" decides the optimal number of epochs based on the size of the dataset. If setting the + "auto" decides the optimal number of epochs based on the size of the dataset. If setting the number manually, we support any number between 1 and 50 epochs. default: auto + required: + - n_epochs description: |- The hyperparameters used for the fine-tuning job. See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. - training_file: + model: type: string - description: |- - The file ID used for training. You can retrieve the training data with the - [Files API](/docs/api-reference/files/retrieve-contents). - validation_file: + description: The base model that is being fine-tuned. + object: type: string - nullable: true - description: |- - The file ID used for validation. You can retrieve the validation results with the - [Files API](/docs/api-reference/files/retrieve-contents). + enum: + - fine_tuning.job + description: The object type, which is always "fine_tuning.job". + organization_id: + type: string + description: The organization that owns the fine-tuning job. result_files: type: array items: @@ -4509,45 +4221,47 @@ components: description: |- The compiled results file ID(s) for the fine-tuning job. You can retrieve the results with the [Files API](/docs/api-reference/files/retrieve-contents). + status: + type: string + enum: + - validating_files + - queued + - running + - succeeded + - failed + - cancelled + description: |- + The current status of the fine-tuning job, which can be either `validating_files`, `queued`, + `running`, `succeeded`, `failed`, or `cancelled`. trained_tokens: type: integer format: int64 nullable: true description: |- - The total number of billable tokens processed by this fine tuning job. The value will be null + The total number of billable tokens processed by this fine-tuning job. The value will be null if the fine-tuning job is still running. - error: - type: object - properties: - message: - type: string - description: A human-readable error message. - code: - type: string - description: A machine-readable error code. - param: - type: string - nullable: true - description: |- - The parameter that was invalid, usually `training_file` or `validation_file`. This field - will be null if the failure was not parameter-specific. + training_file: + type: string + description: |- + The file ID used for training. You can retrieve the training data with the + [Files API](/docs/api-reference/files/retrieve-contents). + validation_file: + type: string nullable: true description: |- - For fine-tuning jobs that have `failed`, this will contain more information on the cause of the - failure. + The file ID used for validation. You can retrieve the validation results with the + [Files API](/docs/api-reference/files/retrieve-contents). FineTuningJobEvent: type: object required: - id - - object - created_at - level - message + - object properties: id: type: string - object: - type: string created_at: type: integer format: unixtime @@ -4559,6 +4273,11 @@ components: - error message: type: string + object: + type: string + enum: + - fine_tuning.job.event + description: Fine-tuning job event object FunctionObject: type: object required: @@ -4618,6 +4337,11 @@ components: type: array items: $ref: '#/components/schemas/Image' + LearningRateMultiplier: + type: number + format: double + minimum: 0 + exclusiveMinimum: true ListAssistantFilesResponse: type: object required: @@ -4678,42 +4402,20 @@ components: type: string enum: - list - ListFineTuneEventsResponse: + ListFineTuningJobEventsResponse: type: object required: - - object - data - properties: - object: - type: string - data: - type: array - items: - $ref: '#/components/schemas/FineTuneEvent' - ListFineTunesResponse: - type: object - required: - object - - data properties: - object: - type: string data: type: array items: - $ref: '#/components/schemas/FineTune' - ListFineTuningJobEventsResponse: - type: object - required: - - object - - data - properties: + $ref: '#/components/schemas/FineTuningJobEvent' object: type: string - data: - type: array - items: - $ref: '#/components/schemas/FineTuningJobEvent' + enum: + - list ListMessageFilesResponse: type: object required: @@ -4782,18 +4484,20 @@ components: ListPaginatedFineTuningJobsResponse: type: object required: - - object - data - has_more + - object properties: - object: - type: string data: type: array items: $ref: '#/components/schemas/FineTuningJob' has_more: type: boolean + object: + type: string + enum: + - list ListRunStepsResponse: type: object required: From a7abb18bd32f792381a2fbd8958d2449c172c64c Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado <45773732+joseharriaga@users.noreply.github.com> Date: Fri, 8 Mar 2024 16:38:53 -0800 Subject: [PATCH 25/50] Expose protocol methods publicly (#10) * Exposed missing protocol methods publicly * Removed protocol methods that use multipart/form-data for now (`TranscribeAudio`, `TranslateAudio`, `UploadFile`, `GenerateImageEdit`, and `GenerateImageVariation`) * Removed `[EditorBrowsable(EditorBrowsableState.Never)]` attribute from existing protocol methods that do not have a convenience method counterpart * Renamed `RequestOptions` parameter from "context" to "options" in existing protocol methods * Added missing `async` keyword to existing protocol methods when applicable (also `await` and `.ConfigureAwait(false)`) * Added doc comments to protocol methods * Created the `FineTuningClient` to organize the library in a way that aligns more closely to OpenAI's REST API and documentation * Made a small fix to the fine-tuning TypeSpec (the `limit` query parameter should be defined as an `int32`) --- .../Assistants/AssistantClient.Protocol.cs | 515 ++++++++++-------- .../src/Custom/Assistants/AssistantClient.cs | 13 +- .../src/Custom/Audio/AudioClient.Protocol.cs | 19 + .dotnet/src/Custom/Audio/AudioClient.cs | 35 +- .../src/Custom/Chat/ChatClient.Protocol.cs | 20 + .dotnet/src/Custom/Chat/ChatClient.cs | 13 +- .../Embeddings/EmbeddingClient.Protocol.cs | 19 + .../src/Custom/Embeddings/EmbeddingClient.cs | 17 +- .../src/Custom/Files/FileClient.Protocol.cs | 49 ++ .dotnet/src/Custom/Files/FileClient.cs | 74 +-- .../FineTuning/FineTuningClient.Protocol.cs | 74 +++ .../src/Custom/FineTuning/FineTuningClient.cs | 90 +++ .../src/Custom/Images/ImageClient.Protocol.cs | 19 + .dotnet/src/Custom/Images/ImageClient.cs | 16 +- .../LegacyCompletionClient.Protocol.cs | 16 + .../LegacyCompletionClient.cs | 14 +- .../Models/ModelManagementClient.Protocol.cs | 39 ++ .../Custom/Models/ModelManagementClient.cs | 67 +-- .../Moderations/ModerationClient.Protocol.cs | 16 + .../Custom/Moderations/ModerationClient.cs | 18 +- .dotnet/src/Custom/OpenAIClient.cs | 31 +- .dotnet/src/Generated/FineTuning.cs | 14 +- fine-tuning/operations.tsp | 4 +- 23 files changed, 691 insertions(+), 501 deletions(-) create mode 100644 .dotnet/src/Custom/Audio/AudioClient.Protocol.cs create mode 100644 .dotnet/src/Custom/Chat/ChatClient.Protocol.cs create mode 100644 .dotnet/src/Custom/Embeddings/EmbeddingClient.Protocol.cs create mode 100644 .dotnet/src/Custom/Files/FileClient.Protocol.cs create mode 100644 .dotnet/src/Custom/FineTuning/FineTuningClient.Protocol.cs create mode 100644 .dotnet/src/Custom/FineTuning/FineTuningClient.cs create mode 100644 .dotnet/src/Custom/Images/ImageClient.Protocol.cs create mode 100644 .dotnet/src/Custom/LegacyCompletions/LegacyCompletionClient.Protocol.cs create mode 100644 .dotnet/src/Custom/Models/ModelManagementClient.Protocol.cs create mode 100644 .dotnet/src/Custom/Moderations/ModerationClient.Protocol.cs diff --git a/.dotnet/src/Custom/Assistants/AssistantClient.Protocol.cs b/.dotnet/src/Custom/Assistants/AssistantClient.Protocol.cs index a0f55c3e0..1ac71c23b 100644 --- a/.dotnet/src/Custom/Assistants/AssistantClient.Protocol.cs +++ b/.dotnet/src/Custom/Assistants/AssistantClient.Protocol.cs @@ -1,5 +1,4 @@ using System.ClientModel; -using System.ClientModel; using System.ClientModel.Primitives; using System.ComponentModel; using System.Threading.Tasks; @@ -8,219 +7,246 @@ namespace OpenAI.Assistants; public partial class AssistantClient { - + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult CreateAssistant(BinaryContent content, RequestOptions context = null) - { - return Shim.CreateAssistant(content, context); - } + public virtual ClientResult CreateAssistant( + BinaryContent content, + RequestOptions options = null) + => Shim.CreateAssistant(content, options); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task CreateAssistantAsync(BinaryContent content, RequestOptions context = null) - { - return Shim.CreateAssistantAsync(content, context); - } + public virtual async Task CreateAssistantAsync( + BinaryContent content, + RequestOptions options = null) + => await Shim.CreateAssistantAsync(content, options).ConfigureAwait(false); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult GetAssistant(string assistantId, RequestOptions context) - { - return Shim.GetAssistant(assistantId, context); - } + public virtual ClientResult GetAssistant( + string assistantId, + RequestOptions options) + => Shim.GetAssistant(assistantId, options); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task GetAssistantAsync(string assistantId, RequestOptions context) - { - return Shim.GetAssistantAsync(assistantId, context); - } + public virtual async Task GetAssistantAsync( + string assistantId, + RequestOptions options) + => await Shim.GetAssistantAsync(assistantId, options).ConfigureAwait(false); + /// [EditorBrowsable(EditorBrowsableState.Never)] public virtual ClientResult GetAssistants( int? maxResults, string createdSortOrder, string previousAssistantId, string subsequentAssistantId, - RequestOptions context) - { - return Shim.GetAssistants(maxResults, createdSortOrder, previousAssistantId, subsequentAssistantId, context); - } + RequestOptions options) + => Shim.GetAssistants(maxResults, createdSortOrder, previousAssistantId, subsequentAssistantId, options); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task GetAssistantsAsync( + public virtual async Task GetAssistantsAsync( int? maxResults, string createdSortOrder, string previousAssistantId, string subsequentAssistantId, - RequestOptions context) - { - return Shim.GetAssistantsAsync(maxResults, createdSortOrder, previousAssistantId, subsequentAssistantId, context); - } + RequestOptions options) + => await Shim.GetAssistantsAsync(maxResults, createdSortOrder, previousAssistantId, subsequentAssistantId, options).ConfigureAwait(false); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult ModifyAssistant(string assistantId, BinaryContent content, RequestOptions context = null) - { - return Shim.ModifyAssistant(assistantId, content, context); - } + public virtual ClientResult ModifyAssistant( + string assistantId, + BinaryContent content, + RequestOptions options = null) + => Shim.ModifyAssistant(assistantId, content, options); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task ModifyAssistantAsync(string assistantId, BinaryContent content, RequestOptions context = null) - { - return Shim.ModifyAssistantAsync(assistantId, content, context); - } - + public virtual async Task ModifyAssistantAsync( + string assistantId, + BinaryContent content, + RequestOptions options = null) + => await Shim.ModifyAssistantAsync(assistantId, content, options).ConfigureAwait(false); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult DeleteAssistant(string assistantId, RequestOptions context) - { - return Shim.DeleteAssistant(assistantId, context); - } + public virtual ClientResult DeleteAssistant( + string assistantId, + RequestOptions options) + => Shim.DeleteAssistant(assistantId, options); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task DeleteAssistantAsync(string assistantId, RequestOptions context) - { - return Shim.DeleteAssistantAsync(assistantId, context); - } + public virtual async Task DeleteAssistantAsync( + string assistantId, + RequestOptions options) + => await Shim.DeleteAssistantAsync(assistantId, options).ConfigureAwait(false); + /// [EditorBrowsable(EditorBrowsableState.Never)] public virtual ClientResult CreateAssistantFileAssociation( string assistantId, BinaryContent content, - RequestOptions context = null) - { - return Shim.CreateAssistantFile(assistantId, content, context); - } + RequestOptions options = null) + => Shim.CreateAssistantFile(assistantId, content, options); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task CreateAssistantFileAssociationAsync( + public virtual async Task CreateAssistantFileAssociationAsync( string assistantId, BinaryContent content, - RequestOptions context = null) - { - return Shim.CreateAssistantFileAsync(assistantId, content, context); - } - + RequestOptions options = null) + => await Shim.CreateAssistantFileAsync(assistantId, content, options).ConfigureAwait(false); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult GetAssistantFileAssociation(string assistantId, string fileId, RequestOptions context) - { - return Shim.GetAssistantFile(assistantId, fileId, context); - } + public virtual ClientResult GetAssistantFileAssociation( + string assistantId, + string fileId, + RequestOptions options) + => Shim.GetAssistantFile(assistantId, fileId, options); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task GetAssistantFileAssociationAsync(string assistantId, string fileId, RequestOptions context) - { - return Shim.GetAssistantFileAsync(assistantId, fileId, context); - } + public virtual async Task GetAssistantFileAssociationAsync( + string assistantId, + string fileId, + RequestOptions options) + => await Shim.GetAssistantFileAsync(assistantId, fileId, options).ConfigureAwait(false); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult GetAssistantFileAssociations( + public virtual ClientResult GetAssistantFileAssociation( string assistantId, int? maxResults, string createdSortOrder, string previousId, string subsequentId, - RequestOptions context) - { - return Shim.GetAssistantFiles(assistantId, maxResults, createdSortOrder, previousId, subsequentId, context); - } + RequestOptions options) + => Shim.GetAssistantFiles(assistantId, maxResults, createdSortOrder, previousId, subsequentId, options); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task GetAssistantFileAssociationsAsync( + public virtual async Task GetAssistantFileAssociationAsync( string assistantId, int? maxResults, string createdSortOrder, string previousId, string subsequentId, - RequestOptions context) - { - return Shim - .GetAssistantFilesAsync(assistantId, maxResults, createdSortOrder, previousId, subsequentId, context); - } + RequestOptions options) + => await Shim.GetAssistantFilesAsync(assistantId, maxResults, createdSortOrder, previousId, subsequentId, options).ConfigureAwait(false); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult RemoveAssistantFileAssociation(string assistantId, string fileId, RequestOptions context) - { - return Shim.DeleteAssistantFile(assistantId, fileId, context); - } + public virtual ClientResult RemoveAssistantFileAssociation( + string assistantId, + string fileId, + RequestOptions options) + => Shim.DeleteAssistantFile(assistantId, fileId, options); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task RemoveAssistantFileAssociationAsync(string assistantId, string fileId, RequestOptions context) - { - return Shim.DeleteAssistantFileAsync(assistantId, fileId, context); - } + public virtual async Task RemoveAssistantFileAssociationAsync( + string assistantId, + string fileId, + RequestOptions options) + => await Shim.DeleteAssistantFileAsync(assistantId, fileId, options).ConfigureAwait(false); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult CreateThread(BinaryContent content, RequestOptions context = null) - { - return ThreadShim.CreateThread(content, context); - } + public virtual ClientResult CreateThread( + BinaryContent content, + RequestOptions options = null) + => ThreadShim.CreateThread(content, options); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task CreateThreadAsync(BinaryContent content, RequestOptions context = null) - { - return ThreadShim.CreateThreadAsync(content, context); - } + public virtual async Task CreateThreadAsync( + BinaryContent content, + RequestOptions options = null) + => await ThreadShim.CreateThreadAsync(content, options).ConfigureAwait(false); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult GetThread(string threadId, RequestOptions context) - { - return ThreadShim.GetThread(threadId, context); - } + public virtual ClientResult GetThread( + string threadId, + RequestOptions options) + => ThreadShim.GetThread(threadId, options); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task GetThreadAsync(string threadId, RequestOptions context) - { - return ThreadShim.GetThreadAsync(threadId, context); - } + public virtual async Task GetThreadAsync( + string threadId, + RequestOptions options) + => await ThreadShim.GetThreadAsync(threadId, options).ConfigureAwait(false); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult ModifyThread(string threadId, BinaryContent content, RequestOptions context = null) - { - return ThreadShim.ModifyThread(threadId, content, context); - } + public virtual ClientResult ModifyThread( + string threadId, + BinaryContent content, + RequestOptions options = null) + => ThreadShim.ModifyThread(threadId, content, options); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task ModifyThreadAsync(string threadId, BinaryContent content, RequestOptions context = null) - { - return ThreadShim.ModifyThreadAsync(threadId, content, context); - } + public virtual async Task ModifyThreadAsync( + string threadId, + BinaryContent content, + RequestOptions options = null) + => await ThreadShim.ModifyThreadAsync(threadId, content, options).ConfigureAwait(false); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult DeleteThread(string threadId, RequestOptions context) - { - return ThreadShim.DeleteThread(threadId, context); - } + public virtual ClientResult DeleteThread( + string threadId, + RequestOptions options) + => ThreadShim.DeleteThread(threadId, options); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task DeleteThreadAsync(string threadId, RequestOptions context) - { - return ThreadShim.DeleteThreadAsync(threadId, context); - } + public virtual async Task DeleteThreadAsync( + string threadId, + RequestOptions options) + => await ThreadShim.DeleteThreadAsync(threadId, options).ConfigureAwait(false); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult CreateMessage(string threadId, BinaryContent content, RequestOptions context = null) - { - return MessageShim.CreateMessage(threadId, content, context); - } + public virtual ClientResult CreateMessage( + string threadId, + BinaryContent content, + RequestOptions options = null) + => MessageShim.CreateMessage(threadId, content, options); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task CreateMessageAsync(string threadId, BinaryContent content, RequestOptions context = null) - { - return MessageShim.CreateMessageAsync(threadId, content, context); - } + public virtual async Task CreateMessageAsync( + string threadId, + BinaryContent content, + RequestOptions options = null) + => await MessageShim.CreateMessageAsync(threadId, content, options).ConfigureAwait(false); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult GetMessage(string threadId, string messageId, RequestOptions context) - { - return MessageShim.GetMessage(threadId, messageId, context); - } + public virtual ClientResult GetMessage( + string threadId, + string messageId, + RequestOptions options) + => MessageShim.GetMessage(threadId, messageId, options); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task GetMessageAsync(string threadId, string messageId, RequestOptions context) - { - return MessageShim.GetMessageAsync(threadId, messageId, context); - } + public virtual async Task GetMessageAsync( + string threadId, + string messageId, + RequestOptions options) + => await MessageShim.GetMessageAsync(threadId, messageId, options).ConfigureAwait(false); + /// [EditorBrowsable(EditorBrowsableState.Never)] public virtual ClientResult GetMessages( string threadId, @@ -228,41 +254,39 @@ public virtual ClientResult GetMessages( string createdSortOrder, string previousMessageId, string subsequentMessageId, - RequestOptions context) - { - return MessageShim - .GetMessages(threadId, maxResults, createdSortOrder, previousMessageId, subsequentMessageId, context); - } + RequestOptions options) + => MessageShim.GetMessages(threadId, maxResults, createdSortOrder, previousMessageId, subsequentMessageId, options); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task GetMessagesAsync( + public virtual async Task GetMessagesAsync( string threadId, int? maxResults, string createdSortOrder, string previousMessageId, string subsequentMessageId, - RequestOptions context) - { - return MessageShim - .GetMessagesAsync(threadId, maxResults, createdSortOrder, previousMessageId, subsequentMessageId, context); - } + RequestOptions options) + => await MessageShim.GetMessagesAsync(threadId, maxResults, createdSortOrder, previousMessageId, subsequentMessageId, options).ConfigureAwait(false); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult GetMessageFileAssociation(string threadId, string messageId, string fileId, RequestOptions context) - { - return MessageShim.GetMessageFile(threadId, messageId, fileId, context); - } + public virtual ClientResult GetMessageFileAssociation( + string threadId, + string messageId, + string fileId, + RequestOptions options) + => MessageShim.GetMessageFile(threadId, messageId, fileId, options); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task GetMessageFileAssociationAsync( + public virtual async Task GetMessageFileAssociationAsync( string threadId, string messageId, string fileId, - RequestOptions context) - { - return MessageShim.GetMessageFileAsync(threadId, messageId, fileId, context); - } + RequestOptions options) + => await MessageShim.GetMessageFileAsync(threadId, messageId, fileId, options).ConfigureAwait(false); + /// [EditorBrowsable(EditorBrowsableState.Never)] public virtual ClientResult GetMessageFileAssociations( string threadId, @@ -271,62 +295,68 @@ public virtual ClientResult GetMessageFileAssociations( string createdSortOrder, string previousId , string subsequentId, - RequestOptions context) - { - return MessageShim - .GetMessageFiles(threadId, messageId, maxResults, createdSortOrder, previousId, subsequentId, context); - } + RequestOptions options) + => MessageShim.GetMessageFiles(threadId, messageId, maxResults, createdSortOrder, previousId, subsequentId, options); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task GetMessageFileAssociationsAsync( + public virtual async Task GetMessageFileAssociationsAsync( string threadId, string messageId, int? maxResults, string createdSortOrder, string previousId, string subsequentId, - RequestOptions context) - { - return MessageShim - .GetMessageFilesAsync(threadId, messageId, maxResults, createdSortOrder, previousId, subsequentId, context); - } + RequestOptions options) + => await MessageShim.GetMessageFilesAsync(threadId, messageId, maxResults, createdSortOrder, previousId, subsequentId, options).ConfigureAwait(false); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult CreateRun(string threadId, BinaryContent content, RequestOptions context = null) - { - return RunShim.CreateRun(threadId, content, context); - } + public virtual ClientResult CreateRun( + string threadId, + BinaryContent content, + RequestOptions options = null) + => RunShim.CreateRun(threadId, content, options); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task CreateRunAsync(string threadId, BinaryContent content, RequestOptions context = null) - { - return RunShim.CreateRunAsync(threadId, content, context); - } + public virtual async Task CreateRunAsync( + string threadId, + BinaryContent content, + RequestOptions options = null) + => await RunShim.CreateRunAsync(threadId, content, options).ConfigureAwait(false); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult CreateThreadAndRun(BinaryContent content, RequestOptions context = null) - { - return RunShim.CreateThreadAndRun(content, context); - } + public virtual ClientResult CreateThreadAndRun( + BinaryContent content, + RequestOptions options = null) + => RunShim.CreateThreadAndRun(content, options); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task CreateThreadAndRunAsync(BinaryContent content, RequestOptions context = null) - { - return RunShim.CreateThreadAndRunAsync(content, context); - } + public virtual async Task CreateThreadAndRunAsync( + BinaryContent content, + RequestOptions options = null) + => await RunShim.CreateThreadAndRunAsync(content, options).ConfigureAwait(false); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult GetRun(string threadId, string runId, RequestOptions context) - { - return RunShim.GetRun(threadId, runId, context); - } + public virtual ClientResult GetRun( + string threadId, + string runId, + RequestOptions options) + => RunShim.GetRun(threadId, runId, options); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task GetRunAsync(string threadId, string runId, RequestOptions context) - { - return RunShim.GetRunAsync(threadId, runId, context); - } + public virtual async Task GetRunAsync( + string threadId, + string runId, + RequestOptions options) + => await RunShim.GetRunAsync(threadId, runId, options).ConfigureAwait(false); + /// [EditorBrowsable(EditorBrowsableState.Never)] public virtual ClientResult GetRuns( string threadId, @@ -334,73 +364,89 @@ public virtual ClientResult GetRuns( string createdSortOrder, string previousRunId, string subsequentRunId, - RequestOptions context) - { - return RunShim.GetRuns(threadId, maxResults, createdSortOrder, previousRunId, subsequentRunId, context); - } + RequestOptions options) + => RunShim.GetRuns(threadId, maxResults, createdSortOrder, previousRunId, subsequentRunId, options); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task GetRunsAsync( + public virtual async Task GetRunsAsync( string threadId, int? maxResults, string createdSortOrder, string previousRunId, string subsequentRunId, - RequestOptions context) - { - return RunShim.GetRunsAsync(threadId, maxResults, createdSortOrder, previousRunId, subsequentRunId, context); - } + RequestOptions options) + => await RunShim.GetRunsAsync(threadId, maxResults, createdSortOrder, previousRunId, subsequentRunId, options).ConfigureAwait(false); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult ModifyRun(string threadId, string runId, BinaryContent content, RequestOptions context = null) - { - return RunShim.ModifyRun(threadId, runId, content, context); - } + public virtual ClientResult ModifyRun( + string threadId, + string runId, + BinaryContent content, + RequestOptions options = null) + => RunShim.ModifyRun(threadId, runId, content, options); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task ModifyRunAsync( + public virtual async Task ModifyRunAsync( string threadId, string runId, BinaryContent content, - RequestOptions context = null) - { - return RunShim.ModifyRunAsync(threadId, runId, content, context); - } + RequestOptions options = null) + => await RunShim.ModifyRunAsync(threadId, runId, content, options).ConfigureAwait(false); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult CancelRun(string threadId, string runId, RequestOptions context) - { - return RunShim.CancelRun(threadId, runId, context); - } + public virtual ClientResult CancelRun( + string threadId, + string runId, + RequestOptions options) + => RunShim.CancelRun(threadId, runId, options); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task CancelRunAsync(string threadId, string runId, RequestOptions context) - { - return RunShim.CancelRunAsync(threadId, runId, context); - } + public virtual async Task CancelRunAsync( + string threadId, + string runId, + RequestOptions options) + => await RunShim.CancelRunAsync(threadId, runId, options).ConfigureAwait(false); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult SubmitToolOutputs(string threadId, string runId, BinaryContent content, RequestOptions context = null) - { - return RunShim.SubmitToolOuputsToRun(threadId, runId, content, context); - } + public virtual ClientResult SubmitToolOutputs( + string threadId, + string runId, + BinaryContent content, + RequestOptions options = null) + => RunShim.SubmitToolOuputsToRun(threadId, runId, content, options); + /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task SubmitToolOutputsAsync(string threadId, string runId, BinaryContent content, RequestOptions context = null) - { - return RunShim.SubmitToolOuputsToRunAsync(threadId, runId, content, context); - } + public virtual async Task SubmitToolOutputsAsync( + string threadId, + string runId, + BinaryContent content, + RequestOptions options = null) + => await RunShim.SubmitToolOuputsToRunAsync(threadId, runId, content, options).ConfigureAwait(false); - public virtual ClientResult GetRunStep(string threadId, string runId, string stepId, RequestOptions context) - { - return RunShim.GetRunStep(threadId, runId, stepId, context); - } + /// + public virtual ClientResult GetRunStep( + string threadId, + string runId, + string stepId, + RequestOptions options) + => RunShim.GetRunStep(threadId, runId, stepId, options); - public virtual Task GetRunStepAsync(string threadId, string runId, string stepId, RequestOptions context) - { - return RunShim.GetRunStepAsync(threadId, runId, stepId, context); - } + /// + public virtual async Task GetRunStepAsync( + string threadId, + string runId, + string stepId, + RequestOptions options) + => await RunShim.GetRunStepAsync(threadId, runId, stepId, options).ConfigureAwait(false); + /// public virtual ClientResult GetRunSteps( string threadId, string runId, @@ -408,22 +454,17 @@ public virtual ClientResult GetRunSteps( string createdSortOrder, string previousStepId, string subsequentStepId, - RequestOptions context) - { - return RunShim - .GetRunSteps(threadId, runId, maxResults, createdSortOrder, previousStepId, subsequentStepId, context); - } + RequestOptions options) + => RunShim.GetRunSteps(threadId, runId, maxResults, createdSortOrder, previousStepId, subsequentStepId, options); - public virtual Task GetRunStepsAsync( + /// + public virtual async Task GetRunStepsAsync( string threadId, string runId, int? maxResults, string createdSortOrder, string previousStepId, string subsequentStepId, - RequestOptions context) - { - return RunShim - .GetRunStepsAsync(threadId, runId, maxResults, createdSortOrder, previousStepId, subsequentStepId, context); - } + RequestOptions options) + => await RunShim.GetRunStepsAsync(threadId, runId, maxResults, createdSortOrder, previousStepId, subsequentStepId, options).ConfigureAwait(false); } diff --git a/.dotnet/src/Custom/Assistants/AssistantClient.cs b/.dotnet/src/Custom/Assistants/AssistantClient.cs index 413a5460f..e20089177 100644 --- a/.dotnet/src/Custom/Assistants/AssistantClient.cs +++ b/.dotnet/src/Custom/Assistants/AssistantClient.cs @@ -99,14 +99,18 @@ public AssistantClient(OpenAIClientOptions options = null) : this(endpoint: null, credential: null, options) { } - public virtual ClientResult CreateAssistant(string modelName, AssistantCreationOptions options = null) + public virtual ClientResult CreateAssistant( + string modelName, + AssistantCreationOptions options = null) { Internal.Models.CreateAssistantRequest request = CreateInternalCreateAssistantRequest(modelName, options); ClientResult internalResult = Shim.CreateAssistant(request); return ClientResult.FromValue(new Assistant(internalResult.Value), internalResult.GetRawResponse()); } - public virtual async Task> CreateAssistantAsync(string modelName, AssistantCreationOptions options = null) + public virtual async Task> CreateAssistantAsync( + string modelName, + AssistantCreationOptions options = null) { Internal.Models.CreateAssistantRequest request = CreateInternalCreateAssistantRequest(modelName, options); ClientResult internalResult @@ -114,7 +118,7 @@ public virtual async Task> CreateAssistantAsync(string m return ClientResult.FromValue(new Assistant(internalResult.Value), internalResult.GetRawResponse()); } - public virtual ClientResult GetAssistant(string assistantId) + public virtual ClientResult GetAssistant(string assistantId) { ClientResult internalResult = Shim.GetAssistant(assistantId); return ClientResult.FromValue(new Assistant(internalResult.Value), internalResult.GetRawResponse()); @@ -175,7 +179,8 @@ public virtual async Task> ModifyAssistantAsync( return ClientResult.FromValue(new Assistant(internalResult.Value), internalResult.GetRawResponse()); } - public virtual ClientResult DeleteAssistant(string assistantId) + public virtual ClientResult DeleteAssistant( + string assistantId) { ClientResult internalResponse = Shim.DeleteAssistant(assistantId); return ClientResult.FromValue(internalResponse.Value.Deleted, internalResponse.GetRawResponse()); diff --git a/.dotnet/src/Custom/Audio/AudioClient.Protocol.cs b/.dotnet/src/Custom/Audio/AudioClient.Protocol.cs new file mode 100644 index 000000000..527e5b672 --- /dev/null +++ b/.dotnet/src/Custom/Audio/AudioClient.Protocol.cs @@ -0,0 +1,19 @@ +using System.ClientModel; +using System.ClientModel.Primitives; +using System.ComponentModel; +using System.Threading.Tasks; + +namespace OpenAI.Audio; + +public partial class AudioClient +{ + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult GenerateSpeechFromText(BinaryContent content, RequestOptions options = null) + => Shim.CreateSpeech(content, options); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual async Task GenerateSpeechFromTextAsync(BinaryContent content, RequestOptions options = null) + => await Shim.CreateSpeechAsync(content, options).ConfigureAwait(false); +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Audio/AudioClient.cs b/.dotnet/src/Custom/Audio/AudioClient.cs index c5835c6d9..1eaaeb708 100644 --- a/.dotnet/src/Custom/Audio/AudioClient.cs +++ b/.dotnet/src/Custom/Audio/AudioClient.cs @@ -1,13 +1,10 @@ using OpenAI.ClientShared.Internal; using System; using System.ClientModel; -using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; -using System.ComponentModel; using System.Text; using System.Text.Json; -using System.Threading; using System.Threading.Tasks; namespace OpenAI.Audio; @@ -15,7 +12,7 @@ namespace OpenAI.Audio; /// The service client for OpenAI audio operations. public partial class AudioClient { - private OpenAIClientConnector _clientConnector; + private readonly OpenAIClientConnector _clientConnector; private Internal.Audio Shim => _clientConnector.InternalClient.GetAudioClient(); /// @@ -147,16 +144,6 @@ public virtual Task> GenerateSpeechFromTextAsync( return Shim.CreateSpeechAsync(request); } - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult GenerateSpeechFromText(BinaryContent content, RequestOptions context = null) - => Shim.CreateSpeech(content, context); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task GenerateSpeechFromTextAsync(BinaryContent content, RequestOptions context = null) - => Shim.CreateSpeechAsync(content, context); - public virtual ClientResult TranscribeAudio(BinaryData audioBytes, string filename, AudioTranscriptionOptions options = null) { PipelineMessage message = CreateInternalTranscriptionRequestMessage(audioBytes, filename, options); @@ -171,16 +158,6 @@ public virtual async Task> TranscribeAudioAsync return GetTranscriptionResultFromResponse(message.Response); } - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult TranscribeAudio(BinaryContent content, RequestOptions context = null) - => Shim.CreateTranscription(content, context); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task TranscribeAudioAsync(BinaryContent content, RequestOptions context = null) - => Shim.CreateTranscriptionAsync(content, context); - public virtual ClientResult TranslateAudio(BinaryData audioBytes, string filename, AudioTranslationOptions options = null) { PipelineMessage message = CreateInternalTranslationRequestMessage(audioBytes, filename, options); @@ -195,16 +172,6 @@ public virtual async Task> TranslateAudioAsync(Bi return GetTranslationResultFromResponse(message.Response); } - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult TranslateAudio(BinaryContent content, RequestOptions context = null) - => Shim.CreateTranslation(content, context); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task TranslateAudioAsync(BinaryContent content, RequestOptions context = null) - => Shim.CreateTranslationAsync(content, context); - private PipelineMessage CreateInternalTranscriptionRequestMessage(BinaryData audioBytes, string filename, AudioTranscriptionOptions options) { PipelineMessage message = Shim.Pipeline.CreateMessage(); diff --git a/.dotnet/src/Custom/Chat/ChatClient.Protocol.cs b/.dotnet/src/Custom/Chat/ChatClient.Protocol.cs new file mode 100644 index 000000000..7d6c4c1b9 --- /dev/null +++ b/.dotnet/src/Custom/Chat/ChatClient.Protocol.cs @@ -0,0 +1,20 @@ +using System.ClientModel; +using System.ClientModel.Primitives; +using System.ComponentModel; +using System.Threading.Tasks; + +namespace OpenAI.Chat; + +/// The service client for the OpenAI Chat Completions endpoint. +public partial class ChatClient +{ + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult CompleteChat(BinaryContent content, RequestOptions options = null) + => Shim.CreateChatCompletion(content, options); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual async Task CompleteChatAsync(BinaryContent content, RequestOptions options = null) + => await Shim.CreateChatCompletionAsync(content, options).ConfigureAwait(false); +} diff --git a/.dotnet/src/Custom/Chat/ChatClient.cs b/.dotnet/src/Custom/Chat/ChatClient.cs index e9990e3c9..2a029bbf1 100644 --- a/.dotnet/src/Custom/Chat/ChatClient.cs +++ b/.dotnet/src/Custom/Chat/ChatClient.cs @@ -2,7 +2,6 @@ using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; -using System.ComponentModel; using System.Text; using System.Threading.Tasks; @@ -11,7 +10,7 @@ namespace OpenAI.Chat; /// The service client for the OpenAI Chat Completions endpoint. public partial class ChatClient { - private OpenAIClientConnector _clientConnector; + private readonly OpenAIClientConnector _clientConnector; private Internal.Chat Shim => _clientConnector.InternalClient.GetChatClient(); /// @@ -315,16 +314,6 @@ public virtual async Task> CompleteCh e => StreamingChatUpdate.DeserializeStreamingChatUpdates(e))); } - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult CompleteChat(BinaryContent content, RequestOptions context = null) - => Shim.CreateChatCompletion(content, context); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task CompleteChatAsync(BinaryContent content, RequestOptions context = null) - => Shim.CreateChatCompletionAsync(content, context); - private Internal.Models.CreateChatCompletionRequest CreateInternalRequest( IEnumerable messages, ChatCompletionOptions options = null, diff --git a/.dotnet/src/Custom/Embeddings/EmbeddingClient.Protocol.cs b/.dotnet/src/Custom/Embeddings/EmbeddingClient.Protocol.cs new file mode 100644 index 000000000..b9fd3c746 --- /dev/null +++ b/.dotnet/src/Custom/Embeddings/EmbeddingClient.Protocol.cs @@ -0,0 +1,19 @@ +using System.ClientModel; +using System.ClientModel.Primitives; +using System.ComponentModel; +using System.Threading.Tasks; + +namespace OpenAI.Embeddings; + +public partial class EmbeddingClient +{ + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult GenerateEmbeddings(BinaryContent content, RequestOptions options = null) + => Shim.CreateEmbedding(content, options); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual async Task GenerateEmbeddingsAsync(BinaryContent content, RequestOptions options = null) + => await Shim.CreateEmbeddingAsync(content, options).ConfigureAwait(false); +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Embeddings/EmbeddingClient.cs b/.dotnet/src/Custom/Embeddings/EmbeddingClient.cs index 8a94c33d9..441c64064 100644 --- a/.dotnet/src/Custom/Embeddings/EmbeddingClient.cs +++ b/.dotnet/src/Custom/Embeddings/EmbeddingClient.cs @@ -1,11 +1,6 @@ -using OpenAI.Internal.Models; using System; using System.ClientModel; -using System.ClientModel; -using System.ClientModel.Primitives; using System.Collections.Generic; -using System.ComponentModel; -using System.Threading; using System.Threading.Tasks; namespace OpenAI.Embeddings; @@ -13,7 +8,7 @@ namespace OpenAI.Embeddings; /// The service client for the OpenAI Embeddings endpoint. public partial class EmbeddingClient { - private OpenAIClientConnector _clientConnector; + private readonly OpenAIClientConnector _clientConnector; private Internal.Embeddings Shim => _clientConnector.InternalClient.GetEmbeddingsClient(); public EmbeddingClient(Uri endpoint, string model, ApiKeyCredential credential, OpenAIClientOptions options = null) @@ -97,16 +92,6 @@ public virtual async Task> GenerateEmbeddingsA return ClientResult.FromValue(resultCollection, response.GetRawResponse()); } - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult GenerateEmbeddings(BinaryContent content, RequestOptions context = null) - => Shim.CreateEmbedding(content, context); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task GenerateEmbeddingsAsync(BinaryContent content, RequestOptions context = null) - => Shim.CreateEmbeddingAsync(content, context); - private Internal.Models.CreateEmbeddingRequest CreateInternalRequest(object inputObject, EmbeddingOptions options) { options ??= new(); diff --git a/.dotnet/src/Custom/Files/FileClient.Protocol.cs b/.dotnet/src/Custom/Files/FileClient.Protocol.cs new file mode 100644 index 000000000..263efec6c --- /dev/null +++ b/.dotnet/src/Custom/Files/FileClient.Protocol.cs @@ -0,0 +1,49 @@ +using System.ClientModel; +using System.ClientModel.Primitives; +using System.ComponentModel; +using System.Threading.Tasks; + +namespace OpenAI.Files; + +public partial class FileClient +{ + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult GetFileInfo(string fileId, RequestOptions options) + => Shim.RetrieveFile(fileId, options); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual async Task GetFileInfoAsync(string fileId, RequestOptions options) + => await Shim.RetrieveFileAsync(fileId, options).ConfigureAwait(false); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult GetFileInfoList(string purpose, RequestOptions options) + => Shim.GetFiles(purpose, options); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual async Task GetFileInfoListAsync(string purpose, RequestOptions options) + => await Shim.GetFilesAsync(purpose, options).ConfigureAwait(false); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult DownloadFile(string fileId, RequestOptions options) + => Shim.DownloadFile(fileId, options); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual async Task DownloadFileAsync(string fileId, RequestOptions options) + => await Shim.DownloadFileAsync(fileId, options).ConfigureAwait(false); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult DeleteFile(string fileId, RequestOptions options) + => Shim.DeleteFile(fileId, options); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual async Task DeleteFileAsync(string fileId, RequestOptions options) + => await Shim.DeleteFileAsync(fileId, options).ConfigureAwait(false); +} diff --git a/.dotnet/src/Custom/Files/FileClient.cs b/.dotnet/src/Custom/Files/FileClient.cs index 4f2c6e3b1..b57ebefc8 100644 --- a/.dotnet/src/Custom/Files/FileClient.cs +++ b/.dotnet/src/Custom/Files/FileClient.cs @@ -2,8 +2,6 @@ using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; -using System.ComponentModel; -using System.Runtime.InteropServices.ComTypes; using System.Text; using System.Threading.Tasks; @@ -14,7 +12,7 @@ namespace OpenAI.Files; /// public partial class FileClient { - private OpenAIClientConnector _clientConnector; + private readonly OpenAIClientConnector _clientConnector; private Internal.Files Shim => _clientConnector.InternalClient.GetFilesClient(); /// @@ -114,20 +112,6 @@ public virtual async Task> UploadFileAsync(BinaryDa return GetUploadResultFromResponse(uploadMessage.Response); } - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult UploadFile(BinaryContent requestBody, RequestOptions context) - { - return Shim.CreateFile(requestBody, context); - } - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task UploadFileAsync(BinaryContent requestBody, RequestOptions context) - { - return Shim.CreateFileAsync(requestBody, context); - } - public virtual ClientResult GetFileInfo(string fileId) { ClientResult internalResult = Shim.RetrieveFile(fileId); @@ -140,20 +124,6 @@ public virtual async Task> GetFileInfoAsync(string return ClientResult.FromValue(new OpenAIFileInfo(internalResult.Value), internalResult.GetRawResponse()); } - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult GetFileInfo(string fileId, RequestOptions context) - { - return Shim.RetrieveFile(fileId, context); - } - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task GetFileInfoAsync(string fileId, RequestOptions context) - { - return Shim.RetrieveFileAsync(fileId, context); - } - public virtual ClientResult GetFileInfoList(OpenAIFilePurpose? purpose = null) { Internal.Models.OpenAIFilePurpose? internalPurpose = ToInternalFilePurpose(purpose); @@ -188,20 +158,6 @@ public virtual async Task> GetFileInfoLis return ClientResult.FromValue(new OpenAIFileInfoCollection(infoItems), result.GetRawResponse()); } - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult GetFileInfoList(string purpose, RequestOptions context) - { - return Shim.GetFiles(purpose, context); - } - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task GetFileInfoListAsync(string purpose, RequestOptions context) - { - return Shim.GetFilesAsync(purpose, context); - } - public virtual ClientResult DownloadFile(string fileId) { PipelineMessage message = Shim.Pipeline.CreateMessage(); @@ -247,20 +203,6 @@ public virtual async Task> DownloadFileAsync(string fil return ClientResult.FromValue(message.Response.Content, message.Response); } - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult DownloadFile(string fileId, RequestOptions context) - { - return Shim.DownloadFile(fileId, context); - } - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task DownloadFileAsync(string fileId, RequestOptions context) - { - return Shim.DownloadFileAsync(fileId, context); - } - public virtual void DeleteFile(string fileId) { _ = Shim.DeleteFile(fileId); @@ -271,20 +213,6 @@ public virtual async Task DeleteFileAsync(string fileId) _ = Shim.DeleteFileAsync(fileId); } - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult DeleteFile(string fileId, RequestOptions context) - { - return Shim.DeleteFile(fileId, context); - } - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult DeleteFileAsync(string fileId, RequestOptions context) - { - return Shim.DeleteFile(fileId, context); - } - internal PipelineMessage CreateInternalUploadMessage(BinaryData fileData, string filename, OpenAIFilePurpose purpose) { MultipartFormDataContent content = new(); diff --git a/.dotnet/src/Custom/FineTuning/FineTuningClient.Protocol.cs b/.dotnet/src/Custom/FineTuning/FineTuningClient.Protocol.cs new file mode 100644 index 000000000..3626eb6d1 --- /dev/null +++ b/.dotnet/src/Custom/FineTuning/FineTuningClient.Protocol.cs @@ -0,0 +1,74 @@ +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Threading.Tasks; + +namespace OpenAI.FineTuning; + +public partial class FineTuningClient +{ + /// + public virtual ClientResult CreateFineTuningJob( + BinaryContent content, + RequestOptions options = null) + => FineTuningShim.CreateFineTuningJob(content, options); + + /// + public virtual async Task CreateFineTuningJobAsync( + BinaryContent content, + RequestOptions options = null) + => await FineTuningShim.CreateFineTuningJobAsync(content, options).ConfigureAwait(false); + + /// + public virtual ClientResult GetFineTuningJob( + string jobId, + RequestOptions options) + => FineTuningShim.RetrieveFineTuningJob(jobId, options); + + /// + public virtual async Task GetFineTuningJobAsync( + string jobId, + RequestOptions options) + => await FineTuningShim.RetrieveFineTuningJobAsync(jobId, options).ConfigureAwait(false); + + /// + public virtual ClientResult GetFineTuningJobs( + string previousJobId, + int? maxResults, + RequestOptions options) + => FineTuningShim.GetPaginatedFineTuningJobs(previousJobId, maxResults, options); + + /// + public virtual async Task GetFineTuningJobsAsync( + string previousJobId, + int? maxResults, + RequestOptions options) + => await FineTuningShim.GetPaginatedFineTuningJobsAsync(previousJobId, maxResults, options).ConfigureAwait(false); + + /// + public virtual ClientResult CancelFineTuningJob( + string jobId, + RequestOptions options) + => FineTuningShim.CancelFineTuningJob(jobId, options); + + /// + public virtual async Task CancelFineTuningJobAsync( + string jobId, + RequestOptions options) + => await FineTuningShim.CancelFineTuningJobAsync(jobId, options).ConfigureAwait(false); + + /// + public virtual ClientResult GetFineTuningJobEvents( + string jobId, + string previousEventId, + int? maxResults, + RequestOptions options) + => FineTuningShim.GetFineTuningEvents(jobId, previousEventId, maxResults, options); + + /// + public virtual async Task GetFineTuningJobEventsAsync( + string jobId, + string previousEventId, + int? maxResults, + RequestOptions options) + => await FineTuningShim.GetFineTuningEventsAsync(jobId, previousEventId, maxResults, options).ConfigureAwait(false); +} diff --git a/.dotnet/src/Custom/FineTuning/FineTuningClient.cs b/.dotnet/src/Custom/FineTuning/FineTuningClient.cs new file mode 100644 index 000000000..7e1e6ea2e --- /dev/null +++ b/.dotnet/src/Custom/FineTuning/FineTuningClient.cs @@ -0,0 +1,90 @@ +using System; +using System.ClientModel; + +namespace OpenAI.FineTuning; + +/// +/// The service client for OpenAI fine-tuning operations. +/// +public partial class FineTuningClient +{ + private readonly OpenAIClientConnector _clientConnector; + private Internal.FineTuning FineTuningShim => _clientConnector.InternalClient.GetFineTuningClient(); + + /// + /// Initializes a new instance of , used for fine-tuning operation requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The connection endpoint to use. + /// The API key used to authenticate with the service endpoint. + /// Additional options to customize the client. + public FineTuningClient(Uri endpoint, ApiKeyCredential credential, OpenAIClientOptions options = null) + { + _clientConnector = new("none", endpoint, credential, options); + } + + /// + /// Initializes a new instance of , used for fine-tuning operation requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The connection endpoint to use. + /// Additional options to customize the client. + public FineTuningClient(Uri endpoint, OpenAIClientOptions options = null) + : this(endpoint, credential: null, options) + { } + + /// + /// Initializes a new instance of , used for fine-tuning operation requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// The API key used to authenticate with the service endpoint. + /// Additional options to customize the client. + public FineTuningClient(ApiKeyCredential credential, OpenAIClientOptions options = null) + : this(endpoint: null, credential, options) + { } + + /// + /// Initializes a new instance of , used for fine-tuning operation requests. + /// + /// + /// + /// If an endpoint is not provided, the client will use the OPENAI_ENDPOINT environment variable if it + /// defined and otherwise use the default OpenAI v1 endpoint. + /// + /// + /// If an authentication credential is not defined, the client use the OPENAI_API_KEY environment variable + /// if it is defined. + /// + /// + /// Additional options to customize the client. + public FineTuningClient(OpenAIClientOptions options = null) + : this(endpoint: null, credential: null, options) + { } +} diff --git a/.dotnet/src/Custom/Images/ImageClient.Protocol.cs b/.dotnet/src/Custom/Images/ImageClient.Protocol.cs new file mode 100644 index 000000000..b95c9b4d0 --- /dev/null +++ b/.dotnet/src/Custom/Images/ImageClient.Protocol.cs @@ -0,0 +1,19 @@ +using System.ClientModel.Primitives; +using System.ClientModel; +using System.ComponentModel; +using System.Threading.Tasks; + +namespace OpenAI.Images; + +public partial class ImageClient +{ + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult GenerateImage(BinaryContent content, RequestOptions options = null) + => Shim.CreateImage(content, options); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual async Task GenerateImageAsync(BinaryContent content, RequestOptions options = null) + => await Shim.CreateImageAsync(content, options).ConfigureAwait(false); +} diff --git a/.dotnet/src/Custom/Images/ImageClient.cs b/.dotnet/src/Custom/Images/ImageClient.cs index 24f8ae4fd..6a303045e 100644 --- a/.dotnet/src/Custom/Images/ImageClient.cs +++ b/.dotnet/src/Custom/Images/ImageClient.cs @@ -1,10 +1,6 @@ using System; using System.ClientModel; -using System.ClientModel; -using System.ClientModel.Primitives; using System.Collections.Generic; -using System.ComponentModel; -using System.Threading; using System.Threading.Tasks; namespace OpenAI.Images; @@ -12,7 +8,7 @@ namespace OpenAI.Images; /// The service client for OpenAI image operations. public partial class ImageClient { - private OpenAIClientConnector _clientConnector; + private readonly OpenAIClientConnector _clientConnector; private Internal.Images Shim => _clientConnector.InternalClient.GetImagesClient(); /// @@ -172,16 +168,6 @@ public virtual async Task> GenerateImage return ClientResult.FromValue(new ImageGenerationCollection(ImageGenerations), response.GetRawResponse()); } - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult GenerateImage(BinaryContent content, RequestOptions context = null) - => Shim.CreateImage(content, context); - - /// - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task GenerateImageAsync(BinaryContent content, RequestOptions context = null) - => Shim.CreateImageAsync(content, context); - private Internal.Models.CreateImageRequest CreateInternalRequest( string prompt, int? imageCount = null, diff --git a/.dotnet/src/Custom/LegacyCompletions/LegacyCompletionClient.Protocol.cs b/.dotnet/src/Custom/LegacyCompletions/LegacyCompletionClient.Protocol.cs new file mode 100644 index 000000000..f4b576ce9 --- /dev/null +++ b/.dotnet/src/Custom/LegacyCompletions/LegacyCompletionClient.Protocol.cs @@ -0,0 +1,16 @@ +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Threading.Tasks; + +namespace OpenAI.LegacyCompletions; + +public partial class LegacyCompletionClient +{ + /// + public virtual ClientResult GenerateLegacyCompletions(BinaryContent content, RequestOptions options = null) + => Shim.CreateCompletion(content, options); + + /// + public virtual async Task GenerateLegacyCompletionsAsync(BinaryContent content, RequestOptions options = null) + => await Shim.CreateCompletionAsync(content, options).ConfigureAwait(false); +} diff --git a/.dotnet/src/Custom/LegacyCompletions/LegacyCompletionClient.cs b/.dotnet/src/Custom/LegacyCompletions/LegacyCompletionClient.cs index 1b9393daa..460691149 100644 --- a/.dotnet/src/Custom/LegacyCompletions/LegacyCompletionClient.cs +++ b/.dotnet/src/Custom/LegacyCompletions/LegacyCompletionClient.cs @@ -1,9 +1,5 @@ using System; using System.ClientModel; -using System.ClientModel; -using System.ClientModel.Primitives; -using System.ComponentModel; -using System.Threading.Tasks; namespace OpenAI.LegacyCompletions; @@ -16,7 +12,7 @@ namespace OpenAI.LegacyCompletions; /// public partial class LegacyCompletionClient { - private OpenAIClientConnector _clientConnector; + private readonly OpenAIClientConnector _clientConnector; private Internal.Completions Shim => _clientConnector.InternalClient.GetCompletionsClient(); /// @@ -95,12 +91,4 @@ public LegacyCompletionClient(ApiKeyCredential credential, OpenAIClientOptions o public LegacyCompletionClient(OpenAIClientOptions options = null) : this(endpoint: null, credential: null, options) { } - - /// - public virtual ClientResult GenerateLegacyCompletions(BinaryContent content, RequestOptions context = null) - => Shim.CreateCompletion(content, context); - - /// - public virtual Task GenerateLegacyCompletionsAsync(BinaryContent content, RequestOptions context = null) - => Shim.CreateCompletionAsync(content, context); } diff --git a/.dotnet/src/Custom/Models/ModelManagementClient.Protocol.cs b/.dotnet/src/Custom/Models/ModelManagementClient.Protocol.cs new file mode 100644 index 000000000..1e4074647 --- /dev/null +++ b/.dotnet/src/Custom/Models/ModelManagementClient.Protocol.cs @@ -0,0 +1,39 @@ +using System.ClientModel; +using System.ClientModel.Primitives; +using System.ComponentModel; +using System.Threading.Tasks; + +namespace OpenAI.ModelManagement; + +public partial class ModelManagementClient +{ + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult GetModelInfo(string modelId, RequestOptions options) + => Shim.Retrieve(modelId, options); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual async Task GetModelInfoAsync(string modelId, RequestOptions options) + => await Shim.RetrieveAsync(modelId, options).ConfigureAwait(false); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult GetModels(RequestOptions options) + => Shim.GetModels(options); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual async Task GetModelsAsync(RequestOptions options) + => await Shim.GetModelsAsync(options).ConfigureAwait(false); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult DeleteModel(string modelId, RequestOptions options) + => Shim.Delete(modelId, options); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual async Task DeleteModelAsync(string modelId, RequestOptions options) + => await Shim.DeleteAsync(modelId, options).ConfigureAwait(false); +} diff --git a/.dotnet/src/Custom/Models/ModelManagementClient.cs b/.dotnet/src/Custom/Models/ModelManagementClient.cs index 88a3c805c..107c798fa 100644 --- a/.dotnet/src/Custom/Models/ModelManagementClient.cs +++ b/.dotnet/src/Custom/Models/ModelManagementClient.cs @@ -1,8 +1,6 @@ using OpenAI.ClientShared.Internal; using System; using System.ClientModel; -using System.ClientModel.Primitives; -using System.ComponentModel; using System.Threading.Tasks; namespace OpenAI.ModelManagement; @@ -12,10 +10,8 @@ namespace OpenAI.ModelManagement; /// public partial class ModelManagementClient { - private OpenAIClientConnector _clientConnector; + private readonly OpenAIClientConnector _clientConnector; private Internal.ModelsOps Shim => _clientConnector.InternalClient.GetModelsOpsClient(); - private Internal.FineTuning FineTuningShim - => _clientConnector.InternalClient.GetFineTuningClient(); /// /// Initializes a new instance of , used for model operation requests. @@ -94,31 +90,18 @@ public ModelManagementClient(OpenAIClientOptions options = null) : this(endpoint: null, credential: null, options) { } - public virtual ClientResult GetModelInfo(string modelId) + public virtual ClientResult GetModelInfo(string modelId) { ClientResult internalResult = Shim.Retrieve(modelId); return ClientResult.FromValue(new ModelDetails(internalResult.Value), internalResult.GetRawResponse()); } - public virtual async Task> GetModelInfoAsync( - string modelId) + public virtual async Task> GetModelInfoAsync(string modelId) { ClientResult internalResult = await Shim.RetrieveAsync(modelId).ConfigureAwait(false); return ClientResult.FromValue(new ModelDetails(internalResult.Value), internalResult.GetRawResponse()); } - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult GetModelInfo(string modelId, RequestOptions context) - { - return Shim.Retrieve(modelId, context); - } - - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task GetModelInfoAsync(string modelId, RequestOptions context) - { - return Shim.RetrieveAsync(modelId, context); - } - public virtual ClientResult GetModels() { ClientResult internalResult = Shim.GetModels(); @@ -142,56 +125,16 @@ public virtual async Task> GetModelsAsync() return ClientResult.FromValue(new ModelDetailCollection(modelEntries), internalResult.GetRawResponse()); } - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult GetModels(RequestOptions context) => Shim.GetModels(context); - - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task GetModelsAsync(RequestOptions context) => Shim.GetModelsAsync(context); - - public virtual ClientResult DeleteModel(string modelId) + public virtual ClientResult DeleteModel(string modelId) { ClientResult internalResult = Shim.Delete(modelId); return ClientResult.FromValue(internalResult.Value.Deleted, internalResult.GetRawResponse()); } - public virtual async Task> DeleteModelAsync(string modelId) + public virtual async Task> DeleteModelAsync(string modelId) { ClientResult internalResult = await Shim.DeleteAsync(modelId).ConfigureAwait(false); return ClientResult.FromValue(internalResult.Value.Deleted, internalResult.GetRawResponse()); } - - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult DeleteModel(string modelId, RequestOptions context) => Shim.Delete(modelId, context); - - [EditorBrowsable(EditorBrowsableState.Never)] - public virtual Task DeleteModelAsync(string modelId, RequestOptions context) => Shim.DeleteAsync(modelId, context); - - public virtual ClientResult CreateFineTuningJob(BinaryContent content, RequestOptions context = null) - => FineTuningShim.CreateFineTuningJob(content, context); - - public virtual Task CreateFineTuningJobAsync(BinaryContent content, RequestOptions context = null) - => FineTuningShim.CreateFineTuningJobAsync(content, context); - - public virtual ClientResult GetFineTuningJob(string jobId, RequestOptions context) => FineTuningShim.RetrieveFineTuningJob(jobId, context); - - public virtual Task GetFineTuningJobAsync(string jobId, RequestOptions context) - => FineTuningShim.RetrieveFineTuningJobAsync(jobId, context); - - public virtual ClientResult GetFineTuningJobs(string previousJobId, int? maxResults, RequestOptions context) - => FineTuningShim.GetPaginatedFineTuningJobs(previousJobId, maxResults, context); - - public virtual Task GetFineTuningJobsAsync(int? maxResults, string previousJobId, RequestOptions context) - => FineTuningShim.GetPaginatedFineTuningJobsAsync(previousJobId, maxResults, context); - - public virtual ClientResult GetFineTuningJobEvents(string jobId, int? maxResults, string previousJobId, RequestOptions context) - => FineTuningShim.GetFineTuningEvents(jobId, previousJobId, maxResults, context); - - public virtual Task GetFineTuningJobEventsAsync(string jobId, int? maxResults, string previousJobId, RequestOptions context) - => FineTuningShim.GetFineTuningEventsAsync(jobId, previousJobId, maxResults, context); - - public virtual ClientResult CancelFineTuningJob(string jobId, RequestOptions context) => FineTuningShim.CancelFineTuningJob(jobId, context); - - public virtual Task CancelFineTuningJobAsync(string jobId, RequestOptions context) - => FineTuningShim.CancelFineTuningJobAsync(jobId, context); } diff --git a/.dotnet/src/Custom/Moderations/ModerationClient.Protocol.cs b/.dotnet/src/Custom/Moderations/ModerationClient.Protocol.cs new file mode 100644 index 000000000..ac1858316 --- /dev/null +++ b/.dotnet/src/Custom/Moderations/ModerationClient.Protocol.cs @@ -0,0 +1,16 @@ +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Threading.Tasks; + +namespace OpenAI.Moderations; + +public partial class ModerationClient +{ + /// + public virtual ClientResult ClassifyText(BinaryContent content, RequestOptions options = null) + => Shim.CreateModeration(content, options); + + /// + public virtual async Task ClassifyTextAsync(BinaryContent content, RequestOptions options = null) + => await Shim.CreateModerationAsync(content, options).ConfigureAwait(false); +} diff --git a/.dotnet/src/Custom/Moderations/ModerationClient.cs b/.dotnet/src/Custom/Moderations/ModerationClient.cs index 28590087c..640baf66c 100644 --- a/.dotnet/src/Custom/Moderations/ModerationClient.cs +++ b/.dotnet/src/Custom/Moderations/ModerationClient.cs @@ -1,10 +1,5 @@ using System; using System.ClientModel; -using System.ClientModel; -using System.ClientModel.Primitives; -using System.ComponentModel; -using System.Threading; -using System.Threading.Tasks; namespace OpenAI.Moderations; @@ -13,7 +8,7 @@ namespace OpenAI.Moderations; /// public partial class ModerationClient { - private OpenAIClientConnector _clientConnector; + private readonly OpenAIClientConnector _clientConnector; private Internal.Moderations Shim => _clientConnector.InternalClient.GetModerationsClient(); /// @@ -92,15 +87,4 @@ public ModerationClient(ApiKeyCredential credential, OpenAIClientOptions options public ModerationClient(OpenAIClientOptions options = null) : this(endpoint: null, credential: null, options) { } - - public virtual ClientResult ClassifyText(BinaryContent content, RequestOptions context = null) - { - return Shim.CreateModeration(content, context); - } - - public virtual Task ClassifyTextAsync(BinaryContent content, RequestOptions context = null) - { - return Shim.CreateModerationAsync(content, context); - } - } diff --git a/.dotnet/src/Custom/OpenAIClient.cs b/.dotnet/src/Custom/OpenAIClient.cs index b94c3bf93..c42a64082 100644 --- a/.dotnet/src/Custom/OpenAIClient.cs +++ b/.dotnet/src/Custom/OpenAIClient.cs @@ -3,6 +3,7 @@ using OpenAI.Chat; using OpenAI.Embeddings; using OpenAI.Files; +using OpenAI.FineTuning; using OpenAI.Images; using OpenAI.LegacyCompletions; using OpenAI.ModelManagement; @@ -91,7 +92,7 @@ public OpenAIClient(OpenAIClientOptions clientOptions) /// /// A new . public AssistantClient GetAssistantClient() - => new AssistantClient(_cachedEndpoint, _cachedCredential, _cachedOptions); + => new(_cachedEndpoint, _cachedCredential, _cachedOptions); /// /// Gets a new instance of that reuses the client configuration details provided to @@ -103,7 +104,7 @@ public AssistantClient GetAssistantClient() /// /// A new . public AudioClient GetAudioClient(string model) - => new AudioClient(_cachedEndpoint, model, _cachedCredential, _cachedOptions); + => new(_cachedEndpoint, model, _cachedCredential, _cachedOptions); /// /// Gets a new instance of that reuses the client configuration details provided to @@ -115,7 +116,7 @@ public AudioClient GetAudioClient(string model) /// /// A new . public ChatClient GetChatClient(string model) - => new ChatClient(_cachedEndpoint, model, _cachedCredential, _cachedOptions); + => new(_cachedEndpoint, model, _cachedCredential, _cachedOptions); /// /// Gets a new instance of that reuses the client configuration details provided to @@ -127,7 +128,7 @@ public ChatClient GetChatClient(string model) /// /// A new . public EmbeddingClient GetEmbeddingClient(string model) - => new EmbeddingClient(_cachedEndpoint, model, _cachedCredential, _cachedOptions); + => new(_cachedEndpoint, model, _cachedCredential, _cachedOptions); /// /// Gets a new instance of that reuses the client configuration details provided to @@ -139,7 +140,19 @@ public EmbeddingClient GetEmbeddingClient(string model) /// /// A new . public FileClient GetFileClient() - => new FileClient(_cachedEndpoint, _cachedCredential, _cachedOptions); + => new(_cachedEndpoint, _cachedCredential, _cachedOptions); + + /// + /// Gets a new instance of that reuses the client configuration details provided to + /// the instance. + /// + /// + /// This method is functionally equivalent to using the constructor directly with + /// the same configuration details. + /// + /// A new . + public FineTuningClient GetFineTuningClient() + => new(_cachedEndpoint, _cachedCredential, _cachedOptions); /// /// Gets a new instance of that reuses the client configuration details provided to @@ -151,7 +164,7 @@ public FileClient GetFileClient() /// /// A new . public ImageClient GetImageClient(string model) - => new ImageClient(_cachedEndpoint, model, _cachedCredential, _cachedOptions); + => new(_cachedEndpoint, model, _cachedCredential, _cachedOptions); /// /// Gets a new instance of that reuses the client configuration details provided to @@ -163,7 +176,7 @@ public ImageClient GetImageClient(string model) /// /// A new . public LegacyCompletionClient GetLegacyCompletionClient() - => new LegacyCompletionClient(_cachedEndpoint, _cachedCredential, _cachedOptions); + => new(_cachedEndpoint, _cachedCredential, _cachedOptions); /// /// Gets a new instance of that reuses the client configuration details provided to @@ -175,7 +188,7 @@ public LegacyCompletionClient GetLegacyCompletionClient() /// /// A new . public ModelManagementClient GetModelManagementClient() - => new ModelManagementClient(_cachedEndpoint, _cachedCredential, _cachedOptions); + => new(_cachedEndpoint, _cachedCredential, _cachedOptions); /// /// Gets a new instance of that reuses the client configuration details provided to @@ -187,5 +200,5 @@ public ModelManagementClient GetModelManagementClient() /// /// A new . public ModerationClient GetModerationClient() - => new ModerationClient(_cachedEndpoint, _cachedCredential, _cachedOptions); + => new(_cachedEndpoint, _cachedCredential, _cachedOptions); } diff --git a/.dotnet/src/Generated/FineTuning.cs b/.dotnet/src/Generated/FineTuning.cs index 39412b46b..de671f097 100644 --- a/.dotnet/src/Generated/FineTuning.cs +++ b/.dotnet/src/Generated/FineTuning.cs @@ -158,7 +158,7 @@ public virtual ClientResult CreateFineTuningJob(BinaryContent content, RequestOp /// List your organization's fine-tuning jobs. /// Identifier for the last job from the previous pagination request. /// Number of fine-tuning jobs to retrieve. - public virtual async Task> GetPaginatedFineTuningJobsAsync(string after = null, long? limit = null) + public virtual async Task> GetPaginatedFineTuningJobsAsync(string after = null, int? limit = null) { ClientResult result = await GetPaginatedFineTuningJobsAsync(after, limit, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(ListPaginatedFineTuningJobsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -167,7 +167,7 @@ public virtual async Task> Get /// List your organization's fine-tuning jobs. /// Identifier for the last job from the previous pagination request. /// Number of fine-tuning jobs to retrieve. - public virtual ClientResult GetPaginatedFineTuningJobs(string after = null, long? limit = null) + public virtual ClientResult GetPaginatedFineTuningJobs(string after = null, int? limit = null) { ClientResult result = GetPaginatedFineTuningJobs(after, limit, DefaultRequestContext); return ClientResult.FromValue(ListPaginatedFineTuningJobsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -183,7 +183,7 @@ public virtual ClientResult GetPaginatedFin /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -193,7 +193,7 @@ public virtual ClientResult GetPaginatedFin /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// Service returned a non-success status code. /// The response returned from the service. - public virtual async Task GetPaginatedFineTuningJobsAsync(string after, long? limit, RequestOptions options) + public virtual async Task GetPaginatedFineTuningJobsAsync(string after, int? limit, RequestOptions options) { options ??= new RequestOptions(); using PipelineMessage message = CreateGetPaginatedFineTuningJobsRequest(after, limit, options); @@ -218,7 +218,7 @@ public virtual async Task GetPaginatedFineTuningJobsAsync(string a /// /// /// - /// Please try the simpler convenience overload with strongly typed models first. + /// Please try the simpler convenience overload with strongly typed models first. /// /// /// @@ -228,7 +228,7 @@ public virtual async Task GetPaginatedFineTuningJobsAsync(string a /// The request options, which can override default behaviors of the client pipeline on a per-call basis. /// Service returned a non-success status code. /// The response returned from the service. - public virtual ClientResult GetPaginatedFineTuningJobs(string after, long? limit, RequestOptions options) + public virtual ClientResult GetPaginatedFineTuningJobs(string after, int? limit, RequestOptions options) { options ??= new RequestOptions(); using PipelineMessage message = CreateGetPaginatedFineTuningJobsRequest(after, limit, options); @@ -587,7 +587,7 @@ internal PipelineMessage CreateCreateFineTuningJobRequest(BinaryContent content, return message; } - internal PipelineMessage CreateGetPaginatedFineTuningJobsRequest(string after, long? limit, RequestOptions options) + internal PipelineMessage CreateGetPaginatedFineTuningJobsRequest(string after, int? limit, RequestOptions options) { PipelineMessage message = _pipeline.CreateMessage(); message.ResponseClassifier = ResponseErrorClassifier200; diff --git a/fine-tuning/operations.tsp b/fine-tuning/operations.tsp index 21c08b161..d972c4219 100644 --- a/fine-tuning/operations.tsp +++ b/fine-tuning/operations.tsp @@ -36,7 +36,7 @@ interface FineTuning { @query after?: string, /** Number of fine-tuning jobs to retrieve. */ - @query limit?: safeint = 20, + @query limit?: int32 = 20, ): ListPaginatedFineTuningJobsResponse | ErrorResponse; @route("jobs/{fine_tuning_job_id}") @@ -76,6 +76,6 @@ interface FineTuning { @query after?: string, /** Number of events to retrieve. */ - @query limit?: integer = 20, + @query limit?: int32 = 20, ): ListFineTuningJobEventsResponse | ErrorResponse; } \ No newline at end of file From 6e2d84bcfd8b83139d3676b0236ec8bfe8251481 Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado <45773732+joseharriaga@users.noreply.github.com> Date: Mon, 11 Mar 2024 16:29:20 -0700 Subject: [PATCH 26/50] Add convenience methods for image edits and variations (#11) Implement support for image edits and variations as convenience methods that do multipart/form-data. --- .dotnet/src/Custom/Audio/AudioClient.cs | 4 +- .dotnet/src/Custom/Chat/ChatClient.cs | 2 +- .dotnet/src/Custom/Files/FileClient.cs | 4 +- ...lection.cs => GeneratedImageCollection.cs} | 4 +- .dotnet/src/Custom/Images/ImageClient.cs | 391 +++++++++++++++++- .dotnet/src/Custom/Images/ImageEditOptions.cs | 21 + .dotnet/src/Custom/Images/ImageSize.cs | 28 +- .../Custom/Images/ImageVariationOptions.cs | 18 + .dotnet/tests/Assets/edit_sample_image.png | Bin 0 -> 846285 bytes .dotnet/tests/Assets/edit_sample_mask.png | Bin 0 -> 726764 bytes .../tests/{data => Assets}/hello_world.m4a | Bin .dotnet/tests/{data => Assets}/hola_mundo.m4a | Bin .dotnet/tests/{data => Assets}/stop_sign.png | Bin .../tests/Assets/variation_sample_image.png | Bin 0 -> 1769653 bytes .dotnet/tests/OpenAI.Tests.csproj | 23 ++ .../Images/Sample02_SimpleImageEdit.cs | 38 ++ .../Images/Sample02_SimpleImageEditAsync.cs | 39 ++ .../Images/Sample03_SimpleImageVariation.cs | 32 ++ .../Sample03_SimpleImageVariationAsync.cs | 33 ++ .dotnet/tests/TestScenarios/ChatWithVision.cs | 2 +- .../tests/TestScenarios/TranscriptionTests.cs | 4 +- .../tests/TestScenarios/TranslationTests.cs | 2 +- 22 files changed, 603 insertions(+), 42 deletions(-) rename .dotnet/src/Custom/Images/{ImageGenerationCollection.cs => GeneratedImageCollection.cs} (60%) create mode 100644 .dotnet/src/Custom/Images/ImageEditOptions.cs create mode 100644 .dotnet/src/Custom/Images/ImageVariationOptions.cs create mode 100644 .dotnet/tests/Assets/edit_sample_image.png create mode 100644 .dotnet/tests/Assets/edit_sample_mask.png rename .dotnet/tests/{data => Assets}/hello_world.m4a (100%) rename .dotnet/tests/{data => Assets}/hola_mundo.m4a (100%) rename .dotnet/tests/{data => Assets}/stop_sign.png (100%) create mode 100644 .dotnet/tests/Assets/variation_sample_image.png create mode 100644 .dotnet/tests/Samples/Images/Sample02_SimpleImageEdit.cs create mode 100644 .dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs create mode 100644 .dotnet/tests/Samples/Images/Sample03_SimpleImageVariation.cs create mode 100644 .dotnet/tests/Samples/Images/Sample03_SimpleImageVariationAsync.cs diff --git a/.dotnet/src/Custom/Audio/AudioClient.cs b/.dotnet/src/Custom/Audio/AudioClient.cs index 1eaaeb708..4fa2267a5 100644 --- a/.dotnet/src/Custom/Audio/AudioClient.cs +++ b/.dotnet/src/Custom/Audio/AudioClient.cs @@ -154,7 +154,7 @@ public virtual ClientResult TranscribeAudio(BinaryData audio public virtual async Task> TranscribeAudioAsync(BinaryData audioBytes, string filename, AudioTranscriptionOptions options = null) { PipelineMessage message = CreateInternalTranscriptionRequestMessage(audioBytes, filename, options); - await Shim.Pipeline.SendAsync(message); + await Shim.Pipeline.SendAsync(message).ConfigureAwait(false); return GetTranscriptionResultFromResponse(message.Response); } @@ -168,7 +168,7 @@ public virtual ClientResult TranslateAudio(BinaryData audioByt public virtual async Task> TranslateAudioAsync(BinaryData audioBytes, string filename, AudioTranslationOptions options = null) { PipelineMessage message = CreateInternalTranslationRequestMessage(audioBytes, filename, options); - await Shim.Pipeline.SendAsync(message); + await Shim.Pipeline.SendAsync(message).ConfigureAwait(false); return GetTranslationResultFromResponse(message.Response); } diff --git a/.dotnet/src/Custom/Chat/ChatClient.cs b/.dotnet/src/Custom/Chat/ChatClient.cs index 2a029bbf1..9fdc022ae 100644 --- a/.dotnet/src/Custom/Chat/ChatClient.cs +++ b/.dotnet/src/Custom/Chat/ChatClient.cs @@ -298,7 +298,7 @@ public virtual async Task> CompleteCh { PipelineMessage requestMessage = CreateCustomRequestMessage(messages, choiceCount, options); requestMessage.BufferResponse = false; - await Shim.Pipeline.SendAsync(requestMessage); + await Shim.Pipeline.SendAsync(requestMessage).ConfigureAwait(false); PipelineResponse response = requestMessage.ExtractResponse(); if (response.IsError) diff --git a/.dotnet/src/Custom/Files/FileClient.cs b/.dotnet/src/Custom/Files/FileClient.cs index b57ebefc8..a1cdb9ea8 100644 --- a/.dotnet/src/Custom/Files/FileClient.cs +++ b/.dotnet/src/Custom/Files/FileClient.cs @@ -108,7 +108,7 @@ public virtual async Task> UploadFileAsync(BinaryDa if (string.IsNullOrWhiteSpace(filename)) throw new ArgumentException(nameof(filename)); PipelineMessage uploadMessage = CreateInternalUploadMessage(file, filename, purpose); - await Shim.Pipeline.SendAsync(uploadMessage); + await Shim.Pipeline.SendAsync(uploadMessage).ConfigureAwait(false); return GetUploadResultFromResponse(uploadMessage.Response); } @@ -193,7 +193,7 @@ public virtual async Task> DownloadFileAsync(string fil request.Uri = uriBuilder.Uri; request.Headers.Set("content-type", "multipart/form-data"); - await Shim.Pipeline.SendAsync(message); + await Shim.Pipeline.SendAsync(message).ConfigureAwait(false); if (message.Response.IsError) { diff --git a/.dotnet/src/Custom/Images/ImageGenerationCollection.cs b/.dotnet/src/Custom/Images/GeneratedImageCollection.cs similarity index 60% rename from .dotnet/src/Custom/Images/ImageGenerationCollection.cs rename to .dotnet/src/Custom/Images/GeneratedImageCollection.cs index 7774309b5..78d217f1a 100644 --- a/.dotnet/src/Custom/Images/ImageGenerationCollection.cs +++ b/.dotnet/src/Custom/Images/GeneratedImageCollection.cs @@ -6,7 +6,7 @@ namespace OpenAI.Images; /// /// Represents an image generation response payload that contains information for multiple generated images. /// -public class ImageGenerationCollection : ReadOnlyCollection +public class GeneratedImageCollection : ReadOnlyCollection { - internal ImageGenerationCollection(IList list) : base(list) { } + internal GeneratedImageCollection(IList list) : base(list) { } } \ No newline at end of file diff --git a/.dotnet/src/Custom/Images/ImageClient.cs b/.dotnet/src/Custom/Images/ImageClient.cs index 6a303045e..624fb2410 100644 --- a/.dotnet/src/Custom/Images/ImageClient.cs +++ b/.dotnet/src/Custom/Images/ImageClient.cs @@ -1,6 +1,12 @@ +using OpenAI.Audio; +using OpenAI.ClientShared.Internal; using System; using System.ClientModel; +using System.ClientModel.Primitives; using System.Collections.Generic; +using System.Runtime.InteropServices.ComTypes; +using System.Text; +using System.Text.Json; using System.Threading.Tasks; namespace OpenAI.Images; @@ -99,9 +105,11 @@ public ImageClient(string model, OpenAIClientOptions options = null) /// Additional options for the image generation request. /// The cancellation token for the operation. /// A result for a single image generation. - public virtual ClientResult GenerateImage(string prompt, ImageGenerationOptions options = null) + public virtual ClientResult GenerateImage( + string prompt, + ImageGenerationOptions options = null) { - ClientResult multiResult = GenerateImages(prompt, imageCount: null, options); + ClientResult multiResult = GenerateImages(prompt, imageCount: null, options); return ClientResult.FromValue(multiResult.Value[0], multiResult.GetRawResponse()); } @@ -112,9 +120,11 @@ public virtual ClientResult GenerateImage(string prompt, ImageGe /// Additional options for the image generation request. /// The cancellation token for the operation. /// A result for a single image generation. - public virtual async Task> GenerateImageAsync(string prompt, ImageGenerationOptions options = null) + public virtual async Task> GenerateImageAsync( + string prompt, + ImageGenerationOptions options = null) { - ClientResult multiResult = await GenerateImagesAsync(prompt, imageCount: null, options).ConfigureAwait(false); + ClientResult multiResult = await GenerateImagesAsync(prompt, imageCount: null, options).ConfigureAwait(false); return ClientResult.FromValue(multiResult.Value[0], multiResult.GetRawResponse()); } @@ -128,19 +138,21 @@ public virtual async Task> GenerateImageAsync(strin /// Additional options for the image generation request. /// The cancellation token for the operation. /// A result for a single image generation. - public virtual ClientResult GenerateImages( + public virtual ClientResult GenerateImages( string prompt, int? imageCount = null, ImageGenerationOptions options = null) { - Internal.Models.CreateImageRequest request = CreateInternalRequest(prompt, imageCount, options); + Internal.Models.CreateImageRequest request = CreateInternalImageRequest(prompt, imageCount, options); ClientResult response = Shim.CreateImage(request); - List ImageGenerations = []; + + List images = []; for (int i = 0; i < response.Value.Data.Count; i++) { - ImageGenerations.Add(new(response.Value, i)); + images.Add(new GeneratedImage(response.Value, i)); } - return ClientResult.FromValue(new ImageGenerationCollection(ImageGenerations), response.GetRawResponse()); + + return ClientResult.FromValue(new GeneratedImageCollection(images), response.GetRawResponse()); } /// @@ -153,22 +165,126 @@ public virtual ClientResult GenerateImages( /// Additional options for the image generation request. /// The cancellation token for the operation. /// A result for a single image generation. - public virtual async Task> GenerateImagesAsync( + public virtual async Task> GenerateImagesAsync( string prompt, int? imageCount = null, ImageGenerationOptions options = null) { - Internal.Models.CreateImageRequest request = CreateInternalRequest(prompt, imageCount, options); + Internal.Models.CreateImageRequest request = CreateInternalImageRequest(prompt, imageCount, options); ClientResult response = await Shim.CreateImageAsync(request).ConfigureAwait(false); - List ImageGenerations = []; + + List images = []; for (int i = 0; i < response.Value.Data.Count; i++) { - ImageGenerations.Add(new(response.Value, i)); + images.Add(new GeneratedImage(response.Value, i)); + } + + return ClientResult.FromValue(new GeneratedImageCollection(images), response.GetRawResponse()); + } + + public virtual ClientResult GenerateImageEdits( + BinaryData imageBytes, + string prompt, + int? imageCount = null, + ImageEditOptions options = null) + { + PipelineMessage message = CreateInternalImageEditsPipelineMessage(imageBytes, prompt, imageCount, options); + Shim.Pipeline.Send(message); + + if (message.Response.IsError) + { + throw new ClientResultException(message.Response); } - return ClientResult.FromValue(new ImageGenerationCollection(ImageGenerations), response.GetRawResponse()); + + using JsonDocument responseDocument = JsonDocument.Parse(message.Response.Content); + Internal.Models.ImagesResponse response = Internal.Models.ImagesResponse.DeserializeImagesResponse(responseDocument.RootElement); + + List images = []; + for (int i = 0; i < response.Data.Count; i++) + { + images.Add(new GeneratedImage(response, i)); + } + + return ClientResult.FromValue(new GeneratedImageCollection(images), message.Response); } - private Internal.Models.CreateImageRequest CreateInternalRequest( + public virtual async Task> GenerateImageEditsAsync( + BinaryData imageBytes, + string prompt, + int? imageCount = null, + ImageEditOptions options = null) + { + PipelineMessage message = CreateInternalImageEditsPipelineMessage(imageBytes, prompt, imageCount, options); + await Shim.Pipeline.SendAsync(message).ConfigureAwait(false); + + if (message.Response.IsError) + { + throw new ClientResultException(message.Response); + } + + using JsonDocument responseDocument = JsonDocument.Parse(message.Response.Content); + Internal.Models.ImagesResponse response = Internal.Models.ImagesResponse.DeserializeImagesResponse(responseDocument.RootElement); + + List images = []; + for (int i = 0; i < response.Data.Count; i++) + { + images.Add(new GeneratedImage(response, i)); + } + + return ClientResult.FromValue(new GeneratedImageCollection(images), message.Response); + } + + public virtual ClientResult GenerateImageVariations( + BinaryData imageBytes, + int? imageCount = null, + ImageVariationOptions options = null) + { + PipelineMessage message = CreateInternalImageVariationsPipelineMessage(imageBytes, imageCount, options); + Shim.Pipeline.Send(message); + + if (message.Response.IsError) + { + throw new ClientResultException(message.Response); + } + + using JsonDocument responseDocument = JsonDocument.Parse(message.Response.Content); + Internal.Models.ImagesResponse response = Internal.Models.ImagesResponse.DeserializeImagesResponse(responseDocument.RootElement); + + List images = []; + for (int i = 0; i < response.Data.Count; i++) + { + images.Add(new GeneratedImage(response, i)); + } + + return ClientResult.FromValue(new GeneratedImageCollection(images), message.Response); + } + + public virtual async Task> GenerateImageVariationsAsync( + BinaryData imageBytes, + int? imageCount = null, + ImageVariationOptions options = null) + { + PipelineMessage message = CreateInternalImageVariationsPipelineMessage(imageBytes, imageCount, options); + await Shim.Pipeline.SendAsync(message).ConfigureAwait(false); + + if (message.Response.IsError) + { + throw new ClientResultException(message.Response); + } + + using JsonDocument responseDocument = JsonDocument.Parse(message.Response.Content); + Internal.Models.ImagesResponse response = Internal.Models.ImagesResponse.DeserializeImagesResponse(responseDocument.RootElement); + + List images = []; + for (int i = 0; i < response.Data.Count; i++) + { + images.Add(new GeneratedImage(response, i)); + } + + return ClientResult.FromValue(new GeneratedImageCollection(images), message.Response); + } + + private Internal.Models.CreateImageRequest CreateInternalImageRequest( string prompt, int? imageCount = null, ImageGenerationOptions options = null) @@ -184,6 +300,7 @@ private Internal.Models.CreateImageRequest CreateInternalRequest( _ => throw new ArgumentException(nameof(options.Quality)), }; } + Internal.Models.CreateImageRequestResponseFormat? internalFormat = null; if (options.ResponseFormat != null) { @@ -194,19 +311,21 @@ private Internal.Models.CreateImageRequest CreateInternalRequest( _ => throw new ArgumentException(nameof(options.ResponseFormat)), }; } + Internal.Models.CreateImageRequestSize? internalSize = null; if (options.Size != null) { internalSize = options.Size switch { + ImageSize.Size256x256 => Internal.Models.CreateImageRequestSize._256x256, + ImageSize.Size512x512 => Internal.Models.CreateImageRequestSize._512x512, ImageSize.Size1024x1024 => Internal.Models.CreateImageRequestSize._1024x1024, ImageSize.Size1024x1792 => Internal.Models.CreateImageRequestSize._1024x1792, ImageSize.Size1792x1024 => Internal.Models.CreateImageRequestSize._1792x1024, - ImageSize.Size256x256 => Internal.Models.CreateImageRequestSize._256x256, - ImageSize.Size512x512 => Internal.Models.CreateImageRequestSize._512x512, _ => throw new ArgumentException(nameof(options.Size)), }; } + Internal.Models.CreateImageRequestStyle? internalStyle = null; if (options.Style != null) { @@ -217,6 +336,7 @@ private Internal.Models.CreateImageRequest CreateInternalRequest( _ => throw new ArgumentException(nameof(options.Style)), }; } + return new Internal.Models.CreateImageRequest( prompt, _clientConnector.Model, @@ -228,4 +348,241 @@ private Internal.Models.CreateImageRequest CreateInternalRequest( options.User, serializedAdditionalRawData: null); } + + private PipelineMessage CreateInternalImageEditsPipelineMessage( + BinaryData imageBytes, + string prompt, + int? imageCount = null, + ImageEditOptions options = null) + { + PipelineMessage message = Shim.Pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_clientConnector.Endpoint.AbsoluteUri); + StringBuilder path = new(); + path.Append("/images/edits"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + + options ??= new(); + MultipartFormDataContent requestContent = CreateInternalImageEditsMultipartFormDataContent( + imageBytes, + prompt, + options.MaskBytes, + imageCount, + options.ResponseFormat, + options.Size, + options.User); + requestContent.ApplyToRequest(request); + + return message; + } + + private MultipartFormDataContent CreateInternalImageEditsMultipartFormDataContent( + BinaryData imageBytes, + string prompt, + BinaryData maskBytes, + int? imageCount, + ImageResponseFormat? imageResponseFormat, + ImageSize? imageSize, + string user) + { + MultipartFormDataContent content = new(); + + content.Add(MultipartContent.Create(imageBytes), name: "image", fileName: "image.png", headers: []); + + content.Add(MultipartContent.Create(BinaryData.FromString(prompt)), name: "prompt", headers: []); + + content.Add(MultipartContent.Create(BinaryData.FromString(_clientConnector.Model)), name: "model", headers: []); + + if (OptionalProperty.IsDefined(maskBytes)) + { + content.Add(MultipartContent.Create(maskBytes), name: "mask", fileName: "mask.png", headers: []); + } + + if (OptionalProperty.IsDefined(imageCount)) + { + content.Add(MultipartContent.Create(BinaryData.FromString(imageCount.ToString())), name: "n", headers: []); + } + + if (OptionalProperty.IsDefined(imageResponseFormat)) + { + content.Add(MultipartContent.Create( + BinaryData.FromString( + imageResponseFormat switch + { + ImageResponseFormat.Uri => "url", + ImageResponseFormat.Bytes => "b64_json", + _ => throw new ArgumentException(nameof(imageResponseFormat)), + }) + ), + name: "response_format", + headers: []); + } + + if (OptionalProperty.IsDefined(imageSize)) + { + content.Add(MultipartContent.Create( + BinaryData.FromString( + imageSize switch + { + ImageSize.Size256x256 => "256x256", + ImageSize.Size512x512 => "512x512", + ImageSize.Size1024x1024 => "1024x1024", + // TODO: 1024x1792 and 1792x1024 are currently not supported in image edits. + ImageSize.Size1024x1792 => "1024x1792", + ImageSize.Size1792x1024 => "1792x1024", + _ => throw new ArgumentException(nameof(imageSize)) + }) + ), + name: "size", + headers: []); + } + + if (OptionalProperty.IsDefined(user)) + { + content.Add(MultipartContent.Create(BinaryData.FromString(user)), "user", []); + } + + return content; + } + + private PipelineMessage CreateInternalImageVariationsPipelineMessage( + BinaryData imageBytes, + int? imageCount = null, + ImageVariationOptions options = null) + { + PipelineMessage message = Shim.Pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; + request.Method = "POST"; + UriBuilder uriBuilder = new(_clientConnector.Endpoint.AbsoluteUri); + StringBuilder path = new(); + path.Append("/images/variations"); + uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + + options ??= new(); + MultipartFormDataContent requestContent = CreateInternalImageVariationsMultipartFormDataContent( + imageBytes, + imageCount, + options.ResponseFormat, + options.Size, + options.User); + requestContent.ApplyToRequest(request); + + return message; + } + + private MultipartFormDataContent CreateInternalImageVariationsMultipartFormDataContent( + BinaryData imageBytes, + int? imageCount, + ImageResponseFormat? imageResponseFormat, + ImageSize? imageSize, + string user) + { + MultipartFormDataContent content = new(); + + content.Add(MultipartContent.Create(imageBytes), name: "image", fileName: "image.png", headers: []); + + content.Add(MultipartContent.Create(BinaryData.FromString(_clientConnector.Model)), name: "model", headers: []); + + if (OptionalProperty.IsDefined(imageCount)) + { + content.Add(MultipartContent.Create(BinaryData.FromString(imageCount.ToString())), name: "n", headers: []); + } + + if (OptionalProperty.IsDefined(imageResponseFormat)) + { + content.Add(MultipartContent.Create( + BinaryData.FromString( + imageResponseFormat switch + { + ImageResponseFormat.Uri => "url", + ImageResponseFormat.Bytes => "b64_json", + _ => throw new ArgumentException(nameof(imageResponseFormat)), + }) + ), + name: "response_format", + headers: []); + } + + if (OptionalProperty.IsDefined(imageSize)) + { + content.Add(MultipartContent.Create( + BinaryData.FromString( + imageSize switch + { + ImageSize.Size256x256 => "256x256", + ImageSize.Size512x512 => "512x512", + ImageSize.Size1024x1024 => "1024x1024", + // TODO: 1024x1792 and 1792x1024 are currently not supported in image variations. + ImageSize.Size1024x1792 => "1024x1792", + ImageSize.Size1792x1024 => "1792x1024", + _ => throw new ArgumentException(nameof(imageSize)) + }) + ), + name: "size", + headers: []); + } + + if (OptionalProperty.IsDefined(user)) + { + content.Add(MultipartContent.Create(BinaryData.FromString(user)), "user", []); + } + + return content; + } + + private static PipelineMessageClassifier _responseErrorClassifier200; + private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); + + private Internal.Models.CreateImageEditRequest CreateInternalImageEditRequest( + BinaryData imageBytes, + string prompt, + int? imageCount = null, + ImageEditOptions options = null) + { + options ??= new(); + + + Internal.Models.CreateImageEditRequestSize? internalSize = null; + if (options.Size != null) + { + internalSize = options.Size switch + { + + ImageSize.Size256x256 => Internal.Models.CreateImageEditRequestSize._256x256, + ImageSize.Size512x512 => Internal.Models.CreateImageEditRequestSize._512x512, + ImageSize.Size1024x1024 => Internal.Models.CreateImageEditRequestSize._1024x1024, + // TODO: 1024x1792 and 1792x1024 are currently not supported in image edits. + ImageSize.Size1024x1792 => new Internal.Models.CreateImageEditRequestSize("1024x1792"), + ImageSize.Size1792x1024 => new Internal.Models.CreateImageEditRequestSize("1792x1024"), + _ => throw new ArgumentException(nameof(options.Size)), + }; + } + + Internal.Models.CreateImageEditRequestResponseFormat? internalFormat = null; + if (options.ResponseFormat != null) + { + internalFormat = options.ResponseFormat switch + { + ImageResponseFormat.Bytes => Internal.Models.CreateImageEditRequestResponseFormat.B64Json, + ImageResponseFormat.Uri => Internal.Models.CreateImageEditRequestResponseFormat.Url, + _ => throw new ArgumentException(nameof(options.ResponseFormat)), + }; + } + + return new Internal.Models.CreateImageEditRequest( + imageBytes, + prompt, + options.MaskBytes, + _clientConnector.Model, + imageCount, + internalSize, + internalFormat, + options.User, + serializedAdditionalRawData: null); + } } diff --git a/.dotnet/src/Custom/Images/ImageEditOptions.cs b/.dotnet/src/Custom/Images/ImageEditOptions.cs new file mode 100644 index 000000000..8412a42ce --- /dev/null +++ b/.dotnet/src/Custom/Images/ImageEditOptions.cs @@ -0,0 +1,21 @@ +using System; + +namespace OpenAI.Images; + +/// +/// Represents additional options available to control the behavior of an image generation operation. +/// +public partial class ImageEditOptions +{ + /// + public BinaryData MaskBytes { get; set; } + + /// + public ImageSize? Size { get; set; } + + /// + public ImageResponseFormat? ResponseFormat { get; set; } + + /// + public string User { get; set; } +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Images/ImageSize.cs b/.dotnet/src/Custom/Images/ImageSize.cs index e92dbf99d..c857509d1 100644 --- a/.dotnet/src/Custom/Images/ImageSize.cs +++ b/.dotnet/src/Custom/Images/ImageSize.cs @@ -5,6 +5,20 @@ namespace OpenAI.Images; /// public enum ImageSize { + /// + /// A small, square image with 256 pixels of both width and height. + /// + /// Supported only for the older dall-e-2 model. + /// + /// + Size256x256, + /// + /// A medium-small, square image with 512 pixels of both width and height. + /// + /// Supported only for the older dall-e-2 model. + /// + /// + Size512x512, /// /// A square image with 1024 pixels of both width and height. /// @@ -26,18 +40,4 @@ public enum ImageSize /// /// Size1792x1024, - /// - /// A small, square image with 256 pixels of both width and height. - /// - /// Supported only for the older dall-e-2 model. - /// - /// - Size256x256, - /// - /// A medium-small, square image with 512 pixels of both width and height. - /// - /// Supported only for the older dall-e-2 model. - /// - /// - Size512x512, } \ No newline at end of file diff --git a/.dotnet/src/Custom/Images/ImageVariationOptions.cs b/.dotnet/src/Custom/Images/ImageVariationOptions.cs new file mode 100644 index 000000000..129c14cb7 --- /dev/null +++ b/.dotnet/src/Custom/Images/ImageVariationOptions.cs @@ -0,0 +1,18 @@ +using System; + +namespace OpenAI.Images; + +/// +/// Represents additional options available to control the behavior of an image generation operation. +/// +public partial class ImageVariationOptions +{ + /// + public ImageSize? Size { get; set; } + + /// + public ImageResponseFormat? ResponseFormat { get; set; } + + /// + public string User { get; set; } +} \ No newline at end of file diff --git a/.dotnet/tests/Assets/edit_sample_image.png b/.dotnet/tests/Assets/edit_sample_image.png new file mode 100644 index 0000000000000000000000000000000000000000..869bb1e047d7f3e5f9c7cee379eb1a7859210993 GIT binary patch literal 846285 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

!(5;Ontjn19`9Yk}4{Z}MK}#lo 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

kKbe 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 z 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%0ApWHpr^jv>gm5g0J;r*mWeVJIG#K??u=w# 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π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 z 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%0AGvct@ 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

OG2&IR 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

MDnCf=ckZ|?=#(5hi1=PZ37S9Z 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%0D5pC8VadZ)< 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�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�CGv~=`&LDT_P8xp%>2eCBJ5tQkGQBW&o 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 O1zDCa$!~&2rCof{SeV; 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%0AoSl$YqtC@lfh4AJAWuG5zI5X7C3s;VYYMX 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

NkUlijq`4|b608YrT-WStbFh@e) zQ+T{9Vd7GIlm|luWDr2*DdTZ*TfdOkY4YD^><*)_KJZnB@mUDp#qb|RkUo8u@hO*h z?wz!IVU}ROj((1Ycr9i{!>rp&rrq8uPQCeJS?V=oyh0`h&7f`URj>KV$(6KWPeCn4 z5wP~CtBoZo^rYL|>p<01y@=aPV0<2f4Ns~Iji+2iJ$c6pLi2>+6`WpC;R7<);Wvgfn_CYN zP@hGA<}8i+({)V^5C3!pK8h~_n>2XN(i@^uo0;biJk$D#y*evc742 zLRr=W67~bDwx`YLbkJr~{RQn2z0bcFwzI#5gwA$lKR?z?8M$m@RRCAbh)bgs6O0^G zE34F@F$3_XUkpCqu39Lv((rb0=7ih3%Pu3z&(9E^;K6Fxz*Wy(t8T;%{a*1YGmPBJ zKU=R5v;20Bn94Gm1N8`E9t~_&1n{D-YGoQf(1QpcB_BybQ^n$I5#_Jb^y>kGjot12 zg12UErrc-YTiN5w%iKy>d_<%#+om_y-;bLX8Q6Hb?CievI`$@1L!HmtH?#1#X9=!c z{$cme0rN(I;E6Nee1G1nckcLDsO0mo>iCk()>8?>yhiJ1 zNim~XSIR>ppYw>OmM@~Zr*lA6(~z#G4&Ok{IhYU=R#{A`y5@tQj~2iKh^frfA-c%Y z8r{Z3`xsHSm(ys!u~@|+y1~#DvIh(ZFz`UcF@g0vM-YW1sj+eyN;uSvFIjO_AI=xW zkyijz%$}K~Plzx+{Ns)ff+V3U-gA)AF8(y13x#PjGr#xblXK?H0I*>qI2%cBG`|cw zd6SXwOVUF%ZjgK|GoBhEvnRU7$p&$RJ;7Yb^4~~Dvk+X2v8@$qp&zebLJ%hB^EgBe z{zjHIGZMhRrUr84aZT6PY=q&%J1KvB(rqeLN63Lcp01xVmAaza8uR+Kl+Eqa|KsSo zOwcU*cp%Ry4@CBN2+0J&RJA5i-u5Qk2Y$WSmL^*|NDKdzWlE<77L| zzV-Z`@9%Hh>v=w(&-?Rv4|VltN~S5s_wL;b@MsHY515gza4`|PmzQ(WVsMc2OMd?T znT*ZJkoiooddow}v&*=~oDhP3O|}j3>`y5l9_u^i*L^yKgYdwuKJbK){!vg=FgGbm zLyel3$RAcoO<=B#2V%gYuxsC4>~vVL{K@Jm(u-@Yu$_by5y;#?g;_-41ohada)-C> zF~9I8ULF1MjTSeDGhe){c}r)giCxT;@P4Og-g6V8Sbx^8lx`$7aKvd22;F-FGdpwj z4M*}D%H`EVn)b8XyHxosMLWONb|D$|xL;exP~D?a~x+pz#m-R<+7@<>KM!%q%~C>40;rDm(ORVsr5!s@YQe&b_u8s!&?G$Fb$3YP%c2) z8}skrbBFD7?qH{`;r90tYh60~0moFB;hq3}ULO!?jFbXy1J|btZbFG+-V3Y4vHl}F z$x^Gnvm}q|ilR%7T9eA&Ss8NFEE{QWbV)yn&1J5f5SQhsOvrMQC!mD1Yp?94c5#{e zkFkYQhuZrbZB@`gw+lRpbv4Fe{+`iHX6J#B3C8@B`hD8y^P{xs0aFifr^K>4C~DX4 zlzE|2yn4Rx9LDac$G3yY7ME_ideQiEhx;H;gUHveH|o#BFh!3Luo_j2F!KIFr}6Yy zJG8Ze{DbRO7pNh_9m+706u67%)!W5#@Gqm9lm@oyc4N%u-c1$q*sF+DId%^hq`!OW zTytja`gowS!sQFY*NsL-=WAvmOO|}+=|n8)?2t~c&hVeLhQgo-aw9H%ccE~Vcj7>q z{@Qo)&!>mCcm4HG51%T$X>YgJ`|TY)TMoDqe63S<()-Ondt_8^(v{nYsUJ6V=LB-! zn($|TFh#7p0ZFGrLSAs?fq0ZUM&p>Co6y3iXw*G|`cZs~$ym9bB}`hnUzX!>LKr=) zgr%k*5BVa88p^;7PuwPRDocu30q2Z`t|0<7s}hW@i z#0vrE55yY-x0sS3KRa`ir~7a8*(}O>!Ro&35rj+I(>sC!PY!22yG9yHKXL8eZM+5? zVwG{A4jvn|!Z0(D&hYTWAh-R<1%@Zc+gJ&sNK}~+rI=e_E!G$4^~m}}y5Rw=1DW{j}k@IK7<@3l?$9Z68{q~FKC?Pc4ms-_}E7ZE=SqNXluLTBOS7#9X~7! zKeQ;Nen408Hivj=!8n)K1OYdRQ|;J=a?|P5HNNcVJ@W;IL)r*6gnnUn41tfojZVtF zxb~)adNP6MeH&3kRstYk{T>&LF-pv3I&(J<#DqO{cy*%R|laX+~D>U ze?+*~hG&OI)I$l*ydrkcPfb?jCFYQ|b#`;^857G}Cyg!d=s5MMM;Y1;8OVsv=12x5 z*(990v%URg`}8B&b(OoFD5*UJT*x5iO=6WXebdOac|Gz95G8@e+-ci-BXUtZerr*x zn;T;ac!lRBJ-9(o|8av|a%*$)iG%*3v}yDg4O__lP1=Eceiew9M;y-kT#nSsLJGBr zOd&3RKFpupPJZm*_rfAn0B9F@PrqQrJ=NQ*=6?8T)FYkT8??YshiDIi)14EPpJxyI zhV5#P4kbwCKXiKs6o1nBqX;6vX#fN4P5m+pVx{?8matpWgI`ZwkSX=nAzm-ca#WcSq?*KIc4Gpztujpn=8%!EizVYG4!$UA{KEoZ{Uh1rCGv%=8HSyzt8yc~z!FBNbT z-Z47+hYFC)_;L^Y1^OA1lOB?D@sF)?x%hFZf_VOQZ`?(VDI-`kIu?fB;47qU28XSy zGjl*EaNSIJvUHbY6ykl?D}by@dKk{H>l=szm!Tx5%XBoH*bc*(UD}98UYTe*GkO#V*x9q%W_wWj^9t@VvIlH}Ix!+Y@ci=Cx@6-ne z#pXQLCM5nKm3-df{wqCe8~H?A%RTSqWlk@fqqAv^x(z1Vh#J;gZu#_8xJg02IQS7XzZ}F9OIa;PHFLRZc*ts-pd{FGul$ z%f`GMNK*235XX?b{@uU$OlE2K1fq&FKLIO438Q(p)j-GN20@sR5n09bp6=8q=JM%g z2rjmJO0k1qbHlD2#2_%%KJaHwz&fZH^11<%Q*61xiK{8kD_LeWb8llPv;@!@mVF7- zZKRMd6Z6+kt)ZAECz$KFl-12|1V8;fltk#z{D_MB!BV zp@80Nv^XRl=vSM)&T`saJk92##ce~$xysnD9-U$eYB)d$3SsuLh_$y*Q%W78 zbakbhQeGUvM&PXith#!1zWZLR9R8$)s@DDYY*eyyJyMcimA!#Z~pQ%%E?REkJ-3Ac|caI_PzFU zYkG(DI*h9oloYa`9KZh*_JC1-u#VAuBMAJK=-U$FmeL_AC)9b0ZvPbFEs+VGET6EN z?SF{I1-?DGK9tK@ft_m?3z}Q-2-^H-_j{M!m-&tmH{o~3ATy?gv`>a~+}4DN-~oP4 z6clxB!Hy<)uhHu*ck*+*2O4{u@|l~ z+`EJaehx45P;kcI9No9hjo;nK!jc7^pdSUciR}jtD}kPZYS_3yIKDPE$V@hFi>ngQ zKHeosq>?m*Ud104Z1S&{wx2f%r zTm~@0__Rp;;@j}I3wg~q{`a&arOChp$3twpNIeE=uBtDIepf^|=CyKf*Bd zT$+TFg;JZPrHI+LLT*<;<2I?$0zA%qkAud>c62XLAvb)U)92wuKNSD^-qHa`!99im znt;k4CDorC!hqg`{AGwRS79xbqZn(Ged3#7_9ajV-70}5F0?P#KDdhn)<*Vp$<**i zaiM*fJqbKheK>0rL_nFPa(pv8_0aeF#j8psETMCV7~_E3$5KKKmo`K)JY3&(O1hG% z04jMr+=TF)<^K}!GBw4E&K^|+oWFD3LX}8LovX^i$sNG3)1aJPu1 zfxy1%ml{TQ8!#_93pBTAn`LgF%u{0PRBfycO!dDiN=rI%|D@5Z%fzIRs;5G)CphjV zOFKXJzA`{K{?iHU!>-!5uEhZ)X#kiuPd{hh(RW#=5FALrc60KpEkp*SU%}V4m)tmV zUatfDwp%$%o+qzv=lEFA+x6=jE_h1MvHOFpQO=(!eDNQLWvq;!cL!R^zf_1TO#uvm zyib(m_?D@s!a?;G{vDRvbDHt$9w0PYE$QuW-73k!&~zfj&3!P!3XiG!zL(2aQH z3jKXaYAwb*3N-gVUXlW+0Sh*6Vkk4bilYvSFgbCmNVm+^QH$8C2Agas@1T#Tc|+%7 zMqd`UHHh0B9e`M38(pVpR_OW@M8*u~epg?T7)X1^{NY_E9voTA4Xi+KAF^5yhN3zq zPYMF|W+Wo>dnymVBD8crOt*Jzv)E@*$lM%AK{Lc&C2`1wPA?oLC*VlB6p4gqY!J<6 zCNfw1veaQy!xB1@=rB)WD3fNnzusxMzcMBi1pW#(Wy=Bao#6A#7+E00(dzSXkG^K< zH_T3VS7MLS%TlaaO^kcaOk9t|mt#lS6?KbhrrerGH%3R_Y_pHmUY*PA<5cCcS-ir4 zGVInJ;EQd^W&QzK)tBE||9q?4lOazT2a1TqIM==>SI|FZKb774{LSM^V(V*eS%nSk zT|!$fOIjr~>Lm<05_MR)>qWtEmRgTJ()EdS4Ap!7#?sdN#G~)$J#rjx&a{oXXb4M! z?hj{PZ@K)TDyGRUFS&KnUsx|H@|OI>nr`{M>LH%EQDoC8^Y5D%Ceel8(~m@UcG5&j z{mk+rN99Wk2ODyC&sLx;)L36LZgYI+)43>SKhC2@< zC4dtGWVKLejqSt=Jb}68q_Qp1MZ5@^H2VUT;R=a3q8 zU?^I~tn8iuzC~H+lVt$RisW|Yb#(bEy_~I+0mN=e9nkoK_xopkO!*>-5A35~fRU84 z_v`nL*H3VGUni#n{plPe*lE%PP!koPj0YCK_o)NB<2R;(tcbkx?0DCll+;v|=j#`|t-Gy19Ahka>VX$7lsoVxMp#(p|1=vJ`SmGu~-i<6HdF zMqv3b{@~EViTbvUJt6j7dIJSFAZ*^9ZuVeV?+eQue)Ih0#T@mZs_xAFw~w2*hgt7o z>BIz_A;&%Wee>fA?!O>Qff-}pa@{MCY`w1G^vy|f@|X4v1<06W_vpWqWT*QS(6gRe zaJ-r}7SK`=dg*;#O~Hr)IG@aPvd)xJ@j97kwfnohz#)rgYHUYM3am{2-4K>@X;S-~ zouk&+!w7Kjhmz%D!#9ZkG>F}PAsle)6t`F6GUFYkWpz*%n9x0A=XJ7#*ihM$x9y!} zkE%3REWU;|qKKp$HGwf7kNd9rq$gm{uklIZhXAg5e$pkMyMbj1*a%>KXHiBLh?jso zk+7hmAH29l1dk%^3{7kLZeGjh=8y$WdP%r1mr(Kd@z?MnQ}tz;f5rCJbMFQmD&_M! zo^|{Qd+v|Fuh-T0(+kWqqoX-FsE}{v%c%$9nEl^e@c&vY8ItlcFEUxA9jXneLmRsY zT=U`eWe3f#)So-R_o%Ox>7RfrV?mv@o*Q5%|hHRI>F<2Zx&st;)Ti24wu7`?`G z-hQ^3ztE_E5Im63m~(4&muyBGM7Ed|ugHWy24#-jJ=7%k~-Ft7iO@=2Ww%WCe7$pA_^55~n1Bw%S zzE_LFj6t0%J}|0|BSQQ%9^2j^(Fh0n0+kT5sP3MW zwWk1F|4jQDhR3Xb|`okAB9gd9BA9>XYaIh>XB zUnWXN0C*&6=533LCt%w7CV4M%X-3mlctAZzM!mBl`O(cB#a2H+RY(;bnn8IHQ_+c| z|Kor%7eB%6BB9Yak?IIh&z! zYsG?Kvx@|);WhUWpl*q1wapa|=5i2ENnWHT$2XEI9|ahGZqqptv8LH{6{nlr*m{fV z7lj?MU}W-R#DQk=OCZW39yP<{MZ z>6Z>>lWN(~n^&71|Jbx@d_O7Gq?Bgz_K2Zz>u;myNq#E8^Pm_xX&U}DCx9}XbA=Ht*$N7feY=P`i85-=FUbj1A8??G8PwXgB8d7sDpzqX28!fsuK)elVi-`u_GS)NFKVw!IR-0w-hhsY3TeC~cp$Lf*8 za8iGfL=BjRia?sZC_vzAQ0I^G!6X!;wOn3#JnZqTA zJohF75ISCX;-Hw#K_P&tkB6oh)~(0d4C3%6S#+NZDrI3bzF;YE1ibkI1%GVCra~oY zCEN*!TG#}U9)DQzxV6A!5W>`boa=6S%J?ieM9@@5^50sT=|%t!?|04qnoc2jM()#V8Q;6lc3-L3IQHm?Mu#Z_aQbF#Y6r840D5f#olcIh(E_ zHSM(=vKFI~Q>}73L$qj=0agobV=}alWpoOf7qokT zeMLRc*nzIs_ebJ>se)!opwBW=+S-_?8+-l9 zRA*Ljbw%ZMN2?F4tRw77v+mU0t?0!+azb4YWNl}dt7XLnF_xdFF}F4cmcbg`zdIez z4Ywr0FfIUdXq^WhABu-00M}~k_V-Q*Lax-spOgTacj2?u@8Ls$7qPs|v2ZEmF)wUK zKxG6T##J%Qcc!c7A`+RUO7e{Ld)<~k^}bE4>S}Le?wn?6(OJiUbFH0!-yzf9s2V)f zPu4IC>3{mS!3+S{oj7kuv_3cra+}OeyeE^**`hw1kGX;HPFyOB;0`@>>u+$X=q6}! z%|B%TRD`pXn$OgK>aXY<)bAd`pGSRV*dq2VvgoCx&i3?DSl z-ik0*^9^=~?J4{ROHXF9i<2UE5=x63&T&IHuZiTt!H;}_1P&&xUo-?*ElAjimrV`| z?yULwLX)Rks^Uu#w`PFW_bB$d!0p@3LLc~0Ea+xRSBJHsm{CBt(E-JX3{iZ`KNdHw zSaLmSoEd(w;!lZ27C#|5K`8VaHUkR#6c|6eDkc{&p&t*f09;2lgT(DZCMQ-Pee;fr zd`UcM);+1ND1YrXNQEB$M5-`+I0pO28q9x-?b&85FZ=N`IDgrp?W^lj&|9K0UYsw4d zd%{p|HEce&*QZ@0Rr`V?xPh0m2afT>pv7xyRSAa&&!StiL^A|iltm$P7!66(2n@50 zwg!C6@X*`t&iQ18%VFIXu-`^M{+dX+&X*3^phKoUE(_RKRMRbF-VnNfcMEGQ=1*+q zC0gBRlRDtsB5_+fvm6I3wn3ya62v-;J4tfMOFD$vlg!oRpYMms76%P*)N~NHkDo#< zcuBxw38q>=)3ZQADkladQ7y(TD3M&X!IzH2+|3#iyR1>c_y>{3?f6~%wsY%Lh)h5; zD^ZPoy{uWO-0#diB!4-L$aEZx3$h zTM4?j9^8l<0-AoJj802Ql)E2Fz9sALVH1BU{X*&8N1hq=aa;0OX_sG8ljJkLUt#)} z^MU5q?(h?ML1cB@@|8kIKmId5hchR&yJ+a4?>P%WroBd))xjx)1|5?v&;P=w&MD(7 zv;HWa@B5Y%m_@!rA)qiT?5Rzwovyaw0GpF2Wq=0g)|Ze!1I)qsc`85TRSgCbYi{o` zh*d`ywj+OQA>4o|eu(bQ|7ceO@^dfk_2fbTMZVPUunEYStCEQAYDe#LAYtrbKOZu4JeY!{uklHYJrv@$F2@^rYEzy_BD zP3K+}KF=EOsrvm;v)Ztz#B@9OPl6W|fw4Ar!Fxi2&{o~@>Vr>L48#F6Tljdd$Efb^ z5ujOAkC)c>o%eK9A4lJhlsM5BxyLePep=?vGhX}*tEStWh)V2Jc%S^~rHi!sH^M&# zd`Ux1{H#LbGkTp}ML+$l`sBpaQtT4WG&Z|m<3Bx8$Px7d`7~;zD(b%a<;;=cW=%1_ zP=eaIe*H_^+IDZz4nvlP9fquL-oH1!u~&0E^5PPH@c2;{5<_h)KhK*#xDVtj{P3(T zJZE_Byv)L?>W_b0r4@!Od*dzU-j~)qe8J68JND};@HI~KK9oppCF=eWF8tR#8O<%r zG^ArIk530ibmryh3P4djy_{2dpvSXJ=>L9;$?}0?hN95B*$6GH#&n2DL-LmBKJ^HI zn&svISN?;YbQbbIKTZ~ChMfAoFTxvmg`|~<>aBYth z;Hg?VQF!hsCj8hGlxF}cOYGb^DA zS7tyJl@qlAWnu!w)ToAWzIc{0jjyW5Z=xG_o;d!TU2T6Twsr~UeoG=vbn|Nu(~UyT zE7vR4t|olz5Ibo{d(lytc)gSunvn>;^eqjliRqE*r!K~dq-^2dtG9{)(3(vT;@ec< z)Znj~=dUJ9#oVM^TSbgoX*vcZU#)mpC&Pet&Iit6Z?Mn*jVViGpQ^dRN_FG?ZUEVI zN8yZCFz%c_42WXS(axQH*ZE>rgJGeZvshu4w0Y0V_%2gOsVjVJAEaC>2@O>xS4ga? zB<}7eE9|SJR0ayQi)w8iuG}uEte|xD^l;K>hQVyVxnDKfK@V=0Z12152BzRDaqixk zb-~wO)+I8>Bi}(P{++nH;u!X*Bl=s;9_E?7Rt_b&XdY2jLbP$zIWxZAx)Ef^LlnWe^3A8DUtaGWy=%Dlh+|Lh9R7A{B9&EOx$%Vt zHdaGtU?|UHe!+b?bvlx6E1_N8T?%!J!j zv2>PSI6MJYf8fID!@gZX!(Zp6hA*bhPe;^?Q^><$-}mrkgoQu4@iQl?>M*{5V_3p! zBhYp7&w)k?VcZZhjsdF9F}y>vTS$-@#ZdiuA_s|zC|*u?9M`UV2FZK&=e>WavLqRz z0w?W0x;6xlU6ciGnOWXJcewYcK7J19GhvzlgeR5pdFx>}j_YC`emr1Ya76f8ZnSta zFa|eC+7d(@u(=)HqyJ(E5YoUW;S_5wopyw)=_JN(X$3-yS7)+5aqF}ztlzZbM6?jF zlgUAXeCc4)u@#pt*a_JvtMV6{N1>8+^E7!C*V++4A>CXC`OCb0`2Ae+P#@0uLG_B0 zqhyFb0l?^kJBz2iqz<8=*D*-hrzyNq4sr!?w#EB#^dA9UszNR+90H_jSnxCQVF1O9 zXUUyALx#n=up;-Q0PX6Ybm)?T7bL}SMlh)hC%5bYKW(VF;!^-I*cA@aQOrq{bpLli z@ubNa8aYMSZG0>z9uHu6fNVP7hB-m)_X@ZLx`6+gH9@lqFg<_H3*bWFC)4eO}KvV-kOnF1q2?Ro(1o&jWlE zhB4wpk(vf%!O0h6E&{}E0l`o6t`uZ#T(((y`+JPXY-pL|T=BGtEsCA>UE^N!4?6M5 z?=cS4zvUb2V!t*eB_ilYBlxU-sW+M`TIok5zvKU|86o&Uq-;1I77mmB|_9f^4QBY%m~zGQ1-A)yk1bsQPE zy$Wdkz1vljBAw2{d8HR}^)3X`cxow29Wu1eH~C5&czLL(d!uU&b%TSxF!y%!1mXOM z$*P6#Fy`L&M_T?a0ZMy*((4O^?apq>0?u)fOz=mMQv#7S=U+rGTIT@}%aYJj25tlv zwUfcWpQj07)b9tY+VnbE7PumPb3#L6aC>#)V@USG=Etpr`;l>TAbp&V0@7=DDLDNt z@Ujf(kJaXVHon6IVH?!3r@&~S1*p8<0LhjhXy1IeIhIiGe?zz4pY#;u2iQwS=3VAw z4QXmaxy@wA?fSZn?t?)N!y3?E(Rq)pPLC6U_Ti4roW<3KW{N5)*v+kAZMi{(=~MZ4 zT<^vlv1nz?T`i-+Oo#e-N|eYVE3*%M8$&dJcFpOsmfhxGO9)0`@ghLiOv}7rY%B1| zSO1DZY2CY%I$X1ccFr>6cUV~pu@cHM^ij9hN`(TxT>Omo+$k*qVW0qtsF?Y0TxE*> zWnJ9ckDc{s%Y<_Py^| zqun5F9#A3Mp7`PAFSB0Djx(blcD+4cy{&VB4m{4rK|ppnPpWR5u0CvO*q%odp~=OHX-bk5)Emb6u~z$$x2nfi)OGuv zSSrWCKSdQ_+}hgq?hh3}gGRWpWq!B{z<7&5ExvGDC#Vd;9@*$_bG6Ub>@|maharYb}dgw+75}WD^@Wbvybi13|=v!K5yyvf^u+GjV zGvfw_Mdh?i<^Jt}AitIYzVH#wdN1|#-=b54kk;o@O(sG08ac!%P568}unAT+paJH?Bl&aa~in`j5sKGuPG!B2mGQ^ zx0&Qg#}kzmsh!&eCiL@1I|>{IX`NniD^6say8$?^c62>>es|CYMBA-^_=o81`Aj7W z*rIdx)rIQv{8o>RTis4tW1lIw!a8itKpq&6E1No%YlQH5z^($qm@~5bSA^jbPWEmy zBrX%mXan|MZr#qFzPpI?@)!iezS3{9aH}Js?l26r^2G&&WrngRpi@lKzxy-$hY#!o zNhqIL-=5t9H$#hL0F5uC&GCnn>H>?3=ge9cJeEtGV{!iUN?8lt90Yq)(n<@IO@>ky z@2FlPmfzD>+!kQ5QxQRT5pXn1EdP4A%ApgypJW!Vl|KCY6g;SN4fCr}RA!*{-1dgkS`>v0U z6y$s~MVuULxgyi(RMQ_BT6Hjec{Xs7eM^@g0@ax)Kz`AS4|3Dt+4h|Uas!H~PXS3* zEVJy`2VWyT6*yoAo#(W1Rn9N&M4uofB%k$l zz4~3u)<&L@n%Xh>Nv5>6ti8gS@l<=X>}#_D2T8YRHr$z{EePD_(kL$ftp-E!=@{Tq zFu6%sf-}0p0O!9mWpRS>AZ#V~&ScZWhsy zqW|qiG*E1VP8UsA|D=Pqhu%6&dC^L;J7m2RBbQ@MVVw2wZ8mf*w&Kd zKJCvNTJ&z;zw+!=;XYdhHjdH316^z1B!-9qPBH*LFLFcfKA$9@8qn9eD*xbo6Q3US z65x}QsST+DRR2>W3A{$Cbux_vCirx4(OcFmltuwYPzY=s%YiN*R4os25 zf(8vG!h)CMLqlB%%)gM6hj&=0W7zJ7&Hl_FmbSCGJXb$I+_7w~k}6tLSQBt3D}ilg zt^_GM|9k4(Du+532ZJ+L6ysORZrr^a1T961+Qd_LSpJuW=HG-&QCC5|!U~vRCa`v%7x5 zVrV#`>+_3~qvV8p7;OM~K?6V8~7+9vY>q~xfULEJjL^qW(_y}o z>A=*~G~1AuY1p?#-o7Y-LviA>m7+ijuTLQdvZI_Gg~fe30##DuYPg= zrsfx0vpDoD+x`HwmY|})U(v;eeVjHjnM4N%#Aw1ucIJwwX?;SdgFw4(09d(Y%GZTP z9a*Qbl-(t zJ2zVPZhqNc(HcO$kYe!~vgNe1i(vADeytRC}z&`q!I z0S_`XzeOUi39C1KMqHa#{ES22$^OTPFX0AOEcsBLw9Kv5+NVtGg=?$M8yEfK3#>MF zg)U7*-Y3l-Ukqd*;mZ4jFcThj*NtBvqctm}Rn#x=U&EHTXbyP%79fEDjuT!%5DkS|(VUg*%Dthsb8|B-|v zxPitK7|5+=AE@Ki$fF#0W*8wgsy{byWdJ^RJnPx^-U!qQU;r8rpu5j&m^ARy9k$*M zmgY&@IA(e<$^nSgq{cWO+kl0DjGtNnrmISv<+`ki`-7 zmCld*6MPoFXcJ^_+3BFu-6P`nnkVV|AGa!+wig(yjKWt`52kjj1(h`w1DCy7)9wayb_8({vcYaHSb6(m+ZkaIaib4<-EM{ zM$Ndd`jKqAB&s^m-cp8_6IOZjSk2M>#owDq$ z9_j-K>Xx z{#x##L|%=|bKZN=95fih4i7q6?P&kxrYa867tKW*8eQvqTyt*TnehZ-$e2C! zG3L%D53N?^K1Y=o9N249PDeMBEq0;L|H{VQgaK6tb#CL?kHTqjgtx#HQoBeLN?QdU z>yY_Ea1K=HtatqUZOltFib;(_*D4a9?7j{Sp3R;^UE2rq&9jn-q12?%0Bq_+*u78N zEOO|b1bdw!htj_z5z$^81l-49V*J(hjf;+R~ zxo@@Hj_IqCxkH85iJuEzavv|JIOkWA&@9D%<kEoP58-qN9t?M8DJgPHjQ|joIl)?B%dgFy4jZdt$pKu zBoyO(9_v(xhJ!+jA-2QuC&$Nr-8FK5m9U=K!(ICR#P6ZoM)P;u-&f1)+x>;rxUIRPQX!HgM4X)_7!g3LVOzJS7^}}ALGx@@)10QVvhei zTi2F)Mg26MA#kYTjG^e-eVFs|WkH|8Fo^nb^*nFR%$EZN}!oQC1f zWgz4jDYnlS&n#Rb5;;*m1Sl#Gx+B1${j33As|h$t5!8VE`vGfWzVa&pptDWB17ghr z(OS@e%+`QjX7UwaK^|Uwa+?S6`niOxdL}jRGzU0CCO{R+%)aBB{clzn(_j#OcPirG zWtKtNI->)8{`}{G z9Z7Kh?~9HHWAFKb}lQhM60TmWlCFJWqp z)Zt{nERiSdK5bH>nX4Ov+p_5FT%sME=DpFfB-{>s75wwXZ zs4J|hFB*b__Hp2{QC&RRly0R#>tn~%f45|{9mb4-bD4wsdt}qvyaIaPf|f0yEO@Z0 za&ioS>(FXs4)t5KWe!e`?m3NoibHFRLvFE*`k;W^y4@`W$i^B(>k@~W@qNmLl_|hw zFx_N?TcDX6c+^Jcdl}h(aZK|-;}=eR9@ytNrbw)+acHP3y~>^$^V(nJvHNxvKVR&B z2k$QBqX`GXfxyP^*s?iD2`!5(e!fDmb5L}%I@(bts_=TN3>#`3D@N^BTX8o}ylOFB z`uXv@@4%Th?R)=iFK&TEGw1-|3?pslsHZoiGyMvm^s4n5yGJga0Kt4Xp13OkK_Y;p zJA6zI4j4_r+8kOScxiugly73kfjHqe@&65jA^XoUj1+it>%uvkB2&TbS_@-n(#iu} zJLA(_`l-SsvKR_@asn?`gMue5z(*6p_^>&T74$I@xrY|r;rMy@f)H%UUy>s)iC^#4 z<)zOLTkFE|Xo|fsX>l#I60`vq(nkWZdmKBG;@U5oadNsBBu7Kp${-HtQa>(@P^ zwr3_VMOFbOq;4{BeYU_?`hcA{ny%OJZUW6;#kFs=a)&p}Q~P5{QoLM<-v-Pg46@nO z&|x)F8c<1=BHpp+wjhU!2rm7m%#)r1X2814OMweM-->?Qgx#z z0#JA{@}i_w?sbR;q;I&Nb9L#9t3jU)D=i+Eh1NRtdxA5?I9_!qBK+6e>*qvJDz61_ zjtyMANQDLKuf}X|l?>_4gL0i8e#w{CD_!UHzt>grDabeULF~8uXf>XIkViRZT+Pl( z_S1Bb+OI{A^TQRArUrJ+k8(tIxLD<_P@n;^zCrYyZsOhino^dnp{YP~5 z-fd5d4Ov-(IPA3}UvwX`MwaIn7$g0tzT+81^AA7uVEfW0jc&;4-1jtrkf+Eywa;De zK6}{MCp*Uig@VXub%khdq%+;H;xezzXums@^k@+)de|5gk z204ZPIRM&`LvaKEzbyeH_1|T+WqB(BbZa7VDhlE>;03lICW;KG#RcpJp~pi!r9j;8 zwg3xO`1t&zI^hZ=m)Lo(aNWof+#fh8ny!WR(u;~Zaf^-Hofg@jvum6Cm_JTQmP_r5 zHu~G1EO^{^?tZ#u(IG0+Vmegt%o<*H}Bj&ITXfvp0L{pm1xT~Jnf*TUjM`QrQ&i>rw*y)wK* zt!{%xNZ?Y5l=S&m&UQM1+ggGG;Z(7PXBtI&$_87lFfJ&ozzYQ;T{8r$CifImT6l+- zmoD2_|D&L#<$D#FR97(y=;>L{+dux`-hSKj>RK5`accMXYk&VJmAp{;KK&OUiTK>R zlq=?x?sPNF~QuF5$ZZJ52=9|ZdtmM%aW&hnm!X78% z0>{HUbMv$4-W<^33Cg}aedLO&U>*n1+SJ5Vj z>GRAFTIzViF~UJy*RfCAiA@$D%M&;q$4cvdGQxv=>;lv4cBx|%MC-Ki=+tICoN~v- zZJoo6!iF#2;~`7E9D9WnUb*&l@eYZ>vs7DLVERGK+0o}PI6F*`D7SrcE#dQn-2*}m z@lbgJthfVxB(3l*%Goo6_3Nu5$OXB-jS+tuojL-g*dv9;YdE7%I2*Xo=$dDx>Qp03 zaVi5Sm#W%r33;4tG9Q5tq95yjPvn{kWStefYua1*{g}JIh}1-%GVoF|PpUlc*3Qr>rF?X#Heqho zO`%11t)wN6D<+%sT6MH><20 z!d$9f0^Rg4Gv;L7oUwbLgePAV06A5`t4zSQzQR;njAtAN?0Ezz@VN!}U-8_9g8Fj$z+F{6We{BxeHo$L_tm;E{#aM9~bJ#V{{?Ic8Lq(&0^)m zG@dkJ%=Ko>U{kjR)iR31+ixf1Sgd_<($Q9Oa~T*yArM6b@78sKyPteQg%^jZ*QXF~ z#p+c8C-|-)PGgsO#GNTNx8S8sk1}*h`#z8po(TCW zc2^yK|K(jDJo+F{bcOS}HCI-biwy#vRr~dX?Si1=K*k+OC%eCYJ9juahc?ZNh(>?A zVkQQD^ywPBdw3x^Yz%>7;VWQMUL0ba;x!%UqS?#Z47nkN+tjD-hn;zTVx*nBu(4a4 zV!Qtq9wjxy=8vpbAIQ)GAhy-}N_T%dnKrATuEv&RozFo3Cb9Z#-&8R4IskTxC-7D* zb5&Tj6xz_(`R$pU7fbrdQ^eCZ#I^J~@9ASic+Oj@eO6lx58JwJV#tMPh9-tR2IM97 z!O$6`3Zr(Q8^N02F5?m8N@l@&iIrrC%W4P5C4$t^q1Z<_t8D@s?7$LTc=3Cu<4%T) ze}&xrcj5y$o5f+-x42y|s#S#jr;1QL?1G=izi%qQ0HjVxt(Htk2rcKwG>qOzYqJ5~ z&!09s=5qoT%OP&Gt#fICk`4Y=tz5DR@G7;(_bQhD~ z4AU@;AhF36Tpr6B^b~KX)kC(xQ- zo>NGQ$2{fM^J><>l0PbC^BY|rnc^z&&yl|Ol(Ibg_TNO|*s}Xc+|OP!^ZVW@R|o4z zy5kLY29<1lA9g7QJ+#Wt7@brc|2uEuFlOy{azlL2F1bg{6OM7?T*W*Hu8%6-?eGtm zmxuz&e7{)pz~H2f?ZdtSrqTAe&`;Y;L1yGO0pH}nkERL}u=DsyGB( zOsyyI>pnZ;yS#6uzuJCQD1^%ow%~`CTI1z^Vl$sat*HFqoHWtUBr|S77^>0u6&PuEwcUDe(rNL6>E}}lcm->JCA;S} z6(x4oHQ3|+<0TzK$uip%+u=##v*S%W7;oGZC}7RYpWRBruX+zY8AEt z4O_xKhvu2p1KN;YLxHX+2l zN+Elu2$hmiWbb=P_9(Kl_sm7+b?-gDPrrYv`>02k>zwoXeBQ6u>-oB%H!@akwouS( z{DMXmSGtm8k?s{rq5W;bUi-CjAyOi!nCInK1+(-Fkn;Z~H09rubfkKIP{!<+obbkxW zrv*KY0mYeqAoA)S9GeNkZ&@fgA}CGbD>~>dZE))}OE&`8*xic=^gB5!bM+$7!io=$ z?%ISfa;sXdWu**+9#bA}tA4jW42Pq@kS*|dO1moLYnQ;VX)Aew8%RnK(8zdyXxJQq zHg7ti!UhTf#@?0hK%efJD_2H1@r1tlY( zBiB>8dq;tB13Gjy1qrobkJ3S>6H31|za%?Xt%yW$ySR?NY7md|W~_bw=w$ zj}}*uf<#`8ICgMNXw=up^Px01&uaw=fN?0uz1+VrQxn1%kL-X;JU5bX4VCsykAv!8 zs&7qLu~XgC(WI*hy_-#cvO%fr1c>4oLbQ-H0%F5gB4_B78-;E&S2>bdUY@3&|6m5c zj8V{|XNT4Vc`7OJT(sR2Scwe*rZs?B^*MXWzhym3(`EU6c20OUrUTQ_c!fk>zX9F?&g88odt-kSRdHJ{lGbrLHK$;IkAv;gd8;A+f;pygTPQ>z+7r@6>8lRu(5Wv> znNko=IoBQWe+22kr~}alwIPU;230HSifH?N8L?!ln7w70qW@g+P0yTz zi*=bFngbxz(R5>Js|`e91RJ_Sas>$Mv&MeEcUeC_6Dg9WG+mGm=o+H!DAGdwe z)HuYGp7RY(6AH=7cC1uq_xFjlIDoG$v`9CLYTt@w1Aiw)v7r+PVrB$OvsPhDOdn4i$Xb&EA$&7>KuEQS$uk9EpmOb2dYyT`k@e5`A48?ZnK&AB13oikvhAjj* z0(q9*kAV`L_}g@acOi!@EHM}q4Z&#tT2|oD$!5rc@av?f8fOsD9qf4a;nr(XH}9i< zVs==dF=cB}m>ufS%sv043yk4Z#q67WMkBBzId=CO;c64XB6|egRkU+7{#?KM`Y@5+r$K|0y+KCc+_YQGVJf;{^N{f|hoKWR2qe`L$J?zx_~ zOm&l{A=!=%ARXed&&AlG^wXw^lYVoHrX-Yj#un{2^*%N+>>nJLdJ&u$3O2ZxAsmFa z3Du*l?g0x6SZrDOU=0wYLH`R+9)Q#kksmCJQHU=)ysXH&9f-S_$)TeCZ0IC`Q zi2#I48u-8vsICk;tiQ3S1>MWqA%j5Y@>xw5(Do3K^Z9B0AL$57){xKx5v16*C<{J^ zeue|Zw-ScHPqrau;#GIN4usW-IAdrfYIyo;$C<4XL<0p*?E^BAKgYQ>hzvC#x@mUF&&b^@*Uo@(pX^9X_wOv9{j6SUc4upTb{g%4?KZh0Qpf_@uoDxX1e+e5e$joRZEA{)?#h}F*soEe&%OSqO|3P?f8*NW#q_Wv;pgBg5^mWN>uYI3I9J9FfIOxx) zHaivHN_G6Bx7cc4LaI`~)XVBpS_w~{O}d%kq@$g_SEqM=Dz4W(gM@b@s4wwDTHzyk z>QGC+yxq%@Y>=5Hkj5R!v>c^k=Stp)0Z8>61n~r zuzOu`sQdfOueY_H)f83A^C)*&E^jmmKAL3-xwgZ2X7vaKR%6@04JRm*C`hS&x_;6a zQ0MHEMyK%}@L%#>$Qy~D?1V=cpf71}l@JgIkjZDxeXo4Jp2z^tW3J0>W@Dkm3p*jt zW3TfJ>^*uOHtn=_Ak#4fQ!n709-zfD4x<)KA6c9b-AlS5thC5a)x!q8zWdyt9@5FP zi^dplB+4KhGH$jqGr4QsQhWdNQ+oX0!tiK=|86vvDsXgBkLsPu)z&`U#*Sz^L2k1U zCwmJ(c|5*eG4*9DSV0iSDRsWHxak zz|Vts!&Cb1vLp7_`)Q6-7oL)1x{OhyD%C%pe6ITpKHgxsaRIZ8vKY_cWQFuQ>~5a( zir!7cEJIKrJ9I*z?KKs|#;5u#lV--j6C14~6gH9T$>#72TmJ&;W1FGFP}sbmEMr-isEeV;qw8#6=@#zhH`3tc>T_dyuoi|-cwRNtC7@24GCo)$_M2yokTWn9UUH|>b<+iixk$2mz zyd8d@5{3;9-}^Il-fPKVJ205|#QT~LOV0U$&VpDspZ{7FL27Q%v+Mp??HKX9e3fYi zUXNB&>}6&;TDEyV*ROxUrKqGhI>|roD^cZYDw8yQnX48EpfTNKvNr4a$jFMQ>hJvT z#&GJBr}$%QpD$*AiVfcIrHRjf&@N$Gyc&%2EXccCBr|~1a#?Y>nmsX%;uJYO!`wm7 z>$nL~Zf_GYUC}r0rfJ+-EBj_-qzT=Vj!OODFFst2@ilv&H8JYW9~Qg&{)C$hR?e%3 zUm7}2{}l|VK$n^c-FtVANdom6J<`lyeIjb;SQqIar-|tgR7Be#_vp9-T}Zj1%*GD$ zps^CVM#c~Z%)1c|LVSWSD@b}`wkhJ>pr>&A;w=J|IT<#pM$OG44?D+2i%-uK0nKV# ztC)<$p9kljCq@5E0nh-U14fhk*0%$Z(4B}d1n9MDJOR5^c_j=dcj|hoq8t({rXZ#LxgH@z~cn6S$BixX6LFBSK0Ksh=}^fCmR5VQcuD02=T8+1iP#%>LkJwJ=@ z|K@=`M!7Q0VdGByBB*6ukbJlm&5 z!2bAhb7S9ERTnN>gDF3hWo0gQ{QJg3v~EJkD=70p2b3Y?A+D3B?w=tgoxxXRnBTeo z(L$yCokg})(X?9@PC6Qd48LL*5OM>CZfJ3E%sdRD#Bw$ItA4 z1Dh=5fGH`&4dERGg&RS_!*8zFl{icT#uOXALp{bued(XII5fN+WHAH5zj_xQ;!#aN z(NDd%t{6YQWpS9(H0|(D8lEA{qOg|4>U+aD!}60JGl57{2j+G^8snPa4HhZvJRQR1 zl(%=pzZ9YOX(L)aN@ff1pBBOJFbuTq6|)Wu29jmZyXqQ}$}H)R;>)&O`tu(ogy!&2 zQp)o?URANGjIh1SLu<EM=&rYTgF08*(F)zs!BNWMu1Q|>em z>i5oWx6h&9KIS^n-f=}e{yR8ql!}B@&;uCGDDOPwOe+&B*ER>b-S^VT#?vY@Luo`*BF5*@C3vY^xT>l!K2+TKp;3cz)=| zcr+I@o>xv$RrbN7X;`mAY*X9qP)i^mrK^_Sv8{?*-<7XpA~od_w$muc)t12@^s77S^?tS z3`!FkRm6>=uzx&=s=d+`Sjk9$qAc_HqI80l76PasBF>E(%cp&I{O>zl(!Z7%HoOX= z>|?^OKUkX!+E6PG2c!+@^2%e45O#y=G~GC0 zO@TM}=uYL$Dc_FnY$#^6Oym;iJ|XDjV^<^9!(2I^xauxkc0Ywzo{i6E z0iUckHuB1K0kh6sCg9SQZnSJZ7^R*wwK_58x3 z?wD(Rx?^&+rpJ88Jm4>+giEY*C?T~4~x z3OX%LVL=VWId242&#btH-T$y*Z!Vm<=hsJ|8hd{WdHv&cxXpSw9T3I+%S_M*4YFT2 z11PdR)oc;i0^XVc)-_hhPPqp7=h-vQEp!x~7#pDVIt~)M zKtCkw6cE8TVg7{^dK9peFTR84xkRsLnCaIx*gG^xX@zL>0sH;y#MP6)m|2bx81lb0sN&w(`RibB;8{a~r zH&-(9 zzT9k3J6DcY79xrPYs3%*Q~I>WofV-siS|?P_8qBKO8JTU7LnbI1OY zShw?~^0I5py@qL@nSiyEk8y@Zxp=+e!s1}uO!>17S;;IhNyCpc@jtIz^A)A+;Y6L|_D4t|7?V(IZblP`t^)D!nM05^R_1xW_z|HDf38K14S2AW z=S-<5S>w5z3KRXbp#Xvw?MJ~nclohZ z`uVSy_NIvcoFxCgUT!U{)Y)A^IP`<{BZEsL?g~97RLlcn8ExTAZl312(SP^cR*-)? zlpuH~6Mp9BqWq3fvVRPuvwE$eoO#yF;T6ioY24+`?u`z;yf<>CLc#-`RLC@V@8&%J z>LR;S;E=8$LG-ou!b8I-HF?A8@{b*3D*RW#0i8qjDi~vy`{idULOYl;VWaqq#xK9^ z1(%JOB$0>A7Bv@7jop^F+)rIyPd7?^b9vr5WLCMT&rAGuE;=x_xSPv^Oy=5s7d{F2 zd#~)XwQgbZih(J2o&it?)KOH>VN`&#^%}=Mk<< zsFQ22TGdoz++NI{TPlh7yhKX>sYIBC1+bK9yBEn%({`HQS_Kij8ygyN=2O=MOc%jE z#ah*EF>UfDC2fUpKhaIKaB*#4V!WxLNCaD?TC_N@bYt9Z+*a~s^{uX$ammFG=Wm5K zfeAPs;Xn`TEuYgr${%3qq`jT?V{o2jyBgcjdtryPf2FqK{Z$#y&ne4QtjwbVvKu?P zSjmvIJc3tBX8V~=H&J?`wM@wy3xVncL5YXwR`nPk9ZVR!g?UQ}#AAB;y!;&LyHGoL z+D3rm37=-Ea~@w+STGs%R6&mqdkp*_X#c#8H8e+qlT2Z}=f*cOv%2>o;O(-ZtCw{H z_o{v+mQw*5PB*Ru+dWO&ny@cAyo?roA%e%)RS4hvzB&xvW;Pny>J#mko_`aWm3f77 zn$^CDs0v7#N1I;)!@F?FOW&_2VhC2tU&1$o=b$@ao*Unxs!8l!BYqh(gltmZe0!W+p#E!8@l}R$qT;F+O$p-Dqc== zzmtLPIXjY%St|YPBr1t7nmcir>D&O&e}sl7shyM5xe*&?d%!Cf8U0H};$f4e>`^ar+o5Nr9 zV9+_pzfdO3k*NZzaCz2U?0%;7&W+P(OIYdcjdPzDlzn6A!Px8B^?AmB)q@!)5>-4v z{^JbIr-hu0SWkY3A0u_pCLlR7dlRv=&Q|cTGcX;Chhn@zlmgg7XpGKpJ;iGb!BI&! zQ+dnRFkO#?H_T|S_U*pCC?YHSux78%@qFZeE=J$`D4+6HRkSNv>*Y+Kj`~|Q{xRP^ z2n65E?dQ4nvprxstK}Zr%RPtd?{_y%jTZuRL@pPBF;dp5f+>1ACXKITuz&q|9m>*{ zQ`FG#Zk}|=YxQaNz6Q>@p6~tH8k*DV4xM^fI?j9TkEYeyjCsM91cmpL|8LPd=j*mvQs3Gpv!r6yPdc0U4J!|BF_=_cQMnbAD|+`vTHQfS`U$N#ldktv5ZrSwqH z^LnH6J8D>P;v@EQgB+8nLAvmW%}|4|1mtmJN@+!;A5%$pqW8IRTE2xXn6BNh*bON@>xRf1Px}U zstJetb#O4w1>#QM^G$>Qu$FNDzzvBoP>z3A+CD#!^+>gLP45~4%)GrVo7%VQAD0h$ z(&xKR^iukzLR_y;k7O6X3*EGcJI~;bnCkN(qxE0%C|>%$huP~Gf_TLmf_>6 zjmLj}&+$1F3tLj34-S+4990$p3mV2a!SB?@e!muzENt2Rt*R4HC48d!^%ctP#je_0 zLB0>ek||Sc=DD>sA8s)B7^iyd5l26YjomyiKs(O@?xkWaNkHpLDn)})?g0> z=_Qh!ro-psfk+{PfOc4Fzpri1d?1Ikjzj~Cso5T=cFs}U?cZdDNDF8mZ_^##5dv;s z2qrh2!k~kbVOZb}3;Fgxz~t5~B+vlqsc_D%IiKI+n(`6Za; zm#>un#F}lUsPG#+P9ycd<-NE|J8c2UIh3`WrF6=bS-o?a^xJP6acTjroutn37jA^y!O=Dn4&*sbvaQm+9!MU?b_q%mT0WiwhIL95w5&AJ{oQzv zSZ6>9>`m_uap@ciHTZE*-Puj6YJ>u!v4HUJziBm&t2sqNVNHvmVOkS}h)PY<01mK^ z9?B4ynX#hs=2X)oP~wBfpLCOq<3U#kPVguK5&+~;O-2WRMfy6^n-a^g8|JDD0S_;Q z*EZFY8EX3P;z&=aENjzER_I*nJspbVZo?5k{sQ3IzvCTyhnmHn{m4Qdz+856mB5ZOd)~90z|-xf%->u~TN9>zIEg}x zFwf+mSdA#KA~iH|N*x7}!@@~VD`uzv`rdzzxqWi4zFilabYMXIbS&h!%YxL_Y<3b> zdZ8^0#G1vo3DhV^PBpCNzusLGHbD6A-dCMGexHnF3Y&rNm2)nVKXXzp+Wl4#84U<{ zL5o7@YkFLIe|*Kzc}I+4wq>6{hn}gTD(G>d2LT2B2#O7Z(ZFTZ#=4%+Y?hy5`z{o- z?WY@5g@9bpM~$a+(FoU-D;R^Zax!RUsDbWLf$>3A@16^+v%y9+8rf0*05sCHKa!g9 zF_8l#Fwt|@$kp57F)_w;;8lmZQ1%)cl|zr1nV=Cqc2hq_-@;g-CKe!FDBg0<-ac{) zqYK$Uc9NQ}Y9a7#M$-O!d9w;&E``?NlB0b7J(M zLuZ9&ftLe9YVKF?2gFX1N0ZQUA)#|M$HIUNB?8qH^2dY#P?toQy5Rn)FC$aktUvk> zdal#xA|>Kjk$6|G8$Z&OCZl#*NUH+{$K5B==n`+g%~{_s7GHX&rR?pYD5LjOPE(%= z3H^H;2LWs}z>3kI)1`Ch_6TIWo-6M0I(+-d=vx5h9CJ|Uz`N|r$}nZ{BTS9?8sY=W-2u0X*)Vb?0#}x9w_SC+p87Dg{c2|NZd(>-crkW^^IP2EJW`Vmy2?(g-x5I) zStzwnQ8Tvk&A2IVYgMNGIk2qzFt50q51Eb1?!@k0^nTO2_ z345RK4x)dn!Zo+Vb0@eIU07MQ?v z24WSb933?1nS${-xroCUa@a>>BEgrF7MNo#n`1ZW>5wynTW?>YMPUs?tQVs%EG|K# zsvM~SGdao6-5q=yv!+5WsrQ9cVp@2_$t1$wrSI^Lgw2L%H`q8a=d|}J7 zc3U%xB`JP(xE`InyW?Gc%xje;8p7e!l|JTE_D({#T5<7k$3~?{7vBEB38=SCS+=jF zX@9$RO;x?}4Kpi zo-e8(_W2JY=;nkR>L6(l953q~{2EahB*93~B>Dgc4P`*!=y+S0f0NU;^Rp8xZ#)7{+%ttDN z)FuX;%aM=44N4BhP3u4zpJTkLh+F39M4c z(XcX^ceoY=zW>h8iN=}XoJ_pH7(2p3h^y|*Rw6vZhy`X3JP{5BcM(qGR}p0%>3#Z& z#(Qwem-<+*G2%WMstg_4*T9{(lm6-2kjrI_2S}(nXmlAsHAt%kO5>Pju`w%oyMPgp z3(I^bbV=8w=Z3&%6!F)FoQkSmbj3-`4Y+ymyyC*EAU1O{#@90{>%kiV(buA#+ik19 zc``SdhfS)x;4fvJW#zvF$qufwx?^^^tvQs(-`haJ68{L0YcNq7dDF>cPC~vn5edKK0(SSXx2L6rtp829 zl}}?N$fhMlH+Sq^8gK00RZnT%&yFGLfV48~hadPG(kej}OkvjMz?Oo^~i3$ul zX%MZzTI@P}s(X;Dd*SFjQE6<%eUOfoiWSj;$YlaXEhIMc)K*hVG(?(OKxA2)iMg6D zWfEhp8a~Uk=t931EWeUJ$dK-ckNABw>SsYg?1*4~GEc+t8|a5INqugu1NZE%z>hoR zk##GE&#L?f;EvWDzS_!?wj1(FgtD$PQ#V^5rYsNk89Z;{2Y^Wq>=0WvRVIwy3C`W? z#YSO0Uou6q*E~8XJ9!kEeez5wwKWU}GC-@})M~E%j%c1vui>v78jt=)NLpY!xccH` z*01a6)Q5gZHL0T%p0p>Op=t<+D;ORB8ksMG$ACS~t!m*S%9yra@pB+m`KDEJWT$&0 zO~uDJg&D?`jsMWBThd8Kt9>uD4P!r^Co7KJVVV2x)1f zytTn4FJj5zT=!uOoiBFtciLgU^eqMLTWlxaT3k~Z)LfjNrkT-2fOYaAE0jg&4a9Km zevlOsMSAxXt-Ks>DkAA@7Hp_yqRBA65^-pac;vn{|CP&8HQ)|5mS45HR#aprlZ=Y1T zA@1%Rd7}YQv`Z~jEPGGJiZOe~8x3U#vM7n=7>&SULnE-m8*=Pa4PA?JcXs)Q43@T1 zsKG@`$2V?Vp3+m+@bRLRxjCQ*cFC>twq1Gb9hRPDZ7=Dn^s8&?Sy0)R%V@JSc?H#w zGB!y9Df`~(-(yDxKYTx0*PIK25-Ixwk1TJ#UtY@6wzSF-|NKn;Mh>UMkz%{S+O8H6 z9_(+~Iu`bA)k&WPZUwcVTw^9p)Tda%#}8wH8|a`aPhj}B^$NACuQutd?ZImQbY*F4 z$N7bv^-inM9K8|qPRgQiS%^2AU~X&X;Ss@>5|jr(gWDYu0<#&;L4 z_4X>B{#l06D$BBYBdd35aIrP{VNif$5GWT&^wTYz0EPRMt_h^wQUEa2TG< zEB>hi1e4EqE@xO@tMB(daQ)2=9bz*0*mVz|&a%O@$lPU2 zz)kyCisd;Kl1KKbpIXsDrBbH60+OJqvV&X9?eFu>;WBxH?EH@A=LNnM)Y`oKu7Kx! z|XPgcy@qe z?9r^RAdFV|c&yhQOTze83`D`Sk&=t#_ZN2BrhJ1!?LRa$Ra=D*;V$w)*Ny<`Ji7}w z1_w$c5eg}|nu1?dtYK(ASe8(n(oM9W)5y!I1qoswgv~&^8m`tx#$D=`uf6+eZ;9F4 z0ZQF5s^?A_gA&9mL7s+hY$j~n?qb=YzApv9n`pLPv{>L@X};&cdk4hOY5Tl9{`&_l zO{9#sb98ehgm@sT6Xuz7t1)4GEZA$fzym>r^}U0WZjpSbK#3m1%=`S?Q~XFETThh%nid_TD}RMf6U9fBYfz&4 zA%$=OxQl^XP+#2pjK3+gWp!Uo-nbtv4AVWN$$_AnKCP%Y(z=S8Yy-ITzOV%JUVCEv zVY2X#EyyDiVQ`qn!c`&M{oA-R*6heS2{N#xc-9}R5MU6Z&v=iMT!|y4P|Zio;42ME zRKTusTmi}YFU8zs&-!}sc^L2*wen9Vy`q9Auym~Gg^*-rlHF5wghHFTP!Ky2#SIDb zlk*;5K?}k|Yzds(Ij7OBRepn44Bh7BUZp6sv|?*H9g*YIWAjXJg3O#RcQSr!d2AcI zY?`D(o${gaULmyyqVUj!&f(``E zKZ0NTzoi?^Pu7tH5D_b=lp+8nQi0l-QkG8FZjWUe?5^3*z*}Jwq}US?4fVNbJxcic z5iqO+ElN8Vlq_s1+kK-)cxpq~EwexED)=*eG<-;J-g)5dfdFdDnGQ+Rc*9yc`ZSXU ze+twXnctWAFbXc58EETY2FuRDrWCsN@?D;^Phl-21<$a>NV9`kyX^WcuwBZk|fwy=UTcI+U}gnkeq|J3QIlPXn?rBohE?|8g+9HiS4 zNxG)J_jOihQ_%gl-m)9VJue~8Oi|SR% zvBgEGYpvy zrB5ZwJ7-$6K{uRS^{U+8d|vn<{F6a8^NmaA#`=RaK7Wbm>pNFGp^L;`KZVw%3Q2y^ zk*9yhjNx2#re>uO^5i!?eUnx>h66X*xU^f+DrKdYI zQGo!4g3ElW4>N9xnr;$RV}JFpiWU9dQCwa9=*u83#L8NK(UWfnS;Ndq8M%H^Vw_{4 zgErWW|%?i1jzNMRyYl(SnHnl>>6O0nsbl&J&4WoPXo{)Te1#sf$+DLlHbL zwkcaX0rke<`2yjB4}iA?9ZClJ0$SkIR@%3nm%QqNn8Ueb(zfeuX$Cwj;)Y%C<4DzuK}d*GUPg&#z!bFV5iS0H zrBF>ktYO+nwr8J6<)(>Fm0>*Pduj_8=)Qj6XL%L*%W<#$YkBddJ~tNYYeIX(&6YWBpu~xf6DIZ4yO7##5Xe9V6~O=e9|eXn*P2 zO*x|XeeCn%izvfl&kIJCQ8q^;)ZSOzm7dZ)5Vysf#pN}0q$uf|IwP6^m13Ctu=mEs zxbK`MiKZ`}9n%A=6kc4@KgY3xiTicT*~E|SioKj$J-=_%202tUU>>}+nY=F9z6*d- zK56&$u8kddO~zt^Nmnaf-O@25>m|q3j;R}xFWSOx`y_0xzjOW-*qZqlmL9*PnRu0w zzeDK2p;12oXn6_)PhjY9(-aV3zFo;Puqg^p3IP3%HFl~MQHJ2oILQjK^v*6gu&e`n zAAh?1?l^Jk=zJYD7;%xnlyj5NIz6Jl91+48iz?13j;NBP&AqU}|CAoOcygVB*B+3T zYP`He^_)i{>__>=J~tT9uBh;)SIs3j@SP@wU(;? z%nn^*=SiaWQRn#UIURmr%z$;H0>z5WKwZ2>)&t2CGs}n8f?RZvftuQ*)=BEbuNlv? zl%KRziQd`P*EqH~p8Q*POi@?R!RKWDG3`Rnlcg499ZTa59G56dPiD)CoKiphGj50-7V+qT_;#(U!C3M`#<>p$@pYaJ4M|@rzp& zrR4;A2e)Pms$<|%oa?v1oqpx${8eU&Y>_J0Iso>Rb`JaSU0p;dsjygn|8Z%pcS9vt zq89#GFmtAB$0Eql?Ri7FWOv(fXh4mASU}m0u*dJD!2Jd?Q#ij;?Ws}wJFW13lNA*L zLkC5W5D|d3auZ%X$X~;Z>1({Fq>iqq&!^Mp3h`?0l*kLuTr0Qx@!CC>SCE{s3eWYO z8z&;Rzf(;2a(o`elTuRGCV=~3m*jYy|C{A!J~4p-uL7WESf-t4lYXhBlp5T`1T?}T zIX3d_8<%NuBH+ST#A3%2WLLHGCoVNzBiIXh<=FBQG(PCQ3BbmzFQhCFcXP;kB=O1< z>Pw!{$t0<9EG%3OH^+y8t#m^$r4&d!+{HE9ouS+>h@pxNLuSh?fV3rhGx~9l&BXC z^)5%V`k`{QEPN}$i?kzBGhcifc+lT$yGNIUUyuQ8WHJqNpb>Hc+I;;7;BmGC!SgE- z2-J9gI#y)I!M&+_Y$d8dFFvYEJTn{9ILQjRd}mVRz-L9=QIPeokkaQAkJ+pHDi!iXO8=mZ z;j@_ez#GM>QX#K0sapfMcVfEcD|5loQ+oYd0ytzH758tf)<|^ewtsdCdo_O zw#CjSl|QduSVcv|RZ$!UzG+p;Y}Mqf-7)lx>gi%A=bXLigB|yhjZcjqIQ#1M(lcc8 zVQ-HYmJ2HdanRBI%wJ;}JFupl|2bV>p}Q|7o=)!WUKp*jQqdi)RH8hsF zd^^;(^}GUs1Mz8JRZp{&PScxrKeX_G^^q?1KbqIURjD zAjDuCx^b*ve9)X4cA$T_6QRnt@bz^Hx?_NRk-5;b~2~9XR>MDY1t3c2oi31{g>)A)>HH4cyWW?(L zT5DMD$>KGPgtLngg~K&0qaRII2QOIlyXoMKAyxr8E~#j4;WWi|&aOxtenFf-d%=@V!Ox6k%DHSf|UeiF1ea0~uV>dn(t19~UlMj!W-q6(7h_*P)+$ zc-+W$x53o4(QZ6drfA*F$fk!Wq^E;>S!J1=+$DBjHbZ3m(k@wI6apbWW;<1_}hW!5T&U&C}m#OEUv;@0Rv65^{DKCvm8;zj*<&PiTZ*1@hD6r8O zl`!=xN;f=yy*Mysc@g0-^0;Mtz!+;eZj|2r(9%Y$)IN`l_WlX341B z?`bS^t3uz)qi3@UC49fE*lRGxp-lUZwta~c80^QyQSK-p0^{=?%W(M2uG-PUb{?3k5VbRU`7ivyuns(+-EO z6dmHze`zd8fA#>hdAveG-Un1TMSL^@xJW@cgeZ_O&nrZR>S5YF5m?+aaG*YZQn)=0 zsscQv_++q_E(xJOP*?|`D23BcwD?`$(0RW3?4D8<1O;3Fr&@DtL8`mFHHm*$Q$3%% z`~=L>S)ns+2gSLy2g|w)a;6wjFe>N-Lbj$(lq>n*TXCB$K6nF65UO)&8j~;`8f4N& z$PgtmIQEc1gyMIXH>uV@|BQ(Eoeplk^_|G>k1ewoLofiDsbZt36+dE{l){vMFH<3o}37me@^l(yZ_wvxa9SN1&r4#JwO|s4%ZDsVU2^{*A>CF z^TtqVExC~nl2mL9UO?C3?p$x-vrNA<(FQ39JGg}(yskKx^@AZpk0Q9x_2O)8ql$_q ziJy!PYG~Q|{&h#S6Ao7ZNA%j{kPR|ej0_KNpPXjurw2jTHPe1{E8Mj&5p>_}+4**Q zyu9WI-fna`1%bo@JYJgmp4PpJ6Ni7t*Njlut@^xQgWWM8S3zof01o6{pVACft$H@$ zxi2cdL4oy?ADJLm=#gi;dytQ5ebc5*ZGb~l5=H@hwsz>s3A{!-eoqjfe>5{~rqJ#C zUJ4Y#FM%L49N%=1Z|&oUcRoK3xSvAWSbVb+!&SfNI#Si0U^gMgYyazV`_Zi(B0KSS zLcijKMgf}8!3}<3RIK#g2Lsr8P$_2EA=N8cX^_})61=eT|MuIbBYbYBN6HV z(z#W7Gh#2LZY6x+tl}p_=q&&FtAfSU_X_L;(_Ir%`eLsS6pTcq)#+O&EB!2O(C@@0 zhq*Vqb$@g6ejIG6JQ-V#fVvDFM!c0;wNO_S{N#kKm;@MCl_5Ss1I%ErbOw@u zGnbvl(hD^f@Y5qWFUx`?OckxUSW@J#5_8`YKF!!d_2JMcv~@Ls7hVpe1~PdiN|Ry> zYk+bLsy0?0Yg;$$=u`Hhv|sDPNue_vK$!m5M={^gb&33Hhg}0h(Xt2Xl@5GrxE3o=2jV(KR&WAZ3Zy>BQH=D!Kr${4|evZNqeK3S_ z#FB+vh=GWKe!tQjz4(EH|91H4IiDPE*}gg)t#(?&6AV`5$SO}alS=sy^i#7UC_W_BLX3obxLdd6`?v~^tTg8l$d6;S-)=BN%6i$Qn`l`; z%-*{+l$y8f{^kQf@{d#sb<}#q?Hm#%f|grEg63EKuMq8j5q7Lii&Mv!&AZd)8H_=U zpeEGwLqi}~AX_b_loBjyAS7PWbZz_PS*AxF+)xFA4@{1>#ww|Hj^cE721iV~O3;t% z+|J?CuxV5D5JK$dk_HHgY*~P3{{kR<^8IB7r=k|qcrY8x;sXyCMi_yZIml6y#vJa7 zA1$uyEe>{%FPygxkt4vBeuj&mUCl@Lm!gkEK;ud6jqEWy!R3d4F7M^wuj=OAGTtt` zf!2%JRefJBp`AXw2AA8F%p0^WpMDn2P!iEWg+2n7%=i&kqn`viGR`&jC9%in;-7F5 zZFlBR!YLkxLsEcwTPEJ6_N;hHuZrUt4B13`>j~-atF?}i9K9On-zYA7sxLn8Y}!{=`N8If-OaImzjUn z$ajj@;PZ!}|?Cc!?L|oafxnec!(oeGqd0PCiG3E)bX(c;-0C-`+pi zqLL1}hbP#f-bEQME3XmP%ds=#V@LQb`=nX2{XOYtTcuGZX2x3ev$bwk&EM50on~^0 z7Tdc)s9MD7lN;_}%xknwH=$IXs97%gkPchvWVN7a#f!&W0gMvV2cr#%6vs%dUCc=# zGG#g%I7otD|KY>jp8@nW#UNuT6=*K;(|kqi`Um(qVW9zt8?V9vvN`cG=EK3v^AmU^ zH}S?5!ppw|7LDeH3Cw%w^gz@8__K-x{g{H@r2!^T{1k%lR5`Fk1)J)&s1n2<-}t|M zG(}g#^JMfcW4xd-xZ89YW-qMoVXRZst*R|!Q^qZ(8#eB5rNG#zsgh|*UuTMUZUoii z{F|9?-!dBwP?4w`T~(cD*E1@L{=mF=5BqJG?MpD|%t_=nqCBF*vedop+&`qhD(sV| z84UG1fHk{H3oP|4-iPpS&uIAJ^AcX#k%`XGYs*HwP3#Z`o$vn6UR5 zHOzW8`#4S<;WW8tEbf0*`!9i6U5ds0KyIy=S>!-Kb#-|y??4nfZn}$PQ$?A}jbIhn zas0w8E$#94h17Qg|DoSehh^f9BmZ(EWLIvVgFpmEKY-r-w68RH54na!yQck%UrdyEKGq#uGzTx8wrFB*r}tUApFJbYp&o95V_SzF*fb11au zjN6>%4!$=GeY-ct3C?>^!&+}kVyz4OXji;8xKn^51=!w}CbQe}^i%uAQ`|1E^87!S z;0DVh*`F_lPC@Y`V<`blHj36poOnOs`TD)pfn61jVZ-uh2V?hj@jXV6-Dd)Xmf33Y zxGo;?LA&diVqU!6+p)mKE>BaHRUs;s6_)odWl;Bbp@28hf*SP20q6kZl^_H}!LI6{ z5oy1^P}W0ICjtv6!XGXe9})PiyR(vD*?KHw4{}W+T6-?SJLnX1sQKa>21A|Sj+tC4 z-)OPhyH1+4Sn*1lg{?^T*Iaa*EX%$h8B<}k=y3(zwsi?RGB%DyK8>$2|GeIHbG;E~ zrVP@l7wIiMd?yzcD zc$Yb-jtD>$qe6G@dzRW}$QIS=Fic3udgW?=SwaNbkOL{$RCn0%NWVB->CNA@)mK6>15t4 zwv|SH--Z#f>~ZFn2ls?Uw)w#XoN(~g*o7-Au(d)zZA9_vQQf{9TiyBR3ie!#Idz6jCnJ7`D=q215nX{pWzmRYSq=Pl4o(FaF zmpKJ{snd|4xObJ8kj|~u5v|%VFjU4gf8&aP#J_fpX9o{uo52jrSKsRcVilI7Yf1sn zBTVRRw@`{+uV4WWI7#%7{bZV=_O5IWiAMlGn&)DF=Vfk{Yxxu&(~W=LmdA7*@#L6n zQFIbZr~SL*LTInsol4DY;Z#PpA~myEqA0#>Rz8o~N5y$MRZI6S4Q^C%`8%!g)%h3p z>0&(-VacI{ZVomj7!9Lc45m21L{2J1g2}Q$Gy0kkW(OOzqWA z`T=MfQb0ufRKm*1wnB)*IU%6xOf{wju$hywQFMzkO@S^CFm~q$#Py8N)xm_b(a~3N za3uz*OFoFnwFt_?I{t{m9?pd#n$6Y6fqJ_RS`$u+)M1ZR>NAo@Ye3k^IC3sQyXkTa z-L&`3%Mfycgsa1UYBpB#-)XTw`xQIS&Bc|(R&<~9izIxNV_eUCziGNOJhgZ;Oe;66 zi#c14(V-IOXY6$;^X9x=n0+3dhq5^5<|jgMs-l~VVSczTqVS+-|HaFFYln#~%_raE zsvp~VFOYyUh^lOW|MZL8K--AS93J|ZvxNyZnEpRX{yJ-EW;0)Y?>K5ufi8n zql-F$-sxiMi{EE|Wz*J`R-5P8Tio=naP`ovQZV&h3b34Mn@Bq~jIzbO{ih$Uh`?G? z1r~PTu6A#S7Mml2_S>Q^(E{Fs`F;2VofM@iBPKoJtE~cd#Q!~@Cj1A!#=~Fq+U7<# zXm$nnsu8LP;Ml!<9Mn%3@2hGe@XR>{y`!4YfZCtM;4KU6EXFsWNbOUV&8}_(XlsYFMy#h6P`_0>=ZG$QlEZ=u z)VpCB8lxOeHNyMz+##C8U~%eG#R?CrHp<3l_5#Y9Oz!XTr4m;`=T%?C*(J=YeU#0B zYy4*&AT$IE#VYl;mU>{B&0*gF+Wt}Q_h{|+TtYUEqz{{HkeTflbCkLW#V{@P>k_$q zvWhUtN4W+q*$24KA9Q_Iq?0^HIS?9%S1Oxp*#JYpU zDKxSH+;_F_1p4YbN?}E*P*--FRF(ne2M%NEhO(d(#;zpD`KFo56{!eM zt^^o%ApD%7BISs!g-E`ANUWqR@^0?tA9 zThyEqF0gAd`Q^d3c(ENjTtTkEA{olp>=X6_41Qv25D@))DN;~&sIta0C3t18n*)q_ zN5ns}6WpqY;BZdydz^sXV?1yKfxtT)ut`v1%Gk(ta4lwn7W>NG$%(-jV_U+)oT>0Zg-i*^cHK6@)cP?$MoYvd0nxIP<~!ZO?E z8rUOdZK0~IZ1JRRVDUtGgY1PMB|Y1d@q;N2e=b9;fpL?uBIq-V}xCDOLdV&jBSW|mgIMNPJPzYL9|FyJcN(v@* zFzG|~5!+rA(S?f1mcsc6@3Uhh0f^U@_$x_~Lg330&nu^4ZwdBM#g6*!PoTdITf`bw z5NJ%)#m@vT@b>~>0(aknN48*~#+88<*uWbV%?yy}FzwhnczF9AI@@6akR4MUjfBYG zI67K74i|BCS93NFEac@NVV7PV;{UaIuD@vDMLNEF8v)AWt2FFegTIN16U^v`L)4_Y zVBtK4wQF+?HHY_9g+SnhXuK9uX9!OcbDw#17%^nWu&YmLU*=m%!X*4n#M;7lz{NU{;HjNG!W#wOoCv}j|)A2QrQS}CLd0`(_o?8QuJs3%y_+h*C?VitF4;QS9vf-5J5J zcw_TT)W|6`pOz~2FBQfat|txBC-R=N`OkSv@nQ*%(%?rov#@5OtaEGmW&rpVU)m^t zF{q<6$+)8T$WW8;ZuWdMAbX8)+%)$4lkItub9UG+pm3gwFTc>B7ir7;J%BXdW(L(D z#Cm>&M;{4uFyjnAxJY&|aX*c8y~UPWg=c}fyf45Bco;%R3;q5pu@P$yV`91E8bS`q zWI-_)R;ila{8wWd>V$=0hy5iwfMcH&SQ1!cY=o!b9fn|3GxW{Ie;Eu&a1(q3&%#MT z#v^1yQ?R>chr|=8%XIDMcRNWRX8$dP&2C9rwwy7QPClbQTF3%8Cf|Jzh$WgG1dHHL zi|47s>c()hY$o7I41+?V$E->3+M`ds)?DIn4R#>!fU!0%PYREeY0=0Pm!wCN_l!!r z!-+d#E-v4V!K8BYoyHEi-fp)$vC>6GXSLx$RCq*JO>Q}$w5n$LMXrlQ_`|bIMA4Zb z?XTt}%G5SYh>KG6)dO5jZOgs9pQeTLx0Zi$dQ$ki>ikUZ;z6d{iOuDa8)}V06ZrGW zz^?mq*}$<%yjg+25p?LN_x_+!02%C{6?4x!ha+5pCdWR@1^G?Ub93hRl)2iNKmp+*N^Uhu74QZl5*KRK)R>!hy}rrY~hbFu8%FDOWXXCQ8clIg>7ww~|XbFU14kTM9& z4TlLEhMho$gU|sC^Jm_za8dGC_(*@Wo3Nke8gJfgEyV&tdQG zR#IfRQa^tz$o%+hF6Oi2z~ibz#kG*jaU>l6`hn>bMy8KjN-iVC(<)I)k z6pxQKf9&K%|FieP;xRqT+yIMno|_O{8$J+-XIDjFiv$y?X=e{ce^CYfa|d_WJ~Lue zHg?$Wk1`=xEzDM#Yw2K9@&1E?UBzykjLl_gM>CuqTD256&FJr4*~DqMV3RQURML{f z@O=trg-)R*#fub+Z4lgKyODqsJ?KJ!4Shbmu-|957ujApvI#22DV!{QvsNp2MgPDc z`i|(|gf@+EN(9eF_x0XfwQns@IF;Fzv#YV5K9aVa`!Uj?m0Dk`t#GD3!CQ@fPBKIk zoZzjM$2?y?bwW~~_x*5K{qGYpzCP_rqbOynoata2w`BgzhYyQKas^9%kDl9HNV?6t zx3l`-ztC{g%&`e;DV5-3?Q!1X21G-e0cyH3S9`yV8$Go9(my9220ZcqvYx`%Vwh8S zW84AFsduKuEy{F6@)Hs9SuX#;Tz#T2b=(B2H?Dk2&9c0twz}k}E|B^|{N^yK-t6b5 z@(p~&8drCBU~Hh3=E|L7X7htP@J!9%bo6*uUm8|@V|Y|TZV8EGzzUjEIlx5N?UykC z)=6*xN&MrLz|C(t5~5UCB`~_AKf*#Jn=O3634VjKS;`q(Bs7Hrw`IF`%^(%Rw3ekJySi``)Dz)H1%~UPrpRAFQ9r!kXi~rDUEN{O#TIU`8T9;)xORL$1B$rm zw=dfLK;Mcv(F?QUshSg|dL^1mh7u=~Q;n1O&pDMB$llmi(#!1kBNS#Jp1z9bz}ltwp)OF}XCDuxU4Nh_F3D=8 z;d!n3a$uWP2|+R7_A7p@R8Q|>9)w=wD)7f^P= zY<838u&8G!O1BJVN{(mGZw8pshD&&e1zNBv2l}94Q&0dBnXp$ z%tCw_1=-r&>|ru|C``cn*R|14}Ko%1Dof zdf2jfCK-wWyB{LFX_D1y=UlN^PNKS0y4CYfyg`TV{Xm`+0*+o?E^Dp5)A>5$`Cd2RyXSoImqmt>uN-zjDd8 zd*XHs=bx8K4|G$foGVniTlqe$eZtKwhPB7=h&(oUE_GB>#U%9Gselu;t^DkA=_g8S zMa~P+{zCq^i!}&mqYY1PvQIa$x>+gx@ls+a*M>rk$kp2w7vk2rPYJt7f!Ek`nZoH`Qpo>sB zJ=vGO(~|DXm+sIQY7nu%c$E`qeXehhK2J3~x^VE%W%Qz#&>)m=wr}sYa!#;=> zoDM`ni2lR#2RkFyQx0%@KP?LOzs%PS29Pl1&8J7hFX6Q82@JMA>KQHTS(Zj%w}yZd zq3RIk2?xYva!o?cb3(*=B>C?MoCiMcLdIkRmAN)WZVb>mO#QY04m;HD9T80AXLA#@;P^Y(BxG7^7jpgVhDX^_$$d3HQo$rfdj0qx z!VTcZO3%OtSR>>oeUNB8!jGY6XA;#F5uB0BAVpb?=q1}#5msFGd=nNtW^(H&&r%qq zLRaP5d+AT^eOSa*xmJ3~@ZUZk$o#a)I$F4nu3PSDa=PVD+gYl<{?no<>OZq{o5N-Q z?QKk-lc2qSx71u~%t2!9^a92+IHtb3!pg^6E-lN}aAtqNIW$xei4Mi@V=nsA=u^B; zVtrnM^{MyHqR>qRzgiy2LBnm(q{0IAzkJFdn-Xse2)T;$gTo0$n9}i`ff1;%b|hsn z%%Ak(yQy-6K$u%uTT3hmd;T#v>A<7rcY6x2rw%LZYO@Km8O{=;j&St}JU3|26Fzj)Be9)3I~u74xuh zGU1CmV(rDhTv6zhj&S;Fcjjf*qRG_SR}M^Z4=XvI&jXH=T@?87yg`rd)IBiCn3+8- z)Fk@NcFO^0$N|dr!`_rL1EZ6hGQQ;8oS^K#6#dqz${q;;1x;7uud2RcHy37v5JDGNmGoPah81VmvsKjw zavUw9-}1LYU8x_hF$Ec-ZaaK-R~8;-T|9OHXg<$NFl%_L31=L%#GImJgX)<3Q*~|Z zQ&HiE1524&!}*Do$Pi(yIhC`}hSm@1m7U^(gjJR^SSa>J5vS?>V8D3__@QC*9o1zC zVm+|rFY-=4&u9Q*^2g`f%nV{|csJzk4ohQOqv&o#trU)C3fs=&nCk+!TQEjVP^-DZ zU0~lY=yj{TYGsfKoVlG6sR6ClR=V9Xu@nOiIEZk9p^~S$Qf~5`?^LfbjUL$qdN3J` zgI+fnXhKuQw^_OIj!?JD`VSOSb8l;=hAoi<`y>+)U;&oX0q_8-(tJ0v0POEQQmOo_ zH&Lk(*Z5>mDp4&k@iAHcVS*ZY*i2B-@q716tzS|bRzyWfEh)M_hRdNdmu_9@wc$p6 z-B!D<;PO#3%|0UMS%aV_YDSRbFv^6n9RG3NG+Myvo_SB%{1+(+G!I%xNQec!ec9N- zZr-A~rrN!wI7qzZ=}PQ3udB&7KFmiY6CXboE`Kfm)#mQNDdmBt)>Z4%a$QIJ} z+aB&G1lZcXj{#X8AKKeqShe$6+jIKPj0MK*>%;E69gm>)y2Elf#Qi&-xLHuYu}mLIQrkoXEtEZi z?H9}2cM2$?V3OWZ0S|Yc*C^{h12%(Em{wgZX8)Yxo-YrK&BN<9m=nR51YOQ!Yf)cv z!)d{e#?HxA<(+9(ERjTq#foZwofe`>Ajxy@$x9`^Eg0&i_+BT;W2Rjt9y+bPs`99Y z4DQzbxzO}l{C6e&?s%Z~pffE(pzmBuwc6$KV)^UG(;ok=I&Z)f@zfsoHgz{D#6u<>~s3c>R+b9&qG0 zdm@A$Q^~e0%Ix!2k`R?2RMK5Kcdln{N0H9OxT?`UG}_Di#p$q7GgrIWyVeexN6<9fuE+cA|=6f=Vn>*j0A_uNC@*O!)^5(2-v+HAP}mS?`{7ROLTArlYf|%_<9C0&z~j5at`oW+pWBn5gn<~| zSYq(kxPwQkJ9A(crhH($k{kHZ(K3UGa>8gCl;Un;*k73fKM{b$lK3IZzKAs%YI5YF zY;fiMGqn+r4X~*L%asnop!VXwaavHrv&HEpNedyn@DITqU*(RJZhfb!;sXwL-?M@! zObI}r67*}J2Gi`&FrwCx2Lj5;36HRjD80R^pIYuWEg|{v-%(Qg!(+Z06Pv%kmP@&m z9$k7}F6{epxsb=>fI{+=IJqbJhtRa&Y2l1g>0qSp(Ovbwqpe#5esORKQ7COFUDC~! z5NJ^9`bNWMX{xY^D>07=*-#y}R+?y`rpflg#EB#lh*Ay6mhafo-9G8WkvSI!Gd0Gf z4wzwHQ$zfK5y_{+=s0?O+%$&jXZ^hGAtujDI{Q@E)>K7-Yh)vC!9Va~cKsJkTP-#7 zzs%(Co2CTJyZipN7bb=+#C%s;(p9RtT0BSpo9$nD?C;|F`Uc^K*kDcCNk}s%3sb!6 zR$6f0I|Hp}NQ<*`0^*zZc&FeK0wHUqEm}ehL!5=Y8%oYIK=81F(apa?0{x(=-9ciS+rK ze)isO4P{90*9+h_G+T)xnZ&r!XpWM3^t9 zaCe$d3681=9Y)Q0?AlKCO)e$Ejw`Fz^F^YR<kkD(*O#mfN+|i3o?3elFm=Y&Xj$R;DLc-T1N%6{h$@z z*>1=(iY@WU-vLha-YI{5^Np7?^763Qur;U1m!)s64my#1x1T0* z1~|`#gk@_?Bnc&Sn=0`+BuY2We>j<8dLQ<3#vo$#MkbDW!~+|e0i}*grCB!vy|lrm zlgBM}Uof8iaO!spe53?n(EWlWm})adSXmwS{9|GQ9FGDs&;sBDrNAf;7pkhD1>t86 zz8vRj*`^Dne~Ui!Lj;taBaB5ZK&T^{_Ec>4E3u&L z82DK76G8X>5SBphK8A{}>@oJk@pw%Hy#|kFDsfp+QGf$LD)x&t(H>C&I4)gTSc}`` zWY6Gw^Fza{_SnVPDuQTuuTTu{Ui6QIMbQ|S{Sij(xi!ufOWjlUN)?nS+n?;ef5as% zX1*2k9dWsK^!z0$(J0>AM5~3^ugU5QS9O{qqr{E7RhXxLLx=z?JW^!*!I4lR7TeZl9vp@^GXV11`_a301(zu4mEPFHt&xIqM)taPG_p}`UJ zEjAgcN|!ITeQt(2552BT#R9)lyBL4Z_k1_ouU{}bCAn2Woq4Z!5dT6(a&Xb(ny*WH zv9a(gzgi|v;|0zmET8I2HU|Eo&bYjZGo9wq+Uztf(jsKk@OiA8sRDzk{SVNZ zz$fiCBk20LSrX8PT|H5l`sy?{%B0nKhZ3I^BhW;72hrSqMtds9`(*PEjG-!^N z*2Z4Zkw}OfuImbo<8(}+2qatMO4-ZoEc5+y^F_S zZ)Z`ni}5R0&lAVg{?NC;pE;jAdzekuO@}}AR##IUkzfk+M{Em|RXzSvYl2RU`)9Ko zH8~Z3j8EkHEIaZ=$Sx=_Z%7ptk99k|kCKb0-4;K!#u8PoL}JBkg@rmf_e zRG!on0n1rj-u)Qp;M#FlBXWepQlQD&I+}+N`-wRVug;b$<+;io%w$q96U4VG34z)P zDm=q3!4MyQ+y=nz1oUrFZ4taB?4mmX<9xm%SW1yz7!oFT&@h*OMZJ|1af26#B8upQ z^0LS@HF)AP@b8V)%^=twxT}tC{F!?_)%OKGqA<|f7uHBK9Ljm zzr+CZ9S9gu#&~ReD9N4I*|tsf>oEPsN_d=y_;%yI7uB#Ys&%vDHAEzPuvKwj)D84o z8yA@j$T~BA-(A&4lq^g-SV~V z3*+YpZk(>BtyaVKs(RIPaq^ouwJ%?$;N@GhmPCDBp1o5b)SufEVZLWfdu7w~ogf0Q zi`CUE&OimcO6N#a9*Y=U5$Bw_>GE;8h)3MCizUf+DP`v0_jj8=H?F}LlX(VMAMTNY zzYiOPWXTdAnMBKDHPv^MAnOyoMg7Tgk$#(h4}$RE+ld|2zS5>ROjwAkY!9@Z8=?99 z9#I={n){9a)tcfR!CyNG>|huc74~4bYs}jMYzw4m*EfqLDt@@^HSZ^^{K8O}C69di%u2d?a{CkzFZHPbV^`-N7;aBjPNHx~#f1s&|OX;l`JfnP4p-O*BktAX&l1cggqpfQ8u?I+!B8MU?=5 z_vnV%^sr=oO|Kt>*LK}@!Tev~EiI;3a);MQG7$e57H+>JkVbnPlnXoHJbqzNgy;)9*Bh9#%ssHD)bN-WwgcYSW#GKaQE*+8^Ll9Ax-)~ z;7{1kY=0sZex}Q4sN}BWSRoD}=gA${xnCsYYiul|tA^viZdBZ>8Pg@vS;hU!-oJ%z z#q&$8#MA=4mN&$tat+%OIXX`GKY?ms)xEfnZ0V2U{`l9bT@&!lIxQK9xNF1BZ7OZF zc;V@v-xuua?<%}FWeoe`sxJPXP>UHr)qN1{zjvXg!=UG)Q=u&WjS;}ACXN|fM7Ifx zU~|_i#L2!_E$Z)HmxPZEZ#cT1Sxk|kaWoEi>Xngli%XjpSnky{Qe~6z@;DkGkB8LI zF+kkY5dq51!K0DbKvzUa9>Lr0IPeC1kBExBYsAm*?Z1YDtN0iYp@I&c#a)WQysiR? zh{bxnh1WHf9MG}9 z7e$5U$^66OfAa&y4{S-~=%j1MGzZ|%<<@tx+bsu2)u)^;^BjE4GvRsF{N$2-hJLSb zV|-*yo^kT$NO|`7gEA`Iz&+(>ZcODXhx@A~W=~8>>Z)mzAXGD^9S<{~s z`rYb?dw%kuo~zmPENs9wz+BFpAlQJpMUMcJ*Mp1SJ%UHGy#jzx$g-W)WSorj3#YXQ zL=1GLe=yDAh`69W>~qU>&=Y!O57q%|r6cdBKS3h`s?Q`CW<#`nSs?%xlr8HO7p=soxQoSiOv#`CSK{f3egk&u7yAxP<@ zD}8mO<`V2OeW$2zRfQ?De|tRbC+|>h3is>ziyw11%~HpfLNio*Y+Tq8eofL+&*UH6 z)G>SV5|tQXxYx~8k&ki~uvJiIXUVv&{c)!L+o$qM|0jjMvGO0j^}HJ{cZokrqN^Q+fVVdmwD2q&>P67$r z;Mvgw!!~f)^$i<{v256Uc=5E}Q0K~LiSA|Um;?&+VCT{Mw?so$&~NMWO1d``pPA7L zJm{;g{klW&2xOLgkq`08 z+%laMT<_jvh!sQKYOsMjdkK9W%vMTf#x&B| zcBKP@4+b|L4H6#>PH)*cl!WE-_pqH}3Llc928al=PSm1Wbj~s!6{Y>9i~U7Rw+Kz|uMzP+Xmv*Bw-&c`OMSSQJw56r|?7S*6` zD9;>8@_zi?&2*SY%}Udrb%94U!>tbwD+Hah^Z+6@=4d0{P zf0Xq1zxq(Wuq%R_zWr3<)$4l>NnHWYiQ;T2v!}nir6i;FDJPsRr6JxlK|VxXy@JUE zA;t4DRZy^F?ZRs}#Qj>FF2oB;mw0!l+GbVErgrXaE>=5>QU{f1cwyDX%-9;h4)raW zzRP9ij?5h;>I}zX#P`_4@r4jb$UBotV_ZF}j0Dw~l6{A_BnyA*n2mG1qWyNc*_iC+e74!R4Fd;i2F4pifPiRB~dH1LBW*@h5D}$+QN>-GO zF?rJ0&nGV8#9jB6#%3FGNU}0)D^k<=Ke-9T`%M zseucxubDyd!fjXgFlX8QRPAd~)iN*m%#2Xq?^erlTU@O5&tz|9x?a-mdVU zvS>sOjU$vwtX~o{ygBIbZL}r#)}lmrVBK;9|D#Fuo@5fc9(-XoKM3=!H=X1L^-I2{ z9N_h%rD{@Gsi|RP`=xaS&IreF>HrnBpe0H@{@JsiDmWA@Gc51g60&``zfgl^+2QT9 z*i1WN?A3&DTM<$q9b*3?h-dq(?@S-=F!f~2Lx@wzds!!0iz3{bvl)HN1Y_RjL0l6? z-pxCr$l>_d-t#)QadP0h6j!r4NwDmh4VlnyD+0C0mCbT8)XloO64C>n9i46M61({H zkC(@bKON3&<_axLLw)(rk_J=_uS^)d@VA4#1^?AlgE3&v%59-1bti)ZQkRaOE%8kH z%fN-f^PsD9ero<~0oNTFzkYTX*C?9k@NatLr0K?d8D?`NvB-3MPM1gt1``^S6y8#g zd$V?rZ1;{3M|7!1**1~uu40teFy}77q;x-A!qnS1rq{#CfyHGw%4Sn zUsdTFuG&Dicm;m6-Nv!Zm^IE5`r%eN^w zT0Weqm?y4j{-XE75!#V{N#mrZ=f7mR@#dZkc)DMjT#j(aUP#f*Gd?MCnls8^YDhcz ztULCo|It0t<>imfu5&FBM>WY;V@{5UBk#^4*#F~ESQlnn-odj$xIje56R#&{q21w_nP)hl(30w0sbdR|Wa<;13X5g8VM2fV zwOT%Wp}BYUQ#6nBOs@Bz%7|-RYF3NxtSL=DdU}z!x-*>7s*c+c)-z|rSng#OOgA$t z9%N2;f7HD9^2CzmOVzJ>Wci7NGR$xv1J7TQ+!6kp&d9ab3hsGz?2DYuS*dlRrcA;6 zO4iqm=JfIlODwMulHDUGc)L%C7)pJMyy_K|eyr{FPda}`?f7ha3t`j3p6+`d4{}mY z5A2MkowK*OroR-HD-?V2ZEt*k4h3fT%HK;ZuquwCW_X36T)&M$eO&E2lkmK2QPp}N z@vyX7hM02WfzrXt|K2oTIxQS?y6?#2JJaHU`>@4)>(vj_kRN&vy3YI?xvyHXSMTfF zUUfW*-+Q>cT%qd+!x)EEi{)?07cKgfCWuo|t9f@hXJo|72Oc+t^ObbJ9yNwt%^A~Z zFpw3rla}M}SsShJGzPmp?WCEM_Ag%NK`~a4pz0_KBYx1?M_(V{^oalaHg#?soFA%fOcpdDbEM>B;IOEQn4OXXaZvTOiYIH+!sAp_RrJQ+g5tqCVwFClOH5S{nc3<_pXLDJH3t7CE633BT~Ks zUcFTi!f5kcsJpPEbUxc5Q)WIbudT0LK|>#ZZ6wUu4P%=}$1LJps`-X6Xmpa15d_m! zV|rgdYJqbHb?q3W7Q@{Hh=l5%ZTxV!!6fx95*S`eldS>W+lCkbS8a*; zalo;n;#0nH-_LWh*kWiG10Qoj|K4W$oBv9^cP;uHbDv{*_wia1pS1^p=$+0Z>t|eW;>78u!JLQ4zxW0tyAw5Lb$_322mBu)i~g~d$Bre$S)q@=fW7P;wBuA(`> z$5m1hg`HY3dd4d(+#~L*_}fE%gv$2s(c_y5r~E>*JV=;3VO31PGPwW59ws!n27o`o zqSS05M<=X7y#w6y4H6Aoz02Bg$UQAB!ZI~Ic)=x=?4bV9!Ieb3LmKUvF#Sm#E~-*) zWD~~T*7`*4;)i;|?4y5iyAJA=_-)@sXCwzci?Q@uBn@Qv+`ptAIk836nY>Ja8=~$z zEhrQ0PL93XGy>5a!a_?EN!!FYCGskDa-b(DbZ6`ueBa;Rn|d6#`K(}cRx(|=O|rW% zS;bVg6!#q>6$|%2H>epX4@S1VUu3to)v~^RJTB$&ex^-c?x)AMIvxm$tS~)tH5mi9 z;uj@Z6!$N^%+W92C$KNRw1qE0L~mHsvu4qsiPX>}fra2t)HHI*ppbrfT@Lg)GUy6U zt?2^Y2XL$NB`G|(gFl!QKl9}_?h8xp%IjbVbRLHl?BwC8=>Mw#E~MZ;7_R9rG$HL0 z6nvv6a}$)AGDS5!P9V{nS4{5)A)(3eAYN&cu+x2y5jgFKa}BK79-W|mIjXrXkg2w7 zA0xP}1DicyMyK_y;91*pSb%I#7Qtudy_P^q_juARP(7bXX2B>fHhk;#98lE*SI>x` ziTomXv!UZ$rgE24KBV1Kt?6Js@2vfpr|N@DnJw+dK{}_vNEucRkT&q+l814n^Ly$1 zUOMMlBN}1MSE0S!4U9R(vR^#QVrcGB_w}jKH_y7Bh-ERYVz-XT164_ohnQmBlhp7U z{B}e1KNE1ae2sa>Wl1~6jQbCyYy1G!`j+M=<4f|D~IbKmvk97%8+H_k3`~oH$yz>Ugf5t(YjbQHMorJXu~`6x?ezx znqX%>(MtkzNh6N;bZ42M%GJU&A%>OR%++v;7K;-k$HDx)C)4gp1ip7qn4wg5GHr=hc)2p$+eqi6SJ47of6PP4Aa zxfyhMy2mGmS_>=4g}vxl`Iek~$=Zrtq9W5(8};QVyFW5R$Am6r?_f{SkN1djax(Av zmS}^KJpHY;oy5i+t)r-Y?HGZeTuMXBzgmJiMqlex>sx{3BM1Edh~d|Dzwz0`%cD^$zuPm=&Uz9YSv>@(~QKoV(E(+)6c=sX|cThwrod=&a-DTKc4;<>TLIt z&+h&F*JNk$!OZe%<%y=y4LA!S?;j-IPAPtb(9wUMtqE* zqjq4SbiQ%&z?)O22MH(@=RAl6x`uL?J#FUA=eWG9b##mRZdLC4(&vi14wX6c*Q1w-(LwtAW0I*8VS=@S6CPdXxNqMos-vu_Pi(~ZBp8|uo$}_(HlVsmP6Ylqa^byB>TWpgC6Uyp)nsIr@AsPEav5PN;bgREJ>40W2C{Ue~{BvXbyBw&^2GtZb>R5a`;)AxzUa&L7 z8ja_Y*2k#1nEQS4!dhpm*9lu%KHDf4Rwk4#*c}c(P_gxA@Zr~byW9skT&5S`X z0`BV0^l49KBU;sR3DY1Ix0dRC^M!mE?0qRoyywjyT}`Vo74l$4@qF^6ek4#3V$3Zx z%5jfGsf1)CQJ?-eEs@wif3c-)Q!I<|%EP~D8m(inerfo3Tq4ID&t!zEkE)3+%R?@w zO7h&VHPdy%VqL`y+T|(V%}do)M?Le3m>(9Zz`-wcU7;tz#Tb@IoHOz9 z=?PqAMHW`f()}z5YnvU{>4zY6Oqk(=qX*Jz6(aKJzwpM|iXcom!b0ZzvmQ?3kuQ8Efz z@;x_0t)&Pkx=o&;0~Mscqpx=J+c0c?{Y&8W7x?v1kLw?;dH>Bt)yQK z-2R@kEKGHP{o5C@jYxC?JG!5GwPA%bNOSbXS-lCC=k(%AUczm$Uu;w4%d^(cY?$)j z{u699sp6WD))~-r*#q9kFHqV+=_ch`)bIUfGcDgf`QP6-vb4hxN$J@+q?|#Q4m&LWEbKc08fAGtT0hM66h1ad08mG#3ZL3P0EonRQYnsj^Eug@a zP7Kw{@_qbSW>h~F3to+W&Onqaea2NGVE-=nD@Du;zQQA^FE5(8`o=UC=R4NrKig`L zyE;(q7wr9}zCmUj@_|Nixn$gUs&GlLd&Wv`8?JytSlgtu$PIzsUt6*C$EA#hATYE@*!DP)03)uTbXReT?aFM_atbBk zfI9oVy@(6D#0c(F$tT7C70ixT+~YmW{j!IuP!gsAG=)P`@+_Ndaaw|0a7%)(S8{^v z29FputVZY9WMedl1^1msHNrcYXRF?BZT8eD@BNuQH%IG8YI|@p0LkZNl-$+k2+i7? zY#N(u7Gbu%O_v@;n84itBL4!Zl{{<;@5@EZyVa~Kp9nP!Y7k7V^(u}59bZNc`$16W zh99@ufVf;DiqVA8kHjXjzbwjF_!QGsy{d{`-f1|}vtvmKYr*a8k9oSb*QEx?&0jO^ zSY{bx?VxCiPl-w$+(D_MF`r`jTtz_cv+dZ8atV(&g}I7XKR;%6H#7is+JlmQ)c}hPYvq=~eqH&1*nkI<7e@MFxE<*sjp4ASS8E z(D`|--V4rG4bo%zcZsZ`$Vw@u*ZB-XzL~tk%sx447P;|st<|qwnK$6B2EHo*1F*uK z?fGTV9F2dDJ`RK*um@SresGTNBv_C*kcIg}*&ctKy)=&vg@2tG5aFaHBk>Qo_G_Q& zc#A^^x!>?3%Z*?s4D6*#6GE$OvTYJ-_Dur?p=$)&`K&fpR7eKBuO5OrW&-~iA>)DT zd6#T&Wh-&(wmt2oh0!p&Nn?7(louTW!mmnrAs7z_65sw%MDdNTMxuGaGzinhB93Z4 zDZB4r3NqBzW8}DCx_iITr{M_D+d}A*nN~#`2wQvV2%(_mlnc><{V-+i1-W#Jb1`y^ zpv;97DuUOQBg@(OGK?{5!Df@l%hz7ch(~*vuKB(ycX%C{r!e4D>2zmP_tR6s4?i$@ z<4sA)^^-|+dY4}OHg#xr*&j1lOkI~WbyvU(aY}7o&>!~v`3cMOb;&vF{4H#r(Xw1C zXHJS&1M5r&UvUk;Y^ZSMxmX2+sQ(O`*!|zZ;%@g)t*j@+++wElP6g=-1vW@KRf_MX z)M?8pKRnUJ!(FOBDWFD^sHkGko^>wW)_|y(GXIY9Wd=hFxc@Ey;Sabha{L}`{X5f? zC&{NS#;$fJkFA#_pAWc+J~ZSW1+qXFG_kucgk68XrlyV6kW^zd-oHO1DBYQT`W?r9 zO}D_QOl=x(8^(FM#+tOgviIgD#aSN+eK!KOlx9p-5Ru9PBS_Vz5VS6&68Z@ICb)`I za>pl}>VP>Fg{v8C(dvT$6TeJI{xaXk?9Fj3Q5m8ED%33(AwQ{on7A5(Siywh@3-0b zLZfzRTIxg(C~)C3uk5qLeWbR?Zkq|{?SA1$_z+^~O=x$ils?<)?no?#yujjVz1u8k zU)_U=RUcsnOH}PZ;K9zEcyvZ7P2uMaS;r-z>e6BHA(KRWx7^u8;#NxnCjMYMyz7z%4tdW zg@OFbHxEmPtPToCqdSEqDtoA=>Zb1^xH&5PDwUSz!6vRk_@c6RsX` z-pOX1tU~<#wugbA*jR`DauMzqUncJwI2nPEZSNQ_Gt&(BlVx#w;K9S?KG zo$;;oI>YDrKa$QnkgEUx+nTyIEHzV6M@8z!Zd;9+W;2-`d_ni0pHJ;DMbI459n#=O%^?tORHub3hd5{GK zGDacvuFP!CBP=_*C1(+x$5g8-eU!PZD5Ma)|7sTo0GOfrM_9js)5CG9w+7Oo(?&Ma zY=-V*MD6WKUTheU%WWF%B*`y8O*@vOvsnzT5^Hmhpe*2aiN?Qdm0#iBp75<==P zxr&+JuZ%8K$m%Hx?7KTwUshicWJ`s!1fkFH&l8;8WKy_0B4DNW3>alGEp{hwC=AwZ z)fN9q*&@Yb4pCD(qi7F;<3m7vbHRwm%p`4Ya74@d8`cBe_{Bu4u4X{Lo)7VHO9CpJ zEtg>dxDnf-3s_x*BdPQ1UlMH!GNv9ymw|m0*Zi{Q<{T z@Dr>XgY>Qc;f5E3skOl^RJ$q%Z57jLN+6eH1q$uh12i>_?@J&N(f^iV%oHq&zzw$7 z{^5WoYC)N(nA1vvpfK@^2%Jx(JprzM58~kWeTV5>5Jqshy3!V!H)jk^wtoaDeEc~@ zmL>@pdw&K?{$)tbp?(P0LTYwZ>!m_A0Khx*EvwGfje^F z+4V75$2wKTpz5$m;t8o=u9UGi<)wG3gzR#o7G6}$&QI}Nu;;t02t~kwhh9Aney?Dl zD5qF#be0!KLTkpzSW0&N{h-5#cp@Le83Bc{*hp&!27ot#>3lU<^JwR4eSN{AXryw!=~KCyl+QYX7aGO8 zvsm3YT+I3R-hGA0^D?0E4K)e-?HVrlQJh5vNn|e*!qpT4uOM}Pv$<_yD)^mC&++@> zxbsIGlWGx6H-JzFW2x)AGEiJLP^jd!1xPTWx8!#HPr*G@?jg769Cw5xz7%SThTC~# zmzdMiJd*RCH>Jfv5g~ z-SH`H+Sm3a9!MyV4HSM)a)!OSjBdwXeNAiBF%7Znzsp_b6JqrHqrUm&WVIghxa$uu z#h!F0GDd!z2P1t@o4EusNHRN6x2$*(9*TI(KT%(H=nL|9&zoV+ttZpHV)f5CgpCj< zEe=^+YP>|1@8A%021>&dAe6r8Ebee<=~RJ++%f7zA6HXIfPHiMm?$m8a>==WFzY?c zE!$=!PbAq?s~O@Sj8r9g&by}YUww0Q!qbK)GJ`C}E7Pv^bx84Wap3q-Xx zpo?-5L6X1;=#N!YsTWaWg9uAHh^kes)!j@Mq6h|K#{9b}Fhdc^Nkn6U`hYuLkO$Ig z{Q74Zq(0dym1f>cP!C^>*~*!?C0n4Ha&)&1fn$gWH1+(rRRNRk_oOJC3o_~748D>* zC-hDCnP(1xFOspvG}|V`_L9<&6t-ee7Kky`?t)A+?O3Jm{r!X=E`lm=1kdR6=bNM~ zZY^Bh;T@HombQvIpr97r;nB1CqpvD?Uq|Byqv63cr>EEzU9)a7-kn$Hg3S{PHtQqV z*_eTHoy=%Pd|V?f;GX&6ByQXJb+6|WB2+ppr46_)YC$=AW z;z}PsG*5RuLPV++4LZ@<5ZWn-hd8gDNX=X-k&W|E6?1e;3SMYtc823Q06C@O3Ug5o zg~Knhf{Bw381~WjLzf7T@-o(Ff5-N&(ka*#5Glj(rR+F}D1aDqM`(INSWicJ$M24} z%MLP3xUY&r^LJiTJhz$?GzWrB3%7X4VIZ$VhVzmPboyY^1t^W3I08WkGazsk8xgQK z|0HviXRDZ5KRkfbRmfc=kx$h6)3_8JyK)59CM6&sVL8ZaYWUS2f0kYd1Qf`bNf`*$ z8=5&Pe*k00|H6@hz5L*NP70M>ire6dyaHar^`l4k&1Vj$?IW315_I)fKe`5<-6$_` zX>bZ=o*XvUFd?UyobEzD!4|Fa?DG9dJh-)OrqH$+`xAYAom54=LT8kDqort8OkU)W z|7kYdvo*Y??)27fTlM9OvHrFt4PT|M zO)Pe&P@Wv_pw-VEpO~-~r(E=#oh=UZHSK_l4_f>B-LA^QT|f2TDJMqTkC}eM;mhn`gK`(;*ip ziwUn2j!DE6Qg?d^tXA1)>{5OlOrq|5E0Zf&D17`F8t=wW&AsJfx{^vOrewuI0NP7-h{khU~Vo5PRY5%uFH>VQJ+r8iZE zuOy!V-a5Gb={T|}7laUMLjiFt5K43N{2r`i_{=fUyOKyqXHGd5XB1?3=7WZ-xHi*+ zz@aUy?b*#^ovmRr(DUYjc+)?6NBP%BbsSKA*N4uDK$UI|94GPC?J!C+SO=E( z%nL&p3IotAZIIwwJ4hGcaVii4(d5b)OLq7zl3@HWfv9dHRd=O)Ayn_;g9gMi$8Rr^T*>-a5d{J z$!Qes2_1;RjAK7=d=tofVE-KKQA*Q?>}(*OiD|FL|>pWULEk~=2&g*B7I2@8e%dID7$LId#zE*@O6L9dWSN42=$aXMXEHW0maQ7}5Mgu}d$>$6G+MC;RP#dC(>ZtCT?U zLhW-_A95;K3(el24*C)abyEsDITuWS!`zC%T+RsW<9mP7>C@pBW1OntUNT+e(_eF?9eUhh0?=evC3>l_s1kpy~=i^Mcj!1 z?YZCOm)EFU2!3gUC}<{!U~%cUeqm>tq95N@$YG6^#?;FDDz1Sg*=<`DcBMHBx*X1~ z_ZI^)NO*tiI*;3jJ@c4HH>-8Azqo#19o4`Ft(BG%QqEJ7IzFo#&Qy-iUhQ?5u<*z~ zF=hOIq82I22!j#Ja2TBRXY!le=U+3|jUzNlb?C{(tyC+&*&w|SnfCmiqxD%6L(5Ai z7JSV)XvySTwMF>YvDi7};omze`E{nr@YY5EA2NWxSsXd=M2|MUo8nSi@t?N+s%(5U zWvR}~>?to+7S`L+QWto+sCwh#_W2C*ORt&-jn8xDfyI_l?Nf!-qh3&w>7M-5(SYbi^^}=_@Rn8?+h#pxKTf;@F8{(A@vu*+9Dkm41taxDSCSbD%HC z0nuXpe9)O68uHc+rQ_ga+aU!FnCd{c*{6`XmuI{XW%0OQ!Q~)nQ}u}Ge3Up&{l~je zhyR)K=3f_$`rM8f{ca(!T+%rk4w!%9xY4;FiWL{ontKa^7(Jl|X;3BDKmdpYLSB2L z=+A-ScP}B=4TJuR*#c{|$#k^IMZbkP5wDgUN$h13IXQ+KMMDfOVQYL7c(KF;nyFIu zLjY&_BL90&t#y8adjq8Rwjf0^A>3?EFItg?SeMzwy04yG=oXe*Qn_k1pCbV)tPjzG ziLOVtas_rR9slS;#Jbl->-_X;*-m{F4hyAy8cF5#AfyHu@cbWJv7xY#=I?rtoIu1;k{t=ly1Xh{w zEt(h;1@{qV!avg~jt_G;VvlMQ&`+^jFdvgGzLiQ^n<{znJp$dXMWc`v7g!_U0W0Y@ck59&}-M}`pnxjB`>8?ccQ2w1``4x4U^!%gup8wZ3V)v3cZ zo5owR(4)Ut zt^pYCu8yXg{+j%J%rsO^6bjpdO|*d}3u3fv30w*Ls6*Ao6+Pt5)p&%vfOy~>e$72y zG5w5;zTT?ju$`K2RkBgy%6l_c)7`Vf4i}njfDxkU#a&ZWP5*J3K?~{j=tupMjYLu={?99Ae7 z1giYm`-8>>qabq3jHL`4@FjP#igJto1UzmIo_lQ9r}nZ!5Edz|8SG8S5NrDy4v32# zQWSACxElA{D^$q!J_@|+72V7U;YnD3%~2sI$1cR_=mdQ4v%AQ8it z7~lW^ONMxCHz)+nz*n28kmDaOsCHjSNmf>l0&Xb$VDJ}OMQNU@Tz{AKK}Y@Z9rS2HXO6mG8R8Ny8{Rl6rD$jpC||Ve zazOOv=|a)FnV7i`2fuVmSKXy12WDqlKVMm&{-JT#5v`QAJDX=5u@=QUmOaQOs_(+l z&2j93r10fihgGgtH%oaAR2Y5`IWK7%+zCdpujNF~heSvkhxXsyPSuI+YdhxIlH*<3 znPeahC0&&hGyC5K_(_3`)q$EQ#hzMkGy4W?t|x1Ctab&Q5BkCj1t@^ER>Wy&Rl{w1&?7(0D7LiNDYEoug&R3tIqD_3zTpFEvyYwJ* zjUj>!=m=U`Xbs;{S3?j9h-bj@vNQ<)IU&J}U;+EPJ--jni2#!@wyJ1x`uTBj6up^H zn!&zCz}MZU!E3wbd=PW3?*a|PPd806)_?xo=xIH-K`pch+`X4K_PcVR_NS|FqaV;> zxgbT6LQ5yVFyWH-9RtX+&o?GXt&vZJWg6n|^VeKZV-q_Y^z07z4pv}(F2nDDv%&5p zUqT0k_1gh}`GHms=|Ebf=vS@0+Sjyi^j^RJtIa-MME3E0kgPy{RQOs@?Aos%ogeml zHNyX1IcAt#na$x1i6+$7^<>O~Lq3K^Zafp{?o~TBkvXaW9kwYsNDkJ14_AKO1Wa?} zw}lT@7wiNdjOIQ5YcY(k)M^`Xww9ZImFG>~7(mv3RUTE$`N*AEVeB)Y8qSU*;&^bu zuNB0wdjKXL7R3_%GhzUHJ(7N)wl6-9psZ&W>`*tQQUxD@+S1hr2ZBE$)8w5ujQ26v+# zm67VhThrzjOA1&2=WrH)&$MG!pM$fb1~KNb-iU0X4^N&yx;uzJr_Bu1ne;$A|p?FcUcoj%PcZ$rIo~*nLNDZUiqgqshP8 zmND{d?RdSdwzOHilJ^M@pF;Rev+HfDw{_OVF?o1v`+TbtNkqJ>zAts{Jo($ma%8rO z=|n;r;H}XlH^IA#>o`_{A0uLLgb;{j{n4^;6Saz?QU#y zodtjlJ^j^nqi^+Qpu27S7^%Cu1})e08lIAsB1``Ok>;iShhPq-bB=Qj zNPh#UZJJUR1s`$BNBq7=wJh|=p@zos@k;V^ag=n5dWEK zwjN%lzQM&CK6B+q);ai>d)+p|sfkNp&2&O{c8;xBHyq^ zkoRRAC$qlxaW)7@?97C`P86p4$10_M7EE^h-D1V=7~1bxI6(3>A2Qpg4^OqbX>OFJ z$|d*G{u7<&==!sB5sW5x%n)l|t2d3#2mZ60)^oVb)#2X)gN1SEXGT*zW^SMN8XvQ9 zM;45Q?*lJ)1&y>zIs#n4YkwW*x~0Q}FOhPfDHZ*u%JyUDMr{prrj_5?7+&QZH*bEa+h7A{6N zF~7p`*>dk@XXEa#pCEn6=VNAJRKjLVpRZG3w4KLm3!P5RmGyt9n&0V;N4RvL<>W8O z>+zy_cd()F6x!?fTWwDM`mkuV)VIasri~KSc`*Jgz}g|1c*Xxnrq*4ltvFsiLmn1U z7yvj}0o0U-4Y-&uLt%)Uj(->ruj_^_Q;r}s#G1Mw@E*uOLyvH)53r<9SZ?}TtV0o# z(#`NkLM_5mz=79SK$?7;$a`N4kz2|Ri85CFrVqNyl}!V`Klq*e{nxEoLs@ZB*56cP zGp;KRrbh8JAvMvrI^5PycBE@|f`9saWa7RIPGHQk7u3c>m#=EP4`Ui|94FUw3vZ-( zo~Ri!+a>WrX$%qNfA=GgQ#^73LqEqday1&L(t455aQGG+qrdlOtSJDCyIQv$Se$zi_&&~?6W~2zMrm|NjW-SwWYvJcaDIx1a z*zfUd1y7WQG=We3AILQnZ_|=8Fw5RNU6|9@SRjSzPPAB zGG!ItQt^jh%x@r4FEsL8!`qkWA9YR%Nv)btMcY_(N8P$yq9f}Q?ZUc1Q)Sjug&Eps z?vfKPyk$w&S0;Ps9@a~cIz4oi%A0bvA5Hj)vF_Fn*6e2bOF$g^W`ciE*bulPu1v_~ zK+=!bDYZV%^5Z8iy*m^5>StivK+IQlr3Xd%at6)+OpoB@AE(5_MG@6-LCut)%g}hrg9biCgJFm%Cr)BR$gc`Jw-4Ci zG+R!5=kh7=B}|vS_$?T3c?d9fhDJ6Q{Qd*BQeGSlUT{-7%G~+&c_Tc>E(J}WPv8Le zJL$_$rVI(Ui1y@RhrF^qY0n_FdvTpH?uBSB-zEjMdAyDWCB&AN&2mLSMlvcwnN|*ZoR* z!&m$*`$=u&0!n8D(el?vpOBa16ERNk-n7@ zKR?llou6E4>nzB5~$)KxT^z)nop*#uCw> zzADQoIg;z8-ZaPy(Lsr&tt8O27OsKF4ZbvIjN0+##p#LxEHLourb!&MvZ@o+R^lYq zb00;~bSdp0l8JKN#0#y&+j;0c6p73fKth)N2P@g|%C>y2WtH4j;-O_`7_$!fk zJ_H?!%c1kB4t!oD0eZDLb2np(?c}bA_~(kN?H8p6>J6nkzXkqsog9nw&G)TKAc8tn zXeqmuV8oQzlsP7}KmmmV@wFIAls{kw`zanPusX*^W`1p*F2-YNLZO;1w7#e*;60dR267xvXK}%C#5EPrQW)c}vKp!|}e&-MN z5bSWX92@#L-F&m8$Uyn%?xgu$oyqqMvvoaGfHOAv#9X;x=(B@qiPHO}zBzVly7s{5 zY*;Tw8L}>MaC{QLtxl@b{W~(%+;mN(i229Ocfr$&_4>s2)TdJ@| z9bZ?mkDMx>E{W1hPkqDA{Wjd44+#$mco;*Ud0`R=8`ab27o~UYu=D8J@`<(SrL4=Q zjph@{YgZ=3wwK|x7cu-pZ5~W}M-x2v*axKmBeoVun7fQHUGdoa8SrF9a1*MBPimu} zDiV59oRsa6Fv#`$_^#f`OY8yD-dQV&Ic0uMHD}+)#*KiO!Fc8a2G?!}jFj5q!D^RW zbwD_FEDHl=+N344c9%}cWE-M(;Qbo|%OE1LnqEO-YZDsw55tpO-L~O6B&5K>4DE?+ zFafL=@&&A>J~YpJH`w$lXzPq1ZK!Ehw_afF3?xiO;grW$p5%GI(zJpij&BS~Lt##^ z2yq(*Ug$xjBQWT**Z?uu(St`X&O33Opx&!yCvIz8c@U(7E0Ar{18--1fW2uP2ffQ!h0v*ht^4UcKoLV1e<4l&GPNs zqY^Xfh_!X%6C+3~=*FJ_jB9x%vTWz#L?)O#H`YlGe?6=$dZS9gAg(w{)8p5RY4ZE~ z<;AMzRq`g~hBu+8q#e1Bt7bp-*qeB@v1e?r!j}NIrGoHXgctI`sX`;D8t&@97j=-S zg3w3ti=*f}KrYw|(AKmbL=y^UABGQ>g@z`lteK1>Ak1{HrR51yq7&jntGI;shC%hW zy~IS%i6VJWLpGP6Ty6kA$9U9W)HVoHVL*UBdO*8g}R7Cu;4D4u8&6vCZkjUu3P96}avFUXQ$3H)}P3Nl#hlo||d&z@% zJ9A+g-jA)9|B9(rShfLlijT$`cY4)8iV|D{eU2ch11^**msS%s%+T4N@G>to$s6xZz za^{9xb8XROp0|G-E;P=OKX;$c)u}U}9^nkooMvaz_@10 zD{)lt8g{+yp}*GH>+%bfgMPD zzQeT}{zZKQ0Ib1S(3z@cGCRqK4B~_|URP}U(M7P-%Yb-5+~pAtc*u^X03qwMrb#SD z7qhu=VRx2R0L)Ocwr#~Aiw3v(ZAA3p<4$)%>FEuTdk8B_*|x#MoqgmG38p}``5PA8 z0o;j$_y5fUJtpCfrGKyF(-3=3Tq?p5={(|5Xq4@A1gj-NC*1Dhoy&Yl*Dw6Zaju#Z z_)b_JY>&0hark$Jq{lR%0wQC_o`fHtir(@6 znWOM|qb;-#0VzK|y)ii+H6$R!rnshL{uc=caX@ue>#|PuwO)oh6^8Ws zYSHCmAj6%FS<8=8Y8F7@3YdxA7^>2NON_>2Lne6#i5;+|k`WfEhpQ$qmK!4w`zbpv zJf|Z?GY3$*4l_2-OeiYtO{rs_!FHtX$*3DaH&2WqGhfJZdbc3;hHRa) zD__XFWVb4ya$b~3kP-7MLSvzf*lz=1`pk)8gO#%h)?p`vcG({8$DQXOaujB72lx-A zC19S%0in}^E?he zl0-PiZ&A?o77%Q*qrzm_|+UBoj)3K+&;rStOCwXsYo=61fGb~Igg8Maot zK|XA9ItnIV$W!=>b^9AIeB-o5)ocvcE#}~RuK#+`oXl(H$Vtt9ZUl(9XWL{5I*ZYp zJsaWj9jAT1h?Ld?Uucy}&ZmF$=Fa3q?$aQ>Nq4O66OyX7`98Z{xxSI7={FNj^PLrF zi<+rm)Nb@O%J0r-XNUNnbih0+(z#KR+BNfB)74@Z8>98!++gF`rAWNu6o=xsL#(?p z@~zwCUlc;h4NUa5UmnA51TVNgM`TBvGlPRa%`h8Z`1)5T3~F-Dw2mkH`gCC<;Y z(^2k5C`UN)njv#r6t{*!lg_q^ zFm-n2$vDaWFUEGo2lL1?D~6WWPhvJ!=Xj+InySuEj-4cB-%sG~`O+!lHd+LOi*1A3 z+k^{V1Unp{tp0L7$eEX$XYB&baB&iMIux@E6}=aldJoo^Xh^ z{N_lWP$rOLBXCiuG1hHCJPf{T}>tl$<8d*?Mfd=Iqrq%67Ef zPu`dN8V(!Ynxo#-qKs9N8_xOZxiNzHOkDIC2yIMkq#%=apw?@%M#Mi(Ot{_ zoDQ!SNJP_JfW|{WVO+QRC*h1kMR>I6{4hSrnh;{v0Xqy0)YFS0?|mpV<@_O?KYnWx zSHTk7=D_#nH04+xrx%!h!K@E1GNDs^2`aON+NVVyLK!?frE|GS@%`CaR|i~UQxyXF zTrC&QUby~tuKB_3B>DAcH++O{+Y3uursvI$yt1nOlzRln%5@~Z>%=ks0})5{M>aMU z3Vk00eiAA%O?iHe&&9#>-Ey%(Tvk;5f0EW!gOV9X%L1J;Jsi@-gHzqCu?qurhci}I z4lw~|U}w-G9w$;dbH0x~PUP0Ri?T;qUc9jPa#)eyj(k>u3;ncoyYfwWvErzHUCzfV z69y}6CB6i$BcYbV{^m?JOWNjv`s04d^KRRhUO$~1uRD9KAs^mSVr{{0em7zXWlAzx zV2qyYr)`s86#TohCKf%$znvElUFfJKY6H8iBMbk`E$eY*;Jtd^b6Nm0w<55DjGErh z>M{XeSO<75^aOE!2qLsLhrq4fU>smaaG3yk9@AKGEg}KywTf-;6=C;d-X1}#Vr7|4 z9&qB;g&!JDxl>%H3SMy!nF>u3e3c;D)~^C%;d`k*Euy&hCKwwB7!uRXT-4N=;6r4e z^Cft8^b%>!l-8J|GrK#hH7Uo-*=o?Mh$1Ra@Pvq;VfO&#DyeNH;DC(AnotDS7tS~Y z?(1X`(=eT*K0`o7`ucWw?iI3tRP2o@^d+19cZXf?Ql7tv%+|)8)?Pd2%sB4nHiQYj zAGU0pE#s!zZTa0oUOnkR>8aS$XI)JDXs2oi+lr$FPn|oKXneY+r>4AeAgch!_^C%WC$uqPJ2d( z9UpA@jYv4AYGcUv0We@Xr!sje0^Gt6#LKpvl!}a+3%lk-mwdygX|ZVN?D8KoW}6yx zejxv7-{jYKO}$ncwimY=d_tVxFW<{{F6Bi$AH+09`8?@*F&3K81YvZix)q2c*w zbn>|K(?zri#D`d2P2u+PsxU;OU@%zktKxwj8bfb&z?;ujM8u6JVRUGTr0pfwY*|_k z=1FtAR@ez7cOctxaB_$#@Jo%RHKM=1onf?Umx-ic*tJ|HYB@xAdu}v62D;uV(5sOl z`*04#crkM9C1Vm3Vu2y|`0V~C~G0L_zE5S zeCR`)HRa~t0%M#G=F^7E@jDu}7~Ayt$0g0j+>_z$H_|7sGti%w)>t?TI^KNHudT4h z($e3}+{$8FRLy%i`#?|`azjq1?I z0Z~|8pgXB&qtJdE>+~@`l-aW_Wp*GViTj)zS1NVp=~q_B^37iQ4KLRJ7y_bS07JcP zG<3Tiq+#ZB?^2p|AgR%ZW0PPSpsmE4o6)X*lf^8%6p0X5k-c_ zB~P4c_O!WF!8GpTIh)kINx2Z9!sKOrX=paZe!nmA*k#B7_AJb+*L{xYPc9``pJ^W9 zVAmQmKilz{IT+SHUKJ4N=~*7~<(!@t`no7u{ibA&+~0yD#BermXr?QiwmB>Dbv2J6 zwLyM;Ind11E)EVBETk8-$GpB(``dm+c{5PU( zkU#V%R0o$cv5=JWH9|C(^0oYjzPf5?JCo!v>UGdYuJad>OO zY4?{p+ia|tNE|kVmPgA;@Im#RFy*ew+4YH=D@S;1)67)Th+0O)GK~X>c z-oNQ`?;p+%hoQO-Y%J94yjxwIFyELz$&0ZJ^iLJr0#B0An6kfMebymtI9dk!qMN8d zoZS^#L-A?Ple;t8}|e8{>;{FRn9l7AG$h!%bSI{5M#nXL$@ z^-?zbb>4IBHb^z@U0vLYRN{>G3z=x~q>CUFY=hkoX?H(H`FvBQ`ML#1pi`D&%D{(F z@s4e^Y=`&{oVhN6ji*{$aMN98Gxx5%68h987AIT(Akl^PPR);P`F6^x)CIXG3Z|61 z#)E->f^iDNKM=C<;6H|c+{DWO8rvMHTkYGbT5oYx$kowdO|MBM6d(btsF#y~sT#;t zh)?Xop|apzq33*1)t~hpOu$Ue-0Zn6DMrb6k)hH7e6=8$DgZt%sQN*C_jV2k6aoFz zjh=dS;q(BqTAS7RzBLaL%6NgyyrK0^|gQ0Ie- z&8XLI3>`fcmHmjkrzc~O+S;c*$x zDZMu;5U-=bB8m^Cc9r{)o^?`@Vr1OEv4!%l(&mZ}Kc#F6${uVR+3)J$oZ?aPD*2D= zTWQ%Z{HU(|QomAa-`+d**H76za>U9Vfz$qV{50Ap(;7xdATpww+1jfLP*JSaca&4dfuAufEI<<7Oa8EgF$kb^r%?FzQfPu)3J}- z>R-@r%!0j+Iq-!oZvqV%!!th{`7GwAa7Z$6WTpK8&y<$=u6;Ph+&8EgSiKf&)A=C~InUu}YF3g>@pXCZn#6i$ zs>N}H(^-Ner>KJ?;m14u`#CvxrX=Q0_%r{GHP5|(g9A4n0a?9ND|Pol?`WdRrP&;U zYaT}A=yr8T&!hWFU;(77lK<5^z35c>18e;u;;~J=rBlU)-HYh)LlR0J?Mb6XRU>~xWD7!)bET7SgCgLK z3fUibYQb0BNiR~$l62oMb9A9#WHLqFX5felGU&_M4_vCeqM{&9B4&+-LJ-+Mv#6{v zyd#0eNB=l^FhOmr6p5o_pKj6CvE`6<>!c}Nj8Q@*FjFHT2Wbcg#)eE)2+s*F#x(Y( zV6q4g1P$Cc?@uFeK-@NQS6UdHe*C2mpElZ6V?Y|RNL(XEq;uSc|H$;@1^p(E_6mwijqI1WeyWgBIafRdY4@U_&xKla^+0;;I zvF?V-5%@g^?dEu>SzT1sW|~?Ub2Xv+xi<*T0h{z~<+zD_Ur8Ha>l>nD2M#WXDx^{$*ZqDe@UV#{L5J-i-kS0TVXqrkO z&kalBD3qCw(fW;<;;h|`{+Eve?}vV9_$bpjTBlz?%4s^3aP5L}zl^TwVP~U~QiAFR zNqZ6fCsYx}d=9YzT&^@vS08{;2JD&C$4QUM$luMt#y-*n7=m z%f26UjN5rYllJHcP?ww5)8}v0WCD+D^PoYnh}F&a{8x&Rj6n`IL{BsvjL4Bgb|Hz zZdibZ;`!P%9*RRIxS~SSj?7~O{TpQj4jxUbJGYd}RoxmqIt67$w?lqOAOlQr zoL!(orEhrqAsWikTg@8AtWpm*ZC7?wo&0XC10`6W9POW7?mWvF>(A>jnm&7>M&6j~ z?1v7fYhk(9g{YsmZW}FP%syBf`zuN?)JNrMarfFak6_xh%rR(H`RHoh`<4n%0%Mnh zowpm77>sQIZ;e32`B}c#L*a(_=I20`APNwKp@E@^-oa8r>t=B2XFZhnjEGtkI$vai z^oi;I2w|K9Li1wRC_gqH_7kcMl)!caIH-``w%Bd>5)!A!)U$e_?p&wGJVCdHfU^}a z4l0-nAdI#mMwpiLo@T~iQ$yITZeT^M~#+Wf!f;utrdgc7vuyJTXU;Hi=KF3Z0^-MKJqFKMZ2 z*-=|L>x&6}lR0`_nk{3i;&#TJYF+kwmI?a;o4*?$5wL`&$N1gAkiCZYX6{_r_m6LH z9#Xk1oA~2eXixXUIb#5_i6+TKt|Qqt#b1teV=g0kkvl?1uEr)u6U7GhL+ftfRl$-w z*!8n64Czm9Or2yDU0s^q;EW9iY$*laiwy?oafl}vZ`Gtl zWb$C`Agta9w)$w378w@7`{-b(|D1MbCLZqU56b2&O!my<&p%e!9N10%2i0I349eh~ zd16Sa=fk2BsUVD9<{j~-Zv!EkN^Th-Ee5x_GVp%l!f{^Q!hsVJ#+%L_ue!>=pUx2a z1_$WA!K@liKhC%}C)J~V3-&=I{a6SLAIRH@B*Sj_yC!AX70-+!Y|_u&9{Crfz_v>J z@11wuBgKfgnAr-~;Kyl<4?;yz34&Ry1MfNyz=DRqOT9Yd>eV-9lgC?M-K@>W8+0$Q zxmijN2LNvj{)X@{g}TXt)K)jAMdO@_tqOJg6G^A$Y@I=lv%<1C06B68>+SP#`Ic}+?Y+#W{E!>07u^)^{ZVyn?;^4M7o9+E z_|Ia+>!?4&80(5{Ue=lZqH|vxu(Y9l=n_)KO3OUhBBfl zewUlRW*w16?WM2?O=$f?l*1d$7lx~!SyF(H6iBJcssu!tdlHAi{m`x+s)-fo!e>N+ z(Mat{e&{ve{D#^>W#CK}g@6f-TS7A+@&kZqDUfYXZKnb^(ghC{c_Ue z#7csL-QcK$_5XNlAXlYYDb8I`g9aD!OWpDu_ASxWdt&jTLzWSuDisJKG8yzOen`0b zM*8Eoroi^qm4 z!zL6%xnesv{19mp+JqR@pJ90G$tY?riESCa_5n)(_RMmA0<*CaF|-Wdj}0KhrzUC! z?biSeIL~`LaP{KY9UPB!1_Ye>ItQpJVcbAIZUW7Z?gRViVM;uViQY&53|s{xAn-9L z3?~vGuI=yT_kF$%NZo|tuzZt{@9g?YyrLmE`Pag-F$Q@?D66bg$Pb=PuKON6 zkG~~vD5eUea_emf;uu1B!J_|{0`hu{KQ5CcXuEKy{u4Tqsb`VAS1+?Z1rsP9IUydv zIhfl8Ha9R7!*-%W!NcPLe)9p=??%!K&+TW5MPih=&~=8HiSb za@TYeL9TjGtyaXwhPK6+ufJSrlnBR~et)TPI6x?jh1N6g2ZgbXK%h>I zJ-rs7Q4;Jy(a@;6wpMKqt9c=zI|y@ZJHC=Q@BVye+AvMBgU1AA zMmA=@zx1sgFqiUwGB`5pEcdVd%{eLGx;&lN^IDg+H!}Mhxtq=45LCG&X zIYgc3h1d^w9}Mb2?bjdrv~d&!BB*Pdrzf0~x(Aqdr}z{^%hZDME7^!#`so|dI;H{r z67);W#ieN7NrF|V(v&a{V8=o)x_*f2(LK zds9aLwo{qMWjot!x$uksj{S8r{8rebTW%7$nBc*Xmx-+&L$<^3Ph4}gToS6qKB?T^ zW!cM6jbl>0JpX&OV+!b=$=HANX;c%Lgu+c?y+=lXQ%`#qcECO!WmnS?L^K6alIg(` zbd7#fQ4#M{1`@KB+1mn@uL?lSU4dIvO$5;a6Ku;|5^3l~KU_jVbBBpXFNaAmXL!Be z47M?qCe)?Sfh%S7neFHQyaP-J<-edCd>U`B=6J+Y6ief|6^oS-#8)Ls^R&tFG(}p5 zpM1{yJdF{YAaQ5$j=D%`>FfV^Ed7Ni`r@4C?%7nf+l%R!f7LLtnd`rrAnJJ}67e)) zlY34m>?$zAp{L;nsOiniR_o}30|_JDr&1F8RL>g`uz!OlG8AL{q&q$Vu1~$u!y3@}FY^NL+w%Cz^wKxMP(hA74NE=tP6o_%qn#cX%4qD|&tnM{!+ zoY(2nMTHF<24EGN_y=mW@)l%^pD7Abe6Hh}H_FAZ(Ur(d&yCBEOBXh??1bH(UA1gA z0;!VlAiwch-rQ5pY39rIqr%=a-1l|8->=v6nX^Y$jlJ7b z;FujnbRb)?eN?wpjD*Lw=}2LRs#6C8=L_wghK}$5s0Zp>t}GdgeU7+fReM{8@VXz3 zkwX7ve%#%7MUNHJh9Z=#Lk((pV61JRMt$HB6|zNEkYZazlT#M#u&KjkgZ)VLdC%bJ zrsg`ca}4L@A6LUtNKBGE-di$ZZ|*Q@@(}~U{2jCEBf0t{L^>(^dnE#GyyRc_`qa35cCFd6URbH|wq0NqWX zg9Gu>&v0PpDnkUKg!`dr$$2xoJZ|OvGU5;t$|S=l1qtHIj8o{w-(5;iFkNUqsI&H- zJQM^fxImx&OkM`m`0pqg`l~_3eB`V9E<=|G&w?4qFFXes#@})yOtz z5Ozi!&aYnnV`l|8dFQ~c0x$prfjzmwYWw=#>~>~E#fLmH$QlIh{vcS*-x)jy01n>FlZ zuW_&1tZ^$sFoyFrd6N#ph)7c_V_b+2DCZk{6^~Dte;6TU5hxv^MWCpV!Y7QSeA<{4 zgj-&BHhQ+u>6{r9LZ3auX3VOf+@o@$Cp3ar@4K96P-UbBCtmoD(YD(7_unZ5{e`i2 z>E4f4T;(dR-w_w3Pw4&e*89Dp-oVwUs$brL=FxoG?j>6H1-kz+>O2;Zz^d7G@Rj|X zn`&+S*Vn_~|5Z_+Q9|cIXyWDYH$(GQJ})zkQ$S2PCQ~n-UfCDNFX}bDkl$So#Tdu_~`(VP@}Y#B@+Uxx8J_1YX>=sler&v5DiL)PZ*bic0eQ zOiPr?c%7(e^>Ci%C~F)^o(78xvZ^4Rjt4$rs?Ld}j)%3}6_igz`8l0>^l7O(Y&&D) z`?&=Zo6yPu)p1qDk#~a&x~iZK#^ngqQD4=LPl3KMlAOh*m_K4Q>$_j3l%z${4lbao_rbk%MEvB@Cl z^8T~bvOU$WWsCYjOOmJk#RG>i-UylT3XL4%$Gr4ZP~0UOgp;GZYRV>8lC$65_e?HJ$=%%Dc>Ot+Lknr;*Uog%*35jCN|2FyW{}Fy%GvXiiQU`^47aZ z$UPRU(8S{hz=vxUedvMlLxVBx$Z<0JSjGtB3pw#68sN_FiI4@^SRGF2J&phQS{5hG z!*FiPL^OH%9qCWO5(5Sv_n)MMHik72WtxM2tHm<8Kkf+}mF{tIH0lu%el!2iM`VHD z9CL+trFBtKu3mDWjql+dMkyfU&gIp-TO0hKJ1uu9XW&0&*|}$Z{%3!&`LQoe?Uy?# zdbDS_M4BZIpT0DBLx$J0pO*@|jdA^Rid7V@q`y+kI*CrAP8~>hjy>I0x?dMnZZi1r zy5WT8ho0Cs7su-a%os2Ka$xvZX0NNUyt5EPK8+_*>hK*QdUfSWx)#$}jz@mJS%J0U z_hO~hjFq5tDGPV4H?vQJo(t~bCiO1*NiU8oCAn|75BgRXr<_e7_f$WttKwDN@cmKd zyW5@r?ZGy>!3=XWl7H?nOTJ$APOKPR)z$i?H|hVlC5((#e2VUz+@*Lt&}%NUYJAMD zmH5~9>Y|eJ<6Om=r?!o*S?I|Ld2nb*m3oonI`8AtamV@2Sw6A!_qzxFdB647?~e33 z^Urg}wp94$C11caUzv%3!+BswZJ=;GP6m~K2;3kTM6$WvZtM7=W zxc?E#U}l#tcx38oxgsu1og&Oh5Kb-u_#-DJeo9J`qMoIqA!Gk}F=6&)j?doj)+H{u zfw%uP6{yB{AB5!;Hf9M!(TCTxT68EiOEF1ea<&csDDUlUCq6>k9y(`Sogz7N1)7_` z=}?T?n6BY*5%~|StHBR~wK3^>n!Bte)~fp9vJk;52Xw({C5pD67Hgz zTuOLM%~mR_HK4F@%RnknrzcXGghPL4AU~MoJ0WWg z&CurdFwOdz3ZEd6Mx+S~=P$#PKmt#A6+qb7S6;}bz;WV5gPm_-%q!5Jeyza7h{}eu zu8HBN2`TJnmN$Bp{!wjayHz#Qus~_whl?fas;kT_#-w%JH!?jsH`WUi(-_5nbK7hx z+NvOH2f9?-oBq)=Ncb9d{m}ARz@H;qK0ehoe%i$Q3-8_i2kKoP-Z>9`MxW43p67?I zXi))%*P@;x4fM6p9mnLSZMD{a6%CoIWGJLqE?G{c0LSFn`b=jDe%gYKW-h94lY@8#^m;N#~6dz{?{beG^c94D9t zsZ&DOs6@|r&U|N8`dAKAm)Be(y_xwPj*c%ol`-1k@`S}CHJcHYq9GO z?Bf#qZ4_lB{p~3Ra(PR`e_ws*NuOBp{^V6{=0caaCc=zt)uOHa!y@8$gZ0$is8dYU z%7Z%zt+!*J*iE2VGH>5wlKYj&r*7If0;ypY_wFv9Xo>yrSIs@>&tTYpjp@HN;!ox2 z2ijnlPFxAB5Wk&8`%{;N;|%|uk}F_oM2^R_94b4)es8gm&1T8|5WA=Ao&s25k9kkg zL9SlNb>lamP~zXY=)s)J$}so^8<1p|%ksk_n(yrG%Y>0ugn~IHLIEg?JzmLV=GTgV za+L=7Nx;CvtepSDki-jXGkYSj93+``cAUXqTA#4mvMV`kDnBPLUZUl;MJf|3c}GqF zNeBcb3NbR!Lebyfp9Z&(>;)VrOhd>~+S09{$kRZy=P6-WdZ?9&P}7F_Bg_e`7sH2k zg5$dED;da1ll z(rjNmre@{b^Y5uU|PF&0QSVJMV7$3mnc;=+~m==ZH2( z+P~bXn31s}zb1#`#W_XZi(QG25;xXmx8{S!q0@90%Cl1+-%3h6c`n+U^|s_%NAGXr z*B5)ELi0qOqsMn#ydBOWI?vwEzM_q94c9EE;9Awu4t&bV6rC(u&}2deaeHMcla^U5 z<k1EqcHV`UZ4vs%I!s0h2 zq2T=vUBd9B@cgDyoz*-it9xqT?e(DGc7E`3*C2YKWOr+!#&Jq8Vg?r+IPm$%D|*iBzVwwmgnnRW~0k`?Enxf%YCCXEhbZWHBaMvifkPxcIGw+}A!e z?2-DpAf)owcR#%aM^@pCmb>^%%z&*~TNcnZhGL6-{W6rcG{E9Z@K@FK%moydT`^4# zKalFfxOApN+57BVT&YQt)Q~Iu3{6|F_WDr{C!a`^;~mo#1`~57Q*_|B!JESkuAkSx z(4{1aur56Ru@#pp!_=SV$2cG}3BQ{3o_}EUa_Ucd{@M^`xRiEr{+PGQ3gr!W3V zs+x6xg~6;4;ssH)YFJD#$ro+BZy4T{FmX|kLiD@d)}2uABv&e+A)RtB?PU9qU6ze6 z#jahApAz#)HDAh<08ES}edpYe(4@z%Afb40^Nykw?wbzrk9{?)a|)_mk5E*@>1>5q zLjNNulj06|4m*+HHkCuG+yT-M*ua6Qz^nx`=nqh9x56US*oA2*^&_BF1@B@ia3FYuXyK&3GYGSac8RZ`pX7eIbH*+ejxmXcbyGcoH>b4u z@jI^H)WRcvX}g;!@Cg4_?p3`<+r+W!cPFkc3JyuU$_}KYzwXIB2)Tb{Sadg6y5K{oMn$Peq!Q);*Gp>+mYT1l*!MIFW(I5WxSPqd{!}#~zS7jn} zQqab9u$3Ss44Dga9|1hUgx>Af^r0>24m!z)o|tXpIs-N#iR)@zy>4ZAO6om=tIk`n z&E4ox$q*Ov6CUSpqz>{%8^@Bf0fgb8UX8aQZ3wAym4n-`+XG^cG(4Ip+iY+yuBz z5G)@LKl}@M&LNa(t@?80&T3zuz;)p?C#h6g+O^ufgMC8GmPM0$vvxh%yQ{PWQ}^Q* zxXn!T^Uwywztz4WQxn&9V9R`B^BWPP(bXWM#h&z$dp-cvFaud7-nKQv=%8qgSWEH( z{VRh;DdlNiaB10TS4r*0;Dfv{?GwOS@NnsIQ}fO46WGJ0ggN7ZwD}AD7Rk z*I^I8nn{1YXA>ViFrNS?A22w30avaHtR^Um?^=uiqL7!Y$kI{;LR;9V%XAC7H>f(^ zx5plZu$~7UH$i=lH9372WHyTma_PlE+Umy;J+{IeesjAog6pTeD(y1Yv(%+qWaV@f zb^C|4Q+sF<)bvg-r3V8w?l7mbUyTbY+96<PC=12fW-3Y<<*EvIL&@{kNR12rQ|S(m>Fu0^jP z>>;;F`$F9!a;!?BZ z36QDu_UoemP4mO5DZ6Vv(a-wSuF!zxZ#X-$OEFH16XAv|dmn5y7j|%tIN603=BkZG zTqY|R?e`%PrQSEQ!0#e>rS%5(evFEEQAewrzLC>^bS-&3Pe)2q@w9K-&c3jn=ubk;N05x_xIFBzQyaop#E~5v7-O)Ld&sIbVvCd21DD zn_x&;+mn+K*GLmgzh)N~%+2)WO@W>FOV`go;>m8rjJgJG_X}o1X@0|9ow85^HJG%S zZ=(5H;x;$SE;kzzW7fH)YsXe}F4sL4k9}dOseq{m!Kr-bn zp^l;mB%agC9pAu>8w6sO(I~8ZeRaSNVMGF?-{2aty9vHKw)ukSI}hm{dwXmIaXatV zeI|{dQt5&>*L_TjF2+`R<%zXNq*y-*wkBEn-Y(7ZlWpdK5UAYLLE|G!*11|9>&%#% zb-Op3_O3j;9(z+J1j$IRECua^j+blF?RTf5$} zU$xddLzwA-mQ?G&I>x8AC?d&LGt|DsJ0)nRp!ZihulFy?J0s4h6EV) z%>eK;Ad{_e3BiFCKe2Ri8_p4fo+d#G^vz+G491MQM(>yiexBM;u@Ak!-%$x4r9}s- zjY~k8U#H0}S?NWA>6x+H*id!;X`U;8(W@rT28jqlL3nmB&|t)d{u&8nTJZzd{Jmpk za!vl{xT>5-AZ)XSR%WoGCpg}K+HyMW9<^ALStS=Yl?m5fuFll)!nDl5rZ9>*pO@(x z+Gag6ier}nHZ5aP*}8nZH5U4LM)4;Q?n1T{W@z>O%QKlk-K@efTrWr}k+XjOg9Jz| zm zGTWhFa7yA)iV5*MGjBm^0q3}5pc>uJogcN*crC76L4e3aSlLqSoVCx{@d4}c^M>lI zX_E_#8_#CCnqdVI^E>9bW=I5@3Hj zOansUKy-&6`07HV3|-;P%^-pO%`>Qw;ztkBpVo$6qyN2CrsbK(YzTPti2zo8)9XEq zD4QR1m?Aib%x)ARKM++&^1@`PaXJme_r z3>N}~vzbfJ zlL#B7_@4!y832Wz=LVcl!)r6oA@+&lp3Tc-a5y@OCCN{sTc~H`pbk(KX2-U6{klzA z2~t0X(gDx8JrL6;x^`j4?gUVB?w7-PV3JC|ec%W^kNG)ZAv5cD^#4J$1~qb}v%%8J z@WCLN1v0}cxkHZK!s!dzk(R^ngj$+>f8aA=%?Z141Edr{*oLVN8&@b(mlvvEt>FN%Xa6 zx8qJG-*Wz&_sJ@if^pO^T@e)|vk(apS6xe9CGiJLqswlXGK%U*TCZCLeVLt)vdf?b zH!@6`Q9<{MDh<6ShQ`y3&1I+!$tMTIk-C6p1G)TW9LLB~ce>QL(5ZEgh?>pOke7Bo zbX-n-R|doRLn?iV#T@zC_xU&;%`=Hev(bX;`G@Eluh8fq(}s(`kc21K7fdywvrvB7 z`#qnCGt91P*~fyPd!s%q#~H|I6IB7>$F)JzJg_VcGxSh{H~OX?v(#X~H@X+53c?2L zizrjcXQuXvzd3GqbqJ0RmhqVM*mhnd+)Fy`WBVl_`WhBkV!r8vq8;TD(nJw8MAOnRe~kRWxZgIlsdf zv&9eXx*@C>M8x=Hi{IeC?^YBorMGoIQF=RJc}8lwL&5v&O=jh1YMyE+l`AT__Ms4R zsGjgEU|J__?=%Yn-&|}{?OMz*Jo=%TT1vM(NcW@QJhv%3|G?Tg!Xf^S-1sS8?wp6N z$QFWOnRk$WRHIK`-xRbo$+lonL170+eoNeI`wb%^(GsWcU`saUXs&U z$*^8SxO=2d-+rm_thd!$Rth1Sl_9Ok@NIx=_2X3Sq&-4Xo>*XJ)vVM92BTIqfGh2% z2{9xufcUkdy4-(^A>f7W(2pYAp3C((5z)wh#AUk{p_n%A&B=l9WY1%`CHu2IN?ecY zqnYuZ%I4n=h^UU}U_5kyFb|-o`)F$BeFi#`0RcAR4q(HZ+$JjaZ7e1DLuKJxM@Mke zU-%X8a(Z?UOb#Ok?P#*#E0HWS>CIOXkY#)}EtcadKfcK!MCo%)QCklYU&WliH`^-a z2%wi@SAZarvFv`H-u!V7#EP$_a#Le(cQc)~^y!FgQ_E9vl?K|)Rn1zK6Qm7D_`llr zM*fWmRCRpZGSKY~psE?o+zo7|xuzws3mQ{*TdRYbrX`dCf}HuOmT@GNVtYLkGcbZ} zeZw0MNCVGryxZcM=`d#Fso)Bmt7bcnX>@0kNCE3+Qxr6~%}bc_^Vl{H2-01^=)&e}HK=D@1S^VHCgTI$yedF)9 z&n@Yc3^5%PbJL_n7Ff$4Q3}z3dhI$a+GU=fBX;e9++r2DRxN+a-y?YYxTH6h*GxFT zY-Z}AU8JA412`jY16Wc=m zge}RV?e|UCRAl)HvzA;JVeCAhuM%jc^AMpYWQ>{6?@6z>2iVh~PNn8LiyBVR-*I-B zfFthb+~&3#-yRaSV|?-7+EefoW%{{9$~`Z%SpRLsup7HiJ;U_I{fzcbDezkObY`X5@=u`Yf1 zC`=`A{#A2W^PCPXw^N+|qUM$vw*r5mP0G}f-VyJn*}knW>Do&vx&aN-J~q%lu&iM$ zoV!Cg7=+1u%7K*@96Nb#=Sj~&z{5S~Z|Pcp^OFpgF&_NG6C)C;ax0c z`JZM|-&y4c%1iH_j+^8NO+HGpH&Xpzh%;%_OPQ#A{-~LiBG_I2>45~5;$pZ9ou@d2 zf|y@3=BiColdo>VRxWR6e@58|J`$|{Q=%4OYv#~v&symxW!Kw(BPcU}`l7PV>#i#- z5E#JcJUTlZeEY}*2b(b!32tljB+ooH!jsuCx1De9*G(PB0x|%3wQ{`ae!>+oEdHqu z3VT>#RUjD-L8a}saWuxWWt||os91=$R){2P%y;f4Md<3>J?s(|G@wJ%Ucd*XD<0~m z%gr=MALQ7YaZ3@MeHc8sTkJaw1GYZH7Wue}y})k5z?&lO*KEphr%@-<6a1s) z)9Jdvhd3R;5C7fUzOCpU*B%Ve=6$E3SwL*P7bh}qr1Iv*w?Od?$AjS|&;GMC9j<)2 z+vm$B`?)T*&jJ=raHdVPfv`@zpmS1+tWJ4vJ1g1npysGaNG#;Ejq3N>mxUjW2hr_;UEc#*_3sx2j-OoYmPl)`r zvo!q_gh^fOW9|@lxQFSG6lAx*GKqP4N-ef3I(#d^VvU9`4j7jLbrY_C`@B#4IEI>6 zDEHKD#SWsnX}=gIvw) z8hyQ*8lN~+HGXM60902obX`L)9%4qGp^t#JDrA_>0eV!ZNsD(e*8{N zoaxMkysYWq&tzH16G>We)EL{Vqj9i z&{KxY6Y!p2Ktm2L5gq*G7G)zzb5X7I35pAWV!up)$-<6(`@k5;54;-$&TxiJ+|;9| zORFaWC73}TMh$xU&n~GrX7wJ#6S&~%5}WBHk@#JVz>acyKpLbSH_H+z+^zUVdzTiS z67bMuWbNpmP{qu%S$W+Qg?6R2cnnHGiRyIsHM`)|-3%(1 zLPy7SfBW!a51Cb>Z$9h6h%t!JU#)DE?B6`rSzrP~_I52F*(PeeX{>+Wg$2a;YKpt^ z1{u4&S&}JKu-ZCLczNf$HJNPtXnc{xB9yo(o^iQhQLBO>>(A+Hu9`TI!!`g*;TN1v zxG5!xG4ITg`RKIU3!GJDRCfOOJA%Z&Cq*PX?x?mhXB?t<;7Ym~)D@tcJ{VVW0#_~` z+THUzY1hZ7)VP(2F^4ct0E`U+XID0^psAnZBB6ddkZp%x@=YA|1IuH`qcK&13t_e5rT*2nQ=|XQ;~wrZGPEB`QN~5k-X-$ganam>|Y>e z05Gu8%iESIl5N?X>aCw%RJi`eHA&IowH@o9l`8h$CL?Z>c%d1nG#M`Ds%w@rwfOT| z&`*BQ_ifgr$w?9Y`E1G<&OGUo%mbm`BHwyLeB9uQU`D`mT!;z0JD*6xd=(pxPK8invyArPN@s{~%9NksL8Vy-K&|%Hg$VNk8 z*=+yxx$i}an#d!GjY26r(`+~?=_+Wb@nK!~a|dXCnieMs{fdC3?V7;BQP9;n$ zOHxN+4a>;(zL~;EeIK1=|ZsA8tO& z2YFI`J_sHp4|E-M+ys9V_H~U8y4LKt)z!>_G`_lEov|27+aj0cBR>!JG?owq!uz=} zP7)+k;k4Pc|DcUpODH#B<;y@*7feMB30nQv+FM@WuQ+_`rYcZh=(vsDH%Yh-I51kt zKk7jxCo=Gn&aX3abyoG6rq?yahfj2;5P9l;of42S4V@o}8n4d+%p%o=_LKzgn)AFo z4=l{sTuczsH*@(dioZl8_KHPoYs9}2dHiiSSwMX)#Y{9NMX}1O+*UW*)p9+g8e8=0 zuia!K3TWWPG^^%!i{A*0f5FALRechIz~-NalCd_JU!nA#9;>teXu!TLLFNF*#{elVQMM52( zrI$(33Qs;EG$;r_^U_4E;NOE zHQ@xGYiy(niya<7a+-aFsL25kGpgd!&C_;{2_f z<<-{>r2FEM4Fzuw#w*@>B$-TFx>vIgp|BnA?wd66On<%hEd0%X-`#>63O6K|vRFI_ zEViP55g@P}w7&U+Vx%&#{54;0=sAmbUh}{!ZnwKzzSOg+R4rXCd7pFwLzVkQeNKKU z(nwJJ(Jq|@6)+9}jqle^m*iYl=y0%%-Jf8WF?FM{Zvs+ksQ5AYwGy;tFeUfNG{*BQ z37te8B8Idc9=~ZBd-1mXy=xTf%8E@=;hEl1 z<_~Lm0(I5WhT5X~Hq)$t#2T7-XU0T6b%)_IPHY$_6( zU*Y<}4S2QSmpStwnod#yb356&xF&8AoCHDOg~~&Wr_4CA&??Mrs^g9@=Z}|axdmb~ zrhmktY4n7U0t=6AZ5k<4@gYZ85DIeSXr}{XJgg7$r-aAPpb4r>T4=>lAcg8LBCv+$ zu_Ho387j5?GaRfA>`{o@``>rVnIa&C>V}h^m*!@`_U``Pfh+v|OZ{}ZqDJ+?%A9U9 zLtjn7LniC+txb{hj)u?nd3OLJ6J4ulx}mxU-_t5}`?TNCiCnyRG0SNfR<$>v6rA10 z=_{B#Ijtp$$ECQn*=X4wr-lni z5Es|D$51ziLcbQv&!mpFl2 zuf?s4+S4C8*bl5jxUUIQWS)p6t_1{EYoD2sE;fhebmGvaX~M^OrL7~Q{jp`V1EJw+ zaC4x2K@5I}9%6P?T>owJ&&}os>Fu7hj z@sxqX=E)3^d1`XTK&4$TLJ+Npn_b|&&B_5<$WH1;1@Y)LLXQ| z<^VJ5fdE7NqOnp2v56rFU=L(#qcE0pn<#`Z^sJ6~3oQfg$L@ zlS(4(Rj_H)Ks)Pn@+idGzw5mo`pEhd6ET|(@(my~tAiIU3|7Uo|KL#s%gjxiW7&IX z&Jib-8v06y8cR`b`3icQmOOqBG3kZ$bv@%$_PWc^r=gv3jdEQ{ z^{$R7mcdW-*(zUc_3%s zGUdjaiyWY@D4)Rc!?oZU$FMexoN0y3MU-9rIHBhk-ffl~a()}N#jb&Poe|W6z_wWR zhi!}#i@`ciu@wT+BT~f&#`wy+1I8D5iXezJZj5@CM%L0P(#!o!8xTu+JI2H(Mntkd zj)(|Z0Bg3Ito>aXLD!#t0?uEAUmAAYOMbDfZ?8Ld{ZrJ?fylGGKK;J9bD!)iA~B?k z{5!k7MrurH{<`1ozEb*avpo9gQ_DZ3) zxz)JAY3nvzhxLe>e_QhMT8bepMnm789mI692MAJh(okGUb$9W0~3Cuk&^=OkFoU=T_uUa{gnI z=9Vf2?lT$)sSh20+oL8ARzA|cP-x;loz?2XL#FK`j6`bXR~{K=~Y z!p(YcHPBL)UvWw0>r#Wh0KXlWLm2m}>+Yh+ef^1pV+o1Z8geR=pP!2?;Ok=`5I*V0 z?3S3kc4x%SJCl)ORJGJytGU#jUz2)wPF8Mjoq2xB-8k9mEVv4d?$*FXuUv{wLi7sn zw}MG{_g)CfgNOKahL8Dcx)c*SMHT1>e%E$k61jKBnc*g~0(?H0RZ2HpJ^QTN2HU{P5Oa7ktLSzzGy&QE+?)Ga&O) zA`oDU`yYgC;Y^e13Njy>k{fh73rVcpSjkt_Tv)I@>1}WNBGWjlunn!B;3meKsYw^1 zhBE$?$ISr^W6JqFLw_=c{xr;y8}33YLm~{@l9Fch&=MOL_X6?HELVFaOWTdmt1Lfi zxra<2RS4ZVja1%dkT1#DanVh-H(ob+*VZIvT3jq`IG={~d*9DTSq%6Jr{20ao6WoQ@SX4Z%ts*6PkUuD#}-BTW0qm# zL)MXbex{U|<4&7oD^>A>qO%7-4tkzx!fr1Pxx%LZ-F^dD6w0(S(^1YsdagNzX13GU z%?o4FP7?ltT5Asaru6AG-9NNz(1&sd^R5ZiyxhB3-I@}9?742TGy z-#&N+fr!!8CM*YbBqu?#Tp^<6X!7{m&UmaFTMmRv04{_DR9a?`Gm3zjy`mau29`C1 z_ZLKwvK-0_$(!h()c2)!j_Q}!olgP*GSGkV99I<7rgiqSXq8JjIu*QH_;+LxuT3^L zmN+2r_TKi0e0Dqa#nU)kp*>GeSPlvN?^rRUvgx2Q;D)(&kP>Q}3!E~6e(FvG|6vR6 z1oZVD$nE%~Pj1PY4X|Gg>BJdH-gV8JZcGQE0E*u-hgV@R3om?+cWWkwfBh54vO(Bg ziIZy{A5R8pKl+}X@Fu=M3qa4U1`%K{TSx75mPeEs->l?Q>1u#)7WaAm^`)-&Gu`+p zC(Y!vUAtR}=)WYTsce@ZFf{+!YdSbTe3B0Dt=>509{1~oPo|k=iq$nr$!hD&gTOaa zrfDEJI1dK|Mm7FS6*WqCu5Zn7iGq~Jxb1LEi)4K=#zN;qC#NsVbhbMmw(zjIykPJ) zoIvyl!E*i=I7@oN_4XwA{W9Bi&LKVjwEOyls+*Av`-z8;ySqdh=VXs4eG8L1iFc9F z>`4mwRYuR3b5C7w#nM5>@Cq5@wP{nat>5mrc1Ho&PAPs&Bc}3@3YMFedTNyVqzcho z6FS(GKj3bKC(~*&pe?_Wjp`s_2$Tg+5V~W05$^y+eFh)COK0UjjwMDVTMuT+sy$eB z^s~n^yC9tIE(6yaq|Brfu*?tDvS8waN52n@AS7`{sAVzKE{IcK1>#u>h*NsD;m(7t zb|D~@148Fdm6?qOp%JiGU-3KM>$b*0Enge@>7Yu4C=;<*4tnz)1C)03pr{96BD4s4 z#{fPE$h;9BU*k*FDV>Q`#%S3l-TZw`T3qchfp*Lk1HS?vLa#CHQ^{ zvkTn!%=oIJ*|Iatw$M6v*V}%@&fj_*Q1qrE5r0%#qIl|>2EPL*s&|EyUa|Cx-a32h z2ZnOv%!1)At@gNgp5skdRGt{T?3I3Kamw^`hDfWuk9{5;q89N{&)qzeC!^5DZMOcs zv=|Sv^hFCM9V#{PI07dVzdn8#v1~hc1v{k*M3c3UnFx?1)MkadvO!N3P}rg>xns%e zYueI_`qH9(@q5E7gSzRL|JmPlfPs#$_rG_pvDM(>TfXTB$=<|9fg%w$7mc3Xq}PF7 z3%p>lJ(&lC9QeQm>$aStUgQn z7H8~oizAaBNWTF0Gv+yhxRQq8*nkdfoty;9-F@0JIFCfu?{+JW@9`nul8JqWor5oj1JO7R&pdfxXi(R@ZY~%z=IG_ zs<*K&ni?3`yAUwSRo8fFNSq(p==ZsQ0>SvZy=!~X?x-l(+NW;nrt9=W=Od1hQ@sGo zf0Xs_A-HdGTEB3!uY7ke?ah?4p3ZIMyT&~FVbdgg0+G=7#(J3CGk?ipi6*^*Mr2!k z%YRCRoA*T}UHtj@s}(sh82(pb%*`n~bJ6Qbmy}gVsYHeJj4KuzHn;EE>eec$m(nq! z+&4Tfl}^Pr72N^{SlqT@fVS+X=JXmyv9wq6pBG|w3KyD0IOnrK8jhzW5U>E4;}doE zfHO2lseuPxC>V8JJ60>I900LKi4GAEDmWn2G+3}dZ3g?ikgtqb%n{kVkm8ehn zGwT;b0TA4Hj2adu4Q1fh4*Fk1Tj6p2)W>Nk+`#k=8!QQ|1-YlE7wI65k?uc9V)(gV z3l4B|VC^>*s0_9oks6*oeKxhGynxp*wpjEh?BDn$ozq>BU;y7;1QJ?~mc-piy(|T7 z^yJ?>>7erL_n}|lW@+0u^L@aK*fFQ6heVnV*P4 zsNmDbF=pMw4QhQVBvxicqgg#Bq1=Zez<<=YSuip16pey92rP^0R{MKWcQuIL=ey=s zyvyCISup6#y&SP5FL1eib$c@P0W^g`A>4E1f2o1fZq|#xc0tp|I;i^;Yk#d58u)9S z8ZN6BO>TcRUOl54xUVKiPAXc(z1yS7|Y3xl4dXRs6Y65kK`M#Bzmj}ry+gxVo!Zr%~OVI?{ zjbc61-nU#HX~77BI9D*A#ia`{mY*Gz93~&Nx1NooRzaF;VnP0qqB`@3{oVhjt5nLb z)4&tkJtU>xX{QDWiG#`7X9_cH)nr+7%v=O91n@Y8YFXEPy^h@dpc)sO%ZOokYzZ*i zs=mS}O;n4Bn?DW?M2}+EO*NWZ6P^KH6%E(QQb0r#|KS*X_8(|Pb^44!uPXEW$T&6+BYXTWhOVO;Zj+DTg?xNuo=P0FPr4)k?^cu z-co5iMVNatli$N#yTYo7;fgUcT_VWr)hG_v0T*-woB=(D;C zx8fHR^VO{hutF+rDt!{m5(q@iN_jZFbzkdQ!3mBxsx!Ao&Fa49|3-oHndOwZb8THy zYXF=@4@olp3LjG?lHDP;6Uod}4-v1uqHUqHmK7=g+w+#cxTU(}4TC;VHTt<%y&(O9 z;~?xm?yFGgfUP&C#fKMFy5Pma{gmNC?*di)>VO?o4gu`qLnQMFz-;q!tcX0Gi;^M` zvAg=)@G=tlU6LQ(RA`?143}K6ye#prq#7#l(-EzxjvPIZNUhncI}7_c>ZhBTXGs*K z=67un-g@812>7kM^RnGg^GO7b#I3l@lS-CiUR0+B(#be#l9WioiGJcH5Y&=*@;rQz zc@z`=JtiSI8|bT>X_|7BWSYpawerd&xeXN5OLISQQ<&uP_o%yGEy#@fn|d&7C#L6)6l*L%N5*|tA^iPf9q-g#;@$#V4Et?o}x>87Sj*Fm1#@~j0?Imvx3 zj630>B5+>)9D;QgxbblO9xRW@^<1xMT7^G0?|p{y_!AT`E0}EB*@AGh3QHEJA5w{Sv?V;)CnaZ zKfNpva3lRql-l;{&Y93z><@mhNUg|EuaceGK083GZ~lNf)12QmwELGo+rra!l$^Pg zMZZ|)3>{*T_O)P5Mwo&yHk8a6Q?cOSQkz*qpUC#gp{wlHH8-ys$8VzJbyn4Tn(jFq zmra*eZ0`TcpU2pmeEcGE^1WILPeBF%Fk|H;9^X{Se38%@Qd%UWU%z{m z1vHzKfps%tG|`7ER(u8r;$`7(`Ej zoipq8dzblcpCx$opOk!c{ejbSP&u(rQ2k#PtUPl?FGJe!p|`5NuUGWrzL~VCK*_oMh67!XAy>HhXlRw`ib011`|ubr0W}1*%y<%ICq7UKKwm& z6N^!5{MbrfjsFQ2f z576*fkj($_kPVJGMKmbt8({8xA|6JQBJL~4k^Y`I9K}sleL?_0-J}r2tZ{h6)Zc|( z`$sXf9KujY<)rP3id5&8=V6vjK5gYEojeY=o}@Jf*}rcDvB-@a3+JcgK8?EnBk8=u zsr>&xexKtADIQcXhR8g}D0@Wq%--YJXWhSd z-`{^-uB+?fI`?_sulMuyd_JC8s~EN5cXW%1_vn$Ndq zv#&i)zt?P3;+--cN?S1@KJ* zZ8N7BNi_x0be!)g>Or+UMJDwhaQ1WyM&&C&s>iFYLoKe)J5QDr`;@NP%KTJER7J$# z-J>MlNd_er%c%NWck7tHSJgBDDp}Xdc!?!XSMwM*sSK9^3~>4rV}keds0w0Xc6_XM zt}m(GiF9X2rYaRJ-|H}aBYTz82|A0{VIetp$?inck;WPkHG-;wj zcv?dr!MG(YYC|R)q@GE&4a$n9pKit2ox*~O8RAh;JZ6g@G2OAn5BPKd=?=z+Cpeq| z)OwE6%JEM#2xSF@vnlAK8s3~c6wKPwe@$$Vl zi1ymVytEmdNJi^GUXuS(ju=aTWvkSXz>+o8N7+c+M`3HvRD@^eb>?@~<|mCd_yDS> z1MGWgbn1PNZ7C`u(t#oP*|}lw(~c+XU{O!(IN}-IH&TC7^+o@JM@x<0RlGmMVsrv5 z$^0&nykBm8;=QD4@{8$vJw^^pJ^-LKW3-18nM<_+_eiAOTTUp22m3+o%QSKKcB#By zN-SJA9~hUapmkI7y-Qt5v3pz0P)*A%e9p7a!!{nYN_u)V(tW}e~ zUgy-+FWEafk+t4-v9XvJQ1ZSJJ*xv;R3r@yt>Y7aN5IB&(Zrd%yPzH5p1St|T((l9j`~EJ1>Rl!fmrHU%gd={h` zZBgZ~#%DRjJz13g!1jH}2|D_VNC=H^>X-4b4oHhZ>~!Ev5@F+!mO#39(^ zS)fCy$Jx>4J@UFR?-8a1n&yFk^}mvjb9M;0%2@%CpvuFLtR_sR*)3f}m8@XENeq(j zUt#uB!`A=)7%)5k-3;%at=2*TR@e7$M1_^dehHJNZ7}gLH)5?gGDwae=@qOs?C+%Y z#p6sku!blDTX}Z z@oUmFl1?G#z$1T;_#T>;0uL~DI*j?S!d-xRiA4GQVr3o_px?!;?jGnJfQR-46Y(aV z7G#J3OCA^q@`w&u6~7-=+tI0<$H$8xPa6i^S?GRp2MiLDpv1>{9s?R? z?@nz-kN^EJ@4rd+bHVLg5d*3`MogL@aS5*R~dDjdE6JNHz3a}SJr3l*D*A_^g zOx|<)U23e`xc~B^NtMq(kIPFFzx!~pZv0J6Bp;_h>mUOHF;m>!*sG1&qA|tSJNb5o zfKP`WvSbg4Ui_GQ65j~r-wCw$(~6U3<{zc62VM@}e@ags)dq*T#lH>;eH2SG`Q%5x z0w&&PS+;e~X3Whkv$l+v>zD`u*9D!Lba}roT}PGXa2Dy}2uAO`_O-mskGYY6fUOz* z?2pQS*?i!@B73QWQvx(;ZL`&>UH`f*1mAt>-w?tQ>N!ZY1NGZb=WOmu=CzHBx}21h z5wHd3-w%hzIS^Q0u-RFoT7}WzY47`_kMW~=$81>@v=)Afebh~tV!ZpHEiMAo)h!)~ zy2&`NKyAH4Nmr_Hu^0e7yep!AcV9yAQue&UVpqj~7n(EMzX-zgG$-|ZIK%~P5@c++ z?uY`xfxinZdJX@&EvNIj40PAcSxZF5(d^y!DUh{^Qux_c|L)dE-36WQ;+qNr)AJK7 zVkPs==V7MQQNE}#9|rh%PJ_|l<+}&Wzj9&k?v&7c+B;|Q)=Ha9%M&GlqSlK z2zFkQ^RMI1$r;E!I9YOB_B@uAtQE`=S5Sw&i1=}Q_`KBRW#8N03#5*N?X?^&`A7$U z-=`DIrpyA^T=@j?BU`abrax`xtVPGsAoEjGJE@7SEG{rTUpJ+535jK-Xh8UVxL9v# z#3GTh!!c(Y`j<7ZY>|Y56!xPF87a>@YeJqIK_E1TIPjH(HbP@U7oq7Y79Q%dvqBeQ z%Qp0}I6p*QsOu*%XQn4($O$Icw}gYt^xwF@CEvknbAlZ)on<*T*Y$R_5QaYscFbRy zxQc*E>PM_OJVOpFy*UOy0|l;1%*NzQ7^gYi3#$89z49H=>sWdll#P@DPqC1y0ebas z=>_k&mo{+&Pw8)^Dh?nKtkBnZk+yaq_O)xWQ{e4k!>ah*noGB@>N&TyKhrHOyxQ0i zn)f>4x!-M~icZX;WgH-8-5mIOT5#XdBDNc2(RTQpqUdIf&S>fsw10;a?#F5OIB3$4RsEUu83>hAuZ zHhWKb2MbW|_Nz_~$zI1w-p9+&Ur3{;y;uL720PtY6z9@+#Xm>%zhv6Bm9^~~1YJt* zBF;6Ve(3CM_C=?J?~olun{!(6AIw;r>dmrd%Og33O%P!sVO~MKru25WVn%T0dPBpX zzN9_TXkMNNJJL_l5FomPBJ8Qbr^SL$37!ZT(#4w~gPfWbh=TA)*0c*-Z=rIenKIr{ z+Wg(*9Z=46GiVpoxPa_8qs&eavhA^BhK!o$R2i%+itV5Q@80PGYWT5o#E)BQ`72<& z-gq3Mg~S1t&PYf?f5{}rr>z2hI-`PKI7ayot1=lI)PBU$bZ zdWi{=B|{UE&}HqD;HfF3+BJz#-DUug*#>H4wEGVO)D=H)M<#Y#ZUkOjlwGDo2P zzGjHwabfpz!SuYy7~j3WK0$`HwN;XLCnpkJ54U5h2qX39kGvLn0&2uHCRf{&Ob3NV z9kJY9vOXWBtfHh+1e{j|3uiF;y4N(}qhFkizpKmTlzKO#E%cVAA`L;xPCqt|d@A5u zzL|#~$lWGd?-VpLf1_i86_}+e9J&!8+bsYAhAp0=G7vbS4wh?QVvJ2G2V#_Yc2qbJ z)fwp>k@$Q)q5vErasL|s6Vi*g=_WrP&#CjEP2!<42R_zBB~KxDBdPd7NCz% zU_EE84_Bl8_>e}ld^4N$Ko$N-Ivzu>{G0RRp@4Ler-VY?;J=* zB=+ESiKZrdbJC^4>a9E1rV>7(tr+B$_oqMUjHpQKyzV<;o_xu|M1=VcGAGkmcrDzc zd>q;bZ_>j9%iw(s+6x*U1W(0%pjY$u;pDxs1^Qe+ns~)>|4D%p#{KMj$;NUoSoZXEbO+FW19Vfz3k{!h(fZ z!p-dW9c&PxB>;&}|Lur-0@e^}D_#^y6GG3X7!H_3dH;uZP=d}MqZT3rfWf8c45auJ z>)tbr_Y4?>or8c3^6c2|V?^(<>0)3q1i$;PTC`!X-W`!^Qp;?7mlW{nZAOn65k{7- z_+V@LK3+BHte0syQ89*R1^0p#^eQ+`#H)O6n(w`KgYIUG@0ET@i7kuwVd8sbb9X3i zN_9`F*QEJ!8KsG$qPou8Pl}y=x*g3km5m3xQ^n2&+;uYUzGrTFxx)%Nw|imrvE+=J z)(^K&p2i$s(>ffSG+YuG5NTp;jve=fNpB(`%*<;UEMEh~g^gQ;{dgg?bIfG@z(nG@^xZl##G>4w^ zNCmWC0Au_|gaUU#XxMo?i4D|5gci@Be>H<$?^OP-vLe9<132{sR9Od-{%(r1u(~eh zkY0>pw5Q(M+v2p(kA!*4LRxWC2yigOsK!m7J<_J-luME8>NxYE4*TzS;fGlQ!ZG$s zIvq&06IgN@r;K5ns?-@u!TllU960?0Yam63dtG}K8O;DZE!aBrqou3`6n-XJAOEza zEmgKPJTz9-)PCvV#mIMdjcU*8*+=PqFmE76kqcT;vX*E^zA=p9s3v#fP>OPw4sb0G zlhP7SOZU9H$T-`g8$vwol6uJ!s6TCl&WnBW+UT;E*GoSNnaNs4tpvQkrRsK+yIV;L z_}Mn7s8lPV{G)uo?*naB9Dty4u#uVC}4&5Wabr5~W#{XYLhW@ihb;cPI zZ+$d`oB}bv3EEV-3F|LiRAz!bDE6#aL1(AR27u1tVYD0A$-w&^+%~$OVAhd~#Q^FB@!16(Dox&%!rw) zlLPR?frFxHDJ@AlW)Pm{*)7N|o%`jxb8#^YSuD9-QBM~>eGj~~>ajZ!=D z#LqO($})dd#QKsTix;Iq7{m|FdSNhAyx5txZKVHa2?ZQH(^!$CYyH?7@GtOp%dkig=nO`cGl z!vr3j#zMaj7$7G2HUb>bASjF(N@jr05~;bfNKVR@=^OA_3Om%bf!^nKk$}3-MYR7o zTFthVU?kj7C2d@U-Z}^ORPf&Re~jrNZdyThZJpYYc;yZ>YU(Me8k_<(0IP@hD{7zO zC|ZeLPljm_j`8B znkw=?_g(n#lQ?15aGv*Q>zk4%PCcObo*NLY@R)i)7C)NGP`Lh>ed)g3`x2b@U|4iW z;?RoCrB7P=Yy2*s-thgNl7K%*%~kQv@DU^8Lc%f3?8ne~Eqj#Lymrl*XW_2byAI4{ zw;GBHWJ|?8t6*;Aa36n>T^*P%IsdnEw4r_ zBd9V;*1iJ_IH1@{W6O4=MrZPtIz0N+f(^-ECcXakGAnk>-q(Ksv-K)&p)yMRH98O7 zdt65$@v+3wy~%Uii(&2DJGpP;BYh1~iZvC(tx9Kt!>=_@tSj5?h|*wXu|E*wgX=Y8 z0z!7%+B%181PewQV7P7C$u~HyCN%xccC=Eb$kTb(?xWR)M67tV-Hco}^a2Ver-^bE zG#Y)*EJ2q-{3MW)Sq(B^TH4J)S=owb+UyXJs#PU-CY2`b)EwRK))|zWCfTh7|&u zC{k_igD0Jo2JyXOFNeIk7k2WduIf$fh!O1cfjBjUnDz(SI>5NAgSc}y5vDb`LnzjH zfB51xlsC&8-^oy20xpUd+tLUTrwxK`=sB;bqkrK3XkJ>^?8(}GzD~x8?U|3nT)9GXcX@XGj2 zRJu!FhKjjKSL%aij9^w^|kL@t%L$f;OFH+8??`A4)J{{AU3s^vsenX=ZRaa&1@$+O{?SMUTJWN@Iu1 zdm(|PXQS~#0N)U(%s8Tp3Dtz2QLa51fJ=YmJ@BQY-a=!$_&RW9Bn`j}jzJrt!nr60 zpaI|!rvrSAA1axD3~CnA*E3nYJa~9Qrs*Nwc)DTNhA8GE=Ti_8(#*Jp1{|)_Oi)-v zTMyR}-QY2qkdg^rb-rtd_6%Hy;V(dRLo@2h_=6+u6PN<-smezfAK6c@RR3c_@;?92 zLF>(y&}lHR$m3M}a;#?sjy&e>gWc#4x zpL6eLMAD}bnryE@-|CQ??M-z0*6mNsKM#3cj83p-oOSG(dBRvVUd^v_vqH$c5uH7y zP94m?z?zx$LR1$ZPFuHsJ?vOgs*!6e5+!d&KHmW_j*Vyv+`WH(Yz8`tU>v}U;kK|5Q4#&dJSEEbt9Mx~;j|R+r+=Tn(pBbXe zY-EhN7@e1$y}s@dFU8}oI+fnbHA8(T{?xb-SWFDC1WnR)pZEFm+qw5bHX>MJ+e|y4o>+ZY6Ctti6GQs z^5WuSdW4`xDD@Z~1^sJ)V4-1wsC%ZB^HUg79IId1ns@+U?VJhaK|~!M`~=!wDZsVR zqKKL_7|suDKy98@VilksHt7Q>9FTv3Wnm2r8fGx-Wz|scwBSC~n09*LZUzOU zt|HQ!onBL>0ykYxCB6`)MPdDj=2u7<`*2XkSF$6L>8lC7kRF%%Dezq4kI(uw;l0nY zr7{6uI~lm{Cju=N@9gL?=VhLx+`(hcE%xbimXPKsqx0|&9L>o#pK@X2{lTTt2fEqd z-h5GeRpocb3u#KH?M7?KCham++Wox)@Y!LLs|oX6A@dJNxiH@t`k&XPVwc)4=k=f} zG%P9p{ambn>s1w)BT3tQ4^9s~=>8MdN-Ml&YH{BEYFF&byYs!z@*Z>RP#eDH)qSOw z(|D2l-YAZ}v$Web7*X>4%+086sXS&w*>IE06mj)wX>Tw1ZL$}3sIjX|5J{u? z;Je`_Oun?HNIG}Kb}|N2v0jzs6j`*#0!3XB8qQ8Hs_LKT_SVy6d!_m(Up?VBJ%`i<*d9G7WlT4|kRb=8(-`%UC^irov^$fvciE-L< ztxgLNiE^2OT4UtN_F9$ny%WdrW@<4C3-)b%r0~;`q@s^z(OvJ=81Y$mt}El`w41*p z_)&_oc+kLuf~K7iPx=uobY667eeYR%1?itOXGlsR_N@~$C6g&zHPHCHniEdh63_hX zm}TN+HnH$5Y%oIq$VgDrGdync<3!zFlT%tK!{gK9$FF&JqpUj$bL%)-cFHgm(*vLCZ zm=Mr6uKJ3!zx#8$FXOU-ZXZiiX{+;R0iH!915AAf*=C{Bs^uSb0V!k+|>7t-GfZ8dQZz zB%kV!q@bO`lh|w6%ByAb)arXxWpdYxr25&q`gE!WPfJ&t=5~xJFSff{zx2WA$Bs{A zAB+^gu+oJM3#hA$tzh|JJDS~$(f9s9WIn>2VWdVKFC*iIjsJ7Z{12B;tm#F+fIyA$ zvNqk?r3|K3^t9X@ZyfW6Uo_D{pN}-Ay*lSqH{}|Z#P!>`W8ReM&v3mlm06-f?YvJrT@!@Jb3~Ce3hYZ^rI1Z>gCDy;4-T%{n%k4nAc5=d^nTU+OzWZKi2c{Xp2nt!-|@a)-dWb&6$ci1omLIeh?a(^mg%1+LaCCTwyb z1~pZ<@D?6yJ1I{)@&$3uNKj0jMDt;8$`BAo_>s^T4Jc(h=1(Uv-c>=MS)O^Ynk-S;<(VU$q)d=1PhXhmW`VyJ}FpA z?Tj^fvRbkouLc}SFXWS`r<+TgDarpv7|^~py)PJctzeE0xf|0Q8F=qh3t3G!MymeX zkx}4PNb2Baja0ze?5jVrynTs3oQ&@D$H4(UPa(EYg~f=NF5gEV<7u|}1l`-R9G&_u zxae|S>|zki7I^$aDm$l*@JF`vynksG^bVAZys6D=Tq?a1kt7xsc&0iEp-a4O?jaj*+n|`@>?a*vTfb2a> zw_ik#Ca}ogX~Ug=av1+=M1waz^?AK>%9Xj>&(k2a73J5PAgoBXx`Fzz$r~4W7$a+) zX(?Uf5RNb-UdlOns*&QAGkxcJxcV3M+Be*JnaT?XM(5`2iFU5%_w9a6J^UI9g`G5xY;2UCB85X!Xgmv`2V_s$%|BQ}*vlJUw+>CbBL${^w zmnXbpN@!1E?MqiNluvru5m>kWk$6w|(o3HJ_osV`m-e1r%gA3X{a+_}`PJJ+kF#65 zx~&32_@0G)uC4ITphj`D<}H{hO(jW4Z-UxjCTRe(mr7>7x#YPMb-&KNDmbvBTMS0m zmKaPbnMit`yME!zWjcJ1?Za5xDGOm-?e7PbM_YgH1Z*CjVnc4MizU}6cNENH*-`2A zil@9prjIF3CP}4z{WcY*6Mw4m=h?emE4GR9U3lj*RcQ&k5$Pyy$(=hQdVYiVfWOj& zf$AH_q1vZfMytmZzZ)DY@B1Od#)Xca`$*+t6qmas>Ic-yj$JEG=MZ#F9KZCqB=7S0 z1B$~QDET59*+9>pDu-6MeslBeOt9|QQ}ETOvKluL26g9Ul_nmmTz>}^$B+Wpdz}JQ zPwR;b=m0;Q5(Ls;Qu$sfSn#{tkQ{US|B=W_%kB;BVq#J2$Dv+ z8tO2Y&o%}yfbUhN*@qcZrt0d=Cu>G7W=@W|Ag~8LMM*>58@o(l_~&cJ?cm^U2R&63wUO)AeiEMf6;$C(KjPT`$6B3(bB0)5@Wx-X2jc zP#k(Erl7#ln)p3+|NRqtjT|fUWRD%tt;TuO;y*W;6dVxZoR@CHev!jes5Q~J&BxF0 z&EBD{Wmaa`gW{{vS27=A822qNTNi!*+2&pc=Y1|K>|=h|Qdckc3k(X6x+DTVO8zDw zyy*Flxrv{32jViS_a>I*I&VW%DMM+MUHScjsv$Mg<Qh>{o3Ih+z9`$4!ke^*)%r4(=j+ zKhmK^c2H%$8}+BmPZD`!D}-H73Ip6@X5oO);`aLifD0($ zs)h{DBM*yj^4V9o5sp>#oXwlVyt8tlPv#DktNtdZXS1RcQ&}xHH*wBfl>j8>&CRy> zp&Ge)>Z{9DIMpUM*pw^bP~q3;51c~HoB8iuM)=^n)a+!aCdq9dPNms91>JDbFv$Tjh!T&^D3 z3i+>_wWk7vNtxDTLg@NQmpK^lh7%ro#%4~8cxYz)r#d%@5P%dLqgn8(m85M(?)e?= zw8V7J?{o0fzXHzy{~Ge{3K`PmL4&+&Z*ln~8y!ja+neBA1n_w>`?|^*^jef?)s>!h{g)ic2>IN!<*1Z~qBXV{%ngJ!a?_h=m;& zg$|!WC93tA#*}X`_tEAo1VwEDqyfkSIVLf5{dGflXim|rC#k* zKuW#Uh8ZXibD}1oLCl332F0wPu=W^kdRPPU!T}X>J18vw#Ptyd=m+36WQaqJQyjKZ zkeM}Bt)N|+RULfLZRx}UcgogVgh+#QEVwM9Lg=ie)7)DB{2 zSba(y6L=(e1xat~+GN<-(^N)FCB1GH>hMSv>XDOMPR2XQKL4!bQvRpqWb&)*+kFZ0 zH%AFMsfnk{=X(+o1Iiw8OXMHda5B7|@)~mW`>RL$7GGgp{l)3=6?qdNb({@L>9<^K ztztv`uly(OGR+xKvUJX>9)J?Pr2chgcN>E*JLqRP@;5VPcOEED6b1}KZpQNxEC4S% z28eZMm;X@;L6xzvfgGV{&94=6vvtX125rIsU(iicy>llw@)oc)#%TV;yrI*Cq<>EV zdIq_0wD<);k-Ug_BE}D4FZP6J=P;9tHpI92)+0$YtXUZ{x8{w~|4d;yd)bHzc%Z$n zWZh5|$leCd?y{wRrmX~XIIq5@S5F62W7}6a71-`BwG>uI7hZE|_q{>YxS=Z2e@sPU zHiMcJ5kyFnd!EPH#P{7B6V4Dr`P$r8D&&`A4!6;z1sWUQ^-7E23&z<2o1Vc`umj9hT*&3i~FkCA~TsPwPGFXufcQ zvZiG&GjAenGRD!|8vE;BK>d||v4C9#w%(xYx++L&zOvq2SBP(6`_X8|sVZEVrp@3K zk)x8mJ<_nMBARoH`VG*=8)~$_x{*dF4GEZXWUPYGlNS%QdRdUs+E+?mbY!1DAPsNBs zU||aq7W?gr=3$(9Py4aToONb(actJRT_$t7)JAT2ya6Q8{&PHpJ4CGN=kS8HUGM zPx#j|`;revLk_x~I*zEbFwQu~~u8&GZ(gGJk_1gu*C~1SF9r4n+fv(RY&+7UtC7hFU&91+ECT*g>4MH)*U9q%)@aer{akfs-7qq)_pI|W)r=%9wKJGpeScm{n3%f| z#x-33=cm~ys!2S*FOi&U#)$v8;PNUYGQNwrX~T_}UaGy2PdrG7{yqXLC+3>raL;z( z0orzj(y$JK)%>x~Y>s6FjvLU1+n>enzsxQ1ziC|_2RR%)N;^>^XKSnP$!D2TG{rV@ zgY17rI~9=M?KG+sZcl3~&GN-Z$TF{LwHN_9Y$1ecM{I>0-bG@kPC`URsQdNwG_Hq@ z_8J1;FtR~n1bu-^pqHS=eMSvE!`$Hi0*4-P9>ewU9yo(|IE-Loj8P%maHwr?8bPhx zk>_@E?_9es%|e5O)**vqcm!Su0$`A~z^AVn`DJWJ(I=tK*TJLHk;vL)GR;@GLTm(9 zMc|EADC*e!-7%_~G>)bsbg0EB4wp%$x${$ZKg{u#%cDfhgQZKRd@MedH4naaRf;Zc zsP&%~Jdl=pljysXHD3^F_x~+d1z_oiqMUF|$zo#MCuW;>>^9D$>65!`ZNb+=QQ)kq~-GWW) z%Xc1|8kQ)HnC|I6JNmanDUrb`r}-2R;h$8wBZ699gD)}xkWqc9wo@^Z#r-vZQiYO} zvs)uKcmgUb)m10@`T5rVFg`C#Bv3c5YH9Rtz}1tR91uNK@Ce>hEnb8NB+vNVZBt3a zh@#Z?&mL$Kwnh?_9v~bS(CUx_%-NuRi^Y!nI-dD|?^x*dPXx3bwxj{75sKV?AFKi# z33+Pr;ec=WCDf=O*^E$^L5%K}Dm$*~_5E8reW>n4_4fCOZjRb)QXqWG_{3sTr4#b}Yc{7cxDz=c)&e=L{94E^4NcIfG zt9{*zcF%u*v5sfz9+gqM^|U2ON;qaAy7tsF1HYNk(F8FvbMv`B={^cv|nlCqerOv^!UFf8F$1X4LwW zhS8}1Ulatq2lQKCB%+V}*=k}0l5|6m5IjWT|V_(#gv z4=ggvE{u#4Da045RPT^UwmWC2*?+W`0wflc%o8q~dC?Sf@=CbwywWrJ?Zt-NH;#;b zZah0@x2NekrrtcEyO;gwQ$ZWIL;pQ~>N(ve$J+!M^HlEp?#Jk%w*Y$POx0W#dna)& zfX&go?a{JWx|IG~b*BK`ACHo?QaMX*NZ(p+5-EvXksMs#c%>aN2UpvM?#;#I%XCUSUDTNm-0@vw-p$_Q3zKA{T}%E z0!?hhoflYEC8PO@H_^W|mP*1LOXG;c-bPD3gowFUO!04ie3Mf!V)%Lru71I=|4xzS z;n@!aK4k){F4sY}6I1!pl=p4ja*4cfd1YeU8+yTmn!_2J9_04&LxfSke;-($sj?&@sJoDUa5~e!VA5{>`naPHlRfeRI>FgwhPW z+{|C453RoNck!5&q6lVUinB zMq)v{`4pyWPJWozlOpyqwy6;2(}wKEZS}kFHMPHTTrPOTLpRoMwotG2~A2d^g&wyuNtYT4>oCoOj8Z{ghzL+Ht> zCRoq6RKInCXWa4|FBv)=kPXUUfMOdE|6LrFP*}L!Hxwtbx-zq_{3t*xqF``S7{#em z$A);|{3_)F-k;+IPTnQra*jbv)H5&hJ3Lb2`7>)Z3BNJ0Sl3wJ8%$L2ZJ4HnXSAyWGC>=qn!tPaa`x~Kr(6GsqsXT#~XRENWIxU&J7s3KP z;kA>)Z;X1E+E$%F;#0MVXK(Xla7zKKS+KF}%|VXHn03GYf)!8_X3AF@y~nrv=Vp98 z@zzL=P^h+k!dgaQk8R3>SqeUCfphi9)?DVMyoq6%><<>q8WmWmnB^P4tuz^&nBFsl zT6sv}^I)txZ5XUhXi>TEyW)))2j6(+GRVYG9NM37L$~OwLpp zzAroOivXJ+(B6tvYxqHD0A0x3EkSTV=hZqQa;a-lKo3HQy+_;q$@$#vB^S?2yS2P)>r9& z5d<{w<^M{*y}wh~#v^R=V@k$6PR0yV%-XO5c5TVS7_eqXAnZbS`I{&x?7|m>oMju# zLm87Y2p)U@(ir{HPusmqzmKm5s3<$SV z_V){H%TS)tFf4sf{q-JMN zl}tR3!oD{sf0$yAgph3K)%*wT%v1A#U9+q6=pc-29*sK{irz4xZh}FRNC5~U(+OMl zgM_$!=S^1VgzEjx*4q3P(qG&Z?pP%aVCVYNLiq&CJq-Q;{0EBpM1?J6mbe8#5aRdw zWa!lVpK&1Rj})3!|5HPya1gOhK*hX8!GY6g4n3DUB@Q{#p&-%LGNdTKFVkPEWVtnj zO63Jz3>E#FoAqHgq|)PE?~TMZv{EN_=ITf)&RC3}*IC3p>Qm8UUZkfV*zmDHRny;n zR(m=4OM|=MiD~u^?!f!J$%;T0B1YKw64PU}g)!~3cP{VA=B00!U%t^Rc14F>=w#B* zJQ^n#B0n3lHEbkdr`E0QoJ2^VMEvrzAjSjEZgvq%voHT)$tt)=Cn4h>Gs7c8(-aV)-e_E9nVeSEGZZ2T+642^u@Cx{z&G(W-xhV z?hUDRpEIC;*j-X@ti~)M?v9{G6wv~J3Vy{So=**oSya$qt&X>5#RJI3k-vC1B$ZRs zKI4>k3S+Y1S~HFQm&E!?jmfKiB$gK+NlyM5t-ztC3*Iu(%qG-JIVYGK%ZNdCiQ@BXVxVJDICB?}JaK%K8!BH$#3K+YidxMI)MPydQOtHWZ?vq}f9FSp}ozfK+V(a09@&W^n5 zo0(b~Zhz;Ta-UAGmC6Fw-4aSPes8kcaAhTqu9Emdcn zc?V!dai2M3m8tsryn9l`*>QP83}bus-<8zcmGTyL)f_0fhS-dUt*Ynoq_B7Hl-*{Y zqiLPDqQ@?@ft6iz=51^^!c>8S>v!0$2GyJ4knj0J{5=G(|FOn$F^%p*oyy>6&-GfF zBn%Q9I!fnu-`!FA_EjCt=yHR|x%2BDLlo|ngvzmgQPj6DawbU%*(=|;9ss8U^%Ny& z{v~sTLy|+~h5ufh){ed`@IhF*bCdyamH_pgAGKzE+kGECNgQc<{gl4fI+N$ogOUlG z57CACaY+TQOZ6DmmLns5c6#IN_TbhPA4|{oRuAq%OR2d&H;Hi1$p#T<8c$c5wqB%M?N_r-5Xu(Dt6ub?;y~Nx@)k=@JLjNXJAEpf=~MC6X(zbi~fT zOrjcrHx+O|to!nl>5+N_edks#N`3ap54ji3<(FXO`DjKvKkL#^v~ViF$vK5_yfb!F zs=nu4zo>3VpCZL3L&Vi}md3t-sB%@oI?yuSactaiWSmEGY`6Lt3CD1M;-yc8_}!cS zLLG1Q`#am=_61}av7g=dzI_4%l)a9dy!&u4bm0J3+;RncdLar5XHuN_($LK?SWx)* zx>p$Q_xS(fWPz5pwNEI@Ygg&@YtoE~jwV!IXw#+#IH6NeR<(=6q=~G>;~}F`9>@pv zkapPOlFe(J&&S5UrJsH7_Y#5X?yCPQ%@`x8)ovcRo->CD@_iADX=FO66z%vObprV7 z$h+iX>CF4DVS1#Znl5QG?aYHBY~-1{K#xk)h0yK4rR&^OQgfq2)qH-bN`Tw}XnKS2 zYcN$44h1|Tz`B%%4*#OCq=whXP+&d_dI@=^F>;xXEY7r8qn?K6!qL-!|Dr}MB=9|9 zN@S+5W2AjCT;_v7HTVMoM^PKtIIR4B;?{v#0zje=uc(@GyCG#aRE0*ecoVEpSjdVU zx{J^gQ9b`z0Gz%N$G}JALC|Q3#WwuLUdoIa>=ku-oRUm8{T(_%kME!X*4sUthbX*-9tZ7Z?fpb8v>#so(LnFBI~#EXEE--><)I!T%g`{!;oU3Nu$_zJ*U zb`u7x%TpHDew&=yV>lQyLACR;mv-h%hFqr~3$f+IRovnb4 z++}2;4ti0zFD%<8C|Y?kmu0{|8JfBfz3fNnm%D=XxHK~30x2**vhy_`ph3!0_#|!y zf&gTVt4Q0oK^LFLRD&w~aK7<2p?kp~An0y&9Q>%NKVFz`^Frwdv=wAVMNgP|utBQh zccnZ%B}=6XT>}YqU+3VNILB4ccR4j_CE~efGWxP{z_`j}Z?O?k3Rj$J?QmtBBmU~+ z_kyf8t2l<_mtVd-Mb>wH+ZlS;XTi+!FR@SYMtN~7fOALMx$o&R2@?`_>afu72DOW} z_pZw<%z`W-$b^%P$G#tK?dbl^17A{Q7z9O0%*`t$J|CT6sh=l#}t zG2ePUS#PY~UZyMhZ&Pgl-r~0n%p;G)JtF2a$vpK4xcJr~G;Y$lN9*#3ugoKhRpChB z;9e9JJpmg_AEWLyIS_1B75`&;2CJV@lRiQH`(7iER6_n+_nbgdCe3e7jXI=4^w1nY z6_IDIqB1jG;t@gUzo9pwLyD#HGj*t$&mZIpztc{0esG^&*bo7jacbm2SA{O4r<-ex zCAqM2>F3z1<4XOh_U&@)Wh#-Eoc#9r&6A_)6~;ls#ewx}Bktu*gD36y{knlr;gz$` zB@das#`cIL#J0Z&ma0OXx{hr=2ot0pG>H)Ck)v?RyOD%C<9fa?9zRHJo@~fTG$~%5lW%jUZ&=P9M|Ct^*jx}1F@x6lj1v%V53dI z=3Zo7v}!quzWtQy`)M(Oq|eqn!Fj#Wmtk;kbg6dv>c;q^VwtU3enq32w-@P5p5akq(Gc0N4c@Q9GVAgP52JIc* zsn2zOy{+l9IWDWgjY9R%KPTnBEa+Gi+S1dL%FmeiMY8k#eg4>U676aKxvU9QN=pz* zzFfY?@M5UnaQ@91M)Cb1DLa9MR|_Zfi$&CW0YL5;o_0D8uy5QpFxtOWkZLd$et#|k zlDK>w0*mQqYdiG?*tZYC_NY`&cW}Vz!db)842xgLQ>djIpnw-IR`L|Wf6dl4IVv`M zUo?k_NceTLI+qrE9F59c!TBP7d`0KiO#OpqBwg=4X0t z>IZ|s1+-psc$iRNXO;*AY0@>*HXkFP+OxE|tDLR)KZedBwnoEg$OZ+9Cs=AN`bBh| zbrT|wvf6dA=GT|X;#k$6OtZ1`>p=D)eJEcVwZ~r2oDs%COfbx1K6CqN1k;@N55x+a zqN?afYne5u@F~AE5V*b!%AdW0 z5MR3VZLr74FS8!=mHM5ikZ#H)siHTSJdisqPx?YN6^XnuV;j$Pzw!F3P@LoPfq~07 zr%P9={oiN$&ObXoz0t`h3;r_|u)BkE%YWH9Dip3rzeqeARk77c`;!$IauqOd7=pMh z63hzoz$M(uQ{xtR!{QNJX$MRl=-|NiXD|!of%`G2#tyQG7XOT)5OqGSqd`WEzD_`m ziU@%{xUfJ}M$w=k+`q=Pc2zMrlogMJsWzF#J%9JnF!>W}h!_kXY}zKn)G<>7kp2Rv zr}wJ}Y8DZ0n2+?)E`DkwVsJEf=V-c7q$;G^(gr>0#1!sYGd4Fs*_r#?<>wP9$p)1= z4b|RTzI$iGA1Ww(Eyn>l7_%Zwl3u2U>rLA_>%O3D9tBH?F)?1XW5Ex0_6@y@_jEuk zIvXX=JN+JfrS-wi*7Duc?ZQ>(m#fYK<8iQ&L`TJ{ZVj(>s%Wyw!sy=m-uG%bVqi#) zmCbt*jwI3cqt6V3IE-&d)ZV&pVX$`es_R5VQ&f54iV9d#!Ci(`KJMnvtTrOzxk0Py zXuD%mVWg7DLk&*F-|~i0gmWSjV(3Y95XIX&ldP|gSzhaMkYVhzk!nmiD#dehFI~fa4l-txDi*Vq=&YA z-FHd+-r$AIPefc^V09!_gJ*b<)BP^OWG*_n%lML{C{`Zvi=O%=ob6j^?C)c@E^FaZ zcAMYQe0WH1O43^sB~t$CsE!@5A=YG72^ci^)`B}AP8`2U@5Q0CfqeCbPF@GE>Y+^7 zL;+YJ#p?yHoaY$|mK!@(5Cv+KH4#Bkz&w{jSK_{psk8ItF#lIuj=fy>1C-#@r4U|2 z;L#8!fnEoeW8u)PEYi3Tc40Z1dmEQbo;m}K3N9TS1cGJM)tL;&I7~VM$XNsK%8i>9 z)<60BHd|E+q3)HRy@A-ZD{ppV$9=hj#&inIzyD4VOuzcUGiB@1h#$)xm~nQa~jaHwj;Ah(A#)d(zU^ zu_BRtmE@~ubTC!H^z3jh%~c1!n8Rh}%=0U^k7XENE!yisHQo)F#j%Not5Hh|rBXUq zUKpUfQ^FwrM|u9g+JiASp|tizr4!N1DN8!Pkn zjF$rLV!xuK4_V?5K}>il;5-D@9INmw(&4C;mT(j8vX``Dl+Ax6&ZuVOzmaKo*N-}h zF7K=4rf4_8gM-0E&e%f821S4DE63&;cfk{2ecX mjkM+`YQGbp%aAeVEVgVd+^ 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�Ko%b&WlrNCm{45c;tG0f#k#x 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 z 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≦#bygaR5w%17Bi~Wx@#)=JWE$t!U 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�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 %~{irI?1H-uoMfG2t| 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�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≫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%0AfZzT0x6|)`_uJ`T|Mj1zKm7i; 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 ^}uj1(%%rD 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 z�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

public ReadOnlyMemory Vector { get; } /// - public long Index { get; } + public int Index { get; } /// public string Model { get; } /// public EmbeddingTokenUsage Usage { get; } - internal Embedding(ReadOnlyMemory vector, long index, EmbeddingTokenUsage usage) + internal Embedding(ReadOnlyMemory vector, int index, EmbeddingTokenUsage usage) { Vector = vector; Index = index; @@ -27,7 +27,7 @@ internal Embedding(ReadOnlyMemory vector, long index, EmbeddingTokenUsage internal Embedding( Internal.Models.CreateEmbeddingResponse internalResponse, - long internalDataIndex, + int internalDataIndex, EmbeddingTokenUsage usage = null) { Internal.Models.Embedding dataItem = internalResponse.Data[(int)internalDataIndex]; @@ -37,7 +37,7 @@ internal Embedding( float[] vector = new float[bytes.Length / sizeof(float)]; Buffer.BlockCopy(bytes, 0, vector, 0, bytes.Length); Vector = new ReadOnlyMemory(vector); - Index = dataItem.Index; + Index = (int)dataItem.Index; Usage = usage ?? new(internalResponse.Usage); Model = internalResponse.Model; } diff --git a/.dotnet/src/Custom/Embeddings/EmbeddingOptions.cs b/.dotnet/src/Custom/Embeddings/EmbeddingOptions.cs index e16fcec55..da22117b1 100644 --- a/.dotnet/src/Custom/Embeddings/EmbeddingOptions.cs +++ b/.dotnet/src/Custom/Embeddings/EmbeddingOptions.cs @@ -4,5 +4,5 @@ public class EmbeddingOptions { public string User { get; set; } - public long? Dimensions { get; set; } + public int? Dimensions { get; set; } } \ No newline at end of file diff --git a/.dotnet/src/Custom/Embeddings/EmbeddingTokenUsage.cs b/.dotnet/src/Custom/Embeddings/EmbeddingTokenUsage.cs index 4fad06102..92ba47bd4 100644 --- a/.dotnet/src/Custom/Embeddings/EmbeddingTokenUsage.cs +++ b/.dotnet/src/Custom/Embeddings/EmbeddingTokenUsage.cs @@ -5,9 +5,9 @@ public partial class EmbeddingTokenUsage private Internal.Models.EmbeddingUsage _internalUsage; /// - public long InputTokens => _internalUsage.PromptTokens; + public int InputTokens => (int)_internalUsage.PromptTokens; /// - public long TotalTokens => _internalUsage.TotalTokens; + public int TotalTokens => (int)_internalUsage.TotalTokens; internal EmbeddingTokenUsage(Internal.Models.EmbeddingUsage internalUsage) { diff --git a/.dotnet/src/Custom/Files/OpenAIFileInfo.cs b/.dotnet/src/Custom/Files/OpenAIFileInfo.cs index 26988b297..3fb799ca4 100644 --- a/.dotnet/src/Custom/Files/OpenAIFileInfo.cs +++ b/.dotnet/src/Custom/Files/OpenAIFileInfo.cs @@ -16,7 +16,7 @@ internal OpenAIFileInfo(Internal.Models.OpenAIFile internalFile) Purpose = internalFile.Purpose.ToString() switch { "fine-tune" => OpenAIFilePurpose.FineTuning, - "fine-tune-result" => OpenAIFilePurpose.FineTuningResults, + "fine-tune-results" => OpenAIFilePurpose.FineTuningResults, "assistants" => OpenAIFilePurpose.Assistants, "assistants_output" => OpenAIFilePurpose.AssistantOutputs, _ => throw new ArgumentException(nameof(internalFile)), diff --git a/.dotnet/src/Custom/Images/GeneratedImage.cs b/.dotnet/src/Custom/Images/GeneratedImage.cs index 807268544..4643ffc24 100644 --- a/.dotnet/src/Custom/Images/GeneratedImage.cs +++ b/.dotnet/src/Custom/Images/GeneratedImage.cs @@ -38,7 +38,7 @@ public class GeneratedImage ///
public DateTimeOffset CreatedAt { get; } - internal GeneratedImage(Internal.Models.ImagesResponse internalResponse, long internalDataIndex) + internal GeneratedImage(Internal.Models.ImagesResponse internalResponse, int internalDataIndex) { CreatedAt = internalResponse.Created; ImageBytes = internalResponse.Data[(int)internalDataIndex].B64Json; diff --git a/.dotnet/tests/Samples/Images/Sample02_SimpleImageEdit.cs b/.dotnet/tests/Samples/Images/Sample02_SimpleImageEdit.cs index 90c41104a..174645ec2 100644 --- a/.dotnet/tests/Samples/Images/Sample02_SimpleImageEdit.cs +++ b/.dotnet/tests/Samples/Images/Sample02_SimpleImageEdit.cs @@ -8,7 +8,7 @@ namespace OpenAI.Samples public partial class ImageSamples { [Test] - // [Ignore("Compilation validation only")] + [Ignore("Compilation validation only")] public void Sample02_SimpleImageEdit() { ImageClient client = new("dall-e-2", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); diff --git a/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs b/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs index 3ff68efcc..ac8b7373d 100644 --- a/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs +++ b/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs @@ -9,7 +9,7 @@ namespace OpenAI.Samples public partial class ImageSamples { [Test] - // [Ignore("Compilation validation only")] + [Ignore("Compilation validation only")] public async Task Sample02_SimpleImageEditAsync() { ImageClient client = new("dall-e-2", Environment.GetEnvironmentVariable("OpenAIClient_KEY")); diff --git a/.dotnet/tests/TestScenarios/FileClientTests.cs b/.dotnet/tests/TestScenarios/FileClientTests.cs index 3010dc941..e7b64f302 100644 --- a/.dotnet/tests/TestScenarios/FileClientTests.cs +++ b/.dotnet/tests/TestScenarios/FileClientTests.cs @@ -11,7 +11,7 @@ public partial class FileClientTests [Test] public void ListFilesWorks() { - FileClient client = new(); + FileClient client = GetTestClient(); ClientResult result = client.GetFileInfoList(); Assert.That(result.Value.Count, Is.GreaterThan(0)); Console.WriteLine(result.Value.Count); From 950722319bb84a64df9f84d4e52778d84011a1ef Mon Sep 17 00:00:00 2001 From: Patrick Hallisey Date: Wed, 13 Mar 2024 12:47:05 -0700 Subject: [PATCH 30/50] Add client builds to the main workflow (#12) * Add workflow actions for build, pack and test * Add strong name key * Add update-client script * Add assembly strong naming to Directory.Build.props * Use dev nuget feed --- .dotnet/nuget.config | 9 +++++++++ .dotnet/scripts/Update-Client.ps1 | 21 +++++++++++++++++++++ .dotnet/src/Directory.Build.props | 6 ++++++ .dotnet/src/OpenAI.snk | Bin 0 -> 596 bytes .github/workflows/main.yml | 28 ++++++++++++++++++++++++++++ 5 files changed, 64 insertions(+) create mode 100644 .dotnet/nuget.config create mode 100644 .dotnet/scripts/Update-Client.ps1 create mode 100644 .dotnet/src/Directory.Build.props create mode 100644 .dotnet/src/OpenAI.snk diff --git a/.dotnet/nuget.config b/.dotnet/nuget.config new file mode 100644 index 000000000..824446d51 --- /dev/null +++ b/.dotnet/nuget.config @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/.dotnet/scripts/Update-Client.ps1 b/.dotnet/scripts/Update-Client.ps1 new file mode 100644 index 000000000..8832c2393 --- /dev/null +++ b/.dotnet/scripts/Update-Client.ps1 @@ -0,0 +1,21 @@ +$repoRoot = Join-Path $PSScriptRoot .. .. -Resolve +$dotnetFolder = Join-Path $repoRoot .dotnet + +function Invoke([scriptblock]$script) { + $scriptString = $script | Out-String + Write-Host "--------------------------------------------------------------------------------`n> $scriptString" + & $script +} + +Push-Location $repoRoot +try { + Invoke { npm ci } + Invoke { npm exec --no -- tsp compile main.tsp --emit @typespec/openapi3 } + Invoke { npm exec --no -- tsp compile main.tsp --emit @azure-tools/typespec-csharp --option @azure-tools/typespec-csharp.emitter-output-dir="$dotnetFolder" } + Invoke { .dotnet\scripts\Update-ClientModel.ps1 } + Invoke { .dotnet\scripts\ConvertTo-Internal.ps1 } + Invoke { .dotnet\scripts\Add-Customizations.ps1 } +} +finally { + Pop-Location +} diff --git a/.dotnet/src/Directory.Build.props b/.dotnet/src/Directory.Build.props new file mode 100644 index 000000000..722190624 --- /dev/null +++ b/.dotnet/src/Directory.Build.props @@ -0,0 +1,6 @@ + + + true + OpenAI.snk + + \ No newline at end of file diff --git a/.dotnet/src/OpenAI.snk b/.dotnet/src/OpenAI.snk new file mode 100644 index 0000000000000000000000000000000000000000..fa09b4dee086e0e7d0c267abce07e7849511d424 GIT binary patch literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa500988mojfITmCL8N$V;FzUXnqT*#C%TQ_wT zmolw^Y)>#r7U%I)DO85|%&YIC!J7r0QOy~ce8STjF_qRJI?$AcV)Y!x9K-8VU&vD5 zNd(PRYhjS1(#SCe9fk&mi*_gK)C5rIZ8gw^NJf&EzMBMd`wGwVSHH({YYIo)xUuT z`gzBo$WRh%2s!lZyxvP80}p>i!5rOh@#?SfYkJ26U!8cvu#62#ks}rs+`lOr5y&}( is@JZelHsuF4mkx-P&BUWi_Yg= Date: Wed, 13 Mar 2024 19:20:21 -0700 Subject: [PATCH 31/50] Update generated OpenAPIv3 spec (#18) --- tsp-output/@typespec/openapi3/openapi.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tsp-output/@typespec/openapi3/openapi.yaml b/tsp-output/@typespec/openapi3/openapi.yaml index 69b1f6687..394ac492c 100644 --- a/tsp-output/@typespec/openapi3/openapi.yaml +++ b/tsp-output/@typespec/openapi3/openapi.yaml @@ -686,7 +686,7 @@ paths: description: Number of fine-tuning jobs to retrieve. schema: type: integer - format: int64 + format: int32 default: 20 responses: '200': @@ -781,6 +781,7 @@ paths: description: Number of events to retrieve. schema: type: integer + format: int32 default: 20 responses: '200': From ae526611e5987f4d9594133ff9e4324f3f9eac5c Mon Sep 17 00:00:00 2001 From: Patrick Hallisey Date: Thu, 14 Mar 2024 16:42:32 -0700 Subject: [PATCH 32/50] Add version properties to allow for action based package naming (#19) * Add version properties * Rename workflow to Build and Test --- .dotnet/src/Directory.Build.props | 2 ++ .dotnet/src/OpenAI.csproj | 1 - .github/workflows/main.yml | 10 ++++++---- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/.dotnet/src/Directory.Build.props b/.dotnet/src/Directory.Build.props index 722190624..14f9c42e7 100644 --- a/.dotnet/src/Directory.Build.props +++ b/.dotnet/src/Directory.Build.props @@ -1,5 +1,7 @@ + 1.0.0 + beta.1 true OpenAI.snk diff --git a/.dotnet/src/OpenAI.csproj b/.dotnet/src/OpenAI.csproj index ed91914a5..39523f012 100644 --- a/.dotnet/src/OpenAI.csproj +++ b/.dotnet/src/OpenAI.csproj @@ -2,7 +2,6 @@ This is the OpenAI client library for developing .NET applications with rich experience. SDK Code Generation OpenAI - 1.0.0-beta.1 OpenAI netstandard2.0 latest diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 67442cf69..a590d867b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,4 +1,4 @@ -name: Validate OpenAPI definition +name: Build and Test on: workflow_dispatch: push: @@ -42,14 +42,16 @@ jobs: - name: Checkout code uses: actions/checkout@v2 - - name: Pack - run: dotnet pack -c Release -o out + run: dotnet pack + -c Release + -o "${{github.workspace}}/packages" + ${{ github.ref == 'refs/heads/main' && '' || format('--version-suffix="alpha.{0}"', github.run_number) }} working-directory: .dotnet - name: Upload artifact uses: actions/upload-artifact@v2 with: name: package - path: out/*.nupkg + path: packages/*.nupkg if: ${{ github.event_name != 'pull_request' }} From 4c0740edc2a877cfdae8634172b7da4c282ed62f Mon Sep 17 00:00:00 2001 From: Patrick Hallisey Date: Thu, 14 Mar 2024 16:58:04 -0700 Subject: [PATCH 33/50] Remove validation job from workflow (#20) * Remove validation job from workflow * Move empty string to false result in ternary --- .github/workflows/main.yml | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a590d867b..ae6235014 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -8,30 +8,7 @@ on: types: [opened, reopened, synchronize] jobs: - test_swagger_editor_validator_service: - runs-on: ubuntu-latest - name: Swagger Editor Validator Service - - # Service containers to run with `runner-job` - services: - # Label used to access the service container - swagger-editor: - # Docker Hub image - image: swaggerapi/swagger-editor - ports: - # Maps port 8080 on service container to the host 80 - - 80:8080 - - steps: - - uses: actions/checkout@v2 - - name: Validate OpenAPI definition - uses: char0n/swagger-editor-validate@v1 - with: - swagger-editor-url: http://localhost/ - definition-file: openapi.yaml - - # Test, pack and publish the Open AI nuget package as a build artifact - build: + build: # Test, pack and publish the Open AI nuget package as a build artifact runs-on: ubuntu-latest steps: - name: Setup .NET @@ -46,7 +23,7 @@ jobs: run: dotnet pack -c Release -o "${{github.workspace}}/packages" - ${{ github.ref == 'refs/heads/main' && '' || format('--version-suffix="alpha.{0}"', github.run_number) }} + ${{ github.ref != 'refs/heads/main' && format('--version-suffix="alpha.{0}"', github.run_number) || '' }} working-directory: .dotnet - name: Upload artifact From f49feeb6c3bad4c2978fa9607b377c40ff2aebbd Mon Sep 17 00:00:00 2001 From: Patrick Hallisey Date: Thu, 14 Mar 2024 17:20:41 -0700 Subject: [PATCH 34/50] Remove no-PR condition on package upload (#21) --- .github/workflows/main.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ae6235014..02d8fa18a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -31,4 +31,3 @@ jobs: with: name: package path: packages/*.nupkg - if: ${{ github.event_name != 'pull_request' }} From 5da30e94063e83afedeb71e9ef0d835f1f73bfc8 Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado <45773732+joseharriaga@users.noreply.github.com> Date: Fri, 15 Mar 2024 13:51:37 -0700 Subject: [PATCH 35/50] Update CodeGen to version 3.0.0-beta.20240312.2 (#22) --- .dotnet/scripts/Update-ClientModel.ps1 | 77 ++- .../src/ClientShared/OptionalDictionary.cs | 214 ------- .dotnet/src/ClientShared/OptionalList.cs | 191 ------ .dotnet/src/ClientShared/OptionalProperty.cs | 117 ---- .../src/Custom/Assistants/AssistantClient.cs | 8 +- .../Assistants/AssistantCreationOptions.cs | 6 +- .../AssistantModificationOptions.cs | 6 +- .../Assistants/FunctionToolDefinition.cs | 4 +- .../src/Custom/Assistants/FunctionToolInfo.cs | 4 +- .../src/Custom/Assistants/ListQueryPage.cs | 10 +- .../Assistants/MessageCreationOptions.cs | 4 +- .../Custom/Assistants/RunCreationOptions.cs | 4 +- .../Assistants/RunModificationOptions.cs | 2 +- .../Assistants/ThreadCreationOptions.cs | 4 +- .../Assistants/ThreadInitializationMessage.cs | 4 +- .../Assistants/ThreadModificationOptions.cs | 2 +- .../Assistants/ToolOutput.Serialization.cs | 4 +- .dotnet/src/Custom/Audio/AudioClient.cs | 10 +- .dotnet/src/Custom/Chat/ChatCompletion.cs | 2 +- .../src/Custom/Chat/ChatCompletionOptions.cs | 16 +- .../Chat/ChatRequestAssistantMessage.cs | 8 +- .../Chat/ChatRequestMessage.Serialization.cs | 2 +- .../Custom/Chat/ChatRequestSystemMessage.cs | 2 +- .../src/Custom/Chat/ChatRequestUserMessage.cs | 2 +- .dotnet/src/Custom/Images/ImageClient.cs | 18 +- .../Custom/Models/ModelManagementClient.cs | 4 +- .dotnet/src/Generated/Assistants.cs | 472 ++++++++------- .dotnet/src/Generated/Audio.cs | 138 +++-- .dotnet/src/Generated/Chat.cs | 46 +- .dotnet/src/Generated/Completions.cs | 46 +- .dotnet/src/Generated/Embeddings.cs | 46 +- .dotnet/src/Generated/Files.cs | 232 ++++---- .dotnet/src/Generated/FineTuning.cs | 232 ++++---- .dotnet/src/Generated/Images.cs | 138 +++-- .dotnet/src/Generated/Internal/Argument.cs | 126 ++++ .../Internal/ChangeTrackingDictionary.cs | 164 ++++++ .../Generated/Internal/ChangeTrackingList.cs | 150 +++++ .../Internal/ClientPipelineExtensions.cs | 49 ++ .dotnet/src/Generated/Internal/ErrorResult.cs | 23 + .dotnet/src/Generated/Internal/Optional.cs | 48 ++ .../Generated/Internal/Utf8JsonRequestBody.cs | 53 ++ .dotnet/src/Generated/Messages.cs | 376 ++++++------ .../AssistantFileObject.Serialization.cs | 10 + .../Generated/Models/AssistantFileObject.cs | 6 +- .../Models/AssistantObject.Serialization.cs | 27 +- .../src/Generated/Models/AssistantObject.cs | 10 +- .../Models/AudioSegment.Serialization.cs | 23 +- .dotnet/src/Generated/Models/AudioSegment.cs | 6 +- ...pletionFunctionCallOption.Serialization.cs | 10 + .../ChatCompletionFunctionCallOption.cs | 4 +- .../ChatCompletionFunctions.Serialization.cs | 22 +- .../Models/ChatCompletionFunctions.cs | 4 +- ...CompletionMessageToolCall.Serialization.cs | 12 +- .../Models/ChatCompletionMessageToolCall.cs | 6 +- ...onMessageToolCallFunction.Serialization.cs | 10 + .../ChatCompletionMessageToolCallFunction.cs | 6 +- ...CompletionNamedToolChoice.Serialization.cs | 12 +- .../Models/ChatCompletionNamedToolChoice.cs | 4 +- ...onNamedToolChoiceFunction.Serialization.cs | 10 + .../ChatCompletionNamedToolChoiceFunction.cs | 4 +- ...CompletionResponseMessage.Serialization.cs | 24 +- .../Models/ChatCompletionResponseMessage.cs | 4 +- ...sponseMessageFunctionCall.Serialization.cs | 10 + ...atCompletionResponseMessageFunctionCall.cs | 6 +- ...hatCompletionTokenLogprob.Serialization.cs | 16 +- .../Models/ChatCompletionTokenLogprob.cs | 6 +- ...ionTokenLogprobTopLogprob.Serialization.cs | 14 +- .../ChatCompletionTokenLogprobTopLogprob.cs | 4 +- .../ChatCompletionTool.Serialization.cs | 12 +- .../Generated/Models/ChatCompletionTool.cs | 4 +- .../Models/CompletionUsage.Serialization.cs | 10 + ...reateAssistantFileRequest.Serialization.cs | 10 + .../Models/CreateAssistantFileRequest.cs | 4 +- .../CreateAssistantRequest.Serialization.cs | 44 +- .../Models/CreateAssistantRequest.cs | 10 +- ...eateChatCompletionRequest.Serialization.cs | 111 ++-- .../Models/CreateChatCompletionRequest.cs | 10 +- .../CreateChatCompletionRequestModel.cs | 2 +- ...tionRequestResponseFormat.Serialization.cs | 16 +- ...ateChatCompletionResponse.Serialization.cs | 32 +- .../Models/CreateChatCompletionResponse.cs | 8 +- ...tCompletionResponseChoice.Serialization.cs | 14 +- .../CreateChatCompletionResponseChoice.cs | 4 +- ...ionResponseChoiceLogprobs.Serialization.cs | 16 +- .../CreateCompletionRequest.Serialization.cs | 90 ++- .../Models/CreateCompletionRequest.cs | 4 +- .../Models/CreateCompletionRequestModel.cs | 2 +- .../CreateCompletionResponse.Serialization.cs | 32 +- .../Models/CreateCompletionResponse.cs | 8 +- ...eCompletionResponseChoice.Serialization.cs | 12 +- .../Models/CreateCompletionResponseChoice.cs | 4 +- ...ionResponseChoiceLogprobs.Serialization.cs | 10 + .../CreateCompletionResponseChoiceLogprobs.cs | 10 +- .../CreateEmbeddingRequest.Serialization.cs | 30 +- .../Models/CreateEmbeddingRequest.cs | 4 +- .../Models/CreateEmbeddingRequestModel.cs | 2 +- .../CreateEmbeddingResponse.Serialization.cs | 14 +- .../Models/CreateEmbeddingResponse.cs | 8 +- .../Models/CreateFileRequest.Serialization.cs | 10 + .../src/Generated/Models/CreateFileRequest.cs | 4 +- ...reateFineTuningJobRequest.Serialization.cs | 32 +- .../Models/CreateFineTuningJobRequest.cs | 4 +- ...JobRequestHyperparameters.Serialization.cs | 24 +- .../Models/CreateFineTuningJobRequestModel.cs | 2 +- .../CreateImageEditRequest.Serialization.cs | 45 +- .../Models/CreateImageEditRequest.cs | 6 +- .../Models/CreateImageEditRequestModel.cs | 2 +- .../CreateImageRequest.Serialization.cs | 49 +- .../Generated/Models/CreateImageRequest.cs | 4 +- .../Models/CreateImageRequestModel.cs | 2 +- ...eateImageVariationRequest.Serialization.cs | 39 +- .../Models/CreateImageVariationRequest.cs | 4 +- .../CreateImageVariationRequestModel.cs | 2 +- .../CreateMessageRequest.Serialization.cs | 20 +- .../Generated/Models/CreateMessageRequest.cs | 8 +- .../CreateModerationRequest.Serialization.cs | 16 +- .../Models/CreateModerationRequest.cs | 4 +- .../Models/CreateModerationRequestModel.cs | 2 +- .../CreateModerationResponse.Serialization.cs | 12 +- .../Models/CreateModerationResponse.cs | 8 +- ...eModerationResponseResult.Serialization.cs | 14 +- .../Models/CreateModerationResponseResult.cs | 6 +- ...nResponseResultCategories.Serialization.cs | 24 +- ...ponseResultCategoryScores.Serialization.cs | 24 +- .../Models/CreateRunRequest.Serialization.cs | 39 +- .../src/Generated/Models/CreateRunRequest.cs | 8 +- .../CreateSpeechRequest.Serialization.cs | 26 +- .../Generated/Models/CreateSpeechRequest.cs | 4 +- .../Models/CreateSpeechRequestModel.cs | 2 +- ...CreateThreadAndRunRequest.Serialization.cs | 41 +- .../Models/CreateThreadAndRunRequest.cs | 8 +- .../CreateThreadRequest.Serialization.cs | 22 +- .../Generated/Models/CreateThreadRequest.cs | 6 +- ...reateTranscriptionRequest.Serialization.cs | 35 +- .../Models/CreateTranscriptionRequest.cs | 4 +- .../Models/CreateTranscriptionRequestModel.cs | 2 +- ...eateTranscriptionResponse.Serialization.cs | 36 +- .../Models/CreateTranscriptionResponse.cs | 6 +- .../CreateTranslationRequest.Serialization.cs | 30 +- .../Models/CreateTranslationRequest.cs | 4 +- .../Models/CreateTranslationRequestModel.cs | 2 +- ...CreateTranslationResponse.Serialization.cs | 36 +- .../Models/CreateTranslationResponse.cs | 6 +- ...leteAssistantFileResponse.Serialization.cs | 10 + .../Models/DeleteAssistantFileResponse.cs | 4 +- .../DeleteAssistantResponse.Serialization.cs | 10 + .../Models/DeleteAssistantResponse.cs | 4 +- .../DeleteFileResponse.Serialization.cs | 10 + .../Generated/Models/DeleteFileResponse.cs | 4 +- .../DeleteModelResponse.Serialization.cs | 10 + .../Generated/Models/DeleteModelResponse.cs | 4 +- .../DeleteThreadResponse.Serialization.cs | 10 + .../Generated/Models/DeleteThreadResponse.cs | 4 +- .../Models/Embedding.Serialization.cs | 10 + .dotnet/src/Generated/Models/Embedding.cs | 4 +- .../Models/EmbeddingUsage.Serialization.cs | 10 + .../Models/FineTuningJob.Serialization.cs | 31 +- .dotnet/src/Generated/Models/FineTuningJob.cs | 14 +- .../FineTuningJobError.Serialization.cs | 10 + .../Generated/Models/FineTuningJobError.cs | 6 +- .../FineTuningJobEvent.Serialization.cs | 18 +- .../Generated/Models/FineTuningJobEvent.cs | 6 +- ...eTuningJobHyperparameters.Serialization.cs | 10 + .../Models/FineTuningJobHyperparameters.cs | 4 +- .../Models/FunctionObject.Serialization.cs | 22 +- .../src/Generated/Models/FunctionObject.cs | 4 +- .../FunctionParameters.Serialization.cs | 10 + .../Generated/Models/FunctionParameters.cs | 4 +- .../Generated/Models/Image.Serialization.cs | 24 +- .../Models/ImagesResponse.Serialization.cs | 12 +- .../src/Generated/Models/ImagesResponse.cs | 4 +- ...istAssistantFilesResponse.Serialization.cs | 20 +- .../Models/ListAssistantFilesResponse.cs | 8 +- .../ListAssistantsResponse.Serialization.cs | 20 +- .../Models/ListAssistantsResponse.cs | 8 +- .../Models/ListFilesResponse.Serialization.cs | 12 +- .../src/Generated/Models/ListFilesResponse.cs | 4 +- ...neTuningJobEventsResponse.Serialization.cs | 12 +- .../Models/ListFineTuningJobEventsResponse.cs | 4 +- .../ListMessageFilesResponse.Serialization.cs | 20 +- .../Models/ListMessageFilesResponse.cs | 8 +- .../ListMessagesResponse.Serialization.cs | 20 +- .../Generated/Models/ListMessagesResponse.cs | 8 +- .../ListModelsResponse.Serialization.cs | 12 +- .../Generated/Models/ListModelsResponse.cs | 4 +- .dotnet/src/Generated/Models/ListOrder.cs | 1 + ...tedFineTuningJobsResponse.Serialization.cs | 12 +- .../ListPaginatedFineTuningJobsResponse.cs | 4 +- .../ListRunStepsResponse.Serialization.cs | 20 +- .../Generated/Models/ListRunStepsResponse.cs | 8 +- .../Models/ListRunsResponse.Serialization.cs | 20 +- .../src/Generated/Models/ListRunsResponse.cs | 8 +- .../Models/MessageFileObject.Serialization.cs | 10 + .../src/Generated/Models/MessageFileObject.cs | 6 +- .../Models/MessageObject.Serialization.cs | 27 +- .dotnet/src/Generated/Models/MessageObject.cs | 10 +- .../Generated/Models/Model.Serialization.cs | 10 + .dotnet/src/Generated/Models/Model.cs | 6 +- .../ModifyAssistantRequest.Serialization.cs | 48 +- .../Models/ModifyAssistantRequest.cs | 8 +- .../ModifyMessageRequest.Serialization.cs | 16 +- .../Generated/Models/ModifyMessageRequest.cs | 4 +- .../Models/ModifyRunRequest.Serialization.cs | 16 +- .../src/Generated/Models/ModifyRunRequest.cs | 4 +- .../ModifyThreadRequest.Serialization.cs | 16 +- .../Generated/Models/ModifyThreadRequest.cs | 4 +- .../Models/OpenAIFile.Serialization.cs | 25 +- .dotnet/src/Generated/Models/OpenAIFile.cs | 6 +- .../RunCompletionUsage.Serialization.cs | 10 + .../Models/RunObject.Serialization.cs | 42 +- .dotnet/src/Generated/Models/RunObject.cs | 16 +- .../RunObjectLastError.Serialization.cs | 10 + .../Generated/Models/RunObjectLastError.cs | 4 +- .../RunObjectRequiredAction.Serialization.cs | 12 +- .../Models/RunObjectRequiredAction.cs | 4 +- ...edActionSubmitToolOutputs.Serialization.cs | 12 +- ...unObjectRequiredActionSubmitToolOutputs.cs | 4 +- ...ailsMessageCreationObject.Serialization.cs | 12 +- .../RunStepDetailsMessageCreationObject.cs | 4 +- ...tionObjectMessageCreation.Serialization.cs | 10 + ...ilsMessageCreationObjectMessageCreation.cs | 4 +- ...tepDetailsToolCallsObject.Serialization.cs | 10 + .../Models/RunStepDetailsToolCallsObject.cs | 4 +- .../Models/RunStepObject.Serialization.cs | 37 +- .dotnet/src/Generated/Models/RunStepObject.cs | 12 +- .../RunStepObjectLastError.Serialization.cs | 10 + .../Models/RunStepObjectLastError.cs | 4 +- .../Models/RunToolCallObject.Serialization.cs | 12 +- .../src/Generated/Models/RunToolCallObject.cs | 6 +- ...RunToolCallObjectFunction.Serialization.cs | 10 + .../Models/RunToolCallObjectFunction.cs | 6 +- ...bmitToolOutputsRunRequest.Serialization.cs | 12 +- .../Models/SubmitToolOutputsRunRequest.cs | 4 +- ...tputsRunRequestToolOutput.Serialization.cs | 20 +- .../Models/ThreadObject.Serialization.cs | 14 +- .dotnet/src/Generated/Models/ThreadObject.cs | 4 +- .dotnet/src/Generated/ModelsOps.cs | 136 +++-- .dotnet/src/Generated/Moderations.cs | 46 +- .dotnet/src/Generated/OpenAIClient.cs | 4 +- .dotnet/src/Generated/OpenAIModelFactory.cs | 167 +++++- .dotnet/src/Generated/Runs.cs | 554 +++++++++--------- .dotnet/src/Generated/Threads.cs | 204 ++++--- main.tsp | 3 +- package-lock.json | 213 +++---- package.json | 12 +- tsp-output/@typespec/openapi3/openapi.yaml | 23 +- tspconfig.yaml | 1 - 247 files changed, 4302 insertions(+), 2647 deletions(-) delete mode 100644 .dotnet/src/ClientShared/OptionalDictionary.cs delete mode 100644 .dotnet/src/ClientShared/OptionalList.cs delete mode 100644 .dotnet/src/ClientShared/OptionalProperty.cs create mode 100644 .dotnet/src/Generated/Internal/Argument.cs create mode 100644 .dotnet/src/Generated/Internal/ChangeTrackingDictionary.cs create mode 100644 .dotnet/src/Generated/Internal/ChangeTrackingList.cs create mode 100644 .dotnet/src/Generated/Internal/ClientPipelineExtensions.cs create mode 100644 .dotnet/src/Generated/Internal/ErrorResult.cs create mode 100644 .dotnet/src/Generated/Internal/Optional.cs create mode 100644 .dotnet/src/Generated/Internal/Utf8JsonRequestBody.cs diff --git a/.dotnet/scripts/Update-ClientModel.ps1 b/.dotnet/scripts/Update-ClientModel.ps1 index 9a05eb4e5..6502789ba 100644 --- a/.dotnet/scripts/Update-ClientModel.ps1 +++ b/.dotnet/scripts/Update-ClientModel.ps1 @@ -34,7 +34,6 @@ function Update-OpenAIClient { $content = $content -creplace "\s+\/\/\/ The ClientDiagnostics is used to provide tracing support for the client library. ", "" $content = $content -creplace "\s+internal TelemetrySource ClientDiagnostics { get; }", "" $content = $content -creplace "\(KeyCredential", "(ApiKeyCredential" - $content = $content -creplace "ClientUtilities.AssertNotNull\((?\w+), nameof\((\w+)\)\);", "if (`${var} is null) throw new ArgumentNullException(nameof(`${var}));" $content = $content -creplace "\s+ClientDiagnostics = new TelemetrySource\(options, true\);", "" $content = $content -creplace "_pipeline = MessagePipeline\.Create\(options, new IPipelinePolicy\[\] \{ new KeyCredentialPolicy\(_keyCredential, AuthorizationHeader, AuthorizationApiKeyPrefix\) \}, Array\.Empty>\(\)\);", "var authenticationPolicy = ApiKeyAuthenticationPolicy.CreateBearerAuthorizationPolicy(_credential);`r`n _pipeline = ClientPipeline.Create(options,`r`n perCallPolicies: ReadOnlySpan.Empty,`r`n perTryPolicies: new PipelinePolicy[] { authenticationPolicy },`r`n beforeTransportPolicies: ReadOnlySpan.Empty);" $content = $content -creplace "\(ClientDiagnostics, ", "(" @@ -75,10 +74,6 @@ function Update-Subclients { $content = $content -creplace "\s+using System.ClientModel.Primitives.Pipeline;", "" $content = $content -creplace "using System.ClientModel.Primitives;", "using System.ClientModel.Primitives;`r`nusing System.Text;" - # Fix ClientUtilities - $content = $content -creplace "ClientUtilities.AssertNotNull\((?\w+), nameof\((\w+)\)\);", "if (`${var} is null) throw new ArgumentNullException(nameof(`${var}));" - $content = $content -creplace "ClientUtilities.AssertNotNullOrEmpty\((?\w+), nameof\((\w+)\)\);", "if (`${var} is null) throw new ArgumentNullException(nameof(`${var}));`r`n if (string.IsNullOrEmpty(`${var})) throw new ArgumentException(nameof(`${var}));" - # Delete TelemetrySource $content = $content -creplace "\s+\/\/\/ The ClientDiagnostics is used to provide tracing support for the client library. ", "" $content = $content -creplace "\s+internal TelemetrySource ClientDiagnostics { get; }", "" @@ -115,11 +110,10 @@ function Update-Subclients { $content = $content -creplace " RequestBody content", " BinaryContent content" $content = $content -creplace "\(RequestOptions context", "(RequestOptions options" $content = $content -creplace " RequestOptions context", " RequestOptions options" - $content = $content -creplace "\s+using var scope = ClientDiagnostics\.CreateSpan\(`"(\w+\.\w+)`"\);", "" - $content = $content -creplace "\s+scope\.Start\(\);", "" - $content = $content -creplace "(?s)\s+try\s+\{\s+using PipelineMessage message = (?\w+)\((?[(\w+)(,\s\w+)]*)context\);\s+return Result\.FromResponse\(await _pipeline\.ProcessMessageAsync\(message, context\)\.ConfigureAwait\(false\)\);\s+\}", "`r`n options ??= new RequestOptions();`r`n using PipelineMessage message = `${method}(`${params}options);`r`n await _pipeline.SendAsync(message).ConfigureAwait(false);`r`n PipelineResponse response = message.Response!;`r`n`r`n if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default)`r`n {`r`n throw await ClientResultException.CreateAsync(response).ConfigureAwait(false);`r`n }`r`n`r`n return ClientResult.FromResponse(response);" - $content = $content -creplace "(?s)\s+try\s+\{\s+using PipelineMessage message = (?\w+)\((?[(\w+)(,\s\w+)]*)context\);\s+return Result\.FromResponse\(_pipeline.ProcessMessage\(message, context\)\);\s+\}", "`r`n options ??= new RequestOptions();`r`n using PipelineMessage message = `${method}(`${params}options);`r`n _pipeline.Send(message);`r`n PipelineResponse response = message.Response!;`r`n`r`n if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default)`r`n {`r`n throw new ClientResultException(response);`r`n }`r`n`r`n return ClientResult.FromResponse(response);" - $content = $content -creplace "(?s)\s+catch \(Exception e\)\s+\{\s+scope\.Failed\(e\);\s+throw;\s+\}", "" + $content = $content -creplace "context\)", "options)" + $content = $content -creplace "using var scope = ClientDiagnostics\.CreateSpan\(`"(?\w+)\.(?\w+)`"\);", "options ??= new RequestOptions();`r`n // using var scope = ClientDiagnostics.CreateSpan(`"`${tag}.`${operationId}`"\);" + $content = $content -creplace "scope\.Start\(\);", "// scope.Start();" + $content = $content -creplace "scope\.Failed\(e\);", "// scope.Failed(e);" # Create request $content = $content -creplace "\(RequestBody content", "(BinaryContent content" @@ -136,9 +130,6 @@ function Update-Subclients { $content = $content -creplace "request\.SetHeaderValue", "request.Headers.Set" $content = $content -creplace "request\.Content = content;", "request.Content = content;`r`n message.Apply(options);" - # Delete DefaultRequestContext - # $content = $content -creplace "\s+private static RequestOptions DefaultRequestContext = new RequestOptions\(\);", "" - # Clean up ApiKeyCredential $content = $content -creplace " KeyCredential", " ApiKeyCredential" $content = $content -creplace "_keyCredential", "_credential" @@ -170,16 +161,67 @@ function Update-Models { Write-Output "Editing $($file.FullName)" $content = $content -creplace "\s+#nullable disable", "" - $content = $content -creplace "ClientUtilities.AssertNotNull\((?@?\w+), nameof\((@?\w+)\)\);", "if (`${var} is null) throw new ArgumentNullException(nameof(`${var}));" - $content = $content -creplace "using System.ClientModel.Internal;", "using OpenAI.ClientShared.Internal;" + $content = $content -creplace "using System\.ClientModel\.Internal;", "using OpenAI.ClientShared.Internal;" + $content = $content -creplace "using System\.ClientModel\.Primitives;", "using System.ClientModel;`r`nusing System.ClientModel.Primitives;" $content = $content -creplace ": IUtf8JsonWriteable,", ":" $content = $content -creplace "\s+void IUtf8JsonWriteable\.Write\(Utf8JsonWriter writer\) => \(\(IJsonModel<(\w+)>\)this\)\.Write\(writer, new ModelReaderWriterOptions\(`"W`"\)\);`r`n", "" - $content = $content -creplace "(?s)\s+\/\/\/ Convert into a Utf8JsonRequestBody\. .*?return content;.*?\}", "" + $content = $content -creplace " RequestBody", " BinaryContent" $content | Set-Content -Path $file.FullName -NoNewline } } +function Update-InternalClientPipelineExtensions { + $root = Split-Path $PSScriptRoot -Parent + $directory = Join-Path -Path $root -ChildPath "src\Generated\Internal" + $file = Get-ChildItem -Path $directory -Filter "ClientPipelineExtensions.cs" + $content = Get-Content -Path $file -Raw + + Write-Output "Editing $($file.FullName)" + + $content = $content -creplace "\s+using System\.ClientModel\.Primitives\.Pipeline;", "" + $content = $content -creplace " Pipeline", " ClientPipeline" + $content = $content -creplace "\.ErrorBehavior", ".ErrorOptions" + $content = $content -creplace "ErrorBehavior\.", "ClientErrorBehaviors." + $content = $content -creplace " MessageFailedException", " ClientResultException" + $content = $content -creplace "(?s)\s+public static async ValueTask> ProcessHeadAsBoolMessageAsync.*?\}.*?\}", "" + $content = $content -creplace "(?s)\s+public static NullableResult ProcessHeadAsBoolMessage.*?\}.*?\}", "" + + $content | Set-Content -Path $file.FullName -NoNewline +} + +function Update-InternalErrorResult { + $root = Split-Path $PSScriptRoot -Parent + $directory = Join-Path -Path $root -ChildPath "src\Generated\Internal" + $file = Get-ChildItem -Path $directory -Filter "ErrorResult.cs" + $content = Get-Content -Path $file -Raw + + Write-Output "Editing $($file.FullName)" + + $content = $content -creplace " MessagePipeline", " ClientPipeline" + $content = $content -creplace " Result", " ClientResult" + $content = $content -creplace " MessageFailedException", " ClientResultException" + $content = $content -creplace "\s+public override bool HasValue => false;", "" + $content = $content -creplace "(?s)\s+public override PipelineResponse GetRawResponse\(\)\s+\{\s+return _response;\s+\}", "" + + $content | Set-Content -Path $file.FullName -NoNewline +} + +function Update-InternalUtf8JsonRequestBody { + $root = Split-Path $PSScriptRoot -Parent + $directory = Join-Path -Path $root -ChildPath "src\Generated\Internal" + $file = Get-ChildItem -Path $directory -Filter "Utf8JsonRequestBody.cs" + $content = Get-Content -Path $file -Raw + + Write-Output "Editing $($file.FullName)" + + $content = $content -creplace "using System\.ClientModel\.Primitives;", "using System;`r`nusing System.ClientModel;" + $content = $content -creplace " RequestBody", " BinaryContent" + $content = $content -creplace "_content = CreateFromStream\(_stream\);", "_content = BinaryContent.Create(BinaryData.FromStream(_stream));" + + $content | Set-Content -Path $file.FullName -NoNewline +} + function Update-Tests { $root = Split-Path $PSScriptRoot -Parent $directory = Join-Path -Path $root -ChildPath "tests\Generated\Tests" @@ -201,4 +243,7 @@ Update-OpenAIClient Update-OpenAIClientOptions Update-Subclients Update-Models +Update-InternalClientPipelineExtensions +Update-InternalErrorResult +Update-InternalUtf8JsonRequestBody Update-Tests \ No newline at end of file diff --git a/.dotnet/src/ClientShared/OptionalDictionary.cs b/.dotnet/src/ClientShared/OptionalDictionary.cs deleted file mode 100644 index 138a936da..000000000 --- a/.dotnet/src/ClientShared/OptionalDictionary.cs +++ /dev/null @@ -1,214 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -using System; -using System.Collections; -using System.Collections.Generic; - -namespace OpenAI.ClientShared.Internal; - -internal class OptionalDictionary : IDictionary, IReadOnlyDictionary where TKey : notnull -{ - private IDictionary? _innerDictionary; - - public OptionalDictionary() - { - } - - public OptionalDictionary(OptionalProperty> optionalDictionary) : this(optionalDictionary.Value) - { - } - - public OptionalDictionary(OptionalProperty> optionalDictionary) : this(optionalDictionary.Value) - { - } - - private OptionalDictionary(IDictionary? dictionary) - { - if (dictionary == null) return; - - _innerDictionary = new Dictionary(dictionary); - } - - private OptionalDictionary(IReadOnlyDictionary? dictionary) - { - if (dictionary == null) return; - - _innerDictionary = new Dictionary(); - foreach (KeyValuePair pair in dictionary) - { - _innerDictionary.Add(pair); - } - } - - public bool IsUndefined => _innerDictionary == null; - - public IEnumerator> GetEnumerator() - { - if (IsUndefined) - { - IEnumerator> GetEmptyEnumerator() - { - yield break; - } - return GetEmptyEnumerator(); - } - return EnsureDictionary().GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - public void Add(KeyValuePair item) - { - EnsureDictionary().Add(item); - } - - public void Clear() - { - EnsureDictionary().Clear(); - } - - public bool Contains(KeyValuePair item) - { - if (IsUndefined) - { - return false; - } - - return EnsureDictionary().Contains(item); - } - - public void CopyTo(KeyValuePair[] array, int arrayIndex) - { - if (IsUndefined) - { - return; - } - - EnsureDictionary().CopyTo(array, arrayIndex); - } - - public bool Remove(KeyValuePair item) - { - if (IsUndefined) - { - return false; - } - - return EnsureDictionary().Remove(item); - } - - public int Count - { - get - { - if (IsUndefined) - { - return 0; - } - - return EnsureDictionary().Count; - } - } - - public bool IsReadOnly - { - get - { - if (IsUndefined) - { - return false; - } - return EnsureDictionary().IsReadOnly; - } - } - - public void Add(TKey key, TValue value) - { - EnsureDictionary().Add(key, value); - } - - public bool ContainsKey(TKey key) - { - if (IsUndefined) - { - return false; - } - - return EnsureDictionary().ContainsKey(key); - } - - public bool Remove(TKey key) - { - if (IsUndefined) - { - return false; - } - - return EnsureDictionary().Remove(key); - } - - public bool TryGetValue(TKey key, out TValue value) - { - if (IsUndefined) - { - value = default!; - return false; - } - return EnsureDictionary().TryGetValue(key, out value!); - } - - public TValue this[TKey key] - { - get - { - if (IsUndefined) - { - throw new KeyNotFoundException(nameof(key)); - } - - return EnsureDictionary()[key]; - } - set => EnsureDictionary()[key] = value; - } - - IEnumerable IReadOnlyDictionary.Keys => Keys; - - IEnumerable IReadOnlyDictionary.Values => Values; - - public ICollection Keys - { - get - { - if (IsUndefined) - { - return Array.Empty(); - } - - return EnsureDictionary().Keys; - } - } - - public ICollection Values - { - get - { - if (IsUndefined) - { - return Array.Empty(); - } - - return EnsureDictionary().Values; - } - } - - private IDictionary EnsureDictionary() - { - return _innerDictionary ??= new Dictionary(); - } -} \ No newline at end of file diff --git a/.dotnet/src/ClientShared/OptionalList.cs b/.dotnet/src/ClientShared/OptionalList.cs deleted file mode 100644 index cc95a17ea..000000000 --- a/.dotnet/src/ClientShared/OptionalList.cs +++ /dev/null @@ -1,191 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; - -namespace OpenAI.ClientShared.Internal; - -internal class OptionalList : IList, IReadOnlyList -{ - private IList? _innerList; - - public OptionalList() - { - } - - public OptionalList(OptionalProperty> optionalList) : this(optionalList.Value) - { - } - - public OptionalList(OptionalProperty> optionalList) : this(optionalList.Value) - { - } - - private OptionalList(IEnumerable? innerList) - { - if (innerList == null) - { - return; - } - - _innerList = innerList.ToList(); - } - - private OptionalList(IList? innerList) - { - if (innerList == null) - { - return; - } - - _innerList = innerList; - } - - public bool IsUndefined => _innerList == null; - - public void Reset() - { - _innerList = null; - } - - public IEnumerator GetEnumerator() - { - if (IsUndefined) - { - IEnumerator EnumerateEmpty() - { - yield break; - } - - return EnumerateEmpty(); - } - return EnsureList().GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - public void Add(T item) - { - EnsureList().Add(item); - } - - public void Clear() - { - EnsureList().Clear(); - } - - public bool Contains(T item) - { - if (IsUndefined) - { - return false; - } - - return EnsureList().Contains(item); - } - - public void CopyTo(T[] array, int arrayIndex) - { - if (IsUndefined) - { - return; - } - - EnsureList().CopyTo(array, arrayIndex); - } - - public bool Remove(T item) - { - if (IsUndefined) - { - return false; - } - - return EnsureList().Remove(item); - } - - public int Count - { - get - { - if (IsUndefined) - { - return 0; - } - return EnsureList().Count; - } - } - - public bool IsReadOnly - { - get - { - if (IsUndefined) - { - return false; - } - - return EnsureList().IsReadOnly; - } - } - - public int IndexOf(T item) - { - if (IsUndefined) - { - return -1; - } - - return EnsureList().IndexOf(item); - } - - public void Insert(int index, T item) - { - EnsureList().Insert(index, item); - } - - public void RemoveAt(int index) - { - if (IsUndefined) - { - throw new ArgumentOutOfRangeException(nameof(index)); - } - - EnsureList().RemoveAt(index); - } - - public T this[int index] - { - get - { - if (IsUndefined) - { - throw new ArgumentOutOfRangeException(nameof(index)); - } - - return EnsureList()[index]; - } - set - { - if (IsUndefined) - { - throw new ArgumentOutOfRangeException(nameof(index)); - } - - EnsureList()[index] = value; - } - } - - private IList EnsureList() - { - return _innerList ??= new List(); - } -} \ No newline at end of file diff --git a/.dotnet/src/ClientShared/OptionalProperty.cs b/.dotnet/src/ClientShared/OptionalProperty.cs deleted file mode 100644 index 9ad960789..000000000 --- a/.dotnet/src/ClientShared/OptionalProperty.cs +++ /dev/null @@ -1,117 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#nullable enable - -using System.Collections.Generic; -using System.Text.Json; - -namespace OpenAI.ClientShared.Internal; - -internal static class OptionalProperty -{ - public static bool IsCollectionDefined(IEnumerable collection) - { - return !(collection is OptionalList changeTrackingList && changeTrackingList.IsUndefined); - } - - public static bool IsCollectionDefined(IReadOnlyDictionary collection) - where TKey : notnull - { - return !(collection is OptionalDictionary changeTrackingList && changeTrackingList.IsUndefined); - } - - public static bool IsCollectionDefined(IDictionary? collection) - where TKey : notnull - { - if (collection is null) - return false; - - return !(collection is OptionalDictionary changeTrackingList && changeTrackingList.IsUndefined); - } - - public static bool IsDefined(T? value) where T : struct - { - return value.HasValue; - } - public static bool IsDefined(object value) - { - return value != null; - } - public static bool IsDefined(string? value) - { - return value != null; - } - - public static bool IsDefined(JsonElement value) - { - return value.ValueKind != JsonValueKind.Undefined; - } - - public static IReadOnlyDictionary ToDictionary(OptionalProperty> optional) - where TKey : notnull - { - if (optional.HasValue) - { - return optional.Value!; - } - return new OptionalDictionary(optional); - } - - public static IDictionary ToDictionary(OptionalProperty> optional) - where TKey : notnull - { - if (optional.HasValue) - { - return optional.Value!; - } - return new OptionalDictionary(optional); - } - - public static IReadOnlyList ToList(OptionalProperty> optional) - { - if (optional.HasValue) - { - return optional.Value!; - } - return new OptionalList(optional); - } - - public static IList ToList(OptionalProperty> optional) - { - if (optional.HasValue) - { - return optional.Value!; - } - return new OptionalList(optional); - } - - public static T? ToNullable(OptionalProperty optional) where T : struct - { - if (optional.HasValue) - { - return optional.Value; - } - return default; - } - - public static T? ToNullable(OptionalProperty optional) where T : struct - { - return optional.Value; - } -} - -internal readonly struct OptionalProperty -{ - public OptionalProperty(T? value) : this() - { - Value = value; - HasValue = value is not null; - } - - public T? Value { get; } - public bool HasValue { get; } - - public static implicit operator OptionalProperty(T? value) => new OptionalProperty(value); - public static implicit operator T?(OptionalProperty optional) => optional.Value; -} \ No newline at end of file diff --git a/.dotnet/src/Custom/Assistants/AssistantClient.cs b/.dotnet/src/Custom/Assistants/AssistantClient.cs index e20089177..9fbbc76f0 100644 --- a/.dotnet/src/Custom/Assistants/AssistantClient.cs +++ b/.dotnet/src/Custom/Assistants/AssistantClient.cs @@ -701,10 +701,10 @@ internal static Internal.Models.CreateThreadAndRunRequest CreateInternalCreateTh serializedAdditionalRawData: null); } - internal static OptionalList ToInternalBinaryDataList(IEnumerable values) + internal static ChangeTrackingList ToInternalBinaryDataList(IEnumerable values) where T : IPersistableModel { - OptionalList internalList = []; + ChangeTrackingList internalList = []; foreach (T value in values) { internalList.Add(ModelReaderWriter.Write(value)); @@ -733,10 +733,10 @@ internal static Internal.Models.CreateMessageRequestRole ToInternalRequestRole(M _ => throw new ArgumentException(nameof(role)), }; - internal static OptionalList ToInternalCreateMessageRequestList( + internal static ChangeTrackingList ToInternalCreateMessageRequestList( IEnumerable messages) { - OptionalList internalList = []; + ChangeTrackingList internalList = []; foreach (ThreadInitializationMessage message in messages) { internalList.Add(new Internal.Models.CreateMessageRequest( diff --git a/.dotnet/src/Custom/Assistants/AssistantCreationOptions.cs b/.dotnet/src/Custom/Assistants/AssistantCreationOptions.cs index 9b9f23321..527a1eb77 100644 --- a/.dotnet/src/Custom/Assistants/AssistantCreationOptions.cs +++ b/.dotnet/src/Custom/Assistants/AssistantCreationOptions.cs @@ -43,13 +43,13 @@ public partial class AssistantCreationOptions /// /// ///
- public IList Tools { get; } = new OptionalList(); + public IList Tools { get; } = new ChangeTrackingList(); /// /// A collection of IDs for previously uploaded files that are made accessible to the assistant. These IDs are the /// basis for the functionality of file-based tools like retrieval. /// - public IList FileIds { get; } = new OptionalList(); + public IList FileIds { get; } = new ChangeTrackingList(); /// /// An optional key/value mapping of additional, supplemental data items to attach to the . @@ -61,5 +61,5 @@ public partial class AssistantCreationOptions /// Values can be a maximum of 512 characters in length. /// /// - public IDictionary Metadata { get; } = new OptionalDictionary(); + public IDictionary Metadata { get; } = new ChangeTrackingDictionary(); } \ No newline at end of file diff --git a/.dotnet/src/Custom/Assistants/AssistantModificationOptions.cs b/.dotnet/src/Custom/Assistants/AssistantModificationOptions.cs index 1c72d4490..c8c3bbe01 100644 --- a/.dotnet/src/Custom/Assistants/AssistantModificationOptions.cs +++ b/.dotnet/src/Custom/Assistants/AssistantModificationOptions.cs @@ -49,13 +49,13 @@ public partial class AssistantModificationOptions /// /// /// - public IList Tools { get; } = new OptionalList(); + public IList Tools { get; } = new ChangeTrackingList(); /// /// A new collection of IDs for previously uploaded files that are made accessible to the assistant. These IDs are /// the basis for the functionality of file-based tools like retrieval. /// - public IList FileIds { get; } = new OptionalList(); + public IList FileIds { get; } = new ChangeTrackingList(); /// /// A replacement for the optional key/value mapping of additional, supplemental data items to attach to the @@ -67,5 +67,5 @@ public partial class AssistantModificationOptions /// Values can be a maximum of 512 characters in length. /// /// - public IDictionary Metadata { get; } = new OptionalDictionary(); + public IDictionary Metadata { get; } = new ChangeTrackingDictionary(); } \ No newline at end of file diff --git a/.dotnet/src/Custom/Assistants/FunctionToolDefinition.cs b/.dotnet/src/Custom/Assistants/FunctionToolDefinition.cs index 57592ac9e..d6687feec 100644 --- a/.dotnet/src/Custom/Assistants/FunctionToolDefinition.cs +++ b/.dotnet/src/Custom/Assistants/FunctionToolDefinition.cs @@ -75,11 +75,11 @@ internal override void WriteDerived(Utf8JsonWriter writer, ModelReaderWriterOpti writer.WritePropertyName("function"u8); writer.WriteStartObject(); writer.WriteString("name"u8, Name); - if (OptionalProperty.IsDefined(Description)) + if (Optional.IsDefined(Description)) { writer.WriteString("description"u8, Description); } - if (OptionalProperty.IsDefined(Parameters)) + if (Optional.IsDefined(Parameters)) { writer.WritePropertyName("parameters"u8); writer.WriteRawValue(Parameters.ToString()); diff --git a/.dotnet/src/Custom/Assistants/FunctionToolInfo.cs b/.dotnet/src/Custom/Assistants/FunctionToolInfo.cs index a85cd9158..b6edc1fc5 100644 --- a/.dotnet/src/Custom/Assistants/FunctionToolInfo.cs +++ b/.dotnet/src/Custom/Assistants/FunctionToolInfo.cs @@ -69,11 +69,11 @@ internal override void WriteDerived(Utf8JsonWriter writer, ModelReaderWriterOpti writer.WritePropertyName("function"u8); writer.WriteStartObject(); writer.WriteString("name"u8, Name); - if (OptionalProperty.IsDefined(Description)) + if (Optional.IsDefined(Description)) { writer.WriteString("description"u8, Description); } - if (OptionalProperty.IsDefined(Parameters)) + if (Optional.IsDefined(Parameters)) { writer.WriteRawValue(Parameters.ToString()); } diff --git a/.dotnet/src/Custom/Assistants/ListQueryPage.cs b/.dotnet/src/Custom/Assistants/ListQueryPage.cs index 3d11c9b48..aa4eaefe9 100644 --- a/.dotnet/src/Custom/Assistants/ListQueryPage.cs +++ b/.dotnet/src/Custom/Assistants/ListQueryPage.cs @@ -23,7 +23,7 @@ internal ListQueryPage(string firstId, string lastId, bool hasMore) internal static ListQueryPage Create(Internal.Models.ListAssistantsResponse internalResponse) { - OptionalList assistants = new(); + ChangeTrackingList assistants = new(); foreach (Internal.Models.AssistantObject internalAssistant in internalResponse.Data) { assistants.Add(new(internalAssistant)); @@ -33,7 +33,7 @@ internal static ListQueryPage Create(Internal.Models.ListAssistantsRe internal static ListQueryPage Create(Internal.Models.ListAssistantFilesResponse internalResponse) { - OptionalList assistantFileAssociations = new(); + ChangeTrackingList assistantFileAssociations = new(); foreach (Internal.Models.AssistantFileObject internalFile in internalResponse.Data) { assistantFileAssociations.Add(new(internalFile)); @@ -43,7 +43,7 @@ internal static ListQueryPage Create(Internal.Models.L internal static ListQueryPage Create(Internal.Models.ListMessagesResponse internalResponse) { - OptionalList messages = new(); + ChangeTrackingList messages = new(); foreach (Internal.Models.MessageObject internalMessage in internalResponse.Data) { messages.Add(new(internalMessage)); @@ -53,7 +53,7 @@ internal static ListQueryPage Create(Internal.Models.ListMessages internal static ListQueryPage Create(Internal.Models.ListMessageFilesResponse internalResponse) { - OptionalList messageFileAssociations = new(); + ChangeTrackingList messageFileAssociations = new(); foreach (Internal.Models.MessageFileObject internalFile in internalResponse.Data) { messageFileAssociations.Add(new(internalFile)); @@ -63,7 +63,7 @@ internal static ListQueryPage Create(Internal.Models.Lis internal static ListQueryPage Create(Internal.Models.ListRunsResponse internalResponse) { - OptionalList runs = new(); + ChangeTrackingList runs = new(); foreach (Internal.Models.RunObject internalRun in internalResponse.Data) { runs.Add(new(internalRun)); diff --git a/.dotnet/src/Custom/Assistants/MessageCreationOptions.cs b/.dotnet/src/Custom/Assistants/MessageCreationOptions.cs index a0916f7dd..b11119fa3 100644 --- a/.dotnet/src/Custom/Assistants/MessageCreationOptions.cs +++ b/.dotnet/src/Custom/Assistants/MessageCreationOptions.cs @@ -14,7 +14,7 @@ public partial class MessageCreationOptions /// A collection of IDs for previously uploaded files that are made accessible to the message. These IDs are the /// basis for the functionality of file-based tools like retrieval. /// - public IList FileIds { get; } = new OptionalList(); + public IList FileIds { get; } = new ChangeTrackingList(); /// /// An optional key/value mapping of additional, supplemental data items to attach to the . @@ -26,5 +26,5 @@ public partial class MessageCreationOptions /// Values can be a maximum of 512 characters in length. /// /// - public IDictionary Metadata { get; } = new OptionalDictionary(); + public IDictionary Metadata { get; } = new ChangeTrackingDictionary(); } \ No newline at end of file diff --git a/.dotnet/src/Custom/Assistants/RunCreationOptions.cs b/.dotnet/src/Custom/Assistants/RunCreationOptions.cs index f7106eaac..b584aafa3 100644 --- a/.dotnet/src/Custom/Assistants/RunCreationOptions.cs +++ b/.dotnet/src/Custom/Assistants/RunCreationOptions.cs @@ -51,7 +51,7 @@ public partial class RunCreationOptions /// /// /// - public IList OverrideTools { get; } = new OptionalList(); + public IList OverrideTools { get; } = new ChangeTrackingList(); /// /// An optional key/value mapping of additional, supplemental data items to attach to the . @@ -63,5 +63,5 @@ public partial class RunCreationOptions /// Values can be a maximum of 512 characters in length. /// /// - public IDictionary Metadata { get; } = new OptionalDictionary(); + public IDictionary Metadata { get; } = new ChangeTrackingDictionary(); } \ No newline at end of file diff --git a/.dotnet/src/Custom/Assistants/RunModificationOptions.cs b/.dotnet/src/Custom/Assistants/RunModificationOptions.cs index 88739b12e..3142669f0 100644 --- a/.dotnet/src/Custom/Assistants/RunModificationOptions.cs +++ b/.dotnet/src/Custom/Assistants/RunModificationOptions.cs @@ -20,5 +20,5 @@ public partial class RunModificationOptions /// Values can be a maximum of 512 characters in length. /// /// - public IDictionary Metadata { get; } = new OptionalDictionary(); + public IDictionary Metadata { get; } = new ChangeTrackingDictionary(); } \ No newline at end of file diff --git a/.dotnet/src/Custom/Assistants/ThreadCreationOptions.cs b/.dotnet/src/Custom/Assistants/ThreadCreationOptions.cs index 404b697e8..39246b756 100644 --- a/.dotnet/src/Custom/Assistants/ThreadCreationOptions.cs +++ b/.dotnet/src/Custom/Assistants/ThreadCreationOptions.cs @@ -10,7 +10,7 @@ namespace OpenAI.Assistants; /// public partial class ThreadCreationOptions { - public IList Messages { get; } = new OptionalList(); + public IList Messages { get; } = new ChangeTrackingList(); /// /// An optional key/value mapping of additional, supplemental data items to attach to the . @@ -22,5 +22,5 @@ public partial class ThreadCreationOptions /// Values can be a maximum of 512 characters in length. /// /// - public IDictionary Metadata { get; } = new OptionalDictionary(); + public IDictionary Metadata { get; } = new ChangeTrackingDictionary(); } \ No newline at end of file diff --git a/.dotnet/src/Custom/Assistants/ThreadInitializationMessage.cs b/.dotnet/src/Custom/Assistants/ThreadInitializationMessage.cs index 069bd34b4..797789a5e 100644 --- a/.dotnet/src/Custom/Assistants/ThreadInitializationMessage.cs +++ b/.dotnet/src/Custom/Assistants/ThreadInitializationMessage.cs @@ -16,7 +16,7 @@ public partial class ThreadInitializationMessage /// A list of File IDs that the message should use.There can be a maximum of 10 files attached to a message. Useful /// for tools like retrieval and code_interpreter that can access and use files. /// - public IList FileIds { get; } = new OptionalList(); + public IList FileIds { get; } = new ChangeTrackingList(); /// /// An optional key/value mapping of additional, supplemental data items to attach to the . @@ -28,7 +28,7 @@ public partial class ThreadInitializationMessage /// Values can be a maximum of 512 characters in length. /// /// - public IDictionary Metadata { get; } = new OptionalDictionary(); + public IDictionary Metadata { get; } = new ChangeTrackingDictionary(); [SetsRequiredMembers] public ThreadInitializationMessage(MessageRole role, string content) diff --git a/.dotnet/src/Custom/Assistants/ThreadModificationOptions.cs b/.dotnet/src/Custom/Assistants/ThreadModificationOptions.cs index 07e6380ea..b36224468 100644 --- a/.dotnet/src/Custom/Assistants/ThreadModificationOptions.cs +++ b/.dotnet/src/Custom/Assistants/ThreadModificationOptions.cs @@ -20,5 +20,5 @@ public partial class ThreadModificationOptions /// Values can be a maximum of 512 characters in length. /// /// - public IDictionary Metadata { get; } = new OptionalDictionary(); + public IDictionary Metadata { get; } = new ChangeTrackingDictionary(); } \ No newline at end of file diff --git a/.dotnet/src/Custom/Assistants/ToolOutput.Serialization.cs b/.dotnet/src/Custom/Assistants/ToolOutput.Serialization.cs index 8d5783eaa..33557cacc 100644 --- a/.dotnet/src/Custom/Assistants/ToolOutput.Serialization.cs +++ b/.dotnet/src/Custom/Assistants/ToolOutput.Serialization.cs @@ -42,11 +42,11 @@ ToolOutput IPersistableModel.Create(BinaryData data, ModelReaderWrit void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions options) { writer.WriteStartObject(); - if (OptionalProperty.IsDefined(Id)) + if (Optional.IsDefined(Id)) { writer.WriteString("tool_call_id"u8, Id); } - if (OptionalProperty.IsDefined(Output)) + if (Optional.IsDefined(Output)) { writer.WriteString("output"u8, Output); } diff --git a/.dotnet/src/Custom/Audio/AudioClient.cs b/.dotnet/src/Custom/Audio/AudioClient.cs index 4fa2267a5..12ca6eb4f 100644 --- a/.dotnet/src/Custom/Audio/AudioClient.cs +++ b/.dotnet/src/Custom/Audio/AudioClient.cs @@ -248,15 +248,15 @@ private MultipartFormDataContent CreateInternalTranscriptionRequestContent( { MultipartFormDataContent content = new(); content.Add(MultipartContent.Create(BinaryData.FromString(_clientConnector.Model)), name: "model", []); - if (OptionalProperty.IsDefined(language)) + if (Optional.IsDefined(language)) { content.Add(MultipartContent.Create(BinaryData.FromString(language)), name: "language", []); } - if (OptionalProperty.IsDefined(prompt)) + if (Optional.IsDefined(prompt)) { content.Add(MultipartContent.Create(BinaryData.FromString(prompt)), name: "prompt", []); } - if (OptionalProperty.IsDefined(transcriptionFormat)) + if (Optional.IsDefined(transcriptionFormat)) { content.Add(MultipartContent.Create(BinaryData.FromString(transcriptionFormat switch { @@ -269,11 +269,11 @@ private MultipartFormDataContent CreateInternalTranscriptionRequestContent( name: "response_format", []); } - if (OptionalProperty.IsDefined(temperature)) + if (Optional.IsDefined(temperature)) { content.Add(MultipartContent.Create(BinaryData.FromString($"{temperature}")), name: "temperature", []); } - if (OptionalProperty.IsDefined(enableWordTimestamps) || OptionalProperty.IsDefined(enableSegmentTimestamps)) + if (Optional.IsDefined(enableWordTimestamps) || Optional.IsDefined(enableSegmentTimestamps)) { List granularities = []; if (enableWordTimestamps == true) diff --git a/.dotnet/src/Custom/Chat/ChatCompletion.cs b/.dotnet/src/Custom/Chat/ChatCompletion.cs index 7b4b5ce1b..08c6a75cd 100644 --- a/.dotnet/src/Custom/Chat/ChatCompletion.cs +++ b/.dotnet/src/Custom/Chat/ChatCompletion.cs @@ -60,7 +60,7 @@ internal ChatCompletion(Internal.Models.CreateChatCompletionResponse internalRes Content = internalChoice.Message.Content; if (internalChoice.Message.ToolCalls != null) { - OptionalList toolCalls = []; + ChangeTrackingList toolCalls = []; foreach (Internal.Models.ChatCompletionMessageToolCall internalToolCall in internalChoice.Message.ToolCalls) { if (internalToolCall.Type == "function") diff --git a/.dotnet/src/Custom/Chat/ChatCompletionOptions.cs b/.dotnet/src/Custom/Chat/ChatCompletionOptions.cs index 50c6d45af..69dfd7e8f 100644 --- a/.dotnet/src/Custom/Chat/ChatCompletionOptions.cs +++ b/.dotnet/src/Custom/Chat/ChatCompletionOptions.cs @@ -15,7 +15,7 @@ public partial class ChatCompletionOptions /// public double? FrequencyPenalty { get; set; } /// - public IDictionary TokenSelectionBiases { get; set; } = new OptionalDictionary(); + public IDictionary TokenSelectionBiases { get; set; } = new ChangeTrackingDictionary(); /// public bool? IncludeLogProbabilities { get; set; } /// @@ -29,25 +29,25 @@ public partial class ChatCompletionOptions /// public int? Seed { get; set; } /// - public IList StopSequences { get; } = new OptionalList(); + public IList StopSequences { get; } = new ChangeTrackingList(); /// public double? Temperature { get; set; } /// public double? NucleusSamplingFactor { get; set; } /// - public IList Tools { get; } = new OptionalList(); + public IList Tools { get; } = new ChangeTrackingList(); /// public ChatToolConstraint? ToolConstraint { get; set; } /// public string User { get; set; } /// - public IList Functions { get; } = new OptionalList(); + public IList Functions { get; } = new ChangeTrackingList(); /// public ChatFunctionConstraint? FunctionConstraint { get; set; } internal BinaryData GetInternalStopSequences() { - if (!OptionalProperty.IsCollectionDefined(StopSequences)) + if (!Optional.IsCollectionDefined(StopSequences)) { return null; } @@ -56,7 +56,7 @@ internal BinaryData GetInternalStopSequences() internal IDictionary GetInternalLogitBias() { - OptionalDictionary packedLogitBias = []; + ChangeTrackingDictionary packedLogitBias = []; foreach (KeyValuePair pair in TokenSelectionBiases) { packedLogitBias[$"{pair.Key}"] = pair.Value; @@ -66,7 +66,7 @@ internal IDictionary GetInternalLogitBias() internal IList GetInternalTools() { - OptionalList internalTools = []; + ChangeTrackingList internalTools = []; foreach (ChatToolDefinition tool in Tools) { if (tool is ChatFunctionToolDefinition functionTool) @@ -84,7 +84,7 @@ internal IDictionary GetInternalLogitBias() internal IList GetInternalFunctions() { - OptionalList internalFunctions = new(); + ChangeTrackingList internalFunctions = new(); foreach (ChatFunctionDefinition function in Functions) { Internal.Models.ChatCompletionFunctions internalFunction = new( diff --git a/.dotnet/src/Custom/Chat/ChatRequestAssistantMessage.cs b/.dotnet/src/Custom/Chat/ChatRequestAssistantMessage.cs index cfd1e794d..eb80d71ea 100644 --- a/.dotnet/src/Custom/Chat/ChatRequestAssistantMessage.cs +++ b/.dotnet/src/Custom/Chat/ChatRequestAssistantMessage.cs @@ -25,7 +25,7 @@ public class ChatRequestAssistantMessage : ChatRequestMessage /// instance and is resolved by providing a /// that correlates via id to the item in tool_calls. /// - public IReadOnlyList ToolCalls { get; } = new OptionalList(); + public IReadOnlyList ToolCalls { get; } = new ChangeTrackingList(); /// /// Deprecated in favor of tool_calls. @@ -105,11 +105,11 @@ public ChatRequestAssistantMessage(ChatCompletion chatCompletion) internal override void WriteDerivedAdditions(Utf8JsonWriter writer, ModelReaderWriterOptions options) { - if (OptionalProperty.IsDefined(Name)) + if (Optional.IsDefined(Name)) { writer.WriteString("name"u8, Name); } - if (OptionalProperty.IsCollectionDefined(ToolCalls)) + if (Optional.IsCollectionDefined(ToolCalls)) { writer.WritePropertyName("tool_calls"u8); writer.WriteStartArray(); @@ -119,7 +119,7 @@ internal override void WriteDerivedAdditions(Utf8JsonWriter writer, ModelReaderW } writer.WriteEndArray(); } - if (OptionalProperty.IsDefined(FunctionCall)) + if (Optional.IsDefined(FunctionCall)) { writer.WritePropertyName("function_call"u8); (FunctionCall as IJsonModel).Write(writer, options); diff --git a/.dotnet/src/Custom/Chat/ChatRequestMessage.Serialization.cs b/.dotnet/src/Custom/Chat/ChatRequestMessage.Serialization.cs index 0cf026fd9..96cc4991f 100644 --- a/.dotnet/src/Custom/Chat/ChatRequestMessage.Serialization.cs +++ b/.dotnet/src/Custom/Chat/ChatRequestMessage.Serialization.cs @@ -23,7 +23,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWrit ChatRole.Function => "function", _ => throw new ArgumentException(nameof(Role)) }); - if (OptionalProperty.IsDefined(Content)) + if (Optional.IsDefined(Content)) { writer.WritePropertyName("content"u8); if (Content.Span.Length == 0) diff --git a/.dotnet/src/Custom/Chat/ChatRequestSystemMessage.cs b/.dotnet/src/Custom/Chat/ChatRequestSystemMessage.cs index d391aad3b..6081118d0 100644 --- a/.dotnet/src/Custom/Chat/ChatRequestSystemMessage.cs +++ b/.dotnet/src/Custom/Chat/ChatRequestSystemMessage.cs @@ -31,7 +31,7 @@ public ChatRequestSystemMessage(string content) : base(ChatRole.System, content) internal override void WriteDerivedAdditions(Utf8JsonWriter writer, ModelReaderWriterOptions options) { - if (OptionalProperty.IsDefined(Name)) + if (Optional.IsDefined(Name)) { writer.WriteString("name"u8, Name); } diff --git a/.dotnet/src/Custom/Chat/ChatRequestUserMessage.cs b/.dotnet/src/Custom/Chat/ChatRequestUserMessage.cs index f1e7a3588..95a80567a 100644 --- a/.dotnet/src/Custom/Chat/ChatRequestUserMessage.cs +++ b/.dotnet/src/Custom/Chat/ChatRequestUserMessage.cs @@ -57,7 +57,7 @@ public ChatRequestUserMessage(params ChatMessageContent[] contentItems) internal override void WriteDerivedAdditions(Utf8JsonWriter writer, ModelReaderWriterOptions options) { - if (OptionalProperty.IsDefined(Name)) + if (Optional.IsDefined(Name)) { writer.WriteString("name"u8, Name); } diff --git a/.dotnet/src/Custom/Images/ImageClient.cs b/.dotnet/src/Custom/Images/ImageClient.cs index 624fb2410..5e29e045b 100644 --- a/.dotnet/src/Custom/Images/ImageClient.cs +++ b/.dotnet/src/Custom/Images/ImageClient.cs @@ -396,17 +396,17 @@ private MultipartFormDataContent CreateInternalImageEditsMultipartFormDataConten content.Add(MultipartContent.Create(BinaryData.FromString(_clientConnector.Model)), name: "model", headers: []); - if (OptionalProperty.IsDefined(maskBytes)) + if (Optional.IsDefined(maskBytes)) { content.Add(MultipartContent.Create(maskBytes), name: "mask", fileName: "mask.png", headers: []); } - if (OptionalProperty.IsDefined(imageCount)) + if (Optional.IsDefined(imageCount)) { content.Add(MultipartContent.Create(BinaryData.FromString(imageCount.ToString())), name: "n", headers: []); } - if (OptionalProperty.IsDefined(imageResponseFormat)) + if (Optional.IsDefined(imageResponseFormat)) { content.Add(MultipartContent.Create( BinaryData.FromString( @@ -421,7 +421,7 @@ private MultipartFormDataContent CreateInternalImageEditsMultipartFormDataConten headers: []); } - if (OptionalProperty.IsDefined(imageSize)) + if (Optional.IsDefined(imageSize)) { content.Add(MultipartContent.Create( BinaryData.FromString( @@ -440,7 +440,7 @@ private MultipartFormDataContent CreateInternalImageEditsMultipartFormDataConten headers: []); } - if (OptionalProperty.IsDefined(user)) + if (Optional.IsDefined(user)) { content.Add(MultipartContent.Create(BinaryData.FromString(user)), "user", []); } @@ -488,12 +488,12 @@ private MultipartFormDataContent CreateInternalImageVariationsMultipartFormDataC content.Add(MultipartContent.Create(BinaryData.FromString(_clientConnector.Model)), name: "model", headers: []); - if (OptionalProperty.IsDefined(imageCount)) + if (Optional.IsDefined(imageCount)) { content.Add(MultipartContent.Create(BinaryData.FromString(imageCount.ToString())), name: "n", headers: []); } - if (OptionalProperty.IsDefined(imageResponseFormat)) + if (Optional.IsDefined(imageResponseFormat)) { content.Add(MultipartContent.Create( BinaryData.FromString( @@ -508,7 +508,7 @@ private MultipartFormDataContent CreateInternalImageVariationsMultipartFormDataC headers: []); } - if (OptionalProperty.IsDefined(imageSize)) + if (Optional.IsDefined(imageSize)) { content.Add(MultipartContent.Create( BinaryData.FromString( @@ -527,7 +527,7 @@ private MultipartFormDataContent CreateInternalImageVariationsMultipartFormDataC headers: []); } - if (OptionalProperty.IsDefined(user)) + if (Optional.IsDefined(user)) { content.Add(MultipartContent.Create(BinaryData.FromString(user)), "user", []); } diff --git a/.dotnet/src/Custom/Models/ModelManagementClient.cs b/.dotnet/src/Custom/Models/ModelManagementClient.cs index 107c798fa..06ea5e028 100644 --- a/.dotnet/src/Custom/Models/ModelManagementClient.cs +++ b/.dotnet/src/Custom/Models/ModelManagementClient.cs @@ -105,7 +105,7 @@ public virtual async Task> GetModelInfoAsync(string m public virtual ClientResult GetModels() { ClientResult internalResult = Shim.GetModels(); - OptionalList modelEntries = []; + ChangeTrackingList modelEntries = []; foreach (Internal.Models.Model internalModel in internalResult.Value.Data) { modelEntries.Add(new(internalModel)); @@ -117,7 +117,7 @@ public virtual async Task> GetModelsAsync() { ClientResult internalResult = await Shim.GetModelsAsync().ConfigureAwait(false); - OptionalList modelEntries = []; + ChangeTrackingList modelEntries = []; foreach (Internal.Models.Model internalModel in internalResult.Value.Data) { modelEntries.Add(new(internalModel)); diff --git a/.dotnet/src/Generated/Assistants.cs b/.dotnet/src/Generated/Assistants.cs index 8ccb9e55f..2da58ef6e 100644 --- a/.dotnet/src/Generated/Assistants.cs +++ b/.dotnet/src/Generated/Assistants.cs @@ -44,7 +44,7 @@ internal Assistants(ClientPipeline pipeline, ApiKeyCredential credential, Uri en /// is null. public virtual async Task> CreateAssistantAsync(CreateAssistantRequest assistant) { - if (assistant is null) throw new ArgumentNullException(nameof(assistant)); + Argument.AssertNotNull(assistant, nameof(assistant)); using BinaryContent content = BinaryContent.Create(assistant); ClientResult result = await CreateAssistantAsync(content, DefaultRequestContext).ConfigureAwait(false); @@ -56,7 +56,7 @@ public virtual async Task> CreateAssistantAsync(Cr /// is null. public virtual ClientResult CreateAssistant(CreateAssistantRequest assistant) { - if (assistant is null) throw new ArgumentNullException(nameof(assistant)); + Argument.AssertNotNull(assistant, nameof(assistant)); using BinaryContent content = BinaryContent.Create(assistant); ClientResult result = CreateAssistant(content, DefaultRequestContext); @@ -85,18 +85,21 @@ public virtual ClientResult CreateAssistant(CreateAssistantRequ /// The response returned from the service. public virtual async Task CreateAssistantAsync(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateAssistantRequest(content, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Assistants.CreateAssistant"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateCreateAssistantRequest(content, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -121,18 +124,21 @@ public virtual async Task CreateAssistantAsync(BinaryContent conte /// The response returned from the service. public virtual ClientResult CreateAssistant(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateAssistantRequest(content, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Assistants.CreateAssistant"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateCreateAssistantRequest(content, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Returns a list of assistants. @@ -224,16 +230,18 @@ public virtual ClientResult GetAssistants(int? limit = n public virtual async Task GetAssistantsAsync(int? limit, string order, string after, string before, RequestOptions options) { options ??= new RequestOptions(); - using PipelineMessage message = CreateGetAssistantsRequest(limit, order, after, before, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; - - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + // using var scope = ClientDiagnostics.CreateSpan("Assistants.GetAssistants"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateGetAssistantsRequest(limit, order, after, before, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -275,16 +283,18 @@ public virtual async Task GetAssistantsAsync(int? limit, string or public virtual ClientResult GetAssistants(int? limit, string order, string after, string before, RequestOptions options) { options ??= new RequestOptions(); - using PipelineMessage message = CreateGetAssistantsRequest(limit, order, after, before, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; - - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + // using var scope = ClientDiagnostics.CreateSpan("Assistants.GetAssistants"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateGetAssistantsRequest(limit, order, after, before, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Retrieves an assistant. @@ -293,8 +303,7 @@ public virtual ClientResult GetAssistants(int? limit, string order, string after /// is an empty string, and was expected to be non-empty. public virtual async Task> GetAssistantAsync(string assistantId) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); ClientResult result = await GetAssistantAsync(assistantId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(AssistantObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -306,8 +315,7 @@ public virtual async Task> GetAssistantAsync(strin /// is an empty string, and was expected to be non-empty. public virtual ClientResult GetAssistant(string assistantId) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); ClientResult result = GetAssistant(assistantId, DefaultRequestContext); return ClientResult.FromValue(AssistantObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -336,19 +344,21 @@ public virtual ClientResult GetAssistant(string assistantId) /// The response returned from the service. public virtual async Task GetAssistantAsync(string assistantId, RequestOptions options) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateGetAssistantRequest(assistantId, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Assistants.GetAssistant"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateGetAssistantRequest(assistantId, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -374,19 +384,21 @@ public virtual async Task GetAssistantAsync(string assistantId, Re /// The response returned from the service. public virtual ClientResult GetAssistant(string assistantId, RequestOptions options) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateGetAssistantRequest(assistantId, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Assistants.GetAssistant"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateGetAssistantRequest(assistantId, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Modifies an assistant. @@ -396,9 +408,8 @@ public virtual ClientResult GetAssistant(string assistantId, RequestOptions opti /// is an empty string, and was expected to be non-empty. public virtual async Task> ModifyAssistantAsync(string assistantId, ModifyAssistantRequest assistant) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - if (assistant is null) throw new ArgumentNullException(nameof(assistant)); + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + Argument.AssertNotNull(assistant, nameof(assistant)); using BinaryContent content = BinaryContent.Create(assistant); ClientResult result = await ModifyAssistantAsync(assistantId, content, DefaultRequestContext).ConfigureAwait(false); @@ -412,9 +423,8 @@ public virtual async Task> ModifyAssistantAsync(st /// is an empty string, and was expected to be non-empty. public virtual ClientResult ModifyAssistant(string assistantId, ModifyAssistantRequest assistant) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - if (assistant is null) throw new ArgumentNullException(nameof(assistant)); + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + Argument.AssertNotNull(assistant, nameof(assistant)); using BinaryContent content = BinaryContent.Create(assistant); ClientResult result = ModifyAssistant(assistantId, content, DefaultRequestContext); @@ -445,20 +455,22 @@ public virtual ClientResult ModifyAssistant(string assistantId, /// The response returned from the service. public virtual async Task ModifyAssistantAsync(string assistantId, BinaryContent content, RequestOptions options = null) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateModifyAssistantRequest(assistantId, content, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Assistants.ModifyAssistant"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateModifyAssistantRequest(assistantId, content, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -485,20 +497,22 @@ public virtual async Task ModifyAssistantAsync(string assistantId, /// The response returned from the service. public virtual ClientResult ModifyAssistant(string assistantId, BinaryContent content, RequestOptions options = null) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateModifyAssistantRequest(assistantId, content, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Assistants.ModifyAssistant"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateModifyAssistantRequest(assistantId, content, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Delete an assistant. @@ -507,8 +521,7 @@ public virtual ClientResult ModifyAssistant(string assistantId, BinaryContent co /// is an empty string, and was expected to be non-empty. public virtual async Task> DeleteAssistantAsync(string assistantId) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); ClientResult result = await DeleteAssistantAsync(assistantId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(DeleteAssistantResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -520,8 +533,7 @@ public virtual async Task> DeleteAssistant /// is an empty string, and was expected to be non-empty. public virtual ClientResult DeleteAssistant(string assistantId) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); ClientResult result = DeleteAssistant(assistantId, DefaultRequestContext); return ClientResult.FromValue(DeleteAssistantResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -550,19 +562,21 @@ public virtual ClientResult DeleteAssistant(string assi /// The response returned from the service. public virtual async Task DeleteAssistantAsync(string assistantId, RequestOptions options) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateDeleteAssistantRequest(assistantId, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Assistants.DeleteAssistant"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateDeleteAssistantRequest(assistantId, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -588,19 +602,21 @@ public virtual async Task DeleteAssistantAsync(string assistantId, /// The response returned from the service. public virtual ClientResult DeleteAssistant(string assistantId, RequestOptions options) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateDeleteAssistantRequest(assistantId, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Assistants.DeleteAssistant"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateDeleteAssistantRequest(assistantId, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -613,9 +629,8 @@ public virtual ClientResult DeleteAssistant(string assistantId, RequestOptions o /// is an empty string, and was expected to be non-empty. public virtual async Task> CreateAssistantFileAsync(string assistantId, CreateAssistantFileRequest file) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - if (file is null) throw new ArgumentNullException(nameof(file)); + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + Argument.AssertNotNull(file, nameof(file)); using BinaryContent content = BinaryContent.Create(file); ClientResult result = await CreateAssistantFileAsync(assistantId, content, DefaultRequestContext).ConfigureAwait(false); @@ -632,9 +647,8 @@ public virtual async Task> CreateAssistantFile /// is an empty string, and was expected to be non-empty. public virtual ClientResult CreateAssistantFile(string assistantId, CreateAssistantFileRequest file) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - if (file is null) throw new ArgumentNullException(nameof(file)); + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + Argument.AssertNotNull(file, nameof(file)); using BinaryContent content = BinaryContent.Create(file); ClientResult result = CreateAssistantFile(assistantId, content, DefaultRequestContext); @@ -666,20 +680,22 @@ public virtual ClientResult CreateAssistantFile(string assi /// The response returned from the service. public virtual async Task CreateAssistantFileAsync(string assistantId, BinaryContent content, RequestOptions options = null) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateAssistantFileRequest(assistantId, content, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Assistants.CreateAssistantFile"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateCreateAssistantFileRequest(assistantId, content, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -707,20 +723,22 @@ public virtual async Task CreateAssistantFileAsync(string assistan /// The response returned from the service. public virtual ClientResult CreateAssistantFile(string assistantId, BinaryContent content, RequestOptions options = null) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateAssistantFileRequest(assistantId, content, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Assistants.CreateAssistantFile"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateCreateAssistantFileRequest(assistantId, content, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Returns a list of assistant files. @@ -747,8 +765,7 @@ public virtual ClientResult CreateAssistantFile(string assistantId, BinaryConten /// is an empty string, and was expected to be non-empty. public virtual async Task> GetAssistantFilesAsync(string assistantId, int? limit = null, ListOrder? order = null, string after = null, string before = null) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); ClientResult result = await GetAssistantFilesAsync(assistantId, limit, order?.ToString(), after, before, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(ListAssistantFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -778,8 +795,7 @@ public virtual async Task> GetAssistant /// is an empty string, and was expected to be non-empty. public virtual ClientResult GetAssistantFiles(string assistantId, int? limit = null, ListOrder? order = null, string after = null, string before = null) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); ClientResult result = GetAssistantFiles(assistantId, limit, order?.ToString(), after, before, DefaultRequestContext); return ClientResult.FromValue(ListAssistantFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -826,19 +842,21 @@ public virtual ClientResult GetAssistantFiles(string /// The response returned from the service. public virtual async Task GetAssistantFilesAsync(string assistantId, int? limit, string order, string after, string before, RequestOptions options) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateGetAssistantFilesRequest(assistantId, limit, order, after, before, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Assistants.GetAssistantFiles"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateGetAssistantFilesRequest(assistantId, limit, order, after, before, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -882,19 +900,21 @@ public virtual async Task GetAssistantFilesAsync(string assistantI /// The response returned from the service. public virtual ClientResult GetAssistantFiles(string assistantId, int? limit, string order, string after, string before, RequestOptions options) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateGetAssistantFilesRequest(assistantId, limit, order, after, before, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Assistants.GetAssistantFiles"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateGetAssistantFilesRequest(assistantId, limit, order, after, before, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Retrieves an assistant file. @@ -904,10 +924,8 @@ public virtual ClientResult GetAssistantFiles(string assistantId, int? limit, st /// or is an empty string, and was expected to be non-empty. public virtual async Task> GetAssistantFileAsync(string assistantId, string fileId) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - if (fileId is null) throw new ArgumentNullException(nameof(fileId)); - if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); ClientResult result = await GetAssistantFileAsync(assistantId, fileId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(AssistantFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -920,10 +938,8 @@ public virtual async Task> GetAssistantFileAsy /// or is an empty string, and was expected to be non-empty. public virtual ClientResult GetAssistantFile(string assistantId, string fileId) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - if (fileId is null) throw new ArgumentNullException(nameof(fileId)); - if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); ClientResult result = GetAssistantFile(assistantId, fileId, DefaultRequestContext); return ClientResult.FromValue(AssistantFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -953,21 +969,22 @@ public virtual ClientResult GetAssistantFile(string assista /// The response returned from the service. public virtual async Task GetAssistantFileAsync(string assistantId, string fileId, RequestOptions options) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - if (fileId is null) throw new ArgumentNullException(nameof(fileId)); - if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateGetAssistantFileRequest(assistantId, fileId, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Assistants.GetAssistantFile"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateGetAssistantFileRequest(assistantId, fileId, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -994,21 +1011,22 @@ public virtual async Task GetAssistantFileAsync(string assistantId /// The response returned from the service. public virtual ClientResult GetAssistantFile(string assistantId, string fileId, RequestOptions options) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - if (fileId is null) throw new ArgumentNullException(nameof(fileId)); - if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateGetAssistantFileRequest(assistantId, fileId, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Assistants.GetAssistantFile"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateGetAssistantFileRequest(assistantId, fileId, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Delete an assistant file. @@ -1018,10 +1036,8 @@ public virtual ClientResult GetAssistantFile(string assistantId, string fileId, /// or is an empty string, and was expected to be non-empty. public virtual async Task> DeleteAssistantFileAsync(string assistantId, string fileId) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - if (fileId is null) throw new ArgumentNullException(nameof(fileId)); - if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); ClientResult result = await DeleteAssistantFileAsync(assistantId, fileId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(DeleteAssistantFileResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -1034,10 +1050,8 @@ public virtual async Task> DeleteAssis /// or is an empty string, and was expected to be non-empty. public virtual ClientResult DeleteAssistantFile(string assistantId, string fileId) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - if (fileId is null) throw new ArgumentNullException(nameof(fileId)); - if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); ClientResult result = DeleteAssistantFile(assistantId, fileId, DefaultRequestContext); return ClientResult.FromValue(DeleteAssistantFileResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -1067,21 +1081,22 @@ public virtual ClientResult DeleteAssistantFile(str /// The response returned from the service. public virtual async Task DeleteAssistantFileAsync(string assistantId, string fileId, RequestOptions options) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - if (fileId is null) throw new ArgumentNullException(nameof(fileId)); - if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateDeleteAssistantFileRequest(assistantId, fileId, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Assistants.DeleteAssistantFile"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateDeleteAssistantFileRequest(assistantId, fileId, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -1108,21 +1123,22 @@ public virtual async Task DeleteAssistantFileAsync(string assistan /// The response returned from the service. public virtual ClientResult DeleteAssistantFile(string assistantId, string fileId, RequestOptions options) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (string.IsNullOrEmpty(assistantId)) throw new ArgumentException(nameof(assistantId)); - if (fileId is null) throw new ArgumentNullException(nameof(fileId)); - if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateDeleteAssistantFileRequest(assistantId, fileId, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(assistantId, nameof(assistantId)); + Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Assistants.DeleteAssistantFile"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateDeleteAssistantFileRequest(assistantId, fileId, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } internal PipelineMessage CreateCreateAssistantRequest(BinaryContent content, RequestOptions options) diff --git a/.dotnet/src/Generated/Audio.cs b/.dotnet/src/Generated/Audio.cs index 9065e02c7..2b73c9657 100644 --- a/.dotnet/src/Generated/Audio.cs +++ b/.dotnet/src/Generated/Audio.cs @@ -44,7 +44,7 @@ internal Audio(ClientPipeline pipeline, ApiKeyCredential credential, Uri endpoin /// is null. public virtual async Task> CreateSpeechAsync(CreateSpeechRequest speech) { - if (speech is null) throw new ArgumentNullException(nameof(speech)); + Argument.AssertNotNull(speech, nameof(speech)); using BinaryContent content = BinaryContent.Create(speech); ClientResult result = await CreateSpeechAsync(content, DefaultRequestContext).ConfigureAwait(false); @@ -56,7 +56,7 @@ public virtual async Task> CreateSpeechAsync(CreateSpee /// is null. public virtual ClientResult CreateSpeech(CreateSpeechRequest speech) { - if (speech is null) throw new ArgumentNullException(nameof(speech)); + Argument.AssertNotNull(speech, nameof(speech)); using BinaryContent content = BinaryContent.Create(speech); ClientResult result = CreateSpeech(content, DefaultRequestContext); @@ -85,18 +85,21 @@ public virtual ClientResult CreateSpeech(CreateSpeechRequest speech) /// The response returned from the service. public virtual async Task CreateSpeechAsync(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateSpeechRequest(content, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Audio.CreateSpeech"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateCreateSpeechRequest(content, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -121,18 +124,21 @@ public virtual async Task CreateSpeechAsync(BinaryContent content, /// The response returned from the service. public virtual ClientResult CreateSpeech(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateSpeechRequest(content, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Audio.CreateSpeech"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateCreateSpeechRequest(content, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Transcribes audio into the input language. @@ -140,7 +146,7 @@ public virtual ClientResult CreateSpeech(BinaryContent content, RequestOptions o /// is null. public virtual async Task> CreateTranscriptionAsync(CreateTranscriptionRequest audio) { - if (audio is null) throw new ArgumentNullException(nameof(audio)); + Argument.AssertNotNull(audio, nameof(audio)); using BinaryContent content = BinaryContent.Create(audio); ClientResult result = await CreateTranscriptionAsync(content, DefaultRequestContext).ConfigureAwait(false); @@ -152,7 +158,7 @@ public virtual async Task> CreateTrans /// is null. public virtual ClientResult CreateTranscription(CreateTranscriptionRequest audio) { - if (audio is null) throw new ArgumentNullException(nameof(audio)); + Argument.AssertNotNull(audio, nameof(audio)); using BinaryContent content = BinaryContent.Create(audio); ClientResult result = CreateTranscription(content, DefaultRequestContext); @@ -181,18 +187,21 @@ public virtual ClientResult CreateTranscription(Cre /// The response returned from the service. public virtual async Task CreateTranscriptionAsync(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateTranscriptionRequest(content, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Audio.CreateTranscription"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateCreateTranscriptionRequest(content, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -217,18 +226,21 @@ public virtual async Task CreateTranscriptionAsync(BinaryContent c /// The response returned from the service. public virtual ClientResult CreateTranscription(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateTranscriptionRequest(content, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Audio.CreateTranscription"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateCreateTranscriptionRequest(content, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Translates audio into English.. @@ -236,7 +248,7 @@ public virtual ClientResult CreateTranscription(BinaryContent content, RequestOp /// is null. public virtual async Task> CreateTranslationAsync(CreateTranslationRequest audio) { - if (audio is null) throw new ArgumentNullException(nameof(audio)); + Argument.AssertNotNull(audio, nameof(audio)); using BinaryContent content = BinaryContent.Create(audio); ClientResult result = await CreateTranslationAsync(content, DefaultRequestContext).ConfigureAwait(false); @@ -248,7 +260,7 @@ public virtual async Task> CreateTransla /// is null. public virtual ClientResult CreateTranslation(CreateTranslationRequest audio) { - if (audio is null) throw new ArgumentNullException(nameof(audio)); + Argument.AssertNotNull(audio, nameof(audio)); using BinaryContent content = BinaryContent.Create(audio); ClientResult result = CreateTranslation(content, DefaultRequestContext); @@ -277,18 +289,21 @@ public virtual ClientResult CreateTranslation(CreateT /// The response returned from the service. public virtual async Task CreateTranslationAsync(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateTranslationRequest(content, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Audio.CreateTranslation"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateCreateTranslationRequest(content, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -313,18 +328,21 @@ public virtual async Task CreateTranslationAsync(BinaryContent con /// The response returned from the service. public virtual ClientResult CreateTranslation(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateTranslationRequest(content, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Audio.CreateTranslation"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateCreateTranslationRequest(content, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } internal PipelineMessage CreateCreateSpeechRequest(BinaryContent content, RequestOptions options) diff --git a/.dotnet/src/Generated/Chat.cs b/.dotnet/src/Generated/Chat.cs index 69528f3d3..d164d2a43 100644 --- a/.dotnet/src/Generated/Chat.cs +++ b/.dotnet/src/Generated/Chat.cs @@ -44,7 +44,7 @@ internal Chat(ClientPipeline pipeline, ApiKeyCredential credential, Uri endpoint /// is null. public virtual async Task> CreateChatCompletionAsync(CreateChatCompletionRequest createChatCompletionRequest) { - if (createChatCompletionRequest is null) throw new ArgumentNullException(nameof(createChatCompletionRequest)); + Argument.AssertNotNull(createChatCompletionRequest, nameof(createChatCompletionRequest)); using BinaryContent content = BinaryContent.Create(createChatCompletionRequest); ClientResult result = await CreateChatCompletionAsync(content, DefaultRequestContext).ConfigureAwait(false); @@ -56,7 +56,7 @@ public virtual async Task> CreateChat /// is null. public virtual ClientResult CreateChatCompletion(CreateChatCompletionRequest createChatCompletionRequest) { - if (createChatCompletionRequest is null) throw new ArgumentNullException(nameof(createChatCompletionRequest)); + Argument.AssertNotNull(createChatCompletionRequest, nameof(createChatCompletionRequest)); using BinaryContent content = BinaryContent.Create(createChatCompletionRequest); ClientResult result = CreateChatCompletion(content, DefaultRequestContext); @@ -85,18 +85,21 @@ public virtual ClientResult CreateChatCompletion(C /// The response returned from the service. public virtual async Task CreateChatCompletionAsync(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateChatCompletionRequest(content, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Chat.CreateChatCompletion"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateCreateChatCompletionRequest(content, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -121,18 +124,21 @@ public virtual async Task CreateChatCompletionAsync(BinaryContent /// The response returned from the service. public virtual ClientResult CreateChatCompletion(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateChatCompletionRequest(content, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Chat.CreateChatCompletion"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateCreateChatCompletionRequest(content, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } internal PipelineMessage CreateCreateChatCompletionRequest(BinaryContent content, RequestOptions options) diff --git a/.dotnet/src/Generated/Completions.cs b/.dotnet/src/Generated/Completions.cs index d43e6be89..a8350ff68 100644 --- a/.dotnet/src/Generated/Completions.cs +++ b/.dotnet/src/Generated/Completions.cs @@ -44,7 +44,7 @@ internal Completions(ClientPipeline pipeline, ApiKeyCredential credential, Uri e /// is null. public virtual async Task> CreateCompletionAsync(CreateCompletionRequest createCompletionRequest) { - if (createCompletionRequest is null) throw new ArgumentNullException(nameof(createCompletionRequest)); + Argument.AssertNotNull(createCompletionRequest, nameof(createCompletionRequest)); using BinaryContent content = BinaryContent.Create(createCompletionRequest); ClientResult result = await CreateCompletionAsync(content, DefaultRequestContext).ConfigureAwait(false); @@ -56,7 +56,7 @@ public virtual async Task> CreateCompleti /// is null. public virtual ClientResult CreateCompletion(CreateCompletionRequest createCompletionRequest) { - if (createCompletionRequest is null) throw new ArgumentNullException(nameof(createCompletionRequest)); + Argument.AssertNotNull(createCompletionRequest, nameof(createCompletionRequest)); using BinaryContent content = BinaryContent.Create(createCompletionRequest); ClientResult result = CreateCompletion(content, DefaultRequestContext); @@ -85,18 +85,21 @@ public virtual ClientResult CreateCompletion(CreateCom /// The response returned from the service. public virtual async Task CreateCompletionAsync(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateCompletionRequest(content, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Completions.CreateCompletion"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateCreateCompletionRequest(content, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -121,18 +124,21 @@ public virtual async Task CreateCompletionAsync(BinaryContent cont /// The response returned from the service. public virtual ClientResult CreateCompletion(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateCompletionRequest(content, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Completions.CreateCompletion"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateCreateCompletionRequest(content, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } internal PipelineMessage CreateCreateCompletionRequest(BinaryContent content, RequestOptions options) diff --git a/.dotnet/src/Generated/Embeddings.cs b/.dotnet/src/Generated/Embeddings.cs index eb53ff05a..9b4e99e82 100644 --- a/.dotnet/src/Generated/Embeddings.cs +++ b/.dotnet/src/Generated/Embeddings.cs @@ -44,7 +44,7 @@ internal Embeddings(ClientPipeline pipeline, ApiKeyCredential credential, Uri en /// is null. public virtual async Task> CreateEmbeddingAsync(CreateEmbeddingRequest embedding) { - if (embedding is null) throw new ArgumentNullException(nameof(embedding)); + Argument.AssertNotNull(embedding, nameof(embedding)); using BinaryContent content = BinaryContent.Create(embedding); ClientResult result = await CreateEmbeddingAsync(content, DefaultRequestContext).ConfigureAwait(false); @@ -56,7 +56,7 @@ public virtual async Task> CreateEmbedding /// is null. public virtual ClientResult CreateEmbedding(CreateEmbeddingRequest embedding) { - if (embedding is null) throw new ArgumentNullException(nameof(embedding)); + Argument.AssertNotNull(embedding, nameof(embedding)); using BinaryContent content = BinaryContent.Create(embedding); ClientResult result = CreateEmbedding(content, DefaultRequestContext); @@ -85,18 +85,21 @@ public virtual ClientResult CreateEmbedding(CreateEmbed /// The response returned from the service. public virtual async Task CreateEmbeddingAsync(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateEmbeddingRequest(content, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Embeddings.CreateEmbedding"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateCreateEmbeddingRequest(content, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -121,18 +124,21 @@ public virtual async Task CreateEmbeddingAsync(BinaryContent conte /// The response returned from the service. public virtual ClientResult CreateEmbedding(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateEmbeddingRequest(content, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Embeddings.CreateEmbedding"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateCreateEmbeddingRequest(content, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } internal PipelineMessage CreateCreateEmbeddingRequest(BinaryContent content, RequestOptions options) diff --git a/.dotnet/src/Generated/Files.cs b/.dotnet/src/Generated/Files.cs index acbd43209..f54d4b2ce 100644 --- a/.dotnet/src/Generated/Files.cs +++ b/.dotnet/src/Generated/Files.cs @@ -53,7 +53,7 @@ internal Files(ClientPipeline pipeline, ApiKeyCredential credential, Uri endpoin /// is null. public virtual async Task> CreateFileAsync(CreateFileRequest file) { - if (file is null) throw new ArgumentNullException(nameof(file)); + Argument.AssertNotNull(file, nameof(file)); using BinaryContent content = BinaryContent.Create(file); ClientResult result = await CreateFileAsync(content, DefaultRequestContext).ConfigureAwait(false); @@ -74,7 +74,7 @@ public virtual async Task> CreateFileAsync(CreateFileRe /// is null. public virtual ClientResult CreateFile(CreateFileRequest file) { - if (file is null) throw new ArgumentNullException(nameof(file)); + Argument.AssertNotNull(file, nameof(file)); using BinaryContent content = BinaryContent.Create(file); ClientResult result = CreateFile(content, DefaultRequestContext); @@ -110,18 +110,21 @@ public virtual ClientResult CreateFile(CreateFileRequest file) /// The response returned from the service. public virtual async Task CreateFileAsync(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateFileRequest(content, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Files.CreateFile"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateCreateFileRequest(content, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -153,18 +156,21 @@ public virtual async Task CreateFileAsync(BinaryContent content, R /// The response returned from the service. public virtual ClientResult CreateFile(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateFileRequest(content, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Files.CreateFile"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateCreateFileRequest(content, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Returns a list of files that belong to the user's organization. @@ -205,16 +211,18 @@ public virtual ClientResult GetFiles(string purpose = null) public virtual async Task GetFilesAsync(string purpose, RequestOptions options) { options ??= new RequestOptions(); - using PipelineMessage message = CreateGetFilesRequest(purpose, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; - - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + // using var scope = ClientDiagnostics.CreateSpan("Files.GetFiles"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateGetFilesRequest(purpose, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -239,16 +247,18 @@ public virtual async Task GetFilesAsync(string purpose, RequestOpt public virtual ClientResult GetFiles(string purpose, RequestOptions options) { options ??= new RequestOptions(); - using PipelineMessage message = CreateGetFilesRequest(purpose, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; - - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + // using var scope = ClientDiagnostics.CreateSpan("Files.GetFiles"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateGetFilesRequest(purpose, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Returns information about a specific file. @@ -257,8 +267,7 @@ public virtual ClientResult GetFiles(string purpose, RequestOptions options) /// is an empty string, and was expected to be non-empty. public virtual async Task> RetrieveFileAsync(string fileId) { - if (fileId is null) throw new ArgumentNullException(nameof(fileId)); - if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); + Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); ClientResult result = await RetrieveFileAsync(fileId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(OpenAIFile.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -270,8 +279,7 @@ public virtual async Task> RetrieveFileAsync(string fil /// is an empty string, and was expected to be non-empty. public virtual ClientResult RetrieveFile(string fileId) { - if (fileId is null) throw new ArgumentNullException(nameof(fileId)); - if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); + Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); ClientResult result = RetrieveFile(fileId, DefaultRequestContext); return ClientResult.FromValue(OpenAIFile.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -300,19 +308,21 @@ public virtual ClientResult RetrieveFile(string fileId) /// The response returned from the service. public virtual async Task RetrieveFileAsync(string fileId, RequestOptions options) { - if (fileId is null) throw new ArgumentNullException(nameof(fileId)); - if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateRetrieveFileRequest(fileId, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Files.RetrieveFile"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateRetrieveFileRequest(fileId, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -338,19 +348,21 @@ public virtual async Task RetrieveFileAsync(string fileId, Request /// The response returned from the service. public virtual ClientResult RetrieveFile(string fileId, RequestOptions options) { - if (fileId is null) throw new ArgumentNullException(nameof(fileId)); - if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateRetrieveFileRequest(fileId, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Files.RetrieveFile"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateRetrieveFileRequest(fileId, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Delete a file. @@ -359,8 +371,7 @@ public virtual ClientResult RetrieveFile(string fileId, RequestOptions options) /// is an empty string, and was expected to be non-empty. public virtual async Task> DeleteFileAsync(string fileId) { - if (fileId is null) throw new ArgumentNullException(nameof(fileId)); - if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); + Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); ClientResult result = await DeleteFileAsync(fileId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(DeleteFileResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -372,8 +383,7 @@ public virtual async Task> DeleteFileAsync(stri /// is an empty string, and was expected to be non-empty. public virtual ClientResult DeleteFile(string fileId) { - if (fileId is null) throw new ArgumentNullException(nameof(fileId)); - if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); + Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); ClientResult result = DeleteFile(fileId, DefaultRequestContext); return ClientResult.FromValue(DeleteFileResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -402,19 +412,21 @@ public virtual ClientResult DeleteFile(string fileId) /// The response returned from the service. public virtual async Task DeleteFileAsync(string fileId, RequestOptions options) { - if (fileId is null) throw new ArgumentNullException(nameof(fileId)); - if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateDeleteFileRequest(fileId, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Files.DeleteFile"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateDeleteFileRequest(fileId, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -440,19 +452,21 @@ public virtual async Task DeleteFileAsync(string fileId, RequestOp /// The response returned from the service. public virtual ClientResult DeleteFile(string fileId, RequestOptions options) { - if (fileId is null) throw new ArgumentNullException(nameof(fileId)); - if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateDeleteFileRequest(fileId, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Files.DeleteFile"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateDeleteFileRequest(fileId, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Returns the contents of the specified file. @@ -461,8 +475,7 @@ public virtual ClientResult DeleteFile(string fileId, RequestOptions options) /// is an empty string, and was expected to be non-empty. public virtual async Task> DownloadFileAsync(string fileId) { - if (fileId is null) throw new ArgumentNullException(nameof(fileId)); - if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); + Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); ClientResult result = await DownloadFileAsync(fileId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(result.GetRawResponse().Content.ToObjectFromJson(), result.GetRawResponse()); @@ -474,8 +487,7 @@ public virtual async Task> DownloadFileAsync(string fileId) /// is an empty string, and was expected to be non-empty. public virtual ClientResult DownloadFile(string fileId) { - if (fileId is null) throw new ArgumentNullException(nameof(fileId)); - if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); + Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); ClientResult result = DownloadFile(fileId, DefaultRequestContext); return ClientResult.FromValue(result.GetRawResponse().Content.ToObjectFromJson(), result.GetRawResponse()); @@ -504,19 +516,21 @@ public virtual ClientResult DownloadFile(string fileId) /// The response returned from the service. public virtual async Task DownloadFileAsync(string fileId, RequestOptions options) { - if (fileId is null) throw new ArgumentNullException(nameof(fileId)); - if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateDownloadFileRequest(fileId, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Files.DownloadFile"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateDownloadFileRequest(fileId, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -542,19 +556,21 @@ public virtual async Task DownloadFileAsync(string fileId, Request /// The response returned from the service. public virtual ClientResult DownloadFile(string fileId, RequestOptions options) { - if (fileId is null) throw new ArgumentNullException(nameof(fileId)); - if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateDownloadFileRequest(fileId, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Files.DownloadFile"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateDownloadFileRequest(fileId, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } internal PipelineMessage CreateCreateFileRequest(BinaryContent content, RequestOptions options) diff --git a/.dotnet/src/Generated/FineTuning.cs b/.dotnet/src/Generated/FineTuning.cs index de671f097..fd95bb9ae 100644 --- a/.dotnet/src/Generated/FineTuning.cs +++ b/.dotnet/src/Generated/FineTuning.cs @@ -50,7 +50,7 @@ internal FineTuning(ClientPipeline pipeline, ApiKeyCredential credential, Uri en /// is null. public virtual async Task> CreateFineTuningJobAsync(CreateFineTuningJobRequest job) { - if (job is null) throw new ArgumentNullException(nameof(job)); + Argument.AssertNotNull(job, nameof(job)); using BinaryContent content = BinaryContent.Create(job); ClientResult result = await CreateFineTuningJobAsync(content, DefaultRequestContext).ConfigureAwait(false); @@ -68,7 +68,7 @@ public virtual async Task> CreateFineTuningJobAsync( /// is null. public virtual ClientResult CreateFineTuningJob(CreateFineTuningJobRequest job) { - if (job is null) throw new ArgumentNullException(nameof(job)); + Argument.AssertNotNull(job, nameof(job)); using BinaryContent content = BinaryContent.Create(job); ClientResult result = CreateFineTuningJob(content, DefaultRequestContext); @@ -101,18 +101,21 @@ public virtual ClientResult CreateFineTuningJob(CreateFineTuningJ /// The response returned from the service. public virtual async Task CreateFineTuningJobAsync(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateFineTuningJobRequest(content, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("FineTuning.CreateFineTuningJob"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateCreateFineTuningJobRequest(content, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -141,18 +144,21 @@ public virtual async Task CreateFineTuningJobAsync(BinaryContent c /// The response returned from the service. public virtual ClientResult CreateFineTuningJob(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateFineTuningJobRequest(content, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("FineTuning.CreateFineTuningJob"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateCreateFineTuningJobRequest(content, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// List your organization's fine-tuning jobs. @@ -196,16 +202,18 @@ public virtual ClientResult GetPaginatedFin public virtual async Task GetPaginatedFineTuningJobsAsync(string after, int? limit, RequestOptions options) { options ??= new RequestOptions(); - using PipelineMessage message = CreateGetPaginatedFineTuningJobsRequest(after, limit, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; - - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + // using var scope = ClientDiagnostics.CreateSpan("FineTuning.GetPaginatedFineTuningJobs"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateGetPaginatedFineTuningJobsRequest(after, limit, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -231,16 +239,18 @@ public virtual async Task GetPaginatedFineTuningJobsAsync(string a public virtual ClientResult GetPaginatedFineTuningJobs(string after, int? limit, RequestOptions options) { options ??= new RequestOptions(); - using PipelineMessage message = CreateGetPaginatedFineTuningJobsRequest(after, limit, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; - - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + // using var scope = ClientDiagnostics.CreateSpan("FineTuning.GetPaginatedFineTuningJobs"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateGetPaginatedFineTuningJobsRequest(after, limit, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -253,8 +263,7 @@ public virtual ClientResult GetPaginatedFineTuningJobs(string after, int? limit, /// is an empty string, and was expected to be non-empty. public virtual async Task> RetrieveFineTuningJobAsync(string fineTuningJobId) { - if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); - if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); + Argument.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); ClientResult result = await RetrieveFineTuningJobAsync(fineTuningJobId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -270,8 +279,7 @@ public virtual async Task> RetrieveFineTuningJobAsyn /// is an empty string, and was expected to be non-empty. public virtual ClientResult RetrieveFineTuningJob(string fineTuningJobId) { - if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); - if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); + Argument.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); ClientResult result = RetrieveFineTuningJob(fineTuningJobId, DefaultRequestContext); return ClientResult.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -302,19 +310,21 @@ public virtual ClientResult RetrieveFineTuningJob(string fineTuni /// The response returned from the service. public virtual async Task RetrieveFineTuningJobAsync(string fineTuningJobId, RequestOptions options) { - if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); - if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateRetrieveFineTuningJobRequest(fineTuningJobId, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("FineTuning.RetrieveFineTuningJob"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateRetrieveFineTuningJobRequest(fineTuningJobId, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -342,19 +352,21 @@ public virtual async Task RetrieveFineTuningJobAsync(string fineTu /// The response returned from the service. public virtual ClientResult RetrieveFineTuningJob(string fineTuningJobId, RequestOptions options) { - if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); - if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateRetrieveFineTuningJobRequest(fineTuningJobId, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("FineTuning.RetrieveFineTuningJob"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateRetrieveFineTuningJobRequest(fineTuningJobId, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Immediately cancel a fine-tune job. @@ -363,8 +375,7 @@ public virtual ClientResult RetrieveFineTuningJob(string fineTuningJobId, Reques /// is an empty string, and was expected to be non-empty. public virtual async Task> CancelFineTuningJobAsync(string fineTuningJobId) { - if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); - if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); + Argument.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); ClientResult result = await CancelFineTuningJobAsync(fineTuningJobId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -376,8 +387,7 @@ public virtual async Task> CancelFineTuningJobAsync( /// is an empty string, and was expected to be non-empty. public virtual ClientResult CancelFineTuningJob(string fineTuningJobId) { - if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); - if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); + Argument.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); ClientResult result = CancelFineTuningJob(fineTuningJobId, DefaultRequestContext); return ClientResult.FromValue(FineTuningJob.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -406,19 +416,21 @@ public virtual ClientResult CancelFineTuningJob(string fineTuning /// The response returned from the service. public virtual async Task CancelFineTuningJobAsync(string fineTuningJobId, RequestOptions options) { - if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); - if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCancelFineTuningJobRequest(fineTuningJobId, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("FineTuning.CancelFineTuningJob"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateCancelFineTuningJobRequest(fineTuningJobId, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -444,19 +456,21 @@ public virtual async Task CancelFineTuningJobAsync(string fineTuni /// The response returned from the service. public virtual ClientResult CancelFineTuningJob(string fineTuningJobId, RequestOptions options) { - if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); - if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCancelFineTuningJobRequest(fineTuningJobId, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("FineTuning.CancelFineTuningJob"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateCancelFineTuningJobRequest(fineTuningJobId, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Get status updates for a fine-tuning job. @@ -467,8 +481,7 @@ public virtual ClientResult CancelFineTuningJob(string fineTuningJobId, RequestO /// is an empty string, and was expected to be non-empty. public virtual async Task> GetFineTuningEventsAsync(string fineTuningJobId, string after = null, int? limit = null) { - if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); - if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); + Argument.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); ClientResult result = await GetFineTuningEventsAsync(fineTuningJobId, after, limit, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(ListFineTuningJobEventsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -482,8 +495,7 @@ public virtual async Task> GetFine /// is an empty string, and was expected to be non-empty. public virtual ClientResult GetFineTuningEvents(string fineTuningJobId, string after = null, int? limit = null) { - if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); - if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); + Argument.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); ClientResult result = GetFineTuningEvents(fineTuningJobId, after, limit, DefaultRequestContext); return ClientResult.FromValue(ListFineTuningJobEventsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -514,19 +526,21 @@ public virtual ClientResult GetFineTuningEvents /// The response returned from the service. public virtual async Task GetFineTuningEventsAsync(string fineTuningJobId, string after, int? limit, RequestOptions options) { - if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); - if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateGetFineTuningEventsRequest(fineTuningJobId, after, limit, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("FineTuning.GetFineTuningEvents"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateGetFineTuningEventsRequest(fineTuningJobId, after, limit, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -554,19 +568,21 @@ public virtual async Task GetFineTuningEventsAsync(string fineTuni /// The response returned from the service. public virtual ClientResult GetFineTuningEvents(string fineTuningJobId, string after, int? limit, RequestOptions options) { - if (fineTuningJobId is null) throw new ArgumentNullException(nameof(fineTuningJobId)); - if (string.IsNullOrEmpty(fineTuningJobId)) throw new ArgumentException(nameof(fineTuningJobId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateGetFineTuningEventsRequest(fineTuningJobId, after, limit, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(fineTuningJobId, nameof(fineTuningJobId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("FineTuning.GetFineTuningEvents"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateGetFineTuningEventsRequest(fineTuningJobId, after, limit, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } internal PipelineMessage CreateCreateFineTuningJobRequest(BinaryContent content, RequestOptions options) diff --git a/.dotnet/src/Generated/Images.cs b/.dotnet/src/Generated/Images.cs index e5d910962..52e5ba6f1 100644 --- a/.dotnet/src/Generated/Images.cs +++ b/.dotnet/src/Generated/Images.cs @@ -44,7 +44,7 @@ internal Images(ClientPipeline pipeline, ApiKeyCredential credential, Uri endpoi /// is null. public virtual async Task> CreateImageAsync(CreateImageRequest image) { - if (image is null) throw new ArgumentNullException(nameof(image)); + Argument.AssertNotNull(image, nameof(image)); using BinaryContent content = BinaryContent.Create(image); ClientResult result = await CreateImageAsync(content, DefaultRequestContext).ConfigureAwait(false); @@ -56,7 +56,7 @@ public virtual async Task> CreateImageAsync(CreateI /// is null. public virtual ClientResult CreateImage(CreateImageRequest image) { - if (image is null) throw new ArgumentNullException(nameof(image)); + Argument.AssertNotNull(image, nameof(image)); using BinaryContent content = BinaryContent.Create(image); ClientResult result = CreateImage(content, DefaultRequestContext); @@ -85,18 +85,21 @@ public virtual ClientResult CreateImage(CreateImageRequest image /// The response returned from the service. public virtual async Task CreateImageAsync(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateImageRequest(content, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Images.CreateImage"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateCreateImageRequest(content, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -121,18 +124,21 @@ public virtual async Task CreateImageAsync(BinaryContent content, /// The response returned from the service. public virtual ClientResult CreateImage(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateImageRequest(content, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Images.CreateImage"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateCreateImageRequest(content, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Creates an edited or extended image given an original image and a prompt. @@ -140,7 +146,7 @@ public virtual ClientResult CreateImage(BinaryContent content, RequestOptions op /// is null. public virtual async Task> CreateImageEditAsync(CreateImageEditRequest image) { - if (image is null) throw new ArgumentNullException(nameof(image)); + Argument.AssertNotNull(image, nameof(image)); using BinaryContent content = BinaryContent.Create(image); ClientResult result = await CreateImageEditAsync(content, DefaultRequestContext).ConfigureAwait(false); @@ -152,7 +158,7 @@ public virtual async Task> CreateImageEditAsync(Cre /// is null. public virtual ClientResult CreateImageEdit(CreateImageEditRequest image) { - if (image is null) throw new ArgumentNullException(nameof(image)); + Argument.AssertNotNull(image, nameof(image)); using BinaryContent content = BinaryContent.Create(image); ClientResult result = CreateImageEdit(content, DefaultRequestContext); @@ -181,18 +187,21 @@ public virtual ClientResult CreateImageEdit(CreateImageEditReque /// The response returned from the service. public virtual async Task CreateImageEditAsync(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateImageEditRequest(content, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Images.CreateImageEdit"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateCreateImageEditRequest(content, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -217,18 +226,21 @@ public virtual async Task CreateImageEditAsync(BinaryContent conte /// The response returned from the service. public virtual ClientResult CreateImageEdit(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateImageEditRequest(content, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Images.CreateImageEdit"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateCreateImageEditRequest(content, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Creates an edited or extended image given an original image and a prompt. @@ -236,7 +248,7 @@ public virtual ClientResult CreateImageEdit(BinaryContent content, RequestOption /// is null. public virtual async Task> CreateImageVariationAsync(CreateImageVariationRequest image) { - if (image is null) throw new ArgumentNullException(nameof(image)); + Argument.AssertNotNull(image, nameof(image)); using BinaryContent content = BinaryContent.Create(image); ClientResult result = await CreateImageVariationAsync(content, DefaultRequestContext).ConfigureAwait(false); @@ -248,7 +260,7 @@ public virtual async Task> CreateImageVariationAsyn /// is null. public virtual ClientResult CreateImageVariation(CreateImageVariationRequest image) { - if (image is null) throw new ArgumentNullException(nameof(image)); + Argument.AssertNotNull(image, nameof(image)); using BinaryContent content = BinaryContent.Create(image); ClientResult result = CreateImageVariation(content, DefaultRequestContext); @@ -277,18 +289,21 @@ public virtual ClientResult CreateImageVariation(CreateImageVari /// The response returned from the service. public virtual async Task CreateImageVariationAsync(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateImageVariationRequest(content, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Images.CreateImageVariation"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateCreateImageVariationRequest(content, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -313,18 +328,21 @@ public virtual async Task CreateImageVariationAsync(BinaryContent /// The response returned from the service. public virtual ClientResult CreateImageVariation(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateImageVariationRequest(content, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Images.CreateImageVariation"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateCreateImageVariationRequest(content, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } internal PipelineMessage CreateCreateImageRequest(BinaryContent content, RequestOptions options) diff --git a/.dotnet/src/Generated/Internal/Argument.cs b/.dotnet/src/Generated/Internal/Argument.cs new file mode 100644 index 000000000..29cb5ac18 --- /dev/null +++ b/.dotnet/src/Generated/Internal/Argument.cs @@ -0,0 +1,126 @@ +// + +#nullable disable + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace OpenAI +{ + internal static class Argument + { + public static void AssertNotNull(T value, string name) + { + if (value is null) + { + throw new ArgumentNullException(name); + } + } + + public static void AssertNotNull(T? value, string name) + where T : struct + { + if (!value.HasValue) + { + throw new ArgumentNullException(name); + } + } + + public static void AssertNotNullOrEmpty(IEnumerable value, string name) + { + if (value is null) + { + throw new ArgumentNullException(name); + } + if (value is ICollection collectionOfT && collectionOfT.Count == 0) + { + throw new ArgumentException("Value cannot be an empty collection.", name); + } + if (value is ICollection collection && collection.Count == 0) + { + throw new ArgumentException("Value cannot be an empty collection.", name); + } + using IEnumerator e = value.GetEnumerator(); + if (!e.MoveNext()) + { + throw new ArgumentException("Value cannot be an empty collection.", name); + } + } + + public static void AssertNotNullOrEmpty(string value, string name) + { + if (value is null) + { + throw new ArgumentNullException(name); + } + if (value.Length == 0) + { + throw new ArgumentException("Value cannot be an empty string.", name); + } + } + + public static void AssertNotNullOrWhiteSpace(string value, string name) + { + if (value is null) + { + throw new ArgumentNullException(name); + } + if (string.IsNullOrWhiteSpace(value)) + { + throw new ArgumentException("Value cannot be empty or contain only white-space characters.", name); + } + } + + public static void AssertNotDefault(ref T value, string name) + where T : struct, IEquatable + { + if (value.Equals(default)) + { + throw new ArgumentException("Value cannot be empty.", name); + } + } + + public static void AssertInRange(T value, T minimum, T maximum, string name) + where T : notnull, IComparable + { + if (minimum.CompareTo(value) > 0) + { + throw new ArgumentOutOfRangeException(name, "Value is less than the minimum allowed."); + } + if (maximum.CompareTo(value) < 0) + { + throw new ArgumentOutOfRangeException(name, "Value is greater than the maximum allowed."); + } + } + + public static void AssertEnumDefined(Type enumType, object value, string name) + { + if (!Enum.IsDefined(enumType, value)) + { + throw new ArgumentException($"Value not defined for {enumType.FullName}.", name); + } + } + + public static T CheckNotNull(T value, string name) + where T : class + { + AssertNotNull(value, name); + return value; + } + + public static string CheckNotNullOrEmpty(string value, string name) + { + AssertNotNullOrEmpty(value, name); + return value; + } + + public static void AssertNull(T value, string name, string message = null) + { + if (value != null) + { + throw new ArgumentException(message ?? "Value must be null.", name); + } + } + } +} diff --git a/.dotnet/src/Generated/Internal/ChangeTrackingDictionary.cs b/.dotnet/src/Generated/Internal/ChangeTrackingDictionary.cs new file mode 100644 index 000000000..2eb05d04a --- /dev/null +++ b/.dotnet/src/Generated/Internal/ChangeTrackingDictionary.cs @@ -0,0 +1,164 @@ +// + +#nullable disable + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace OpenAI +{ + internal class ChangeTrackingDictionary : IDictionary, IReadOnlyDictionary where TKey : notnull + { + private IDictionary _innerDictionary; + + public ChangeTrackingDictionary() + { + } + + public ChangeTrackingDictionary(IDictionary dictionary) + { + if (dictionary == null) + { + return; + } + _innerDictionary = new Dictionary(dictionary); + } + + public ChangeTrackingDictionary(IReadOnlyDictionary dictionary) + { + if (dictionary == null) + { + return; + } + _innerDictionary = new Dictionary(); + foreach (var pair in dictionary) + { + _innerDictionary.Add(pair); + } + } + + public bool IsUndefined => _innerDictionary == null; + + public int Count => IsUndefined ? 0 : EnsureDictionary().Count; + + public bool IsReadOnly => IsUndefined ? false : EnsureDictionary().IsReadOnly; + + public ICollection Keys => IsUndefined ? Array.Empty() : EnsureDictionary().Keys; + + public ICollection Values => IsUndefined ? Array.Empty() : EnsureDictionary().Values; + + public TValue this[TKey key] + { + get + { + if (IsUndefined) + { + throw new KeyNotFoundException(nameof(key)); + } + return EnsureDictionary()[key]; + } + set + { + EnsureDictionary()[key] = value; + } + } + + IEnumerable IReadOnlyDictionary.Keys => Keys; + + IEnumerable IReadOnlyDictionary.Values => Values; + + public IEnumerator> GetEnumerator() + { + if (IsUndefined) + { + IEnumerator> enumerateEmpty() + { + yield break; + } + return enumerateEmpty(); + } + return EnsureDictionary().GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public void Add(KeyValuePair item) + { + EnsureDictionary().Add(item); + } + + public void Clear() + { + EnsureDictionary().Clear(); + } + + public bool Contains(KeyValuePair item) + { + if (IsUndefined) + { + return false; + } + return EnsureDictionary().Contains(item); + } + + public void CopyTo(KeyValuePair[] array, int index) + { + if (IsUndefined) + { + return; + } + EnsureDictionary().CopyTo(array, index); + } + + public bool Remove(KeyValuePair item) + { + if (IsUndefined) + { + return false; + } + return EnsureDictionary().Remove(item); + } + + public void Add(TKey key, TValue value) + { + EnsureDictionary().Add(key, value); + } + + public bool ContainsKey(TKey key) + { + if (IsUndefined) + { + return false; + } + return EnsureDictionary().ContainsKey(key); + } + + public bool Remove(TKey key) + { + if (IsUndefined) + { + return false; + } + return EnsureDictionary().Remove(key); + } + + public bool TryGetValue(TKey key, out TValue value) + { + if (IsUndefined) + { + value = default; + return false; + } + return EnsureDictionary().TryGetValue(key, out value); + } + + public IDictionary EnsureDictionary() + { + return _innerDictionary ??= new Dictionary(); + } + } +} diff --git a/.dotnet/src/Generated/Internal/ChangeTrackingList.cs b/.dotnet/src/Generated/Internal/ChangeTrackingList.cs new file mode 100644 index 000000000..c64afc504 --- /dev/null +++ b/.dotnet/src/Generated/Internal/ChangeTrackingList.cs @@ -0,0 +1,150 @@ +// + +#nullable disable + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +namespace OpenAI +{ + internal class ChangeTrackingList : IList, IReadOnlyList + { + private IList _innerList; + + public ChangeTrackingList() + { + } + + public ChangeTrackingList(IList innerList) + { + if (innerList != null) + { + _innerList = innerList; + } + } + + public ChangeTrackingList(IReadOnlyList innerList) + { + if (innerList != null) + { + _innerList = innerList.ToList(); + } + } + + public bool IsUndefined => _innerList == null; + + public int Count => IsUndefined ? 0 : EnsureList().Count; + + public bool IsReadOnly => IsUndefined ? false : EnsureList().IsReadOnly; + + public T this[int index] + { + get + { + if (IsUndefined) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + return EnsureList()[index]; + } + set + { + if (IsUndefined) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + EnsureList()[index] = value; + } + } + + public void Reset() + { + _innerList = null; + } + + public IEnumerator GetEnumerator() + { + if (IsUndefined) + { + IEnumerator enumerateEmpty() + { + yield break; + } + return enumerateEmpty(); + } + return EnsureList().GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + public void Add(T item) + { + EnsureList().Add(item); + } + + public void Clear() + { + EnsureList().Clear(); + } + + public bool Contains(T item) + { + if (IsUndefined) + { + return false; + } + return EnsureList().Contains(item); + } + + public void CopyTo(T[] array, int arrayIndex) + { + if (IsUndefined) + { + return; + } + EnsureList().CopyTo(array, arrayIndex); + } + + public bool Remove(T item) + { + if (IsUndefined) + { + return false; + } + return EnsureList().Remove(item); + } + + public int IndexOf(T item) + { + if (IsUndefined) + { + return -1; + } + return EnsureList().IndexOf(item); + } + + public void Insert(int index, T item) + { + EnsureList().Insert(index, item); + } + + public void RemoveAt(int index) + { + if (IsUndefined) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + EnsureList().RemoveAt(index); + } + + public IList EnsureList() + { + return _innerList ??= new List(); + } + } +} diff --git a/.dotnet/src/Generated/Internal/ClientPipelineExtensions.cs b/.dotnet/src/Generated/Internal/ClientPipelineExtensions.cs new file mode 100644 index 000000000..c34101d11 --- /dev/null +++ b/.dotnet/src/Generated/Internal/ClientPipelineExtensions.cs @@ -0,0 +1,49 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using System.ClientModel.Primitives; +using System.Threading; +using System.Threading.Tasks; + +namespace OpenAI +{ + internal static class ClientPipelineExtensions + { + public static async ValueTask ProcessMessageAsync(this ClientPipeline pipeline, PipelineMessage message, RequestOptions requestContext, CancellationToken cancellationToken = default) + { + await pipeline.SendAsync(message).ConfigureAwait(false); + + if (message.Response == null) + { + throw new InvalidOperationException("Failed to receive Result."); + } + + if (!message.Response.IsError || requestContext.ErrorOptions == ClientErrorBehaviors.NoThrow) + { + return message.Response; + } + + throw new ClientResultException(message.Response); + } + + public static PipelineResponse ProcessMessage(this ClientPipeline pipeline, PipelineMessage message, RequestOptions requestContext, CancellationToken cancellationToken = default) + { + pipeline.Send(message); + + if (message.Response == null) + { + throw new InvalidOperationException("Failed to receive Result."); + } + + if (!message.Response.IsError || requestContext.ErrorOptions == ClientErrorBehaviors.NoThrow) + { + return message.Response; + } + + throw new ClientResultException(message.Response); + } + } +} diff --git a/.dotnet/src/Generated/Internal/ErrorResult.cs b/.dotnet/src/Generated/Internal/ErrorResult.cs new file mode 100644 index 000000000..42938626f --- /dev/null +++ b/.dotnet/src/Generated/Internal/ErrorResult.cs @@ -0,0 +1,23 @@ +// + +#nullable disable + +using System.ClientModel; +using System.ClientModel.Primitives; + +namespace OpenAI +{ + internal class ErrorResult : ClientResult + { + private readonly PipelineResponse _response; + private readonly ClientResultException _exception; + + public ErrorResult(PipelineResponse response, ClientResultException exception) : base(default, response) + { + _response = response; + _exception = exception; + } + + public override T Value => throw _exception; + } +} diff --git a/.dotnet/src/Generated/Internal/Optional.cs b/.dotnet/src/Generated/Internal/Optional.cs new file mode 100644 index 000000000..7b3fe4806 --- /dev/null +++ b/.dotnet/src/Generated/Internal/Optional.cs @@ -0,0 +1,48 @@ +// + +#nullable disable + +using System.Collections.Generic; +using System.Text.Json; + +namespace OpenAI +{ + internal static class Optional + { + public static bool IsCollectionDefined(IEnumerable collection) + { + return !(collection is ChangeTrackingList changeTrackingList && changeTrackingList.IsUndefined); + } + + public static bool IsCollectionDefined(IDictionary collection) + { + return !(collection is ChangeTrackingDictionary changeTrackingDictionary && changeTrackingDictionary.IsUndefined); + } + + public static bool IsCollectionDefined(IReadOnlyDictionary collection) + { + return !(collection is ChangeTrackingDictionary changeTrackingDictionary && changeTrackingDictionary.IsUndefined); + } + + public static bool IsDefined(T? value) + where T : struct + { + return value.HasValue; + } + + public static bool IsDefined(object value) + { + return value != null; + } + + public static bool IsDefined(JsonElement value) + { + return value.ValueKind != JsonValueKind.Undefined; + } + + public static bool IsDefined(string value) + { + return value != null; + } + } +} diff --git a/.dotnet/src/Generated/Internal/Utf8JsonRequestBody.cs b/.dotnet/src/Generated/Internal/Utf8JsonRequestBody.cs new file mode 100644 index 000000000..c86d98827 --- /dev/null +++ b/.dotnet/src/Generated/Internal/Utf8JsonRequestBody.cs @@ -0,0 +1,53 @@ +// + +#nullable disable + +using System; +using System.ClientModel; +using System.IO; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; + +namespace OpenAI +{ + internal class Utf8JsonRequestBody : BinaryContent + { + private readonly MemoryStream _stream; + private readonly BinaryContent _content; + + public Utf8JsonRequestBody() + { + _stream = new MemoryStream(); + _content = BinaryContent.Create(BinaryData.FromStream(_stream)); + JsonWriter = new Utf8JsonWriter(_stream); + } + + public Utf8JsonWriter JsonWriter { get; } + + public override async Task WriteToAsync(Stream stream, CancellationToken cancellationToken = default) + { + await JsonWriter.FlushAsync().ConfigureAwait(false); + await _content.WriteToAsync(stream, cancellationToken).ConfigureAwait(false); + } + + public override void WriteTo(Stream stream, CancellationToken cancellationToken = default) + { + JsonWriter.Flush(); + _content.WriteTo(stream, cancellationToken); + } + + public override bool TryComputeLength(out long length) + { + length = JsonWriter.BytesCommitted + JsonWriter.BytesPending; + return true; + } + + public override void Dispose() + { + JsonWriter.Dispose(); + _content.Dispose(); + _stream.Dispose(); + } + } +} diff --git a/.dotnet/src/Generated/Messages.cs b/.dotnet/src/Generated/Messages.cs index 32579b8bd..22557309c 100644 --- a/.dotnet/src/Generated/Messages.cs +++ b/.dotnet/src/Generated/Messages.cs @@ -46,9 +46,8 @@ internal Messages(ClientPipeline pipeline, ApiKeyCredential credential, Uri endp /// is an empty string, and was expected to be non-empty. public virtual async Task> CreateMessageAsync(string threadId, CreateMessageRequest message) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (message is null) throw new ArgumentNullException(nameof(message)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNull(message, nameof(message)); using BinaryContent content = BinaryContent.Create(message); ClientResult result = await CreateMessageAsync(threadId, content, DefaultRequestContext).ConfigureAwait(false); @@ -62,9 +61,8 @@ public virtual async Task> CreateMessageAsync(string /// is an empty string, and was expected to be non-empty. public virtual ClientResult CreateMessage(string threadId, CreateMessageRequest message) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (message is null) throw new ArgumentNullException(nameof(message)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNull(message, nameof(message)); using BinaryContent content = BinaryContent.Create(message); ClientResult result = CreateMessage(threadId, content, DefaultRequestContext); @@ -95,20 +93,22 @@ public virtual ClientResult CreateMessage(string threadId, Create /// The response returned from the service. public virtual async Task CreateMessageAsync(string threadId, BinaryContent content, RequestOptions options = null) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateMessageRequest(threadId, content, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Messages.CreateMessage"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateCreateMessageRequest(threadId, content, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -135,20 +135,22 @@ public virtual async Task CreateMessageAsync(string threadId, Bina /// The response returned from the service. public virtual ClientResult CreateMessage(string threadId, BinaryContent content, RequestOptions options = null) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateMessageRequest(threadId, content, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Messages.CreateMessage"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateCreateMessageRequest(threadId, content, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Returns a list of messages for a given thread. @@ -175,8 +177,7 @@ public virtual ClientResult CreateMessage(string threadId, BinaryContent content /// is an empty string, and was expected to be non-empty. public virtual async Task> GetMessagesAsync(string threadId, int? limit = null, ListOrder? order = null, string after = null, string before = null) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); ClientResult result = await GetMessagesAsync(threadId, limit, order?.ToString(), after, before, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(ListMessagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -206,8 +207,7 @@ public virtual async Task> GetMessagesAsync(s /// is an empty string, and was expected to be non-empty. public virtual ClientResult GetMessages(string threadId, int? limit = null, ListOrder? order = null, string after = null, string before = null) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); ClientResult result = GetMessages(threadId, limit, order?.ToString(), after, before, DefaultRequestContext); return ClientResult.FromValue(ListMessagesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -254,19 +254,21 @@ public virtual ClientResult GetMessages(string threadId, i /// The response returned from the service. public virtual async Task GetMessagesAsync(string threadId, int? limit, string order, string after, string before, RequestOptions options) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateGetMessagesRequest(threadId, limit, order, after, before, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Messages.GetMessages"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateGetMessagesRequest(threadId, limit, order, after, before, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -310,19 +312,21 @@ public virtual async Task GetMessagesAsync(string threadId, int? l /// The response returned from the service. public virtual ClientResult GetMessages(string threadId, int? limit, string order, string after, string before, RequestOptions options) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateGetMessagesRequest(threadId, limit, order, after, before, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Messages.GetMessages"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateGetMessagesRequest(threadId, limit, order, after, before, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Retrieve a message. @@ -332,10 +336,8 @@ public virtual ClientResult GetMessages(string threadId, int? limit, string orde /// or is an empty string, and was expected to be non-empty. public virtual async Task> GetMessageAsync(string threadId, string messageId) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (messageId is null) throw new ArgumentNullException(nameof(messageId)); - if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(messageId, nameof(messageId)); ClientResult result = await GetMessageAsync(threadId, messageId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(MessageObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -348,10 +350,8 @@ public virtual async Task> GetMessageAsync(string th /// or is an empty string, and was expected to be non-empty. public virtual ClientResult GetMessage(string threadId, string messageId) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (messageId is null) throw new ArgumentNullException(nameof(messageId)); - if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(messageId, nameof(messageId)); ClientResult result = GetMessage(threadId, messageId, DefaultRequestContext); return ClientResult.FromValue(MessageObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -381,21 +381,22 @@ public virtual ClientResult GetMessage(string threadId, string me /// The response returned from the service. public virtual async Task GetMessageAsync(string threadId, string messageId, RequestOptions options) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (messageId is null) throw new ArgumentNullException(nameof(messageId)); - if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateGetMessageRequest(threadId, messageId, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(messageId, nameof(messageId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Messages.GetMessage"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateGetMessageRequest(threadId, messageId, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -422,21 +423,22 @@ public virtual async Task GetMessageAsync(string threadId, string /// The response returned from the service. public virtual ClientResult GetMessage(string threadId, string messageId, RequestOptions options) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (messageId is null) throw new ArgumentNullException(nameof(messageId)); - if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateGetMessageRequest(threadId, messageId, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(messageId, nameof(messageId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Messages.GetMessage"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateGetMessageRequest(threadId, messageId, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Modifies a message. @@ -447,11 +449,9 @@ public virtual ClientResult GetMessage(string threadId, string messageId, Reques /// or is an empty string, and was expected to be non-empty. public virtual async Task> ModifyMessageAsync(string threadId, string messageId, ModifyMessageRequest message) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (messageId is null) throw new ArgumentNullException(nameof(messageId)); - if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); - if (message is null) throw new ArgumentNullException(nameof(message)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(messageId, nameof(messageId)); + Argument.AssertNotNull(message, nameof(message)); using BinaryContent content = BinaryContent.Create(message); ClientResult result = await ModifyMessageAsync(threadId, messageId, content, DefaultRequestContext).ConfigureAwait(false); @@ -466,11 +466,9 @@ public virtual async Task> ModifyMessageAsync(string /// or is an empty string, and was expected to be non-empty. public virtual ClientResult ModifyMessage(string threadId, string messageId, ModifyMessageRequest message) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (messageId is null) throw new ArgumentNullException(nameof(messageId)); - if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); - if (message is null) throw new ArgumentNullException(nameof(message)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(messageId, nameof(messageId)); + Argument.AssertNotNull(message, nameof(message)); using BinaryContent content = BinaryContent.Create(message); ClientResult result = ModifyMessage(threadId, messageId, content, DefaultRequestContext); @@ -502,22 +500,23 @@ public virtual ClientResult ModifyMessage(string threadId, string /// The response returned from the service. public virtual async Task ModifyMessageAsync(string threadId, string messageId, BinaryContent content, RequestOptions options = null) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (messageId is null) throw new ArgumentNullException(nameof(messageId)); - if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateModifyMessageRequest(threadId, messageId, content, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(messageId, nameof(messageId)); + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Messages.ModifyMessage"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateModifyMessageRequest(threadId, messageId, content, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -545,22 +544,23 @@ public virtual async Task ModifyMessageAsync(string threadId, stri /// The response returned from the service. public virtual ClientResult ModifyMessage(string threadId, string messageId, BinaryContent content, RequestOptions options = null) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (messageId is null) throw new ArgumentNullException(nameof(messageId)); - if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateModifyMessageRequest(threadId, messageId, content, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(messageId, nameof(messageId)); + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Messages.ModifyMessage"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateModifyMessageRequest(threadId, messageId, content, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Returns a list of message files. @@ -588,10 +588,8 @@ public virtual ClientResult ModifyMessage(string threadId, string messageId, Bin /// or is an empty string, and was expected to be non-empty. public virtual async Task> GetMessageFilesAsync(string threadId, string messageId, int? limit = null, ListOrder? order = null, string after = null, string before = null) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (messageId is null) throw new ArgumentNullException(nameof(messageId)); - if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(messageId, nameof(messageId)); ClientResult result = await GetMessageFilesAsync(threadId, messageId, limit, order?.ToString(), after, before, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(ListMessageFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -622,10 +620,8 @@ public virtual async Task> GetMessageFile /// or is an empty string, and was expected to be non-empty. public virtual ClientResult GetMessageFiles(string threadId, string messageId, int? limit = null, ListOrder? order = null, string after = null, string before = null) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (messageId is null) throw new ArgumentNullException(nameof(messageId)); - if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(messageId, nameof(messageId)); ClientResult result = GetMessageFiles(threadId, messageId, limit, order?.ToString(), after, before, DefaultRequestContext); return ClientResult.FromValue(ListMessageFilesResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -673,21 +669,22 @@ public virtual ClientResult GetMessageFiles(string thr /// The response returned from the service. public virtual async Task GetMessageFilesAsync(string threadId, string messageId, int? limit, string order, string after, string before, RequestOptions options) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (messageId is null) throw new ArgumentNullException(nameof(messageId)); - if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateGetMessageFilesRequest(threadId, messageId, limit, order, after, before, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(messageId, nameof(messageId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Messages.GetMessageFiles"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateGetMessageFilesRequest(threadId, messageId, limit, order, after, before, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -732,21 +729,22 @@ public virtual async Task GetMessageFilesAsync(string threadId, st /// The response returned from the service. public virtual ClientResult GetMessageFiles(string threadId, string messageId, int? limit, string order, string after, string before, RequestOptions options) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (messageId is null) throw new ArgumentNullException(nameof(messageId)); - if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateGetMessageFilesRequest(threadId, messageId, limit, order, after, before, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(messageId, nameof(messageId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Messages.GetMessageFiles"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateGetMessageFilesRequest(threadId, messageId, limit, order, after, before, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Retrieves a message file. @@ -757,12 +755,9 @@ public virtual ClientResult GetMessageFiles(string threadId, string messageId, i /// , or is an empty string, and was expected to be non-empty. public virtual async Task> GetMessageFileAsync(string threadId, string messageId, string fileId) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (messageId is null) throw new ArgumentNullException(nameof(messageId)); - if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); - if (fileId is null) throw new ArgumentNullException(nameof(fileId)); - if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(messageId, nameof(messageId)); + Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); ClientResult result = await GetMessageFileAsync(threadId, messageId, fileId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(MessageFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -776,12 +771,9 @@ public virtual async Task> GetMessageFileAsync(s /// , or is an empty string, and was expected to be non-empty. public virtual ClientResult GetMessageFile(string threadId, string messageId, string fileId) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (messageId is null) throw new ArgumentNullException(nameof(messageId)); - if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); - if (fileId is null) throw new ArgumentNullException(nameof(fileId)); - if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(messageId, nameof(messageId)); + Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); ClientResult result = GetMessageFile(threadId, messageId, fileId, DefaultRequestContext); return ClientResult.FromValue(MessageFileObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -812,23 +804,23 @@ public virtual ClientResult GetMessageFile(string threadId, s /// The response returned from the service. public virtual async Task GetMessageFileAsync(string threadId, string messageId, string fileId, RequestOptions options) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (messageId is null) throw new ArgumentNullException(nameof(messageId)); - if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); - if (fileId is null) throw new ArgumentNullException(nameof(fileId)); - if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateGetMessageFileRequest(threadId, messageId, fileId, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(messageId, nameof(messageId)); + Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Messages.GetMessageFile"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateGetMessageFileRequest(threadId, messageId, fileId, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -856,23 +848,23 @@ public virtual async Task GetMessageFileAsync(string threadId, str /// The response returned from the service. public virtual ClientResult GetMessageFile(string threadId, string messageId, string fileId, RequestOptions options) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (messageId is null) throw new ArgumentNullException(nameof(messageId)); - if (string.IsNullOrEmpty(messageId)) throw new ArgumentException(nameof(messageId)); - if (fileId is null) throw new ArgumentNullException(nameof(fileId)); - if (string.IsNullOrEmpty(fileId)) throw new ArgumentException(nameof(fileId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateGetMessageFileRequest(threadId, messageId, fileId, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(messageId, nameof(messageId)); + Argument.AssertNotNullOrEmpty(fileId, nameof(fileId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Messages.GetMessageFile"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateGetMessageFileRequest(threadId, messageId, fileId, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } internal PipelineMessage CreateCreateMessageRequest(string threadId, BinaryContent content, RequestOptions options) diff --git a/.dotnet/src/Generated/Models/AssistantFileObject.Serialization.cs b/.dotnet/src/Generated/Models/AssistantFileObject.Serialization.cs index eebbf2b6f..452f90c5c 100644 --- a/.dotnet/src/Generated/Models/AssistantFileObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/AssistantFileObject.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -140,5 +142,13 @@ internal static AssistantFileObject FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeAssistantFileObject(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/AssistantFileObject.cs b/.dotnet/src/Generated/Models/AssistantFileObject.cs index bb30fc168..ff43db447 100644 --- a/.dotnet/src/Generated/Models/AssistantFileObject.cs +++ b/.dotnet/src/Generated/Models/AssistantFileObject.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -48,8 +48,8 @@ internal partial class AssistantFileObject /// or is null. internal AssistantFileObject(string id, DateTimeOffset createdAt, string assistantId) { - if (id is null) throw new ArgumentNullException(nameof(id)); - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + Argument.AssertNotNull(id, nameof(id)); + Argument.AssertNotNull(assistantId, nameof(assistantId)); Id = id; CreatedAt = createdAt; diff --git a/.dotnet/src/Generated/Models/AssistantObject.Serialization.cs b/.dotnet/src/Generated/Models/AssistantObject.Serialization.cs index 962670141..43e63517d 100644 --- a/.dotnet/src/Generated/Models/AssistantObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/AssistantObject.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -80,7 +82,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterO writer.WriteStringValue(item); } writer.WriteEndArray(); - if (Metadata != null && OptionalProperty.IsCollectionDefined(Metadata)) + if (Metadata != null && Optional.IsCollectionDefined(Metadata)) { writer.WritePropertyName("metadata"u8); writer.WriteStartObject(); @@ -228,7 +230,7 @@ internal static AssistantObject DeserializeAssistantObject(JsonElement element, { if (property.Value.ValueKind == JsonValueKind.Null) { - metadata = new OptionalDictionary(); + metadata = new ChangeTrackingDictionary(); continue; } Dictionary dictionary = new Dictionary(); @@ -245,7 +247,18 @@ internal static AssistantObject DeserializeAssistantObject(JsonElement element, } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new AssistantObject(id, @object, createdAt, name, description, model, instructions, tools, fileIds, metadata, serializedAdditionalRawData); + return new AssistantObject( + id, + @object, + createdAt, + name, + description, + model, + instructions, + tools, + fileIds, + metadata, + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -286,5 +299,13 @@ internal static AssistantObject FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeAssistantObject(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/AssistantObject.cs b/.dotnet/src/Generated/Models/AssistantObject.cs index d3b5e5e20..e5488b199 100644 --- a/.dotnet/src/Generated/Models/AssistantObject.cs +++ b/.dotnet/src/Generated/Models/AssistantObject.cs @@ -1,9 +1,9 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; +using OpenAI; namespace OpenAI.Internal.Models { @@ -70,10 +70,10 @@ internal partial class AssistantObject /// , , or is null. internal AssistantObject(string id, DateTimeOffset createdAt, string name, string description, string model, string instructions, IEnumerable tools, IEnumerable fileIds, IReadOnlyDictionary metadata) { - if (id is null) throw new ArgumentNullException(nameof(id)); - if (model is null) throw new ArgumentNullException(nameof(model)); - if (tools is null) throw new ArgumentNullException(nameof(tools)); - if (fileIds is null) throw new ArgumentNullException(nameof(fileIds)); + Argument.AssertNotNull(id, nameof(id)); + Argument.AssertNotNull(model, nameof(model)); + Argument.AssertNotNull(tools, nameof(tools)); + Argument.AssertNotNull(fileIds, nameof(fileIds)); Id = id; CreatedAt = createdAt; diff --git a/.dotnet/src/Generated/Models/AudioSegment.Serialization.cs b/.dotnet/src/Generated/Models/AudioSegment.Serialization.cs index e1641e3c0..a677ceb5d 100644 --- a/.dotnet/src/Generated/Models/AudioSegment.Serialization.cs +++ b/.dotnet/src/Generated/Models/AudioSegment.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -157,7 +159,18 @@ internal static AudioSegment DeserializeAudioSegment(JsonElement element, ModelR } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new AudioSegment(id, seek, start, end, text, tokens, temperature, avgLogprob, compressionRatio, noSpeechProb, serializedAdditionalRawData); + return new AudioSegment( + id, + seek, + start, + end, + text, + tokens, + temperature, + avgLogprob, + compressionRatio, + noSpeechProb, + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -198,5 +211,13 @@ internal static AudioSegment FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeAudioSegment(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/AudioSegment.cs b/.dotnet/src/Generated/Models/AudioSegment.cs index 0ee02b78b..ac48fd377 100644 --- a/.dotnet/src/Generated/Models/AudioSegment.cs +++ b/.dotnet/src/Generated/Models/AudioSegment.cs @@ -1,9 +1,9 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; +using OpenAI; namespace OpenAI.Internal.Models { @@ -62,8 +62,8 @@ internal partial class AudioSegment /// or is null. internal AudioSegment(long id, long seek, TimeSpan start, TimeSpan end, string text, IEnumerable tokens, double temperature, double avgLogprob, double compressionRatio, double noSpeechProb) { - if (text is null) throw new ArgumentNullException(nameof(text)); - if (tokens is null) throw new ArgumentNullException(nameof(tokens)); + Argument.AssertNotNull(text, nameof(text)); + Argument.AssertNotNull(tokens, nameof(tokens)); Id = id; Seek = seek; diff --git a/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.Serialization.cs index 639a83a94..4ca6b989f 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -116,5 +118,13 @@ internal static ChatCompletionFunctionCallOption FromResponse(PipelineResponse r using var document = JsonDocument.Parse(response.Content); return DeserializeChatCompletionFunctionCallOption(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.cs b/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.cs index 148eb7588..cda44802a 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionFunctionCallOption.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -49,7 +49,7 @@ internal partial class ChatCompletionFunctionCallOption /// is null. public ChatCompletionFunctionCallOption(string name) { - if (name is null) throw new ArgumentNullException(nameof(name)); + Argument.AssertNotNull(name, nameof(name)); Name = name; } diff --git a/.dotnet/src/Generated/Models/ChatCompletionFunctions.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionFunctions.Serialization.cs index af8f82426..f638fd9cf 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionFunctions.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionFunctions.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -19,14 +21,14 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReade } writer.WriteStartObject(); - if (OptionalProperty.IsDefined(Description)) + if (Optional.IsDefined(Description)) { writer.WritePropertyName("description"u8); writer.WriteStringValue(Description); } writer.WritePropertyName("name"u8); writer.WriteStringValue(Name); - if (OptionalProperty.IsDefined(Parameters)) + if (Optional.IsDefined(Parameters)) { writer.WritePropertyName("parameters"u8); writer.WriteObjectValue(Parameters); @@ -69,9 +71,9 @@ internal static ChatCompletionFunctions DeserializeChatCompletionFunctions(JsonE { return null; } - OptionalProperty description = default; + string description = default; string name = default; - OptionalProperty parameters = default; + FunctionParameters parameters = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -92,7 +94,7 @@ internal static ChatCompletionFunctions DeserializeChatCompletionFunctions(JsonE { continue; } - parameters = FunctionParameters.DeserializeFunctionParameters(property.Value); + parameters = FunctionParameters.DeserializeFunctionParameters(property.Value, options); continue; } if (options.Format != "W") @@ -101,7 +103,7 @@ internal static ChatCompletionFunctions DeserializeChatCompletionFunctions(JsonE } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new ChatCompletionFunctions(description.Value, name, parameters.Value, serializedAdditionalRawData); + return new ChatCompletionFunctions(description, name, parameters, serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -142,5 +144,13 @@ internal static ChatCompletionFunctions FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeChatCompletionFunctions(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ChatCompletionFunctions.cs b/.dotnet/src/Generated/Models/ChatCompletionFunctions.cs index a8f409a52..b955e356d 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionFunctions.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionFunctions.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -50,7 +50,7 @@ internal partial class ChatCompletionFunctions /// is null. public ChatCompletionFunctions(string name) { - if (name is null) throw new ArgumentNullException(nameof(name)); + Argument.AssertNotNull(name, nameof(name)); Name = name; } diff --git a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.Serialization.cs index 71b3260cc..ec80b0cb1 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -82,7 +84,7 @@ internal static ChatCompletionMessageToolCall DeserializeChatCompletionMessageTo } if (property.NameEquals("function"u8)) { - function = ChatCompletionMessageToolCallFunction.DeserializeChatCompletionMessageToolCallFunction(property.Value); + function = ChatCompletionMessageToolCallFunction.DeserializeChatCompletionMessageToolCallFunction(property.Value, options); continue; } if (options.Format != "W") @@ -132,5 +134,13 @@ internal static ChatCompletionMessageToolCall FromResponse(PipelineResponse resp using var document = JsonDocument.Parse(response.Content); return DeserializeChatCompletionMessageToolCall(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.cs b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.cs index dc5ffd9d0..b2757dca1 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCall.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -47,8 +47,8 @@ internal partial class ChatCompletionMessageToolCall /// or is null. public ChatCompletionMessageToolCall(string id, ChatCompletionMessageToolCallFunction function) { - if (id is null) throw new ArgumentNullException(nameof(id)); - if (function is null) throw new ArgumentNullException(nameof(function)); + Argument.AssertNotNull(id, nameof(id)); + Argument.AssertNotNull(function, nameof(function)); Id = id; Function = function; diff --git a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.Serialization.cs index e9a8bf6c1..8ffbd2090 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -124,5 +126,13 @@ internal static ChatCompletionMessageToolCallFunction FromResponse(PipelineRespo using var document = JsonDocument.Parse(response.Content); return DeserializeChatCompletionMessageToolCallFunction(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.cs b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.cs index fa5776ea0..926277164 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionMessageToolCallFunction.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -51,8 +51,8 @@ internal partial class ChatCompletionMessageToolCallFunction /// or is null. public ChatCompletionMessageToolCallFunction(string name, string arguments) { - if (name is null) throw new ArgumentNullException(nameof(name)); - if (arguments is null) throw new ArgumentNullException(nameof(arguments)); + Argument.AssertNotNull(name, nameof(name)); + Argument.AssertNotNull(arguments, nameof(arguments)); Name = name; Arguments = arguments; diff --git a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.Serialization.cs index d4a77ea78..765cdef78 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -74,7 +76,7 @@ internal static ChatCompletionNamedToolChoice DeserializeChatCompletionNamedTool } if (property.NameEquals("function"u8)) { - function = ChatCompletionNamedToolChoiceFunction.DeserializeChatCompletionNamedToolChoiceFunction(property.Value); + function = ChatCompletionNamedToolChoiceFunction.DeserializeChatCompletionNamedToolChoiceFunction(property.Value, options); continue; } if (options.Format != "W") @@ -124,5 +126,13 @@ internal static ChatCompletionNamedToolChoice FromResponse(PipelineResponse resp using var document = JsonDocument.Parse(response.Content); return DeserializeChatCompletionNamedToolChoice(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.cs b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.cs index 149097e23..bbc4a9013 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoice.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -46,7 +46,7 @@ internal partial class ChatCompletionNamedToolChoice /// is null. public ChatCompletionNamedToolChoice(ChatCompletionNamedToolChoiceFunction function) { - if (function is null) throw new ArgumentNullException(nameof(function)); + Argument.AssertNotNull(function, nameof(function)); Function = function; } diff --git a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.Serialization.cs index b85f015d9..9773625c1 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -116,5 +118,13 @@ internal static ChatCompletionNamedToolChoiceFunction FromResponse(PipelineRespo using var document = JsonDocument.Parse(response.Content); return DeserializeChatCompletionNamedToolChoiceFunction(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.cs b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.cs index 520def419..d040031c5 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionNamedToolChoiceFunction.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -46,7 +46,7 @@ internal partial class ChatCompletionNamedToolChoiceFunction /// is null. public ChatCompletionNamedToolChoiceFunction(string name) { - if (name is null) throw new ArgumentNullException(nameof(name)); + Argument.AssertNotNull(name, nameof(name)); Name = name; } diff --git a/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.Serialization.cs index b2b4ee706..79e67b36a 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -28,7 +30,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, Mode { writer.WriteNull("content"); } - if (OptionalProperty.IsCollectionDefined(ToolCalls)) + if (Optional.IsCollectionDefined(ToolCalls)) { writer.WritePropertyName("tool_calls"u8); writer.WriteStartArray(); @@ -40,7 +42,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, Mode } writer.WritePropertyName("role"u8); writer.WriteStringValue(Role.ToString()); - if (OptionalProperty.IsDefined(FunctionCall)) + if (Optional.IsDefined(FunctionCall)) { writer.WritePropertyName("function_call"u8); writer.WriteObjectValue(FunctionCall); @@ -84,9 +86,9 @@ internal static ChatCompletionResponseMessage DeserializeChatCompletionResponseM return null; } string content = default; - OptionalProperty> toolCalls = default; + IReadOnlyList toolCalls = default; ChatCompletionResponseMessageRole role = default; - OptionalProperty functionCall = default; + ChatCompletionResponseMessageFunctionCall functionCall = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -110,7 +112,7 @@ internal static ChatCompletionResponseMessage DeserializeChatCompletionResponseM List array = new List(); foreach (var item in property.Value.EnumerateArray()) { - array.Add(ChatCompletionMessageToolCall.DeserializeChatCompletionMessageToolCall(item)); + array.Add(ChatCompletionMessageToolCall.DeserializeChatCompletionMessageToolCall(item, options)); } toolCalls = array; continue; @@ -126,7 +128,7 @@ internal static ChatCompletionResponseMessage DeserializeChatCompletionResponseM { continue; } - functionCall = ChatCompletionResponseMessageFunctionCall.DeserializeChatCompletionResponseMessageFunctionCall(property.Value); + functionCall = ChatCompletionResponseMessageFunctionCall.DeserializeChatCompletionResponseMessageFunctionCall(property.Value, options); continue; } if (options.Format != "W") @@ -135,7 +137,7 @@ internal static ChatCompletionResponseMessage DeserializeChatCompletionResponseM } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new ChatCompletionResponseMessage(content, OptionalProperty.ToList(toolCalls), role, functionCall.Value, serializedAdditionalRawData); + return new ChatCompletionResponseMessage(content, toolCalls ?? new ChangeTrackingList(), role, functionCall, serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -176,5 +178,13 @@ internal static ChatCompletionResponseMessage FromResponse(PipelineResponse resp using var document = JsonDocument.Parse(response.Content); return DeserializeChatCompletionResponseMessage(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.cs b/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.cs index 27bcffd13..f67c54a22 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionResponseMessage.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -46,7 +46,7 @@ internal partial class ChatCompletionResponseMessage internal ChatCompletionResponseMessage(string content) { Content = content; - ToolCalls = new OptionalList(); + ToolCalls = new ChangeTrackingList(); } /// Initializes a new instance of . diff --git a/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.Serialization.cs index 5b55a6990..41fdad1bb 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -124,5 +126,13 @@ internal static ChatCompletionResponseMessageFunctionCall FromResponse(PipelineR using var document = JsonDocument.Parse(response.Content); return DeserializeChatCompletionResponseMessageFunctionCall(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.cs b/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.cs index e788deaeb..5e645efab 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionResponseMessageFunctionCall.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -51,8 +51,8 @@ internal partial class ChatCompletionResponseMessageFunctionCall /// or is null. internal ChatCompletionResponseMessageFunctionCall(string arguments, string name) { - if (arguments is null) throw new ArgumentNullException(nameof(arguments)); - if (name is null) throw new ArgumentNullException(nameof(name)); + Argument.AssertNotNull(arguments, nameof(arguments)); + Argument.AssertNotNull(name, nameof(name)); Arguments = arguments; Name = name; diff --git a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.Serialization.cs index cbb9356bb..10b2919c1 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -23,7 +25,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelRe writer.WriteStringValue(Token); writer.WritePropertyName("logprob"u8); writer.WriteNumberValue(Logprob); - if (Bytes != null && OptionalProperty.IsCollectionDefined(Bytes)) + if (Bytes != null && Optional.IsCollectionDefined(Bytes)) { writer.WritePropertyName("bytes"u8); writer.WriteStartArray(); @@ -104,7 +106,7 @@ internal static ChatCompletionTokenLogprob DeserializeChatCompletionTokenLogprob { if (property.Value.ValueKind == JsonValueKind.Null) { - bytes = new OptionalList(); + bytes = new ChangeTrackingList(); continue; } List array = new List(); @@ -120,7 +122,7 @@ internal static ChatCompletionTokenLogprob DeserializeChatCompletionTokenLogprob List array = new List(); foreach (var item in property.Value.EnumerateArray()) { - array.Add(ChatCompletionTokenLogprobTopLogprob.DeserializeChatCompletionTokenLogprobTopLogprob(item)); + array.Add(ChatCompletionTokenLogprobTopLogprob.DeserializeChatCompletionTokenLogprobTopLogprob(item, options)); } topLogprobs = array; continue; @@ -172,5 +174,13 @@ internal static ChatCompletionTokenLogprob FromResponse(PipelineResponse respons using var document = JsonDocument.Parse(response.Content); return DeserializeChatCompletionTokenLogprob(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.cs b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.cs index 0a7ae0ba5..08702fac6 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprob.cs @@ -1,9 +1,9 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; +using OpenAI; namespace OpenAI.Internal.Models { @@ -58,8 +58,8 @@ internal partial class ChatCompletionTokenLogprob /// or is null. internal ChatCompletionTokenLogprob(string token, double logprob, IEnumerable bytes, IEnumerable topLogprobs) { - if (token is null) throw new ArgumentNullException(nameof(token)); - if (topLogprobs is null) throw new ArgumentNullException(nameof(topLogprobs)); + Argument.AssertNotNull(token, nameof(token)); + Argument.AssertNotNull(topLogprobs, nameof(topLogprobs)); Token = token; Logprob = logprob; diff --git a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.Serialization.cs index 7f84c1bca..f8182e28c 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -23,7 +25,7 @@ void IJsonModel.Write(Utf8JsonWriter write writer.WriteStringValue(Token); writer.WritePropertyName("logprob"u8); writer.WriteNumberValue(Logprob); - if (Bytes != null && OptionalProperty.IsCollectionDefined(Bytes)) + if (Bytes != null && Optional.IsCollectionDefined(Bytes)) { writer.WritePropertyName("bytes"u8); writer.WriteStartArray(); @@ -96,7 +98,7 @@ internal static ChatCompletionTokenLogprobTopLogprob DeserializeChatCompletionTo { if (property.Value.ValueKind == JsonValueKind.Null) { - bytes = new OptionalList(); + bytes = new ChangeTrackingList(); continue; } List array = new List(); @@ -154,5 +156,13 @@ internal static ChatCompletionTokenLogprobTopLogprob FromResponse(PipelineRespon using var document = JsonDocument.Parse(response.Content); return DeserializeChatCompletionTokenLogprobTopLogprob(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.cs b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.cs index 74a42012a..2fbfbdfa1 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionTokenLogprobTopLogprob.cs @@ -1,9 +1,9 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; +using OpenAI; namespace OpenAI.Internal.Models { @@ -54,7 +54,7 @@ internal partial class ChatCompletionTokenLogprobTopLogprob /// is null. internal ChatCompletionTokenLogprobTopLogprob(string token, double logprob, IEnumerable bytes) { - if (token is null) throw new ArgumentNullException(nameof(token)); + Argument.AssertNotNull(token, nameof(token)); Token = token; Logprob = logprob; diff --git a/.dotnet/src/Generated/Models/ChatCompletionTool.Serialization.cs b/.dotnet/src/Generated/Models/ChatCompletionTool.Serialization.cs index cb99d68c8..7a0a7cd27 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionTool.Serialization.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionTool.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -74,7 +76,7 @@ internal static ChatCompletionTool DeserializeChatCompletionTool(JsonElement ele } if (property.NameEquals("function"u8)) { - function = FunctionObject.DeserializeFunctionObject(property.Value); + function = FunctionObject.DeserializeFunctionObject(property.Value, options); continue; } if (options.Format != "W") @@ -124,5 +126,13 @@ internal static ChatCompletionTool FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeChatCompletionTool(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ChatCompletionTool.cs b/.dotnet/src/Generated/Models/ChatCompletionTool.cs index 8edef4914..e8c98d082 100644 --- a/.dotnet/src/Generated/Models/ChatCompletionTool.cs +++ b/.dotnet/src/Generated/Models/ChatCompletionTool.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -46,7 +46,7 @@ internal partial class ChatCompletionTool /// is null. public ChatCompletionTool(FunctionObject function) { - if (function is null) throw new ArgumentNullException(nameof(function)); + Argument.AssertNotNull(function, nameof(function)); Function = function; } diff --git a/.dotnet/src/Generated/Models/CompletionUsage.Serialization.cs b/.dotnet/src/Generated/Models/CompletionUsage.Serialization.cs index 9d53d9f78..9c61687cb 100644 --- a/.dotnet/src/Generated/Models/CompletionUsage.Serialization.cs +++ b/.dotnet/src/Generated/Models/CompletionUsage.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -132,5 +134,13 @@ internal static CompletionUsage FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCompletionUsage(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateAssistantFileRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateAssistantFileRequest.Serialization.cs index e3a752244..a407b2f62 100644 --- a/.dotnet/src/Generated/Models/CreateAssistantFileRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateAssistantFileRequest.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -116,5 +118,13 @@ internal static CreateAssistantFileRequest FromResponse(PipelineResponse respons using var document = JsonDocument.Parse(response.Content); return DeserializeCreateAssistantFileRequest(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateAssistantFileRequest.cs b/.dotnet/src/Generated/Models/CreateAssistantFileRequest.cs index be3485d43..ce3571023 100644 --- a/.dotnet/src/Generated/Models/CreateAssistantFileRequest.cs +++ b/.dotnet/src/Generated/Models/CreateAssistantFileRequest.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -49,7 +49,7 @@ internal partial class CreateAssistantFileRequest /// is null. public CreateAssistantFileRequest(string fileId) { - if (fileId is null) throw new ArgumentNullException(nameof(fileId)); + Argument.AssertNotNull(fileId, nameof(fileId)); FileId = fileId; } diff --git a/.dotnet/src/Generated/Models/CreateAssistantRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateAssistantRequest.Serialization.cs index 6c7a3d0b8..960844426 100644 --- a/.dotnet/src/Generated/Models/CreateAssistantRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateAssistantRequest.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -21,7 +23,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReader writer.WriteStartObject(); writer.WritePropertyName("model"u8); writer.WriteStringValue(Model); - if (OptionalProperty.IsDefined(Name)) + if (Optional.IsDefined(Name)) { if (Name != null) { @@ -33,7 +35,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReader writer.WriteNull("name"); } } - if (OptionalProperty.IsDefined(Description)) + if (Optional.IsDefined(Description)) { if (Description != null) { @@ -45,7 +47,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReader writer.WriteNull("description"); } } - if (OptionalProperty.IsDefined(Instructions)) + if (Optional.IsDefined(Instructions)) { if (Instructions != null) { @@ -57,7 +59,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReader writer.WriteNull("instructions"); } } - if (OptionalProperty.IsCollectionDefined(Tools)) + if (Optional.IsCollectionDefined(Tools)) { writer.WritePropertyName("tools"u8); writer.WriteStartArray(); @@ -79,7 +81,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReader } writer.WriteEndArray(); } - if (OptionalProperty.IsCollectionDefined(FileIds)) + if (Optional.IsCollectionDefined(FileIds)) { writer.WritePropertyName("file_ids"u8); writer.WriteStartArray(); @@ -89,7 +91,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReader } writer.WriteEndArray(); } - if (OptionalProperty.IsCollectionDefined(Metadata)) + if (Optional.IsCollectionDefined(Metadata)) { if (Metadata != null) { @@ -146,12 +148,12 @@ internal static CreateAssistantRequest DeserializeCreateAssistantRequest(JsonEle return null; } string model = default; - OptionalProperty name = default; - OptionalProperty description = default; - OptionalProperty instructions = default; - OptionalProperty> tools = default; - OptionalProperty> fileIds = default; - OptionalProperty> metadata = default; + string name = default; + string description = default; + string instructions = default; + IList tools = default; + IList fileIds = default; + IDictionary metadata = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -246,7 +248,15 @@ internal static CreateAssistantRequest DeserializeCreateAssistantRequest(JsonEle } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateAssistantRequest(model, name.Value, description.Value, instructions.Value, OptionalProperty.ToList(tools), OptionalProperty.ToList(fileIds), OptionalProperty.ToDictionary(metadata), serializedAdditionalRawData); + return new CreateAssistantRequest( + model, + name, + description, + instructions, + tools ?? new ChangeTrackingList(), + fileIds ?? new ChangeTrackingList(), + metadata ?? new ChangeTrackingDictionary(), + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -287,5 +297,13 @@ internal static CreateAssistantRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateAssistantRequest(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateAssistantRequest.cs b/.dotnet/src/Generated/Models/CreateAssistantRequest.cs index 6e08eb6ac..750f6db64 100644 --- a/.dotnet/src/Generated/Models/CreateAssistantRequest.cs +++ b/.dotnet/src/Generated/Models/CreateAssistantRequest.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -50,12 +50,12 @@ internal partial class CreateAssistantRequest /// is null. public CreateAssistantRequest(string model) { - if (model is null) throw new ArgumentNullException(nameof(model)); + Argument.AssertNotNull(model, nameof(model)); Model = model; - Tools = new OptionalList(); - FileIds = new OptionalList(); - Metadata = new OptionalDictionary(); + Tools = new ChangeTrackingList(); + FileIds = new ChangeTrackingList(); + Metadata = new ChangeTrackingDictionary(); } /// Initializes a new instance of . diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateChatCompletionRequest.Serialization.cs index dbd787e7b..749771a7c 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionRequest.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -40,7 +42,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelR writer.WriteEndArray(); writer.WritePropertyName("model"u8); writer.WriteStringValue(Model.ToString()); - if (OptionalProperty.IsDefined(FrequencyPenalty)) + if (Optional.IsDefined(FrequencyPenalty)) { if (FrequencyPenalty != null) { @@ -52,7 +54,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelR writer.WriteNull("frequency_penalty"); } } - if (OptionalProperty.IsCollectionDefined(LogitBias)) + if (Optional.IsCollectionDefined(LogitBias)) { if (LogitBias != null) { @@ -70,7 +72,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelR writer.WriteNull("logit_bias"); } } - if (OptionalProperty.IsDefined(Logprobs)) + if (Optional.IsDefined(Logprobs)) { if (Logprobs != null) { @@ -82,7 +84,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelR writer.WriteNull("logprobs"); } } - if (OptionalProperty.IsDefined(TopLogprobs)) + if (Optional.IsDefined(TopLogprobs)) { if (TopLogprobs != null) { @@ -94,7 +96,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelR writer.WriteNull("top_logprobs"); } } - if (OptionalProperty.IsDefined(MaxTokens)) + if (Optional.IsDefined(MaxTokens)) { if (MaxTokens != null) { @@ -106,7 +108,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelR writer.WriteNull("max_tokens"); } } - if (OptionalProperty.IsDefined(N)) + if (Optional.IsDefined(N)) { if (N != null) { @@ -118,7 +120,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelR writer.WriteNull("n"); } } - if (OptionalProperty.IsDefined(PresencePenalty)) + if (Optional.IsDefined(PresencePenalty)) { if (PresencePenalty != null) { @@ -130,12 +132,12 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelR writer.WriteNull("presence_penalty"); } } - if (OptionalProperty.IsDefined(ResponseFormat)) + if (Optional.IsDefined(ResponseFormat)) { writer.WritePropertyName("response_format"u8); writer.WriteObjectValue(ResponseFormat); } - if (OptionalProperty.IsDefined(Seed)) + if (Optional.IsDefined(Seed)) { if (Seed != null) { @@ -147,7 +149,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelR writer.WriteNull("seed"); } } - if (OptionalProperty.IsDefined(Stop)) + if (Optional.IsDefined(Stop)) { if (Stop != null) { @@ -166,7 +168,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelR writer.WriteNull("stop"); } } - if (OptionalProperty.IsDefined(Stream)) + if (Optional.IsDefined(Stream)) { if (Stream != null) { @@ -178,7 +180,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelR writer.WriteNull("stream"); } } - if (OptionalProperty.IsDefined(Temperature)) + if (Optional.IsDefined(Temperature)) { if (Temperature != null) { @@ -190,7 +192,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelR writer.WriteNull("temperature"); } } - if (OptionalProperty.IsDefined(TopP)) + if (Optional.IsDefined(TopP)) { if (TopP != null) { @@ -202,7 +204,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelR writer.WriteNull("top_p"); } } - if (OptionalProperty.IsCollectionDefined(Tools)) + if (Optional.IsCollectionDefined(Tools)) { writer.WritePropertyName("tools"u8); writer.WriteStartArray(); @@ -212,7 +214,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelR } writer.WriteEndArray(); } - if (OptionalProperty.IsDefined(ToolChoice)) + if (Optional.IsDefined(ToolChoice)) { writer.WritePropertyName("tool_choice"u8); #if NET6_0_OR_GREATER @@ -224,12 +226,12 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelR } #endif } - if (OptionalProperty.IsDefined(User)) + if (Optional.IsDefined(User)) { writer.WritePropertyName("user"u8); writer.WriteStringValue(User); } - if (OptionalProperty.IsDefined(FunctionCall)) + if (Optional.IsDefined(FunctionCall)) { writer.WritePropertyName("function_call"u8); #if NET6_0_OR_GREATER @@ -241,7 +243,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelR } #endif } - if (OptionalProperty.IsCollectionDefined(Functions)) + if (Optional.IsCollectionDefined(Functions)) { writer.WritePropertyName("functions"u8); writer.WriteStartArray(); @@ -291,24 +293,24 @@ internal static CreateChatCompletionRequest DeserializeCreateChatCompletionReque } IList messages = default; CreateChatCompletionRequestModel model = default; - OptionalProperty frequencyPenalty = default; - OptionalProperty> logitBias = default; - OptionalProperty logprobs = default; - OptionalProperty topLogprobs = default; - OptionalProperty maxTokens = default; - OptionalProperty n = default; - OptionalProperty presencePenalty = default; - OptionalProperty responseFormat = default; - OptionalProperty seed = default; - OptionalProperty stop = default; - OptionalProperty stream = default; - OptionalProperty temperature = default; - OptionalProperty topP = default; - OptionalProperty> tools = default; - OptionalProperty toolChoice = default; - OptionalProperty user = default; - OptionalProperty functionCall = default; - OptionalProperty> functions = default; + double? frequencyPenalty = default; + IDictionary logitBias = default; + bool? logprobs = default; + long? topLogprobs = default; + long? maxTokens = default; + long? n = default; + double? presencePenalty = default; + CreateChatCompletionRequestResponseFormat responseFormat = default; + long? seed = default; + BinaryData stop = default; + bool? stream = default; + double? temperature = default; + double? topP = default; + IList tools = default; + BinaryData toolChoice = default; + string user = default; + BinaryData functionCall = default; + IList functions = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -415,7 +417,7 @@ internal static CreateChatCompletionRequest DeserializeCreateChatCompletionReque { continue; } - responseFormat = CreateChatCompletionRequestResponseFormat.DeserializeCreateChatCompletionRequestResponseFormat(property.Value); + responseFormat = CreateChatCompletionRequestResponseFormat.DeserializeCreateChatCompletionRequestResponseFormat(property.Value, options); continue; } if (property.NameEquals("seed"u8)) @@ -477,7 +479,7 @@ internal static CreateChatCompletionRequest DeserializeCreateChatCompletionReque List array = new List(); foreach (var item in property.Value.EnumerateArray()) { - array.Add(ChatCompletionTool.DeserializeChatCompletionTool(item)); + array.Add(ChatCompletionTool.DeserializeChatCompletionTool(item, options)); } tools = array; continue; @@ -514,7 +516,7 @@ internal static CreateChatCompletionRequest DeserializeCreateChatCompletionReque List array = new List(); foreach (var item in property.Value.EnumerateArray()) { - array.Add(ChatCompletionFunctions.DeserializeChatCompletionFunctions(item)); + array.Add(ChatCompletionFunctions.DeserializeChatCompletionFunctions(item, options)); } functions = array; continue; @@ -525,7 +527,28 @@ internal static CreateChatCompletionRequest DeserializeCreateChatCompletionReque } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateChatCompletionRequest(messages, model, OptionalProperty.ToNullable(frequencyPenalty), OptionalProperty.ToDictionary(logitBias), OptionalProperty.ToNullable(logprobs), OptionalProperty.ToNullable(topLogprobs), OptionalProperty.ToNullable(maxTokens), OptionalProperty.ToNullable(n), OptionalProperty.ToNullable(presencePenalty), responseFormat.Value, OptionalProperty.ToNullable(seed), stop.Value, OptionalProperty.ToNullable(stream), OptionalProperty.ToNullable(temperature), OptionalProperty.ToNullable(topP), OptionalProperty.ToList(tools), toolChoice.Value, user.Value, functionCall.Value, OptionalProperty.ToList(functions), serializedAdditionalRawData); + return new CreateChatCompletionRequest( + messages, + model, + frequencyPenalty, + logitBias ?? new ChangeTrackingDictionary(), + logprobs, + topLogprobs, + maxTokens, + n, + presencePenalty, + responseFormat, + seed, + stop, + stream, + temperature, + topP, + tools ?? new ChangeTrackingList(), + toolChoice, + user, + functionCall, + functions ?? new ChangeTrackingList(), + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -566,5 +589,13 @@ internal static CreateChatCompletionRequest FromResponse(PipelineResponse respon using var document = JsonDocument.Parse(response.Content); return DeserializeCreateChatCompletionRequest(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionRequest.cs b/.dotnet/src/Generated/Models/CreateChatCompletionRequest.cs index 547e318d9..0cab891f8 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionRequest.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionRequest.cs @@ -1,9 +1,9 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; +using OpenAI; namespace OpenAI.Internal.Models { @@ -54,13 +54,13 @@ internal partial class CreateChatCompletionRequest /// is null. public CreateChatCompletionRequest(IEnumerable messages, CreateChatCompletionRequestModel model) { - if (messages is null) throw new ArgumentNullException(nameof(messages)); + Argument.AssertNotNull(messages, nameof(messages)); Messages = messages.ToList(); Model = model; - LogitBias = new OptionalDictionary(); - Tools = new OptionalList(); - Functions = new OptionalList(); + LogitBias = new ChangeTrackingDictionary(); + Tools = new ChangeTrackingList(); + Functions = new ChangeTrackingList(); } /// Initializes a new instance of . diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionRequestModel.cs b/.dotnet/src/Generated/Models/CreateChatCompletionRequestModel.cs index c15dcb757..a646ff7a2 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionRequestModel.cs @@ -5,7 +5,7 @@ namespace OpenAI.Internal.Models { - /// Enum for model in CreateChatCompletionRequest. + /// The CreateChatCompletionRequestModel. internal readonly partial struct CreateChatCompletionRequestModel : IEquatable { private readonly string _value; diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.Serialization.cs b/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.Serialization.cs index fd284f215..d33e61058 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionRequestResponseFormat.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -19,7 +21,7 @@ void IJsonModel.Write(Utf8JsonWriter } writer.WriteStartObject(); - if (OptionalProperty.IsDefined(Type)) + if (Optional.IsDefined(Type)) { writer.WritePropertyName("type"u8); writer.WriteStringValue(Type.Value.ToString()); @@ -62,7 +64,7 @@ internal static CreateChatCompletionRequestResponseFormat DeserializeCreateChatC { return null; } - OptionalProperty type = default; + CreateChatCompletionRequestResponseFormatType? type = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -82,7 +84,7 @@ internal static CreateChatCompletionRequestResponseFormat DeserializeCreateChatC } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateChatCompletionRequestResponseFormat(OptionalProperty.ToNullable(type), serializedAdditionalRawData); + return new CreateChatCompletionRequestResponseFormat(type, serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -123,5 +125,13 @@ internal static CreateChatCompletionRequestResponseFormat FromResponse(PipelineR using var document = JsonDocument.Parse(response.Content); return DeserializeCreateChatCompletionRequestResponseFormat(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponse.Serialization.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponse.Serialization.cs index 387a43069..3ec1f6602 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponse.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -32,14 +34,14 @@ void IJsonModel.Write(Utf8JsonWriter writer, Model writer.WriteNumberValue(Created, "U"); writer.WritePropertyName("model"u8); writer.WriteStringValue(Model); - if (OptionalProperty.IsDefined(SystemFingerprint)) + if (Optional.IsDefined(SystemFingerprint)) { writer.WritePropertyName("system_fingerprint"u8); writer.WriteStringValue(SystemFingerprint); } writer.WritePropertyName("object"u8); writer.WriteStringValue(Object.ToString()); - if (OptionalProperty.IsDefined(Usage)) + if (Optional.IsDefined(Usage)) { writer.WritePropertyName("usage"u8); writer.WriteObjectValue(Usage); @@ -86,9 +88,9 @@ internal static CreateChatCompletionResponse DeserializeCreateChatCompletionResp IReadOnlyList choices = default; DateTimeOffset created = default; string model = default; - OptionalProperty systemFingerprint = default; + string systemFingerprint = default; CreateChatCompletionResponseObject @object = default; - OptionalProperty usage = default; + CompletionUsage usage = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -103,7 +105,7 @@ internal static CreateChatCompletionResponse DeserializeCreateChatCompletionResp List array = new List(); foreach (var item in property.Value.EnumerateArray()) { - array.Add(CreateChatCompletionResponseChoice.DeserializeCreateChatCompletionResponseChoice(item)); + array.Add(CreateChatCompletionResponseChoice.DeserializeCreateChatCompletionResponseChoice(item, options)); } choices = array; continue; @@ -134,7 +136,7 @@ internal static CreateChatCompletionResponse DeserializeCreateChatCompletionResp { continue; } - usage = CompletionUsage.DeserializeCompletionUsage(property.Value); + usage = CompletionUsage.DeserializeCompletionUsage(property.Value, options); continue; } if (options.Format != "W") @@ -143,7 +145,15 @@ internal static CreateChatCompletionResponse DeserializeCreateChatCompletionResp } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateChatCompletionResponse(id, choices, created, model, systemFingerprint.Value, @object, usage.Value, serializedAdditionalRawData); + return new CreateChatCompletionResponse( + id, + choices, + created, + model, + systemFingerprint, + @object, + usage, + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -184,5 +194,13 @@ internal static CreateChatCompletionResponse FromResponse(PipelineResponse respo using var document = JsonDocument.Parse(response.Content); return DeserializeCreateChatCompletionResponse(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponse.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponse.cs index 1f44df4c1..6317c1996 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionResponse.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponse.cs @@ -1,9 +1,9 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; +using OpenAI; namespace OpenAI.Internal.Models { @@ -50,9 +50,9 @@ internal partial class CreateChatCompletionResponse /// , or is null. internal CreateChatCompletionResponse(string id, IEnumerable choices, DateTimeOffset created, string model) { - if (id is null) throw new ArgumentNullException(nameof(id)); - if (choices is null) throw new ArgumentNullException(nameof(choices)); - if (model is null) throw new ArgumentNullException(nameof(model)); + Argument.AssertNotNull(id, nameof(id)); + Argument.AssertNotNull(choices, nameof(choices)); + Argument.AssertNotNull(model, nameof(model)); Id = id; Choices = choices.ToList(); diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.Serialization.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.Serialization.cs index 850a633f8..8aff6522f 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -92,7 +94,7 @@ internal static CreateChatCompletionResponseChoice DeserializeCreateChatCompleti } if (property.NameEquals("message"u8)) { - message = ChatCompletionResponseMessage.DeserializeChatCompletionResponseMessage(property.Value); + message = ChatCompletionResponseMessage.DeserializeChatCompletionResponseMessage(property.Value, options); continue; } if (property.NameEquals("logprobs"u8)) @@ -102,7 +104,7 @@ internal static CreateChatCompletionResponseChoice DeserializeCreateChatCompleti logprobs = null; continue; } - logprobs = CreateChatCompletionResponseChoiceLogprobs.DeserializeCreateChatCompletionResponseChoiceLogprobs(property.Value); + logprobs = CreateChatCompletionResponseChoiceLogprobs.DeserializeCreateChatCompletionResponseChoiceLogprobs(property.Value, options); continue; } if (options.Format != "W") @@ -152,5 +154,13 @@ internal static CreateChatCompletionResponseChoice FromResponse(PipelineResponse using var document = JsonDocument.Parse(response.Content); return DeserializeCreateChatCompletionResponseChoice(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.cs index 5d127075b..374be9a9e 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoice.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -55,7 +55,7 @@ internal partial class CreateChatCompletionResponseChoice /// is null. internal CreateChatCompletionResponseChoice(CreateChatCompletionResponseChoiceFinishReason finishReason, long index, ChatCompletionResponseMessage message, CreateChatCompletionResponseChoiceLogprobs logprobs) { - if (message is null) throw new ArgumentNullException(nameof(message)); + Argument.AssertNotNull(message, nameof(message)); FinishReason = finishReason; Index = index; diff --git a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.Serialization.cs b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.Serialization.cs index 26c056edb..210e712c6 100644 --- a/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateChatCompletionResponseChoiceLogprobs.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -19,7 +21,7 @@ void IJsonModel.Write(Utf8JsonWriter } writer.WriteStartObject(); - if (Content != null && OptionalProperty.IsCollectionDefined(Content)) + if (Content != null && Optional.IsCollectionDefined(Content)) { writer.WritePropertyName("content"u8); writer.WriteStartArray(); @@ -80,13 +82,13 @@ internal static CreateChatCompletionResponseChoiceLogprobs DeserializeCreateChat { if (property.Value.ValueKind == JsonValueKind.Null) { - content = new OptionalList(); + content = new ChangeTrackingList(); continue; } List array = new List(); foreach (var item in property.Value.EnumerateArray()) { - array.Add(ChatCompletionTokenLogprob.DeserializeChatCompletionTokenLogprob(item)); + array.Add(ChatCompletionTokenLogprob.DeserializeChatCompletionTokenLogprob(item, options)); } content = array; continue; @@ -138,5 +140,13 @@ internal static CreateChatCompletionResponseChoiceLogprobs FromResponse(Pipeline using var document = JsonDocument.Parse(response.Content); return DeserializeCreateChatCompletionResponseChoiceLogprobs(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateCompletionRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateCompletionRequest.Serialization.cs index f5c3b1bb7..9b1c224b8 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionRequest.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -37,7 +39,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReade { writer.WriteNull("prompt"); } - if (OptionalProperty.IsDefined(BestOf)) + if (Optional.IsDefined(BestOf)) { if (BestOf != null) { @@ -49,7 +51,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReade writer.WriteNull("best_of"); } } - if (OptionalProperty.IsDefined(Echo)) + if (Optional.IsDefined(Echo)) { if (Echo != null) { @@ -61,7 +63,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReade writer.WriteNull("echo"); } } - if (OptionalProperty.IsDefined(FrequencyPenalty)) + if (Optional.IsDefined(FrequencyPenalty)) { if (FrequencyPenalty != null) { @@ -73,7 +75,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReade writer.WriteNull("frequency_penalty"); } } - if (OptionalProperty.IsCollectionDefined(LogitBias)) + if (Optional.IsCollectionDefined(LogitBias)) { if (LogitBias != null) { @@ -91,7 +93,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReade writer.WriteNull("logit_bias"); } } - if (OptionalProperty.IsDefined(Logprobs)) + if (Optional.IsDefined(Logprobs)) { if (Logprobs != null) { @@ -103,7 +105,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReade writer.WriteNull("logprobs"); } } - if (OptionalProperty.IsDefined(MaxTokens)) + if (Optional.IsDefined(MaxTokens)) { if (MaxTokens != null) { @@ -115,7 +117,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReade writer.WriteNull("max_tokens"); } } - if (OptionalProperty.IsDefined(N)) + if (Optional.IsDefined(N)) { if (N != null) { @@ -127,7 +129,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReade writer.WriteNull("n"); } } - if (OptionalProperty.IsDefined(PresencePenalty)) + if (Optional.IsDefined(PresencePenalty)) { if (PresencePenalty != null) { @@ -139,7 +141,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReade writer.WriteNull("presence_penalty"); } } - if (OptionalProperty.IsDefined(Seed)) + if (Optional.IsDefined(Seed)) { if (Seed != null) { @@ -151,7 +153,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReade writer.WriteNull("seed"); } } - if (OptionalProperty.IsDefined(Stop)) + if (Optional.IsDefined(Stop)) { if (Stop != null) { @@ -170,7 +172,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReade writer.WriteNull("stop"); } } - if (OptionalProperty.IsDefined(Stream)) + if (Optional.IsDefined(Stream)) { if (Stream != null) { @@ -182,7 +184,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReade writer.WriteNull("stream"); } } - if (OptionalProperty.IsDefined(Suffix)) + if (Optional.IsDefined(Suffix)) { if (Suffix != null) { @@ -194,7 +196,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReade writer.WriteNull("suffix"); } } - if (OptionalProperty.IsDefined(Temperature)) + if (Optional.IsDefined(Temperature)) { if (Temperature != null) { @@ -206,7 +208,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReade writer.WriteNull("temperature"); } } - if (OptionalProperty.IsDefined(TopP)) + if (Optional.IsDefined(TopP)) { if (TopP != null) { @@ -218,7 +220,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReade writer.WriteNull("top_p"); } } - if (OptionalProperty.IsDefined(User)) + if (Optional.IsDefined(User)) { writer.WritePropertyName("user"u8); writer.WriteStringValue(User); @@ -263,21 +265,21 @@ internal static CreateCompletionRequest DeserializeCreateCompletionRequest(JsonE } CreateCompletionRequestModel model = default; BinaryData prompt = default; - OptionalProperty bestOf = default; - OptionalProperty echo = default; - OptionalProperty frequencyPenalty = default; - OptionalProperty> logitBias = default; - OptionalProperty logprobs = default; - OptionalProperty maxTokens = default; - OptionalProperty n = default; - OptionalProperty presencePenalty = default; - OptionalProperty seed = default; - OptionalProperty stop = default; - OptionalProperty stream = default; - OptionalProperty suffix = default; - OptionalProperty temperature = default; - OptionalProperty topP = default; - OptionalProperty user = default; + long? bestOf = default; + bool? echo = default; + double? frequencyPenalty = default; + IDictionary logitBias = default; + long? logprobs = default; + long? maxTokens = default; + long? n = default; + double? presencePenalty = default; + long? seed = default; + BinaryData stop = default; + bool? stream = default; + string suffix = default; + double? temperature = default; + double? topP = default; + string user = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -452,7 +454,25 @@ internal static CreateCompletionRequest DeserializeCreateCompletionRequest(JsonE } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateCompletionRequest(model, prompt, OptionalProperty.ToNullable(bestOf), OptionalProperty.ToNullable(echo), OptionalProperty.ToNullable(frequencyPenalty), OptionalProperty.ToDictionary(logitBias), OptionalProperty.ToNullable(logprobs), OptionalProperty.ToNullable(maxTokens), OptionalProperty.ToNullable(n), OptionalProperty.ToNullable(presencePenalty), OptionalProperty.ToNullable(seed), stop.Value, OptionalProperty.ToNullable(stream), suffix.Value, OptionalProperty.ToNullable(temperature), OptionalProperty.ToNullable(topP), user.Value, serializedAdditionalRawData); + return new CreateCompletionRequest( + model, + prompt, + bestOf, + echo, + frequencyPenalty, + logitBias ?? new ChangeTrackingDictionary(), + logprobs, + maxTokens, + n, + presencePenalty, + seed, + stop, + stream, + suffix, + temperature, + topP, + user, + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -493,5 +513,13 @@ internal static CreateCompletionRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateCompletionRequest(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateCompletionRequest.cs b/.dotnet/src/Generated/Models/CreateCompletionRequest.cs index 4c439168a..9230b6acd 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionRequest.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionRequest.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -58,7 +58,7 @@ public CreateCompletionRequest(CreateCompletionRequestModel model, BinaryData pr { Model = model; Prompt = prompt; - LogitBias = new OptionalDictionary(); + LogitBias = new ChangeTrackingDictionary(); } /// Initializes a new instance of . diff --git a/.dotnet/src/Generated/Models/CreateCompletionRequestModel.cs b/.dotnet/src/Generated/Models/CreateCompletionRequestModel.cs index 784f43da8..80fa984b7 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionRequestModel.cs @@ -5,7 +5,7 @@ namespace OpenAI.Internal.Models { - /// Enum for model in CreateCompletionRequest. + /// The CreateCompletionRequestModel. internal readonly partial struct CreateCompletionRequestModel : IEquatable { private readonly string _value; diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponse.Serialization.cs b/.dotnet/src/Generated/Models/CreateCompletionResponse.Serialization.cs index 2a8633f00..3cd9d4097 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionResponse.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -32,14 +34,14 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelRead writer.WriteNumberValue(Created, "U"); writer.WritePropertyName("model"u8); writer.WriteStringValue(Model); - if (OptionalProperty.IsDefined(SystemFingerprint)) + if (Optional.IsDefined(SystemFingerprint)) { writer.WritePropertyName("system_fingerprint"u8); writer.WriteStringValue(SystemFingerprint); } writer.WritePropertyName("object"u8); writer.WriteStringValue(Object.ToString()); - if (OptionalProperty.IsDefined(Usage)) + if (Optional.IsDefined(Usage)) { writer.WritePropertyName("usage"u8); writer.WriteObjectValue(Usage); @@ -86,9 +88,9 @@ internal static CreateCompletionResponse DeserializeCreateCompletionResponse(Jso IReadOnlyList choices = default; DateTimeOffset created = default; string model = default; - OptionalProperty systemFingerprint = default; + string systemFingerprint = default; CreateCompletionResponseObject @object = default; - OptionalProperty usage = default; + CompletionUsage usage = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -103,7 +105,7 @@ internal static CreateCompletionResponse DeserializeCreateCompletionResponse(Jso List array = new List(); foreach (var item in property.Value.EnumerateArray()) { - array.Add(CreateCompletionResponseChoice.DeserializeCreateCompletionResponseChoice(item)); + array.Add(CreateCompletionResponseChoice.DeserializeCreateCompletionResponseChoice(item, options)); } choices = array; continue; @@ -134,7 +136,7 @@ internal static CreateCompletionResponse DeserializeCreateCompletionResponse(Jso { continue; } - usage = CompletionUsage.DeserializeCompletionUsage(property.Value); + usage = CompletionUsage.DeserializeCompletionUsage(property.Value, options); continue; } if (options.Format != "W") @@ -143,7 +145,15 @@ internal static CreateCompletionResponse DeserializeCreateCompletionResponse(Jso } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateCompletionResponse(id, choices, created, model, systemFingerprint.Value, @object, usage.Value, serializedAdditionalRawData); + return new CreateCompletionResponse( + id, + choices, + created, + model, + systemFingerprint, + @object, + usage, + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -184,5 +194,13 @@ internal static CreateCompletionResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateCompletionResponse(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponse.cs b/.dotnet/src/Generated/Models/CreateCompletionResponse.cs index a0bb30624..859c43a17 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionResponse.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionResponse.cs @@ -1,9 +1,9 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; +using OpenAI; namespace OpenAI.Internal.Models { @@ -53,9 +53,9 @@ internal partial class CreateCompletionResponse /// , or is null. internal CreateCompletionResponse(string id, IEnumerable choices, DateTimeOffset created, string model) { - if (id is null) throw new ArgumentNullException(nameof(id)); - if (choices is null) throw new ArgumentNullException(nameof(choices)); - if (model is null) throw new ArgumentNullException(nameof(model)); + Argument.AssertNotNull(id, nameof(id)); + Argument.AssertNotNull(choices, nameof(choices)); + Argument.AssertNotNull(model, nameof(model)); Id = id; Choices = choices.ToList(); diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.Serialization.cs b/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.Serialization.cs index b68a04694..285a557b4 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -97,7 +99,7 @@ internal static CreateCompletionResponseChoice DeserializeCreateCompletionRespon logprobs = null; continue; } - logprobs = CreateCompletionResponseChoiceLogprobs.DeserializeCreateCompletionResponseChoiceLogprobs(property.Value); + logprobs = CreateCompletionResponseChoiceLogprobs.DeserializeCreateCompletionResponseChoiceLogprobs(property.Value, options); continue; } if (property.NameEquals("finish_reason"u8)) @@ -152,5 +154,13 @@ internal static CreateCompletionResponseChoice FromResponse(PipelineResponse res using var document = JsonDocument.Parse(response.Content); return DeserializeCreateCompletionResponseChoice(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.cs b/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.cs index 1cf6b8df1..6eac09bfc 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionResponseChoice.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -55,7 +55,7 @@ internal partial class CreateCompletionResponseChoice /// is null. internal CreateCompletionResponseChoice(long index, string text, CreateCompletionResponseChoiceLogprobs logprobs, CreateCompletionResponseChoiceFinishReason finishReason) { - if (text is null) throw new ArgumentNullException(nameof(text)); + Argument.AssertNotNull(text, nameof(text)); Index = index; Text = text; diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.Serialization.cs b/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.Serialization.cs index 3658a0aab..7529ee39c 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -203,5 +205,13 @@ internal static CreateCompletionResponseChoiceLogprobs FromResponse(PipelineResp using var document = JsonDocument.Parse(response.Content); return DeserializeCreateCompletionResponseChoiceLogprobs(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.cs b/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.cs index be7a3a78c..7d1986025 100644 --- a/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.cs +++ b/.dotnet/src/Generated/Models/CreateCompletionResponseChoiceLogprobs.cs @@ -1,9 +1,9 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; +using OpenAI; namespace OpenAI.Internal.Models { @@ -50,10 +50,10 @@ internal partial class CreateCompletionResponseChoiceLogprobs /// , , or is null. internal CreateCompletionResponseChoiceLogprobs(IEnumerable tokens, IEnumerable tokenLogprobs, IEnumerable> topLogprobs, IEnumerable textOffset) { - if (tokens is null) throw new ArgumentNullException(nameof(tokens)); - if (tokenLogprobs is null) throw new ArgumentNullException(nameof(tokenLogprobs)); - if (topLogprobs is null) throw new ArgumentNullException(nameof(topLogprobs)); - if (textOffset is null) throw new ArgumentNullException(nameof(textOffset)); + Argument.AssertNotNull(tokens, nameof(tokens)); + Argument.AssertNotNull(tokenLogprobs, nameof(tokenLogprobs)); + Argument.AssertNotNull(topLogprobs, nameof(topLogprobs)); + Argument.AssertNotNull(textOffset, nameof(textOffset)); Tokens = tokens.ToList(); TokenLogprobs = tokenLogprobs.ToList(); diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateEmbeddingRequest.Serialization.cs index 1160d6206..3147e8bb6 100644 --- a/.dotnet/src/Generated/Models/CreateEmbeddingRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateEmbeddingRequest.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -30,17 +32,17 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReader #endif writer.WritePropertyName("model"u8); writer.WriteStringValue(Model.ToString()); - if (OptionalProperty.IsDefined(EncodingFormat)) + if (Optional.IsDefined(EncodingFormat)) { writer.WritePropertyName("encoding_format"u8); writer.WriteStringValue(EncodingFormat.Value.ToString()); } - if (OptionalProperty.IsDefined(Dimensions)) + if (Optional.IsDefined(Dimensions)) { writer.WritePropertyName("dimensions"u8); writer.WriteNumberValue(Dimensions.Value); } - if (OptionalProperty.IsDefined(User)) + if (Optional.IsDefined(User)) { writer.WritePropertyName("user"u8); writer.WriteStringValue(User); @@ -85,9 +87,9 @@ internal static CreateEmbeddingRequest DeserializeCreateEmbeddingRequest(JsonEle } BinaryData input = default; CreateEmbeddingRequestModel model = default; - OptionalProperty encodingFormat = default; - OptionalProperty dimensions = default; - OptionalProperty user = default; + CreateEmbeddingRequestEncodingFormat? encodingFormat = default; + long? dimensions = default; + string user = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -131,7 +133,13 @@ internal static CreateEmbeddingRequest DeserializeCreateEmbeddingRequest(JsonEle } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateEmbeddingRequest(input, model, OptionalProperty.ToNullable(encodingFormat), OptionalProperty.ToNullable(dimensions), user.Value, serializedAdditionalRawData); + return new CreateEmbeddingRequest( + input, + model, + encodingFormat, + dimensions, + user, + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -172,5 +180,13 @@ internal static CreateEmbeddingRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateEmbeddingRequest(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingRequest.cs b/.dotnet/src/Generated/Models/CreateEmbeddingRequest.cs index 7a649c374..67ee0828d 100644 --- a/.dotnet/src/Generated/Models/CreateEmbeddingRequest.cs +++ b/.dotnet/src/Generated/Models/CreateEmbeddingRequest.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -58,7 +58,7 @@ internal partial class CreateEmbeddingRequest /// is null. public CreateEmbeddingRequest(BinaryData input, CreateEmbeddingRequestModel model) { - if (input is null) throw new ArgumentNullException(nameof(input)); + Argument.AssertNotNull(input, nameof(input)); Input = input; Model = model; diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingRequestModel.cs b/.dotnet/src/Generated/Models/CreateEmbeddingRequestModel.cs index 8570f4947..98290654a 100644 --- a/.dotnet/src/Generated/Models/CreateEmbeddingRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateEmbeddingRequestModel.cs @@ -5,7 +5,7 @@ namespace OpenAI.Internal.Models { - /// Enum for model in CreateEmbeddingRequest. + /// The CreateEmbeddingRequestModel. internal readonly partial struct CreateEmbeddingRequestModel : IEquatable { private readonly string _value; diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingResponse.Serialization.cs b/.dotnet/src/Generated/Models/CreateEmbeddingResponse.Serialization.cs index 656eafe81..acdea6442 100644 --- a/.dotnet/src/Generated/Models/CreateEmbeddingResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateEmbeddingResponse.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -83,7 +85,7 @@ internal static CreateEmbeddingResponse DeserializeCreateEmbeddingResponse(JsonE List array = new List(); foreach (var item in property.Value.EnumerateArray()) { - array.Add(Embedding.DeserializeEmbedding(item)); + array.Add(Embedding.DeserializeEmbedding(item, options)); } data = array; continue; @@ -100,7 +102,7 @@ internal static CreateEmbeddingResponse DeserializeCreateEmbeddingResponse(JsonE } if (property.NameEquals("usage"u8)) { - usage = EmbeddingUsage.DeserializeEmbeddingUsage(property.Value); + usage = EmbeddingUsage.DeserializeEmbeddingUsage(property.Value, options); continue; } if (options.Format != "W") @@ -150,5 +152,13 @@ internal static CreateEmbeddingResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateEmbeddingResponse(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateEmbeddingResponse.cs b/.dotnet/src/Generated/Models/CreateEmbeddingResponse.cs index 7d4a885fc..f79cba4b7 100644 --- a/.dotnet/src/Generated/Models/CreateEmbeddingResponse.cs +++ b/.dotnet/src/Generated/Models/CreateEmbeddingResponse.cs @@ -1,9 +1,9 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; +using OpenAI; namespace OpenAI.Internal.Models { @@ -49,9 +49,9 @@ internal partial class CreateEmbeddingResponse /// , or is null. internal CreateEmbeddingResponse(IEnumerable data, string model, EmbeddingUsage usage) { - if (data is null) throw new ArgumentNullException(nameof(data)); - if (model is null) throw new ArgumentNullException(nameof(model)); - if (usage is null) throw new ArgumentNullException(nameof(usage)); + Argument.AssertNotNull(data, nameof(data)); + Argument.AssertNotNull(model, nameof(model)); + Argument.AssertNotNull(usage, nameof(usage)); Data = data.ToList(); Model = model; diff --git a/.dotnet/src/Generated/Models/CreateFileRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateFileRequest.Serialization.cs index 852eb6127..70700f22a 100644 --- a/.dotnet/src/Generated/Models/CreateFileRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateFileRequest.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -124,5 +126,13 @@ internal static CreateFileRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateFileRequest(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateFileRequest.cs b/.dotnet/src/Generated/Models/CreateFileRequest.cs index 6f39101d1..a11d75f03 100644 --- a/.dotnet/src/Generated/Models/CreateFileRequest.cs +++ b/.dotnet/src/Generated/Models/CreateFileRequest.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -52,7 +52,7 @@ internal partial class CreateFileRequest /// is null. public CreateFileRequest(BinaryData file, CreateFileRequestPurpose purpose) { - if (file is null) throw new ArgumentNullException(nameof(file)); + Argument.AssertNotNull(file, nameof(file)); File = file; Purpose = purpose; diff --git a/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.Serialization.cs index a7b573d95..ddfa6fb31 100644 --- a/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -23,12 +25,12 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelRe writer.WriteStringValue(Model.ToString()); writer.WritePropertyName("training_file"u8); writer.WriteStringValue(TrainingFile); - if (OptionalProperty.IsDefined(Hyperparameters)) + if (Optional.IsDefined(Hyperparameters)) { writer.WritePropertyName("hyperparameters"u8); writer.WriteObjectValue(Hyperparameters); } - if (OptionalProperty.IsDefined(Suffix)) + if (Optional.IsDefined(Suffix)) { if (Suffix != null) { @@ -40,7 +42,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelRe writer.WriteNull("suffix"); } } - if (OptionalProperty.IsDefined(ValidationFile)) + if (Optional.IsDefined(ValidationFile)) { if (ValidationFile != null) { @@ -92,9 +94,9 @@ internal static CreateFineTuningJobRequest DeserializeCreateFineTuningJobRequest } CreateFineTuningJobRequestModel model = default; string trainingFile = default; - OptionalProperty hyperparameters = default; - OptionalProperty suffix = default; - OptionalProperty validationFile = default; + CreateFineTuningJobRequestHyperparameters hyperparameters = default; + string suffix = default; + string validationFile = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -115,7 +117,7 @@ internal static CreateFineTuningJobRequest DeserializeCreateFineTuningJobRequest { continue; } - hyperparameters = CreateFineTuningJobRequestHyperparameters.DeserializeCreateFineTuningJobRequestHyperparameters(property.Value); + hyperparameters = CreateFineTuningJobRequestHyperparameters.DeserializeCreateFineTuningJobRequestHyperparameters(property.Value, options); continue; } if (property.NameEquals("suffix"u8)) @@ -144,7 +146,13 @@ internal static CreateFineTuningJobRequest DeserializeCreateFineTuningJobRequest } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateFineTuningJobRequest(model, trainingFile, hyperparameters.Value, suffix.Value, validationFile.Value, serializedAdditionalRawData); + return new CreateFineTuningJobRequest( + model, + trainingFile, + hyperparameters, + suffix, + validationFile, + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -185,5 +193,13 @@ internal static CreateFineTuningJobRequest FromResponse(PipelineResponse respons using var document = JsonDocument.Parse(response.Content); return DeserializeCreateFineTuningJobRequest(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.cs b/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.cs index 5cf2787d4..b7534d1b9 100644 --- a/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.cs +++ b/.dotnet/src/Generated/Models/CreateFineTuningJobRequest.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -59,7 +59,7 @@ internal partial class CreateFineTuningJobRequest /// is null. public CreateFineTuningJobRequest(CreateFineTuningJobRequestModel model, string trainingFile) { - if (trainingFile is null) throw new ArgumentNullException(nameof(trainingFile)); + Argument.AssertNotNull(trainingFile, nameof(trainingFile)); Model = model; TrainingFile = trainingFile; diff --git a/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.Serialization.cs b/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.Serialization.cs index 11f4a766b..ecf71a8e8 100644 --- a/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateFineTuningJobRequestHyperparameters.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -19,7 +21,7 @@ void IJsonModel.Write(Utf8JsonWriter } writer.WriteStartObject(); - if (OptionalProperty.IsDefined(BatchSize)) + if (Optional.IsDefined(BatchSize)) { writer.WritePropertyName("batch_size"u8); #if NET6_0_OR_GREATER @@ -31,7 +33,7 @@ void IJsonModel.Write(Utf8JsonWriter } #endif } - if (OptionalProperty.IsDefined(LearningRateMultiplier)) + if (Optional.IsDefined(LearningRateMultiplier)) { writer.WritePropertyName("learning_rate_multiplier"u8); #if NET6_0_OR_GREATER @@ -43,7 +45,7 @@ void IJsonModel.Write(Utf8JsonWriter } #endif } - if (OptionalProperty.IsDefined(NEpochs)) + if (Optional.IsDefined(NEpochs)) { writer.WritePropertyName("n_epochs"u8); #if NET6_0_OR_GREATER @@ -93,9 +95,9 @@ internal static CreateFineTuningJobRequestHyperparameters DeserializeCreateFineT { return null; } - OptionalProperty batchSize = default; - OptionalProperty learningRateMultiplier = default; - OptionalProperty nEpochs = default; + BinaryData batchSize = default; + BinaryData learningRateMultiplier = default; + BinaryData nEpochs = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -133,7 +135,7 @@ internal static CreateFineTuningJobRequestHyperparameters DeserializeCreateFineT } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateFineTuningJobRequestHyperparameters(batchSize.Value, learningRateMultiplier.Value, nEpochs.Value, serializedAdditionalRawData); + return new CreateFineTuningJobRequestHyperparameters(batchSize, learningRateMultiplier, nEpochs, serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -174,5 +176,13 @@ internal static CreateFineTuningJobRequestHyperparameters FromResponse(PipelineR using var document = JsonDocument.Parse(response.Content); return DeserializeCreateFineTuningJobRequestHyperparameters(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateFineTuningJobRequestModel.cs b/.dotnet/src/Generated/Models/CreateFineTuningJobRequestModel.cs index 670bdc0f5..1845aa01d 100644 --- a/.dotnet/src/Generated/Models/CreateFineTuningJobRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateFineTuningJobRequestModel.cs @@ -5,7 +5,7 @@ namespace OpenAI.Internal.Models { - /// Enum for model in CreateFineTuningJobRequest. + /// The CreateFineTuningJobRequestModel. internal readonly partial struct CreateFineTuningJobRequestModel : IEquatable { private readonly string _value; diff --git a/.dotnet/src/Generated/Models/CreateImageEditRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateImageEditRequest.Serialization.cs index 5da48765a..f08ba1064 100644 --- a/.dotnet/src/Generated/Models/CreateImageEditRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateImageEditRequest.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -23,17 +25,17 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReader writer.WriteBase64StringValue(Image.ToArray(), "D"); writer.WritePropertyName("prompt"u8); writer.WriteStringValue(Prompt); - if (OptionalProperty.IsDefined(Mask)) + if (Optional.IsDefined(Mask)) { writer.WritePropertyName("mask"u8); writer.WriteBase64StringValue(Mask.ToArray(), "D"); } - if (OptionalProperty.IsDefined(Model)) + if (Optional.IsDefined(Model)) { writer.WritePropertyName("model"u8); writer.WriteStringValue(Model.Value.ToString()); } - if (OptionalProperty.IsDefined(N)) + if (Optional.IsDefined(N)) { if (N != null) { @@ -45,17 +47,17 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReader writer.WriteNull("n"); } } - if (OptionalProperty.IsDefined(Size)) + if (Optional.IsDefined(Size)) { writer.WritePropertyName("size"u8); writer.WriteStringValue(Size.Value.ToString()); } - if (OptionalProperty.IsDefined(ResponseFormat)) + if (Optional.IsDefined(ResponseFormat)) { writer.WritePropertyName("response_format"u8); writer.WriteStringValue(ResponseFormat.Value.ToString()); } - if (OptionalProperty.IsDefined(User)) + if (Optional.IsDefined(User)) { writer.WritePropertyName("user"u8); writer.WriteStringValue(User); @@ -100,12 +102,12 @@ internal static CreateImageEditRequest DeserializeCreateImageEditRequest(JsonEle } BinaryData image = default; string prompt = default; - OptionalProperty mask = default; - OptionalProperty model = default; - OptionalProperty n = default; - OptionalProperty size = default; - OptionalProperty responseFormat = default; - OptionalProperty user = default; + BinaryData mask = default; + CreateImageEditRequestModel? model = default; + long? n = default; + CreateImageEditRequestSize? size = default; + CreateImageEditRequestResponseFormat? responseFormat = default; + string user = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -177,7 +179,16 @@ internal static CreateImageEditRequest DeserializeCreateImageEditRequest(JsonEle } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateImageEditRequest(image, prompt, mask.Value, OptionalProperty.ToNullable(model), OptionalProperty.ToNullable(n), OptionalProperty.ToNullable(size), OptionalProperty.ToNullable(responseFormat), user.Value, serializedAdditionalRawData); + return new CreateImageEditRequest( + image, + prompt, + mask, + model, + n, + size, + responseFormat, + user, + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -218,5 +229,13 @@ internal static CreateImageEditRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateImageEditRequest(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateImageEditRequest.cs b/.dotnet/src/Generated/Models/CreateImageEditRequest.cs index 136db1035..529c451fb 100644 --- a/.dotnet/src/Generated/Models/CreateImageEditRequest.cs +++ b/.dotnet/src/Generated/Models/CreateImageEditRequest.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -50,8 +50,8 @@ internal partial class CreateImageEditRequest /// or is null. public CreateImageEditRequest(BinaryData image, string prompt) { - if (image is null) throw new ArgumentNullException(nameof(image)); - if (prompt is null) throw new ArgumentNullException(nameof(prompt)); + Argument.AssertNotNull(image, nameof(image)); + Argument.AssertNotNull(prompt, nameof(prompt)); Image = image; Prompt = prompt; diff --git a/.dotnet/src/Generated/Models/CreateImageEditRequestModel.cs b/.dotnet/src/Generated/Models/CreateImageEditRequestModel.cs index 60e9057d2..0f06a6f24 100644 --- a/.dotnet/src/Generated/Models/CreateImageEditRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateImageEditRequestModel.cs @@ -5,7 +5,7 @@ namespace OpenAI.Internal.Models { - /// Enum for model in CreateImageEditRequest. + /// The CreateImageEditRequestModel. internal readonly partial struct CreateImageEditRequestModel : IEquatable { private readonly string _value; diff --git a/.dotnet/src/Generated/Models/CreateImageRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateImageRequest.Serialization.cs index b2f3758de..0450242da 100644 --- a/.dotnet/src/Generated/Models/CreateImageRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateImageRequest.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -21,12 +23,12 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWrit writer.WriteStartObject(); writer.WritePropertyName("prompt"u8); writer.WriteStringValue(Prompt); - if (OptionalProperty.IsDefined(Model)) + if (Optional.IsDefined(Model)) { writer.WritePropertyName("model"u8); writer.WriteStringValue(Model.Value.ToString()); } - if (OptionalProperty.IsDefined(N)) + if (Optional.IsDefined(N)) { if (N != null) { @@ -38,27 +40,27 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWrit writer.WriteNull("n"); } } - if (OptionalProperty.IsDefined(Quality)) + if (Optional.IsDefined(Quality)) { writer.WritePropertyName("quality"u8); writer.WriteStringValue(Quality.Value.ToString()); } - if (OptionalProperty.IsDefined(ResponseFormat)) + if (Optional.IsDefined(ResponseFormat)) { writer.WritePropertyName("response_format"u8); writer.WriteStringValue(ResponseFormat.Value.ToString()); } - if (OptionalProperty.IsDefined(Size)) + if (Optional.IsDefined(Size)) { writer.WritePropertyName("size"u8); writer.WriteStringValue(Size.Value.ToString()); } - if (OptionalProperty.IsDefined(Style)) + if (Optional.IsDefined(Style)) { writer.WritePropertyName("style"u8); writer.WriteStringValue(Style.Value.ToString()); } - if (OptionalProperty.IsDefined(User)) + if (Optional.IsDefined(User)) { writer.WritePropertyName("user"u8); writer.WriteStringValue(User); @@ -102,13 +104,13 @@ internal static CreateImageRequest DeserializeCreateImageRequest(JsonElement ele return null; } string prompt = default; - OptionalProperty model = default; - OptionalProperty n = default; - OptionalProperty quality = default; - OptionalProperty responseFormat = default; - OptionalProperty size = default; - OptionalProperty style = default; - OptionalProperty user = default; + CreateImageRequestModel? model = default; + long? n = default; + CreateImageRequestQuality? quality = default; + CreateImageRequestResponseFormat? responseFormat = default; + CreateImageRequestSize? size = default; + CreateImageRequestStyle? style = default; + string user = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -184,7 +186,16 @@ internal static CreateImageRequest DeserializeCreateImageRequest(JsonElement ele } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateImageRequest(prompt, OptionalProperty.ToNullable(model), OptionalProperty.ToNullable(n), OptionalProperty.ToNullable(quality), OptionalProperty.ToNullable(responseFormat), OptionalProperty.ToNullable(size), OptionalProperty.ToNullable(style), user.Value, serializedAdditionalRawData); + return new CreateImageRequest( + prompt, + model, + n, + quality, + responseFormat, + size, + style, + user, + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -225,5 +236,13 @@ internal static CreateImageRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateImageRequest(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateImageRequest.cs b/.dotnet/src/Generated/Models/CreateImageRequest.cs index 552a5e8a7..d0e1f19b6 100644 --- a/.dotnet/src/Generated/Models/CreateImageRequest.cs +++ b/.dotnet/src/Generated/Models/CreateImageRequest.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -49,7 +49,7 @@ internal partial class CreateImageRequest /// is null. public CreateImageRequest(string prompt) { - if (prompt is null) throw new ArgumentNullException(nameof(prompt)); + Argument.AssertNotNull(prompt, nameof(prompt)); Prompt = prompt; } diff --git a/.dotnet/src/Generated/Models/CreateImageRequestModel.cs b/.dotnet/src/Generated/Models/CreateImageRequestModel.cs index 6e8ad967e..f5226fa5b 100644 --- a/.dotnet/src/Generated/Models/CreateImageRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateImageRequestModel.cs @@ -5,7 +5,7 @@ namespace OpenAI.Internal.Models { - /// Enum for model in CreateImageRequest. + /// The CreateImageRequestModel. internal readonly partial struct CreateImageRequestModel : IEquatable { private readonly string _value; diff --git a/.dotnet/src/Generated/Models/CreateImageVariationRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateImageVariationRequest.Serialization.cs index 4c9d18ed2..50ff69ef6 100644 --- a/.dotnet/src/Generated/Models/CreateImageVariationRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateImageVariationRequest.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -21,12 +23,12 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelR writer.WriteStartObject(); writer.WritePropertyName("image"u8); writer.WriteBase64StringValue(Image.ToArray(), "D"); - if (OptionalProperty.IsDefined(Model)) + if (Optional.IsDefined(Model)) { writer.WritePropertyName("model"u8); writer.WriteStringValue(Model.Value.ToString()); } - if (OptionalProperty.IsDefined(N)) + if (Optional.IsDefined(N)) { if (N != null) { @@ -38,17 +40,17 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelR writer.WriteNull("n"); } } - if (OptionalProperty.IsDefined(ResponseFormat)) + if (Optional.IsDefined(ResponseFormat)) { writer.WritePropertyName("response_format"u8); writer.WriteStringValue(ResponseFormat.Value.ToString()); } - if (OptionalProperty.IsDefined(Size)) + if (Optional.IsDefined(Size)) { writer.WritePropertyName("size"u8); writer.WriteStringValue(Size.Value.ToString()); } - if (OptionalProperty.IsDefined(User)) + if (Optional.IsDefined(User)) { writer.WritePropertyName("user"u8); writer.WriteStringValue(User); @@ -92,11 +94,11 @@ internal static CreateImageVariationRequest DeserializeCreateImageVariationReque return null; } BinaryData image = default; - OptionalProperty model = default; - OptionalProperty n = default; - OptionalProperty responseFormat = default; - OptionalProperty size = default; - OptionalProperty user = default; + CreateImageVariationRequestModel? model = default; + long? n = default; + CreateImageVariationRequestResponseFormat? responseFormat = default; + CreateImageVariationRequestSize? size = default; + string user = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -154,7 +156,14 @@ internal static CreateImageVariationRequest DeserializeCreateImageVariationReque } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateImageVariationRequest(image, OptionalProperty.ToNullable(model), OptionalProperty.ToNullable(n), OptionalProperty.ToNullable(responseFormat), OptionalProperty.ToNullable(size), user.Value, serializedAdditionalRawData); + return new CreateImageVariationRequest( + image, + model, + n, + responseFormat, + size, + user, + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -195,5 +204,13 @@ internal static CreateImageVariationRequest FromResponse(PipelineResponse respon using var document = JsonDocument.Parse(response.Content); return DeserializeCreateImageVariationRequest(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateImageVariationRequest.cs b/.dotnet/src/Generated/Models/CreateImageVariationRequest.cs index 1986159f7..f96ae71aa 100644 --- a/.dotnet/src/Generated/Models/CreateImageVariationRequest.cs +++ b/.dotnet/src/Generated/Models/CreateImageVariationRequest.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -49,7 +49,7 @@ internal partial class CreateImageVariationRequest /// is null. public CreateImageVariationRequest(BinaryData image) { - if (image is null) throw new ArgumentNullException(nameof(image)); + Argument.AssertNotNull(image, nameof(image)); Image = image; } diff --git a/.dotnet/src/Generated/Models/CreateImageVariationRequestModel.cs b/.dotnet/src/Generated/Models/CreateImageVariationRequestModel.cs index 13ab94757..e7a09b2c7 100644 --- a/.dotnet/src/Generated/Models/CreateImageVariationRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateImageVariationRequestModel.cs @@ -5,7 +5,7 @@ namespace OpenAI.Internal.Models { - /// Enum for model in CreateImageVariationRequest. + /// The CreateImageVariationRequestModel. internal readonly partial struct CreateImageVariationRequestModel : IEquatable { private readonly string _value; diff --git a/.dotnet/src/Generated/Models/CreateMessageRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateMessageRequest.Serialization.cs index bc6fa6aea..447fa0a9c 100644 --- a/.dotnet/src/Generated/Models/CreateMessageRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateMessageRequest.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -23,7 +25,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWr writer.WriteStringValue(Role.ToString()); writer.WritePropertyName("content"u8); writer.WriteStringValue(Content); - if (OptionalProperty.IsCollectionDefined(FileIds)) + if (Optional.IsCollectionDefined(FileIds)) { writer.WritePropertyName("file_ids"u8); writer.WriteStartArray(); @@ -33,7 +35,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWr } writer.WriteEndArray(); } - if (OptionalProperty.IsCollectionDefined(Metadata)) + if (Optional.IsCollectionDefined(Metadata)) { if (Metadata != null) { @@ -91,8 +93,8 @@ internal static CreateMessageRequest DeserializeCreateMessageRequest(JsonElement } CreateMessageRequestRole role = default; string content = default; - OptionalProperty> fileIds = default; - OptionalProperty> metadata = default; + IList fileIds = default; + IDictionary metadata = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -141,7 +143,7 @@ internal static CreateMessageRequest DeserializeCreateMessageRequest(JsonElement } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateMessageRequest(role, content, OptionalProperty.ToList(fileIds), OptionalProperty.ToDictionary(metadata), serializedAdditionalRawData); + return new CreateMessageRequest(role, content, fileIds ?? new ChangeTrackingList(), metadata ?? new ChangeTrackingDictionary(), serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -182,5 +184,13 @@ internal static CreateMessageRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateMessageRequest(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateMessageRequest.cs b/.dotnet/src/Generated/Models/CreateMessageRequest.cs index 9a609327e..b08262e6b 100644 --- a/.dotnet/src/Generated/Models/CreateMessageRequest.cs +++ b/.dotnet/src/Generated/Models/CreateMessageRequest.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -46,11 +46,11 @@ internal partial class CreateMessageRequest /// is null. public CreateMessageRequest(string content) { - if (content is null) throw new ArgumentNullException(nameof(content)); + Argument.AssertNotNull(content, nameof(content)); Content = content; - FileIds = new OptionalList(); - Metadata = new OptionalDictionary(); + FileIds = new ChangeTrackingList(); + Metadata = new ChangeTrackingDictionary(); } /// Initializes a new instance of . diff --git a/.dotnet/src/Generated/Models/CreateModerationRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateModerationRequest.Serialization.cs index b131e485d..2379ab7a5 100644 --- a/.dotnet/src/Generated/Models/CreateModerationRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateModerationRequest.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -28,7 +30,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReade JsonSerializer.Serialize(writer, document.RootElement); } #endif - if (OptionalProperty.IsDefined(Model)) + if (Optional.IsDefined(Model)) { writer.WritePropertyName("model"u8); writer.WriteStringValue(Model.Value.ToString()); @@ -72,7 +74,7 @@ internal static CreateModerationRequest DeserializeCreateModerationRequest(JsonE return null; } BinaryData input = default; - OptionalProperty model = default; + CreateModerationRequestModel? model = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -97,7 +99,7 @@ internal static CreateModerationRequest DeserializeCreateModerationRequest(JsonE } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateModerationRequest(input, OptionalProperty.ToNullable(model), serializedAdditionalRawData); + return new CreateModerationRequest(input, model, serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -138,5 +140,13 @@ internal static CreateModerationRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateModerationRequest(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateModerationRequest.cs b/.dotnet/src/Generated/Models/CreateModerationRequest.cs index d015993c7..e1ed62cf0 100644 --- a/.dotnet/src/Generated/Models/CreateModerationRequest.cs +++ b/.dotnet/src/Generated/Models/CreateModerationRequest.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -46,7 +46,7 @@ internal partial class CreateModerationRequest /// is null. public CreateModerationRequest(BinaryData input) { - if (input is null) throw new ArgumentNullException(nameof(input)); + Argument.AssertNotNull(input, nameof(input)); Input = input; } diff --git a/.dotnet/src/Generated/Models/CreateModerationRequestModel.cs b/.dotnet/src/Generated/Models/CreateModerationRequestModel.cs index 2accc5ab0..12a283230 100644 --- a/.dotnet/src/Generated/Models/CreateModerationRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateModerationRequestModel.cs @@ -5,7 +5,7 @@ namespace OpenAI.Internal.Models { - /// Enum for model in CreateModerationRequest. + /// The CreateModerationRequestModel. internal readonly partial struct CreateModerationRequestModel : IEquatable { private readonly string _value; diff --git a/.dotnet/src/Generated/Models/CreateModerationResponse.Serialization.cs b/.dotnet/src/Generated/Models/CreateModerationResponse.Serialization.cs index 791fd71f1..c88e8b991 100644 --- a/.dotnet/src/Generated/Models/CreateModerationResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateModerationResponse.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -90,7 +92,7 @@ internal static CreateModerationResponse DeserializeCreateModerationResponse(Jso List array = new List(); foreach (var item in property.Value.EnumerateArray()) { - array.Add(CreateModerationResponseResult.DeserializeCreateModerationResponseResult(item)); + array.Add(CreateModerationResponseResult.DeserializeCreateModerationResponseResult(item, options)); } results = array; continue; @@ -142,5 +144,13 @@ internal static CreateModerationResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateModerationResponse(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateModerationResponse.cs b/.dotnet/src/Generated/Models/CreateModerationResponse.cs index 8f42f77c0..aaacf1180 100644 --- a/.dotnet/src/Generated/Models/CreateModerationResponse.cs +++ b/.dotnet/src/Generated/Models/CreateModerationResponse.cs @@ -1,9 +1,9 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; +using OpenAI; namespace OpenAI.Internal.Models { @@ -49,9 +49,9 @@ internal partial class CreateModerationResponse /// , or is null. internal CreateModerationResponse(string id, string model, IEnumerable results) { - if (id is null) throw new ArgumentNullException(nameof(id)); - if (model is null) throw new ArgumentNullException(nameof(model)); - if (results is null) throw new ArgumentNullException(nameof(results)); + Argument.AssertNotNull(id, nameof(id)); + Argument.AssertNotNull(model, nameof(model)); + Argument.AssertNotNull(results, nameof(results)); Id = id; Model = model; diff --git a/.dotnet/src/Generated/Models/CreateModerationResponseResult.Serialization.cs b/.dotnet/src/Generated/Models/CreateModerationResponseResult.Serialization.cs index 6a69b7a0d..d55831a2e 100644 --- a/.dotnet/src/Generated/Models/CreateModerationResponseResult.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateModerationResponseResult.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -77,12 +79,12 @@ internal static CreateModerationResponseResult DeserializeCreateModerationRespon } if (property.NameEquals("categories"u8)) { - categories = CreateModerationResponseResultCategories.DeserializeCreateModerationResponseResultCategories(property.Value); + categories = CreateModerationResponseResultCategories.DeserializeCreateModerationResponseResultCategories(property.Value, options); continue; } if (property.NameEquals("category_scores"u8)) { - categoryScores = CreateModerationResponseResultCategoryScores.DeserializeCreateModerationResponseResultCategoryScores(property.Value); + categoryScores = CreateModerationResponseResultCategoryScores.DeserializeCreateModerationResponseResultCategoryScores(property.Value, options); continue; } if (options.Format != "W") @@ -132,5 +134,13 @@ internal static CreateModerationResponseResult FromResponse(PipelineResponse res using var document = JsonDocument.Parse(response.Content); return DeserializeCreateModerationResponseResult(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateModerationResponseResult.cs b/.dotnet/src/Generated/Models/CreateModerationResponseResult.cs index baea8e148..e9ccb59c9 100644 --- a/.dotnet/src/Generated/Models/CreateModerationResponseResult.cs +++ b/.dotnet/src/Generated/Models/CreateModerationResponseResult.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -48,8 +48,8 @@ internal partial class CreateModerationResponseResult /// or is null. internal CreateModerationResponseResult(bool flagged, CreateModerationResponseResultCategories categories, CreateModerationResponseResultCategoryScores categoryScores) { - if (categories is null) throw new ArgumentNullException(nameof(categories)); - if (categoryScores is null) throw new ArgumentNullException(nameof(categoryScores)); + Argument.AssertNotNull(categories, nameof(categories)); + Argument.AssertNotNull(categoryScores, nameof(categoryScores)); Flagged = flagged; Categories = categories; diff --git a/.dotnet/src/Generated/Models/CreateModerationResponseResultCategories.Serialization.cs b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategories.Serialization.cs index 4f1c9d5eb..62fa766f1 100644 --- a/.dotnet/src/Generated/Models/CreateModerationResponseResultCategories.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategories.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -155,7 +157,19 @@ internal static CreateModerationResponseResultCategories DeserializeCreateModera } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateModerationResponseResultCategories(hate, hateThreatening, harassment, harassmentThreatening, selfHarm, selfHarmIntent, selfHarmInstructions, sexual, sexualMinors, violence, violenceGraphic, serializedAdditionalRawData); + return new CreateModerationResponseResultCategories( + hate, + hateThreatening, + harassment, + harassmentThreatening, + selfHarm, + selfHarmIntent, + selfHarmInstructions, + sexual, + sexualMinors, + violence, + violenceGraphic, + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -196,5 +210,13 @@ internal static CreateModerationResponseResultCategories FromResponse(PipelineRe using var document = JsonDocument.Parse(response.Content); return DeserializeCreateModerationResponseResultCategories(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.Serialization.cs b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.Serialization.cs index 6a8189dc3..3ea9f0a1f 100644 --- a/.dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateModerationResponseResultCategoryScores.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -155,7 +157,19 @@ internal static CreateModerationResponseResultCategoryScores DeserializeCreateMo } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateModerationResponseResultCategoryScores(hate, hateThreatening, harassment, harassmentThreatening, selfHarm, selfHarmIntent, selfHarmInstructions, sexual, sexualMinors, violence, violenceGraphic, serializedAdditionalRawData); + return new CreateModerationResponseResultCategoryScores( + hate, + hateThreatening, + harassment, + harassmentThreatening, + selfHarm, + selfHarmIntent, + selfHarmInstructions, + sexual, + sexualMinors, + violence, + violenceGraphic, + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -196,5 +210,13 @@ internal static CreateModerationResponseResultCategoryScores FromResponse(Pipeli using var document = JsonDocument.Parse(response.Content); return DeserializeCreateModerationResponseResultCategoryScores(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateRunRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateRunRequest.Serialization.cs index 3bdb98f68..15ade4fd0 100644 --- a/.dotnet/src/Generated/Models/CreateRunRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateRunRequest.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -21,7 +23,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriter writer.WriteStartObject(); writer.WritePropertyName("assistant_id"u8); writer.WriteStringValue(AssistantId); - if (OptionalProperty.IsDefined(Model)) + if (Optional.IsDefined(Model)) { if (Model != null) { @@ -33,7 +35,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriter writer.WriteNull("model"); } } - if (OptionalProperty.IsDefined(Instructions)) + if (Optional.IsDefined(Instructions)) { if (Instructions != null) { @@ -45,7 +47,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriter writer.WriteNull("instructions"); } } - if (OptionalProperty.IsDefined(AdditionalInstructions)) + if (Optional.IsDefined(AdditionalInstructions)) { if (AdditionalInstructions != null) { @@ -57,7 +59,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriter writer.WriteNull("additional_instructions"); } } - if (OptionalProperty.IsCollectionDefined(Tools)) + if (Optional.IsCollectionDefined(Tools)) { if (Tools != null) { @@ -86,7 +88,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriter writer.WriteNull("tools"); } } - if (OptionalProperty.IsCollectionDefined(Metadata)) + if (Optional.IsCollectionDefined(Metadata)) { if (Metadata != null) { @@ -143,11 +145,11 @@ internal static CreateRunRequest DeserializeCreateRunRequest(JsonElement element return null; } string assistantId = default; - OptionalProperty model = default; - OptionalProperty instructions = default; - OptionalProperty additionalInstructions = default; - OptionalProperty> tools = default; - OptionalProperty> metadata = default; + string model = default; + string instructions = default; + string additionalInstructions = default; + IList tools = default; + IDictionary metadata = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -228,7 +230,14 @@ internal static CreateRunRequest DeserializeCreateRunRequest(JsonElement element } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateRunRequest(assistantId, model.Value, instructions.Value, additionalInstructions.Value, OptionalProperty.ToList(tools), OptionalProperty.ToDictionary(metadata), serializedAdditionalRawData); + return new CreateRunRequest( + assistantId, + model, + instructions, + additionalInstructions, + tools ?? new ChangeTrackingList(), + metadata ?? new ChangeTrackingDictionary(), + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -269,5 +278,13 @@ internal static CreateRunRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateRunRequest(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateRunRequest.cs b/.dotnet/src/Generated/Models/CreateRunRequest.cs index e7bf9f448..db7f2f182 100644 --- a/.dotnet/src/Generated/Models/CreateRunRequest.cs +++ b/.dotnet/src/Generated/Models/CreateRunRequest.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -46,11 +46,11 @@ internal partial class CreateRunRequest /// is null. public CreateRunRequest(string assistantId) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + Argument.AssertNotNull(assistantId, nameof(assistantId)); AssistantId = assistantId; - Tools = new OptionalList(); - Metadata = new OptionalDictionary(); + Tools = new ChangeTrackingList(); + Metadata = new ChangeTrackingDictionary(); } /// Initializes a new instance of . diff --git a/.dotnet/src/Generated/Models/CreateSpeechRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateSpeechRequest.Serialization.cs index 46fd557d6..d33a4ed9c 100644 --- a/.dotnet/src/Generated/Models/CreateSpeechRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateSpeechRequest.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -25,12 +27,12 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWri writer.WriteStringValue(Input); writer.WritePropertyName("voice"u8); writer.WriteStringValue(Voice.ToString()); - if (OptionalProperty.IsDefined(ResponseFormat)) + if (Optional.IsDefined(ResponseFormat)) { writer.WritePropertyName("response_format"u8); writer.WriteStringValue(ResponseFormat.Value.ToString()); } - if (OptionalProperty.IsDefined(Speed)) + if (Optional.IsDefined(Speed)) { writer.WritePropertyName("speed"u8); writer.WriteNumberValue(Speed.Value); @@ -76,8 +78,8 @@ internal static CreateSpeechRequest DeserializeCreateSpeechRequest(JsonElement e CreateSpeechRequestModel model = default; string input = default; CreateSpeechRequestVoice voice = default; - OptionalProperty responseFormat = default; - OptionalProperty speed = default; + CreateSpeechRequestResponseFormat? responseFormat = default; + double? speed = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -121,7 +123,13 @@ internal static CreateSpeechRequest DeserializeCreateSpeechRequest(JsonElement e } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateSpeechRequest(model, input, voice, OptionalProperty.ToNullable(responseFormat), OptionalProperty.ToNullable(speed), serializedAdditionalRawData); + return new CreateSpeechRequest( + model, + input, + voice, + responseFormat, + speed, + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -162,5 +170,13 @@ internal static CreateSpeechRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateSpeechRequest(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateSpeechRequest.cs b/.dotnet/src/Generated/Models/CreateSpeechRequest.cs index 470717796..591623c69 100644 --- a/.dotnet/src/Generated/Models/CreateSpeechRequest.cs +++ b/.dotnet/src/Generated/Models/CreateSpeechRequest.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -52,7 +52,7 @@ internal partial class CreateSpeechRequest /// is null. public CreateSpeechRequest(CreateSpeechRequestModel model, string input, CreateSpeechRequestVoice voice) { - if (input is null) throw new ArgumentNullException(nameof(input)); + Argument.AssertNotNull(input, nameof(input)); Model = model; Input = input; diff --git a/.dotnet/src/Generated/Models/CreateSpeechRequestModel.cs b/.dotnet/src/Generated/Models/CreateSpeechRequestModel.cs index 806f493d3..576c7c624 100644 --- a/.dotnet/src/Generated/Models/CreateSpeechRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateSpeechRequestModel.cs @@ -5,7 +5,7 @@ namespace OpenAI.Internal.Models { - /// Enum for model in CreateSpeechRequest. + /// The CreateSpeechRequestModel. internal readonly partial struct CreateSpeechRequestModel : IEquatable { private readonly string _value; diff --git a/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.Serialization.cs index b3281386f..1613f3680 100644 --- a/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -21,12 +23,12 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelRea writer.WriteStartObject(); writer.WritePropertyName("assistant_id"u8); writer.WriteStringValue(AssistantId); - if (OptionalProperty.IsDefined(Thread)) + if (Optional.IsDefined(Thread)) { writer.WritePropertyName("thread"u8); writer.WriteObjectValue(Thread); } - if (OptionalProperty.IsDefined(Model)) + if (Optional.IsDefined(Model)) { if (Model != null) { @@ -38,7 +40,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelRea writer.WriteNull("model"); } } - if (OptionalProperty.IsDefined(Instructions)) + if (Optional.IsDefined(Instructions)) { if (Instructions != null) { @@ -50,7 +52,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelRea writer.WriteNull("instructions"); } } - if (OptionalProperty.IsCollectionDefined(Tools)) + if (Optional.IsCollectionDefined(Tools)) { if (Tools != null) { @@ -79,7 +81,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelRea writer.WriteNull("tools"); } } - if (OptionalProperty.IsCollectionDefined(Metadata)) + if (Optional.IsCollectionDefined(Metadata)) { if (Metadata != null) { @@ -136,11 +138,11 @@ internal static CreateThreadAndRunRequest DeserializeCreateThreadAndRunRequest(J return null; } string assistantId = default; - OptionalProperty thread = default; - OptionalProperty model = default; - OptionalProperty instructions = default; - OptionalProperty> tools = default; - OptionalProperty> metadata = default; + CreateThreadRequest thread = default; + string model = default; + string instructions = default; + IList tools = default; + IDictionary metadata = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -156,7 +158,7 @@ internal static CreateThreadAndRunRequest DeserializeCreateThreadAndRunRequest(J { continue; } - thread = CreateThreadRequest.DeserializeCreateThreadRequest(property.Value); + thread = CreateThreadRequest.DeserializeCreateThreadRequest(property.Value, options); continue; } if (property.NameEquals("model"u8)) @@ -220,7 +222,14 @@ internal static CreateThreadAndRunRequest DeserializeCreateThreadAndRunRequest(J } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateThreadAndRunRequest(assistantId, thread.Value, model.Value, instructions.Value, OptionalProperty.ToList(tools), OptionalProperty.ToDictionary(metadata), serializedAdditionalRawData); + return new CreateThreadAndRunRequest( + assistantId, + thread, + model, + instructions, + tools ?? new ChangeTrackingList(), + metadata ?? new ChangeTrackingDictionary(), + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -261,5 +270,13 @@ internal static CreateThreadAndRunRequest FromResponse(PipelineResponse response using var document = JsonDocument.Parse(response.Content); return DeserializeCreateThreadAndRunRequest(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.cs b/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.cs index 942ac10f1..eb2b0b0ba 100644 --- a/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.cs +++ b/.dotnet/src/Generated/Models/CreateThreadAndRunRequest.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -46,11 +46,11 @@ internal partial class CreateThreadAndRunRequest /// is null. public CreateThreadAndRunRequest(string assistantId) { - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); + Argument.AssertNotNull(assistantId, nameof(assistantId)); AssistantId = assistantId; - Tools = new OptionalList(); - Metadata = new OptionalDictionary(); + Tools = new ChangeTrackingList(); + Metadata = new ChangeTrackingDictionary(); } /// Initializes a new instance of . diff --git a/.dotnet/src/Generated/Models/CreateThreadRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateThreadRequest.Serialization.cs index 521c12b25..c763c3fe2 100644 --- a/.dotnet/src/Generated/Models/CreateThreadRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateThreadRequest.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -19,7 +21,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWri } writer.WriteStartObject(); - if (OptionalProperty.IsCollectionDefined(Messages)) + if (Optional.IsCollectionDefined(Messages)) { writer.WritePropertyName("messages"u8); writer.WriteStartArray(); @@ -29,7 +31,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWri } writer.WriteEndArray(); } - if (OptionalProperty.IsCollectionDefined(Metadata)) + if (Optional.IsCollectionDefined(Metadata)) { if (Metadata != null) { @@ -85,8 +87,8 @@ internal static CreateThreadRequest DeserializeCreateThreadRequest(JsonElement e { return null; } - OptionalProperty> messages = default; - OptionalProperty> metadata = default; + IList messages = default; + IDictionary metadata = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -100,7 +102,7 @@ internal static CreateThreadRequest DeserializeCreateThreadRequest(JsonElement e List array = new List(); foreach (var item in property.Value.EnumerateArray()) { - array.Add(CreateMessageRequest.DeserializeCreateMessageRequest(item)); + array.Add(CreateMessageRequest.DeserializeCreateMessageRequest(item, options)); } messages = array; continue; @@ -125,7 +127,7 @@ internal static CreateThreadRequest DeserializeCreateThreadRequest(JsonElement e } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateThreadRequest(OptionalProperty.ToList(messages), OptionalProperty.ToDictionary(metadata), serializedAdditionalRawData); + return new CreateThreadRequest(messages ?? new ChangeTrackingList(), metadata ?? new ChangeTrackingDictionary(), serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -166,5 +168,13 @@ internal static CreateThreadRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateThreadRequest(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateThreadRequest.cs b/.dotnet/src/Generated/Models/CreateThreadRequest.cs index 0fd5b0167..b48c1e449 100644 --- a/.dotnet/src/Generated/Models/CreateThreadRequest.cs +++ b/.dotnet/src/Generated/Models/CreateThreadRequest.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -44,8 +44,8 @@ internal partial class CreateThreadRequest /// Initializes a new instance of . public CreateThreadRequest() { - Messages = new OptionalList(); - Metadata = new OptionalDictionary(); + Messages = new ChangeTrackingList(); + Metadata = new ChangeTrackingDictionary(); } /// Initializes a new instance of . diff --git a/.dotnet/src/Generated/Models/CreateTranscriptionRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateTranscriptionRequest.Serialization.cs index ac4870484..bd02c679e 100644 --- a/.dotnet/src/Generated/Models/CreateTranscriptionRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateTranscriptionRequest.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -23,22 +25,22 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelRe writer.WriteBase64StringValue(File.ToArray(), "D"); writer.WritePropertyName("model"u8); writer.WriteStringValue(Model.ToString()); - if (OptionalProperty.IsDefined(Language)) + if (Optional.IsDefined(Language)) { writer.WritePropertyName("language"u8); writer.WriteStringValue(Language); } - if (OptionalProperty.IsDefined(Prompt)) + if (Optional.IsDefined(Prompt)) { writer.WritePropertyName("prompt"u8); writer.WriteStringValue(Prompt); } - if (OptionalProperty.IsDefined(ResponseFormat)) + if (Optional.IsDefined(ResponseFormat)) { writer.WritePropertyName("response_format"u8); writer.WriteStringValue(ResponseFormat.Value.ToString()); } - if (OptionalProperty.IsDefined(Temperature)) + if (Optional.IsDefined(Temperature)) { writer.WritePropertyName("temperature"u8); writer.WriteNumberValue(Temperature.Value); @@ -83,10 +85,10 @@ internal static CreateTranscriptionRequest DeserializeCreateTranscriptionRequest } BinaryData file = default; CreateTranscriptionRequestModel model = default; - OptionalProperty language = default; - OptionalProperty prompt = default; - OptionalProperty responseFormat = default; - OptionalProperty temperature = default; + string language = default; + string prompt = default; + CreateTranscriptionRequestResponseFormat? responseFormat = default; + double? temperature = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -135,7 +137,14 @@ internal static CreateTranscriptionRequest DeserializeCreateTranscriptionRequest } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateTranscriptionRequest(file, model, language.Value, prompt.Value, OptionalProperty.ToNullable(responseFormat), OptionalProperty.ToNullable(temperature), serializedAdditionalRawData); + return new CreateTranscriptionRequest( + file, + model, + language, + prompt, + responseFormat, + temperature, + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -176,5 +185,13 @@ internal static CreateTranscriptionRequest FromResponse(PipelineResponse respons using var document = JsonDocument.Parse(response.Content); return DeserializeCreateTranscriptionRequest(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateTranscriptionRequest.cs b/.dotnet/src/Generated/Models/CreateTranscriptionRequest.cs index 9bdc65381..0b52b69b5 100644 --- a/.dotnet/src/Generated/Models/CreateTranscriptionRequest.cs +++ b/.dotnet/src/Generated/Models/CreateTranscriptionRequest.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -50,7 +50,7 @@ internal partial class CreateTranscriptionRequest /// is null. public CreateTranscriptionRequest(BinaryData file, CreateTranscriptionRequestModel model) { - if (file is null) throw new ArgumentNullException(nameof(file)); + Argument.AssertNotNull(file, nameof(file)); File = file; Model = model; diff --git a/.dotnet/src/Generated/Models/CreateTranscriptionRequestModel.cs b/.dotnet/src/Generated/Models/CreateTranscriptionRequestModel.cs index 374f27dc3..a4890440f 100644 --- a/.dotnet/src/Generated/Models/CreateTranscriptionRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateTranscriptionRequestModel.cs @@ -5,7 +5,7 @@ namespace OpenAI.Internal.Models { - /// Enum for model in CreateTranscriptionRequest. + /// The CreateTranscriptionRequestModel. internal readonly partial struct CreateTranscriptionRequestModel : IEquatable { private readonly string _value; diff --git a/.dotnet/src/Generated/Models/CreateTranscriptionResponse.Serialization.cs b/.dotnet/src/Generated/Models/CreateTranscriptionResponse.Serialization.cs index 326257fc1..6bf802a18 100644 --- a/.dotnet/src/Generated/Models/CreateTranscriptionResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateTranscriptionResponse.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -21,22 +23,22 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelR writer.WriteStartObject(); writer.WritePropertyName("text"u8); writer.WriteStringValue(Text); - if (OptionalProperty.IsDefined(Task)) + if (Optional.IsDefined(Task)) { writer.WritePropertyName("task"u8); writer.WriteStringValue(Task.Value.ToString()); } - if (OptionalProperty.IsDefined(Language)) + if (Optional.IsDefined(Language)) { writer.WritePropertyName("language"u8); writer.WriteStringValue(Language); } - if (OptionalProperty.IsDefined(Duration)) + if (Optional.IsDefined(Duration)) { writer.WritePropertyName("duration"u8); writer.WriteNumberValue(Convert.ToInt32(Duration.Value.ToString("%s"))); } - if (OptionalProperty.IsCollectionDefined(Segments)) + if (Optional.IsCollectionDefined(Segments)) { writer.WritePropertyName("segments"u8); writer.WriteStartArray(); @@ -85,10 +87,10 @@ internal static CreateTranscriptionResponse DeserializeCreateTranscriptionRespon return null; } string text = default; - OptionalProperty task = default; - OptionalProperty language = default; - OptionalProperty duration = default; - OptionalProperty> segments = default; + CreateTranscriptionResponseTask? task = default; + string language = default; + TimeSpan? duration = default; + IReadOnlyList segments = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -130,7 +132,7 @@ internal static CreateTranscriptionResponse DeserializeCreateTranscriptionRespon List array = new List(); foreach (var item in property.Value.EnumerateArray()) { - array.Add(AudioSegment.DeserializeAudioSegment(item)); + array.Add(AudioSegment.DeserializeAudioSegment(item, options)); } segments = array; continue; @@ -141,7 +143,13 @@ internal static CreateTranscriptionResponse DeserializeCreateTranscriptionRespon } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateTranscriptionResponse(text, OptionalProperty.ToNullable(task), language.Value, OptionalProperty.ToNullable(duration), OptionalProperty.ToList(segments), serializedAdditionalRawData); + return new CreateTranscriptionResponse( + text, + task, + language, + duration, + segments ?? new ChangeTrackingList(), + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -182,5 +190,13 @@ internal static CreateTranscriptionResponse FromResponse(PipelineResponse respon using var document = JsonDocument.Parse(response.Content); return DeserializeCreateTranscriptionResponse(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateTranscriptionResponse.cs b/.dotnet/src/Generated/Models/CreateTranscriptionResponse.cs index ce8ed266d..0fb8162d3 100644 --- a/.dotnet/src/Generated/Models/CreateTranscriptionResponse.cs +++ b/.dotnet/src/Generated/Models/CreateTranscriptionResponse.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -46,10 +46,10 @@ internal partial class CreateTranscriptionResponse /// is null. internal CreateTranscriptionResponse(string text) { - if (text is null) throw new ArgumentNullException(nameof(text)); + Argument.AssertNotNull(text, nameof(text)); Text = text; - Segments = new OptionalList(); + Segments = new ChangeTrackingList(); } /// Initializes a new instance of . diff --git a/.dotnet/src/Generated/Models/CreateTranslationRequest.Serialization.cs b/.dotnet/src/Generated/Models/CreateTranslationRequest.Serialization.cs index 521582c54..aa71298f1 100644 --- a/.dotnet/src/Generated/Models/CreateTranslationRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateTranslationRequest.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -23,17 +25,17 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelRead writer.WriteBase64StringValue(File.ToArray(), "D"); writer.WritePropertyName("model"u8); writer.WriteStringValue(Model.ToString()); - if (OptionalProperty.IsDefined(Prompt)) + if (Optional.IsDefined(Prompt)) { writer.WritePropertyName("prompt"u8); writer.WriteStringValue(Prompt); } - if (OptionalProperty.IsDefined(ResponseFormat)) + if (Optional.IsDefined(ResponseFormat)) { writer.WritePropertyName("response_format"u8); writer.WriteStringValue(ResponseFormat.Value.ToString()); } - if (OptionalProperty.IsDefined(Temperature)) + if (Optional.IsDefined(Temperature)) { writer.WritePropertyName("temperature"u8); writer.WriteNumberValue(Temperature.Value); @@ -78,9 +80,9 @@ internal static CreateTranslationRequest DeserializeCreateTranslationRequest(Jso } BinaryData file = default; CreateTranslationRequestModel model = default; - OptionalProperty prompt = default; - OptionalProperty responseFormat = default; - OptionalProperty temperature = default; + string prompt = default; + CreateTranslationRequestResponseFormat? responseFormat = default; + double? temperature = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -124,7 +126,13 @@ internal static CreateTranslationRequest DeserializeCreateTranslationRequest(Jso } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateTranslationRequest(file, model, prompt.Value, OptionalProperty.ToNullable(responseFormat), OptionalProperty.ToNullable(temperature), serializedAdditionalRawData); + return new CreateTranslationRequest( + file, + model, + prompt, + responseFormat, + temperature, + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -165,5 +173,13 @@ internal static CreateTranslationRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeCreateTranslationRequest(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateTranslationRequest.cs b/.dotnet/src/Generated/Models/CreateTranslationRequest.cs index 46911bdf5..848333e45 100644 --- a/.dotnet/src/Generated/Models/CreateTranslationRequest.cs +++ b/.dotnet/src/Generated/Models/CreateTranslationRequest.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -50,7 +50,7 @@ internal partial class CreateTranslationRequest /// is null. public CreateTranslationRequest(BinaryData file, CreateTranslationRequestModel model) { - if (file is null) throw new ArgumentNullException(nameof(file)); + Argument.AssertNotNull(file, nameof(file)); File = file; Model = model; diff --git a/.dotnet/src/Generated/Models/CreateTranslationRequestModel.cs b/.dotnet/src/Generated/Models/CreateTranslationRequestModel.cs index 633bfd4c6..2c58aab50 100644 --- a/.dotnet/src/Generated/Models/CreateTranslationRequestModel.cs +++ b/.dotnet/src/Generated/Models/CreateTranslationRequestModel.cs @@ -5,7 +5,7 @@ namespace OpenAI.Internal.Models { - /// Enum for model in CreateTranslationRequest. + /// The CreateTranslationRequestModel. internal readonly partial struct CreateTranslationRequestModel : IEquatable { private readonly string _value; diff --git a/.dotnet/src/Generated/Models/CreateTranslationResponse.Serialization.cs b/.dotnet/src/Generated/Models/CreateTranslationResponse.Serialization.cs index 46025de53..d59ef520b 100644 --- a/.dotnet/src/Generated/Models/CreateTranslationResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/CreateTranslationResponse.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -21,22 +23,22 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelRea writer.WriteStartObject(); writer.WritePropertyName("text"u8); writer.WriteStringValue(Text); - if (OptionalProperty.IsDefined(Task)) + if (Optional.IsDefined(Task)) { writer.WritePropertyName("task"u8); writer.WriteStringValue(Task.Value.ToString()); } - if (OptionalProperty.IsDefined(Language)) + if (Optional.IsDefined(Language)) { writer.WritePropertyName("language"u8); writer.WriteStringValue(Language); } - if (OptionalProperty.IsDefined(Duration)) + if (Optional.IsDefined(Duration)) { writer.WritePropertyName("duration"u8); writer.WriteNumberValue(Convert.ToInt32(Duration.Value.ToString("%s"))); } - if (OptionalProperty.IsCollectionDefined(Segments)) + if (Optional.IsCollectionDefined(Segments)) { writer.WritePropertyName("segments"u8); writer.WriteStartArray(); @@ -85,10 +87,10 @@ internal static CreateTranslationResponse DeserializeCreateTranslationResponse(J return null; } string text = default; - OptionalProperty task = default; - OptionalProperty language = default; - OptionalProperty duration = default; - OptionalProperty> segments = default; + CreateTranslationResponseTask? task = default; + string language = default; + TimeSpan? duration = default; + IReadOnlyList segments = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -130,7 +132,7 @@ internal static CreateTranslationResponse DeserializeCreateTranslationResponse(J List array = new List(); foreach (var item in property.Value.EnumerateArray()) { - array.Add(AudioSegment.DeserializeAudioSegment(item)); + array.Add(AudioSegment.DeserializeAudioSegment(item, options)); } segments = array; continue; @@ -141,7 +143,13 @@ internal static CreateTranslationResponse DeserializeCreateTranslationResponse(J } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new CreateTranslationResponse(text, OptionalProperty.ToNullable(task), language.Value, OptionalProperty.ToNullable(duration), OptionalProperty.ToList(segments), serializedAdditionalRawData); + return new CreateTranslationResponse( + text, + task, + language, + duration, + segments ?? new ChangeTrackingList(), + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -182,5 +190,13 @@ internal static CreateTranslationResponse FromResponse(PipelineResponse response using var document = JsonDocument.Parse(response.Content); return DeserializeCreateTranslationResponse(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/CreateTranslationResponse.cs b/.dotnet/src/Generated/Models/CreateTranslationResponse.cs index 0b8ebf971..1cc325c68 100644 --- a/.dotnet/src/Generated/Models/CreateTranslationResponse.cs +++ b/.dotnet/src/Generated/Models/CreateTranslationResponse.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -46,10 +46,10 @@ internal partial class CreateTranslationResponse /// is null. internal CreateTranslationResponse(string text) { - if (text is null) throw new ArgumentNullException(nameof(text)); + Argument.AssertNotNull(text, nameof(text)); Text = text; - Segments = new OptionalList(); + Segments = new ChangeTrackingList(); } /// Initializes a new instance of . diff --git a/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.Serialization.cs b/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.Serialization.cs index c3e231655..95e3075a0 100644 --- a/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -132,5 +134,13 @@ internal static DeleteAssistantFileResponse FromResponse(PipelineResponse respon using var document = JsonDocument.Parse(response.Content); return DeserializeDeleteAssistantFileResponse(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.cs b/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.cs index d4fe927c2..c55f79685 100644 --- a/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.cs +++ b/.dotnet/src/Generated/Models/DeleteAssistantFileResponse.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -50,7 +50,7 @@ internal partial class DeleteAssistantFileResponse /// is null. internal DeleteAssistantFileResponse(string id, bool deleted) { - if (id is null) throw new ArgumentNullException(nameof(id)); + Argument.AssertNotNull(id, nameof(id)); Id = id; Deleted = deleted; diff --git a/.dotnet/src/Generated/Models/DeleteAssistantResponse.Serialization.cs b/.dotnet/src/Generated/Models/DeleteAssistantResponse.Serialization.cs index b6c0c9c62..3cb6f9c8a 100644 --- a/.dotnet/src/Generated/Models/DeleteAssistantResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/DeleteAssistantResponse.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -132,5 +134,13 @@ internal static DeleteAssistantResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeDeleteAssistantResponse(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/DeleteAssistantResponse.cs b/.dotnet/src/Generated/Models/DeleteAssistantResponse.cs index ab93ae628..0648ca31e 100644 --- a/.dotnet/src/Generated/Models/DeleteAssistantResponse.cs +++ b/.dotnet/src/Generated/Models/DeleteAssistantResponse.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -47,7 +47,7 @@ internal partial class DeleteAssistantResponse /// is null. internal DeleteAssistantResponse(string id, bool deleted) { - if (id is null) throw new ArgumentNullException(nameof(id)); + Argument.AssertNotNull(id, nameof(id)); Id = id; Deleted = deleted; diff --git a/.dotnet/src/Generated/Models/DeleteFileResponse.Serialization.cs b/.dotnet/src/Generated/Models/DeleteFileResponse.Serialization.cs index 2ff94aa3f..dab447883 100644 --- a/.dotnet/src/Generated/Models/DeleteFileResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/DeleteFileResponse.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -132,5 +134,13 @@ internal static DeleteFileResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeDeleteFileResponse(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/DeleteFileResponse.cs b/.dotnet/src/Generated/Models/DeleteFileResponse.cs index 5e91f557a..28dd2df8c 100644 --- a/.dotnet/src/Generated/Models/DeleteFileResponse.cs +++ b/.dotnet/src/Generated/Models/DeleteFileResponse.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -47,7 +47,7 @@ internal partial class DeleteFileResponse /// is null. internal DeleteFileResponse(string id, bool deleted) { - if (id is null) throw new ArgumentNullException(nameof(id)); + Argument.AssertNotNull(id, nameof(id)); Id = id; Deleted = deleted; diff --git a/.dotnet/src/Generated/Models/DeleteModelResponse.Serialization.cs b/.dotnet/src/Generated/Models/DeleteModelResponse.Serialization.cs index afd368541..a5c786b8d 100644 --- a/.dotnet/src/Generated/Models/DeleteModelResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/DeleteModelResponse.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -132,5 +134,13 @@ internal static DeleteModelResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeDeleteModelResponse(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/DeleteModelResponse.cs b/.dotnet/src/Generated/Models/DeleteModelResponse.cs index 1e5f9e687..1caef0aa6 100644 --- a/.dotnet/src/Generated/Models/DeleteModelResponse.cs +++ b/.dotnet/src/Generated/Models/DeleteModelResponse.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -47,7 +47,7 @@ internal partial class DeleteModelResponse /// is null. internal DeleteModelResponse(string id, bool deleted) { - if (id is null) throw new ArgumentNullException(nameof(id)); + Argument.AssertNotNull(id, nameof(id)); Id = id; Deleted = deleted; diff --git a/.dotnet/src/Generated/Models/DeleteThreadResponse.Serialization.cs b/.dotnet/src/Generated/Models/DeleteThreadResponse.Serialization.cs index ec4ac2da6..164a4f8bc 100644 --- a/.dotnet/src/Generated/Models/DeleteThreadResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/DeleteThreadResponse.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -132,5 +134,13 @@ internal static DeleteThreadResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeDeleteThreadResponse(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/DeleteThreadResponse.cs b/.dotnet/src/Generated/Models/DeleteThreadResponse.cs index 425135cb5..934684af3 100644 --- a/.dotnet/src/Generated/Models/DeleteThreadResponse.cs +++ b/.dotnet/src/Generated/Models/DeleteThreadResponse.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -47,7 +47,7 @@ internal partial class DeleteThreadResponse /// is null. internal DeleteThreadResponse(string id, bool deleted) { - if (id is null) throw new ArgumentNullException(nameof(id)); + Argument.AssertNotNull(id, nameof(id)); Id = id; Deleted = deleted; diff --git a/.dotnet/src/Generated/Models/Embedding.Serialization.cs b/.dotnet/src/Generated/Models/Embedding.Serialization.cs index 08a9811ea..92ebec50c 100644 --- a/.dotnet/src/Generated/Models/Embedding.Serialization.cs +++ b/.dotnet/src/Generated/Models/Embedding.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -139,5 +141,13 @@ internal static Embedding FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeEmbedding(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/Embedding.cs b/.dotnet/src/Generated/Models/Embedding.cs index 8e4f0cced..508a7cd39 100644 --- a/.dotnet/src/Generated/Models/Embedding.cs +++ b/.dotnet/src/Generated/Models/Embedding.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -50,7 +50,7 @@ internal partial class Embedding /// is null. internal Embedding(long index, BinaryData embeddingProperty) { - if (embeddingProperty is null) throw new ArgumentNullException(nameof(embeddingProperty)); + Argument.AssertNotNull(embeddingProperty, nameof(embeddingProperty)); Index = index; EmbeddingProperty = embeddingProperty; diff --git a/.dotnet/src/Generated/Models/EmbeddingUsage.Serialization.cs b/.dotnet/src/Generated/Models/EmbeddingUsage.Serialization.cs index ca241d62e..e47db418f 100644 --- a/.dotnet/src/Generated/Models/EmbeddingUsage.Serialization.cs +++ b/.dotnet/src/Generated/Models/EmbeddingUsage.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -124,5 +126,13 @@ internal static EmbeddingUsage FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeEmbeddingUsage(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/FineTuningJob.Serialization.cs b/.dotnet/src/Generated/Models/FineTuningJob.Serialization.cs index 2c9e983f6..59e0a3592 100644 --- a/.dotnet/src/Generated/Models/FineTuningJob.Serialization.cs +++ b/.dotnet/src/Generated/Models/FineTuningJob.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -160,7 +162,7 @@ internal static FineTuningJob DeserializeFineTuningJob(JsonElement element, Mode error = null; continue; } - error = FineTuningJobError.DeserializeFineTuningJobError(property.Value); + error = FineTuningJobError.DeserializeFineTuningJobError(property.Value, options); continue; } if (property.NameEquals("fine_tuned_model"u8)) @@ -185,7 +187,7 @@ internal static FineTuningJob DeserializeFineTuningJob(JsonElement element, Mode } if (property.NameEquals("hyperparameters"u8)) { - hyperparameters = FineTuningJobHyperparameters.DeserializeFineTuningJobHyperparameters(property.Value); + hyperparameters = FineTuningJobHyperparameters.DeserializeFineTuningJobHyperparameters(property.Value, options); continue; } if (property.NameEquals("model"u8)) @@ -249,7 +251,22 @@ internal static FineTuningJob DeserializeFineTuningJob(JsonElement element, Mode } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new FineTuningJob(id, createdAt, error, fineTunedModel, finishedAt, hyperparameters, model, @object, organizationId, resultFiles, status, trainedTokens, trainingFile, validationFile, serializedAdditionalRawData); + return new FineTuningJob( + id, + createdAt, + error, + fineTunedModel, + finishedAt, + hyperparameters, + model, + @object, + organizationId, + resultFiles, + status, + trainedTokens, + trainingFile, + validationFile, + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -290,5 +307,13 @@ internal static FineTuningJob FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeFineTuningJob(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/FineTuningJob.cs b/.dotnet/src/Generated/Models/FineTuningJob.cs index 3c69c6a1e..d0b6dc99c 100644 --- a/.dotnet/src/Generated/Models/FineTuningJob.cs +++ b/.dotnet/src/Generated/Models/FineTuningJob.cs @@ -1,9 +1,9 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; +using OpenAI; namespace OpenAI.Internal.Models { @@ -86,12 +86,12 @@ internal partial class FineTuningJob /// , , , , or is null. internal FineTuningJob(string id, DateTimeOffset createdAt, FineTuningJobError error, string fineTunedModel, DateTimeOffset? finishedAt, FineTuningJobHyperparameters hyperparameters, string model, string organizationId, IEnumerable resultFiles, FineTuningJobStatus status, long? trainedTokens, string trainingFile, string validationFile) { - if (id is null) throw new ArgumentNullException(nameof(id)); - if (hyperparameters is null) throw new ArgumentNullException(nameof(hyperparameters)); - if (model is null) throw new ArgumentNullException(nameof(model)); - if (organizationId is null) throw new ArgumentNullException(nameof(organizationId)); - if (resultFiles is null) throw new ArgumentNullException(nameof(resultFiles)); - if (trainingFile is null) throw new ArgumentNullException(nameof(trainingFile)); + Argument.AssertNotNull(id, nameof(id)); + Argument.AssertNotNull(hyperparameters, nameof(hyperparameters)); + Argument.AssertNotNull(model, nameof(model)); + Argument.AssertNotNull(organizationId, nameof(organizationId)); + Argument.AssertNotNull(resultFiles, nameof(resultFiles)); + Argument.AssertNotNull(trainingFile, nameof(trainingFile)); Id = id; CreatedAt = createdAt; diff --git a/.dotnet/src/Generated/Models/FineTuningJobError.Serialization.cs b/.dotnet/src/Generated/Models/FineTuningJobError.Serialization.cs index 7177ea5dd..abf697421 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobError.Serialization.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobError.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -144,5 +146,13 @@ internal static FineTuningJobError FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeFineTuningJobError(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/FineTuningJobError.cs b/.dotnet/src/Generated/Models/FineTuningJobError.cs index 744c38ab4..d4ee65889 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobError.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobError.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -51,8 +51,8 @@ internal partial class FineTuningJobError /// or is null. internal FineTuningJobError(string code, string message, string param) { - if (code is null) throw new ArgumentNullException(nameof(code)); - if (message is null) throw new ArgumentNullException(nameof(message)); + Argument.AssertNotNull(code, nameof(code)); + Argument.AssertNotNull(message, nameof(message)); Code = code; Message = message; diff --git a/.dotnet/src/Generated/Models/FineTuningJobEvent.Serialization.cs b/.dotnet/src/Generated/Models/FineTuningJobEvent.Serialization.cs index dad0768e9..097064e59 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobEvent.Serialization.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobEvent.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -107,7 +109,13 @@ internal static FineTuningJobEvent DeserializeFineTuningJobEvent(JsonElement ele } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new FineTuningJobEvent(id, createdAt, level, message, @object, serializedAdditionalRawData); + return new FineTuningJobEvent( + id, + createdAt, + level, + message, + @object, + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -148,5 +156,13 @@ internal static FineTuningJobEvent FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeFineTuningJobEvent(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/FineTuningJobEvent.cs b/.dotnet/src/Generated/Models/FineTuningJobEvent.cs index c73c76045..2ae386632 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobEvent.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobEvent.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -49,8 +49,8 @@ internal partial class FineTuningJobEvent /// or is null. internal FineTuningJobEvent(string id, DateTimeOffset createdAt, FineTuningJobEventLevel level, string message) { - if (id is null) throw new ArgumentNullException(nameof(id)); - if (message is null) throw new ArgumentNullException(nameof(message)); + Argument.AssertNotNull(id, nameof(id)); + Argument.AssertNotNull(message, nameof(message)); Id = id; CreatedAt = createdAt; diff --git a/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.Serialization.cs b/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.Serialization.cs index 67ef81085..81e7cbb45 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.Serialization.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -123,5 +125,13 @@ internal static FineTuningJobHyperparameters FromResponse(PipelineResponse respo using var document = JsonDocument.Parse(response.Content); return DeserializeFineTuningJobHyperparameters(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.cs b/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.cs index b81c9c19f..1e4314c88 100644 --- a/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.cs +++ b/.dotnet/src/Generated/Models/FineTuningJobHyperparameters.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -52,7 +52,7 @@ internal partial class FineTuningJobHyperparameters /// is null. internal FineTuningJobHyperparameters(BinaryData nEpochs) { - if (nEpochs is null) throw new ArgumentNullException(nameof(nEpochs)); + Argument.AssertNotNull(nEpochs, nameof(nEpochs)); NEpochs = nEpochs; } diff --git a/.dotnet/src/Generated/Models/FunctionObject.Serialization.cs b/.dotnet/src/Generated/Models/FunctionObject.Serialization.cs index 1b0e30bd1..6b0e5e7e5 100644 --- a/.dotnet/src/Generated/Models/FunctionObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/FunctionObject.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -19,14 +21,14 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOp } writer.WriteStartObject(); - if (OptionalProperty.IsDefined(Description)) + if (Optional.IsDefined(Description)) { writer.WritePropertyName("description"u8); writer.WriteStringValue(Description); } writer.WritePropertyName("name"u8); writer.WriteStringValue(Name); - if (OptionalProperty.IsDefined(Parameters)) + if (Optional.IsDefined(Parameters)) { writer.WritePropertyName("parameters"u8); writer.WriteObjectValue(Parameters); @@ -69,9 +71,9 @@ internal static FunctionObject DeserializeFunctionObject(JsonElement element, Mo { return null; } - OptionalProperty description = default; + string description = default; string name = default; - OptionalProperty parameters = default; + FunctionParameters parameters = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -92,7 +94,7 @@ internal static FunctionObject DeserializeFunctionObject(JsonElement element, Mo { continue; } - parameters = FunctionParameters.DeserializeFunctionParameters(property.Value); + parameters = FunctionParameters.DeserializeFunctionParameters(property.Value, options); continue; } if (options.Format != "W") @@ -101,7 +103,7 @@ internal static FunctionObject DeserializeFunctionObject(JsonElement element, Mo } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new FunctionObject(description.Value, name, parameters.Value, serializedAdditionalRawData); + return new FunctionObject(description, name, parameters, serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -142,5 +144,13 @@ internal static FunctionObject FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeFunctionObject(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/FunctionObject.cs b/.dotnet/src/Generated/Models/FunctionObject.cs index 456b879f2..f4ecaf182 100644 --- a/.dotnet/src/Generated/Models/FunctionObject.cs +++ b/.dotnet/src/Generated/Models/FunctionObject.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -49,7 +49,7 @@ internal partial class FunctionObject /// is null. public FunctionObject(string name) { - if (name is null) throw new ArgumentNullException(nameof(name)); + Argument.AssertNotNull(name, nameof(name)); Name = name; } diff --git a/.dotnet/src/Generated/Models/FunctionParameters.Serialization.cs b/.dotnet/src/Generated/Models/FunctionParameters.Serialization.cs index 5af866e0b..54a182600 100644 --- a/.dotnet/src/Generated/Models/FunctionParameters.Serialization.cs +++ b/.dotnet/src/Generated/Models/FunctionParameters.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -102,5 +104,13 @@ internal static FunctionParameters FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeFunctionParameters(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/FunctionParameters.cs b/.dotnet/src/Generated/Models/FunctionParameters.cs index bb8e5abff..56a1024fb 100644 --- a/.dotnet/src/Generated/Models/FunctionParameters.cs +++ b/.dotnet/src/Generated/Models/FunctionParameters.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -18,7 +18,7 @@ internal partial class FunctionParameters /// Initializes a new instance of . public FunctionParameters() { - AdditionalProperties = new OptionalDictionary(); + AdditionalProperties = new ChangeTrackingDictionary(); } /// Initializes a new instance of . diff --git a/.dotnet/src/Generated/Models/Image.Serialization.cs b/.dotnet/src/Generated/Models/Image.Serialization.cs index e568bb123..7e221fa2c 100644 --- a/.dotnet/src/Generated/Models/Image.Serialization.cs +++ b/.dotnet/src/Generated/Models/Image.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -19,17 +21,17 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions opt } writer.WriteStartObject(); - if (OptionalProperty.IsDefined(B64Json)) + if (Optional.IsDefined(B64Json)) { writer.WritePropertyName("b64_json"u8); writer.WriteBase64StringValue(B64Json.ToArray(), "D"); } - if (OptionalProperty.IsDefined(Url)) + if (Optional.IsDefined(Url)) { writer.WritePropertyName("url"u8); writer.WriteStringValue(Url.AbsoluteUri); } - if (OptionalProperty.IsDefined(RevisedPrompt)) + if (Optional.IsDefined(RevisedPrompt)) { writer.WritePropertyName("revised_prompt"u8); writer.WriteStringValue(RevisedPrompt); @@ -72,9 +74,9 @@ internal static Image DeserializeImage(JsonElement element, ModelReaderWriterOpt { return null; } - OptionalProperty b64Json = default; - OptionalProperty url = default; - OptionalProperty revisedPrompt = default; + BinaryData b64Json = default; + Uri url = default; + string revisedPrompt = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -108,7 +110,7 @@ internal static Image DeserializeImage(JsonElement element, ModelReaderWriterOpt } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new Image(b64Json.Value, url.Value, revisedPrompt.Value, serializedAdditionalRawData); + return new Image(b64Json, url, revisedPrompt, serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -149,5 +151,13 @@ internal static Image FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeImage(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ImagesResponse.Serialization.cs b/.dotnet/src/Generated/Models/ImagesResponse.Serialization.cs index 89ccd5aa1..2b30c5157 100644 --- a/.dotnet/src/Generated/Models/ImagesResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ImagesResponse.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -82,7 +84,7 @@ internal static ImagesResponse DeserializeImagesResponse(JsonElement element, Mo List array = new List(); foreach (var item in property.Value.EnumerateArray()) { - array.Add(Image.DeserializeImage(item)); + array.Add(Image.DeserializeImage(item, options)); } data = array; continue; @@ -134,5 +136,13 @@ internal static ImagesResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeImagesResponse(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ImagesResponse.cs b/.dotnet/src/Generated/Models/ImagesResponse.cs index c73c3741c..bcd67116c 100644 --- a/.dotnet/src/Generated/Models/ImagesResponse.cs +++ b/.dotnet/src/Generated/Models/ImagesResponse.cs @@ -1,9 +1,9 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; +using OpenAI; namespace OpenAI.Internal.Models { @@ -48,7 +48,7 @@ internal partial class ImagesResponse /// is null. internal ImagesResponse(DateTimeOffset created, IEnumerable data) { - if (data is null) throw new ArgumentNullException(nameof(data)); + Argument.AssertNotNull(data, nameof(data)); Created = created; Data = data.ToList(); diff --git a/.dotnet/src/Generated/Models/ListAssistantFilesResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListAssistantFilesResponse.Serialization.cs index d0c12f66b..141222ad6 100644 --- a/.dotnet/src/Generated/Models/ListAssistantFilesResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListAssistantFilesResponse.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -91,7 +93,7 @@ internal static ListAssistantFilesResponse DeserializeListAssistantFilesResponse List array = new List(); foreach (var item in property.Value.EnumerateArray()) { - array.Add(AssistantFileObject.DeserializeAssistantFileObject(item)); + array.Add(AssistantFileObject.DeserializeAssistantFileObject(item, options)); } data = array; continue; @@ -117,7 +119,13 @@ internal static ListAssistantFilesResponse DeserializeListAssistantFilesResponse } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new ListAssistantFilesResponse(@object, data, firstId, lastId, hasMore, serializedAdditionalRawData); + return new ListAssistantFilesResponse( + @object, + data, + firstId, + lastId, + hasMore, + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -158,5 +166,13 @@ internal static ListAssistantFilesResponse FromResponse(PipelineResponse respons using var document = JsonDocument.Parse(response.Content); return DeserializeListAssistantFilesResponse(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ListAssistantFilesResponse.cs b/.dotnet/src/Generated/Models/ListAssistantFilesResponse.cs index 96063de70..54d7af52c 100644 --- a/.dotnet/src/Generated/Models/ListAssistantFilesResponse.cs +++ b/.dotnet/src/Generated/Models/ListAssistantFilesResponse.cs @@ -1,9 +1,9 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; +using OpenAI; namespace OpenAI.Internal.Models { @@ -50,9 +50,9 @@ internal partial class ListAssistantFilesResponse /// , or is null. internal ListAssistantFilesResponse(IEnumerable data, string firstId, string lastId, bool hasMore) { - if (data is null) throw new ArgumentNullException(nameof(data)); - if (firstId is null) throw new ArgumentNullException(nameof(firstId)); - if (lastId is null) throw new ArgumentNullException(nameof(lastId)); + Argument.AssertNotNull(data, nameof(data)); + Argument.AssertNotNull(firstId, nameof(firstId)); + Argument.AssertNotNull(lastId, nameof(lastId)); Data = data.ToList(); FirstId = firstId; diff --git a/.dotnet/src/Generated/Models/ListAssistantsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListAssistantsResponse.Serialization.cs index a94da2024..6377a1c9f 100644 --- a/.dotnet/src/Generated/Models/ListAssistantsResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListAssistantsResponse.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -91,7 +93,7 @@ internal static ListAssistantsResponse DeserializeListAssistantsResponse(JsonEle List array = new List(); foreach (var item in property.Value.EnumerateArray()) { - array.Add(AssistantObject.DeserializeAssistantObject(item)); + array.Add(AssistantObject.DeserializeAssistantObject(item, options)); } data = array; continue; @@ -117,7 +119,13 @@ internal static ListAssistantsResponse DeserializeListAssistantsResponse(JsonEle } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new ListAssistantsResponse(@object, data, firstId, lastId, hasMore, serializedAdditionalRawData); + return new ListAssistantsResponse( + @object, + data, + firstId, + lastId, + hasMore, + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -158,5 +166,13 @@ internal static ListAssistantsResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeListAssistantsResponse(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ListAssistantsResponse.cs b/.dotnet/src/Generated/Models/ListAssistantsResponse.cs index 032d0dd9a..7a8a094c5 100644 --- a/.dotnet/src/Generated/Models/ListAssistantsResponse.cs +++ b/.dotnet/src/Generated/Models/ListAssistantsResponse.cs @@ -1,9 +1,9 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; +using OpenAI; namespace OpenAI.Internal.Models { @@ -50,9 +50,9 @@ internal partial class ListAssistantsResponse /// , or is null. internal ListAssistantsResponse(IEnumerable data, string firstId, string lastId, bool hasMore) { - if (data is null) throw new ArgumentNullException(nameof(data)); - if (firstId is null) throw new ArgumentNullException(nameof(firstId)); - if (lastId is null) throw new ArgumentNullException(nameof(lastId)); + Argument.AssertNotNull(data, nameof(data)); + Argument.AssertNotNull(firstId, nameof(firstId)); + Argument.AssertNotNull(lastId, nameof(lastId)); Data = data.ToList(); FirstId = firstId; diff --git a/.dotnet/src/Generated/Models/ListFilesResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListFilesResponse.Serialization.cs index 088451116..f40f8faac 100644 --- a/.dotnet/src/Generated/Models/ListFilesResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListFilesResponse.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -77,7 +79,7 @@ internal static ListFilesResponse DeserializeListFilesResponse(JsonElement eleme List array = new List(); foreach (var item in property.Value.EnumerateArray()) { - array.Add(OpenAIFile.DeserializeOpenAIFile(item)); + array.Add(OpenAIFile.DeserializeOpenAIFile(item, options)); } data = array; continue; @@ -134,5 +136,13 @@ internal static ListFilesResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeListFilesResponse(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ListFilesResponse.cs b/.dotnet/src/Generated/Models/ListFilesResponse.cs index a79ec60fc..caff96df8 100644 --- a/.dotnet/src/Generated/Models/ListFilesResponse.cs +++ b/.dotnet/src/Generated/Models/ListFilesResponse.cs @@ -1,9 +1,9 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; +using OpenAI; namespace OpenAI.Internal.Models { @@ -47,7 +47,7 @@ internal partial class ListFilesResponse /// is null. internal ListFilesResponse(IEnumerable data) { - if (data is null) throw new ArgumentNullException(nameof(data)); + Argument.AssertNotNull(data, nameof(data)); Data = data.ToList(); } diff --git a/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.Serialization.cs index fe4b81c4b..b8673d973 100644 --- a/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -77,7 +79,7 @@ internal static ListFineTuningJobEventsResponse DeserializeListFineTuningJobEven List array = new List(); foreach (var item in property.Value.EnumerateArray()) { - array.Add(FineTuningJobEvent.DeserializeFineTuningJobEvent(item)); + array.Add(FineTuningJobEvent.DeserializeFineTuningJobEvent(item, options)); } data = array; continue; @@ -134,5 +136,13 @@ internal static ListFineTuningJobEventsResponse FromResponse(PipelineResponse re using var document = JsonDocument.Parse(response.Content); return DeserializeListFineTuningJobEventsResponse(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.cs b/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.cs index 57508a714..838a80317 100644 --- a/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.cs +++ b/.dotnet/src/Generated/Models/ListFineTuningJobEventsResponse.cs @@ -1,9 +1,9 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; +using OpenAI; namespace OpenAI.Internal.Models { @@ -47,7 +47,7 @@ internal partial class ListFineTuningJobEventsResponse /// is null. internal ListFineTuningJobEventsResponse(IEnumerable data) { - if (data is null) throw new ArgumentNullException(nameof(data)); + Argument.AssertNotNull(data, nameof(data)); Data = data.ToList(); } diff --git a/.dotnet/src/Generated/Models/ListMessageFilesResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListMessageFilesResponse.Serialization.cs index 6f16b2c6c..1f412eb8f 100644 --- a/.dotnet/src/Generated/Models/ListMessageFilesResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListMessageFilesResponse.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -91,7 +93,7 @@ internal static ListMessageFilesResponse DeserializeListMessageFilesResponse(Jso List array = new List(); foreach (var item in property.Value.EnumerateArray()) { - array.Add(MessageFileObject.DeserializeMessageFileObject(item)); + array.Add(MessageFileObject.DeserializeMessageFileObject(item, options)); } data = array; continue; @@ -117,7 +119,13 @@ internal static ListMessageFilesResponse DeserializeListMessageFilesResponse(Jso } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new ListMessageFilesResponse(@object, data, firstId, lastId, hasMore, serializedAdditionalRawData); + return new ListMessageFilesResponse( + @object, + data, + firstId, + lastId, + hasMore, + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -158,5 +166,13 @@ internal static ListMessageFilesResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeListMessageFilesResponse(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ListMessageFilesResponse.cs b/.dotnet/src/Generated/Models/ListMessageFilesResponse.cs index 80fdc2499..4884dad96 100644 --- a/.dotnet/src/Generated/Models/ListMessageFilesResponse.cs +++ b/.dotnet/src/Generated/Models/ListMessageFilesResponse.cs @@ -1,9 +1,9 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; +using OpenAI; namespace OpenAI.Internal.Models { @@ -50,9 +50,9 @@ internal partial class ListMessageFilesResponse /// , or is null. internal ListMessageFilesResponse(IEnumerable data, string firstId, string lastId, bool hasMore) { - if (data is null) throw new ArgumentNullException(nameof(data)); - if (firstId is null) throw new ArgumentNullException(nameof(firstId)); - if (lastId is null) throw new ArgumentNullException(nameof(lastId)); + Argument.AssertNotNull(data, nameof(data)); + Argument.AssertNotNull(firstId, nameof(firstId)); + Argument.AssertNotNull(lastId, nameof(lastId)); Data = data.ToList(); FirstId = firstId; diff --git a/.dotnet/src/Generated/Models/ListMessagesResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListMessagesResponse.Serialization.cs index dbf0afd83..dcfc3f1c0 100644 --- a/.dotnet/src/Generated/Models/ListMessagesResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListMessagesResponse.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -91,7 +93,7 @@ internal static ListMessagesResponse DeserializeListMessagesResponse(JsonElement List array = new List(); foreach (var item in property.Value.EnumerateArray()) { - array.Add(MessageObject.DeserializeMessageObject(item)); + array.Add(MessageObject.DeserializeMessageObject(item, options)); } data = array; continue; @@ -117,7 +119,13 @@ internal static ListMessagesResponse DeserializeListMessagesResponse(JsonElement } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new ListMessagesResponse(@object, data, firstId, lastId, hasMore, serializedAdditionalRawData); + return new ListMessagesResponse( + @object, + data, + firstId, + lastId, + hasMore, + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -158,5 +166,13 @@ internal static ListMessagesResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeListMessagesResponse(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ListMessagesResponse.cs b/.dotnet/src/Generated/Models/ListMessagesResponse.cs index fc2d652e0..514c43c95 100644 --- a/.dotnet/src/Generated/Models/ListMessagesResponse.cs +++ b/.dotnet/src/Generated/Models/ListMessagesResponse.cs @@ -1,9 +1,9 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; +using OpenAI; namespace OpenAI.Internal.Models { @@ -50,9 +50,9 @@ internal partial class ListMessagesResponse /// , or is null. internal ListMessagesResponse(IEnumerable data, string firstId, string lastId, bool hasMore) { - if (data is null) throw new ArgumentNullException(nameof(data)); - if (firstId is null) throw new ArgumentNullException(nameof(firstId)); - if (lastId is null) throw new ArgumentNullException(nameof(lastId)); + Argument.AssertNotNull(data, nameof(data)); + Argument.AssertNotNull(firstId, nameof(firstId)); + Argument.AssertNotNull(lastId, nameof(lastId)); Data = data.ToList(); FirstId = firstId; diff --git a/.dotnet/src/Generated/Models/ListModelsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListModelsResponse.Serialization.cs index 45281c137..6a5ba3d11 100644 --- a/.dotnet/src/Generated/Models/ListModelsResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListModelsResponse.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -82,7 +84,7 @@ internal static ListModelsResponse DeserializeListModelsResponse(JsonElement ele List array = new List(); foreach (var item in property.Value.EnumerateArray()) { - array.Add(Model.DeserializeModel(item)); + array.Add(Model.DeserializeModel(item, options)); } data = array; continue; @@ -134,5 +136,13 @@ internal static ListModelsResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeListModelsResponse(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ListModelsResponse.cs b/.dotnet/src/Generated/Models/ListModelsResponse.cs index b0751334c..6e3ee41af 100644 --- a/.dotnet/src/Generated/Models/ListModelsResponse.cs +++ b/.dotnet/src/Generated/Models/ListModelsResponse.cs @@ -1,9 +1,9 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; +using OpenAI; namespace OpenAI.Internal.Models { @@ -47,7 +47,7 @@ internal partial class ListModelsResponse /// is null. internal ListModelsResponse(IEnumerable data) { - if (data is null) throw new ArgumentNullException(nameof(data)); + Argument.AssertNotNull(data, nameof(data)); Data = data.ToList(); } diff --git a/.dotnet/src/Generated/Models/ListOrder.cs b/.dotnet/src/Generated/Models/ListOrder.cs index 0a2a6e6cf..9eb4a9780 100644 --- a/.dotnet/src/Generated/Models/ListOrder.cs +++ b/.dotnet/src/Generated/Models/ListOrder.cs @@ -5,6 +5,7 @@ namespace OpenAI.Internal.Models { + /// The ListOrder. internal readonly partial struct ListOrder : IEquatable { private readonly string _value; diff --git a/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.Serialization.cs index c741d8962..5603812f6 100644 --- a/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -80,7 +82,7 @@ internal static ListPaginatedFineTuningJobsResponse DeserializeListPaginatedFine List array = new List(); foreach (var item in property.Value.EnumerateArray()) { - array.Add(FineTuningJob.DeserializeFineTuningJob(item)); + array.Add(FineTuningJob.DeserializeFineTuningJob(item, options)); } data = array; continue; @@ -142,5 +144,13 @@ internal static ListPaginatedFineTuningJobsResponse FromResponse(PipelineRespons using var document = JsonDocument.Parse(response.Content); return DeserializeListPaginatedFineTuningJobsResponse(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.cs b/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.cs index ce7267ba2..d258099cd 100644 --- a/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.cs +++ b/.dotnet/src/Generated/Models/ListPaginatedFineTuningJobsResponse.cs @@ -1,9 +1,9 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; +using OpenAI; namespace OpenAI.Internal.Models { @@ -48,7 +48,7 @@ internal partial class ListPaginatedFineTuningJobsResponse /// is null. internal ListPaginatedFineTuningJobsResponse(IEnumerable data, bool hasMore) { - if (data is null) throw new ArgumentNullException(nameof(data)); + Argument.AssertNotNull(data, nameof(data)); Data = data.ToList(); HasMore = hasMore; diff --git a/.dotnet/src/Generated/Models/ListRunStepsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListRunStepsResponse.Serialization.cs index 4a9b71ed8..9f429e0fd 100644 --- a/.dotnet/src/Generated/Models/ListRunStepsResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListRunStepsResponse.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -91,7 +93,7 @@ internal static ListRunStepsResponse DeserializeListRunStepsResponse(JsonElement List array = new List(); foreach (var item in property.Value.EnumerateArray()) { - array.Add(RunStepObject.DeserializeRunStepObject(item)); + array.Add(RunStepObject.DeserializeRunStepObject(item, options)); } data = array; continue; @@ -117,7 +119,13 @@ internal static ListRunStepsResponse DeserializeListRunStepsResponse(JsonElement } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new ListRunStepsResponse(@object, data, firstId, lastId, hasMore, serializedAdditionalRawData); + return new ListRunStepsResponse( + @object, + data, + firstId, + lastId, + hasMore, + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -158,5 +166,13 @@ internal static ListRunStepsResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeListRunStepsResponse(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ListRunStepsResponse.cs b/.dotnet/src/Generated/Models/ListRunStepsResponse.cs index 6582d2fc6..393a84b03 100644 --- a/.dotnet/src/Generated/Models/ListRunStepsResponse.cs +++ b/.dotnet/src/Generated/Models/ListRunStepsResponse.cs @@ -1,9 +1,9 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; +using OpenAI; namespace OpenAI.Internal.Models { @@ -50,9 +50,9 @@ internal partial class ListRunStepsResponse /// , or is null. internal ListRunStepsResponse(IEnumerable data, string firstId, string lastId, bool hasMore) { - if (data is null) throw new ArgumentNullException(nameof(data)); - if (firstId is null) throw new ArgumentNullException(nameof(firstId)); - if (lastId is null) throw new ArgumentNullException(nameof(lastId)); + Argument.AssertNotNull(data, nameof(data)); + Argument.AssertNotNull(firstId, nameof(firstId)); + Argument.AssertNotNull(lastId, nameof(lastId)); Data = data.ToList(); FirstId = firstId; diff --git a/.dotnet/src/Generated/Models/ListRunsResponse.Serialization.cs b/.dotnet/src/Generated/Models/ListRunsResponse.Serialization.cs index c6b501c8a..47d162aba 100644 --- a/.dotnet/src/Generated/Models/ListRunsResponse.Serialization.cs +++ b/.dotnet/src/Generated/Models/ListRunsResponse.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -91,7 +93,7 @@ internal static ListRunsResponse DeserializeListRunsResponse(JsonElement element List array = new List(); foreach (var item in property.Value.EnumerateArray()) { - array.Add(RunObject.DeserializeRunObject(item)); + array.Add(RunObject.DeserializeRunObject(item, options)); } data = array; continue; @@ -117,7 +119,13 @@ internal static ListRunsResponse DeserializeListRunsResponse(JsonElement element } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new ListRunsResponse(@object, data, firstId, lastId, hasMore, serializedAdditionalRawData); + return new ListRunsResponse( + @object, + data, + firstId, + lastId, + hasMore, + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -158,5 +166,13 @@ internal static ListRunsResponse FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeListRunsResponse(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ListRunsResponse.cs b/.dotnet/src/Generated/Models/ListRunsResponse.cs index 233e26060..deb6ee3ba 100644 --- a/.dotnet/src/Generated/Models/ListRunsResponse.cs +++ b/.dotnet/src/Generated/Models/ListRunsResponse.cs @@ -1,9 +1,9 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; +using OpenAI; namespace OpenAI.Internal.Models { @@ -50,9 +50,9 @@ internal partial class ListRunsResponse /// , or is null. internal ListRunsResponse(IEnumerable data, string firstId, string lastId, bool hasMore) { - if (data is null) throw new ArgumentNullException(nameof(data)); - if (firstId is null) throw new ArgumentNullException(nameof(firstId)); - if (lastId is null) throw new ArgumentNullException(nameof(lastId)); + Argument.AssertNotNull(data, nameof(data)); + Argument.AssertNotNull(firstId, nameof(firstId)); + Argument.AssertNotNull(lastId, nameof(lastId)); Data = data.ToList(); FirstId = firstId; diff --git a/.dotnet/src/Generated/Models/MessageFileObject.Serialization.cs b/.dotnet/src/Generated/Models/MessageFileObject.Serialization.cs index 61eb5abae..37dd97d7f 100644 --- a/.dotnet/src/Generated/Models/MessageFileObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/MessageFileObject.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -140,5 +142,13 @@ internal static MessageFileObject FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeMessageFileObject(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/MessageFileObject.cs b/.dotnet/src/Generated/Models/MessageFileObject.cs index 508d68981..7927dfff5 100644 --- a/.dotnet/src/Generated/Models/MessageFileObject.cs +++ b/.dotnet/src/Generated/Models/MessageFileObject.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -48,8 +48,8 @@ internal partial class MessageFileObject /// or is null. internal MessageFileObject(string id, DateTimeOffset createdAt, string messageId) { - if (id is null) throw new ArgumentNullException(nameof(id)); - if (messageId is null) throw new ArgumentNullException(nameof(messageId)); + Argument.AssertNotNull(id, nameof(id)); + Argument.AssertNotNull(messageId, nameof(messageId)); Id = id; CreatedAt = createdAt; diff --git a/.dotnet/src/Generated/Models/MessageObject.Serialization.cs b/.dotnet/src/Generated/Models/MessageObject.Serialization.cs index 27a044c39..5c0cb8c53 100644 --- a/.dotnet/src/Generated/Models/MessageObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/MessageObject.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -73,7 +75,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOpt writer.WriteStringValue(item); } writer.WriteEndArray(); - if (Metadata != null && OptionalProperty.IsCollectionDefined(Metadata)) + if (Metadata != null && Optional.IsCollectionDefined(Metadata)) { writer.WritePropertyName("metadata"u8); writer.WriteStartObject(); @@ -216,7 +218,7 @@ internal static MessageObject DeserializeMessageObject(JsonElement element, Mode { if (property.Value.ValueKind == JsonValueKind.Null) { - metadata = new OptionalDictionary(); + metadata = new ChangeTrackingDictionary(); continue; } Dictionary dictionary = new Dictionary(); @@ -233,7 +235,18 @@ internal static MessageObject DeserializeMessageObject(JsonElement element, Mode } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new MessageObject(id, @object, createdAt, threadId, role, content, assistantId, runId, fileIds, metadata, serializedAdditionalRawData); + return new MessageObject( + id, + @object, + createdAt, + threadId, + role, + content, + assistantId, + runId, + fileIds, + metadata, + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -274,5 +287,13 @@ internal static MessageObject FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeMessageObject(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/MessageObject.cs b/.dotnet/src/Generated/Models/MessageObject.cs index f796b78be..e314eaf06 100644 --- a/.dotnet/src/Generated/Models/MessageObject.cs +++ b/.dotnet/src/Generated/Models/MessageObject.cs @@ -1,9 +1,9 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; +using OpenAI; namespace OpenAI.Internal.Models { @@ -69,10 +69,10 @@ internal partial class MessageObject /// , , or is null. internal MessageObject(string id, DateTimeOffset createdAt, string threadId, MessageObjectRole role, IEnumerable content, string assistantId, string runId, IEnumerable fileIds, IReadOnlyDictionary metadata) { - if (id is null) throw new ArgumentNullException(nameof(id)); - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (content is null) throw new ArgumentNullException(nameof(content)); - if (fileIds is null) throw new ArgumentNullException(nameof(fileIds)); + Argument.AssertNotNull(id, nameof(id)); + Argument.AssertNotNull(threadId, nameof(threadId)); + Argument.AssertNotNull(content, nameof(content)); + Argument.AssertNotNull(fileIds, nameof(fileIds)); Id = id; CreatedAt = createdAt; diff --git a/.dotnet/src/Generated/Models/Model.Serialization.cs b/.dotnet/src/Generated/Models/Model.Serialization.cs index 13d7f1f3a..5efab5846 100644 --- a/.dotnet/src/Generated/Models/Model.Serialization.cs +++ b/.dotnet/src/Generated/Models/Model.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -140,5 +142,13 @@ internal static Model FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeModel(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/Model.cs b/.dotnet/src/Generated/Models/Model.cs index d5b78f33f..a15763f6c 100644 --- a/.dotnet/src/Generated/Models/Model.cs +++ b/.dotnet/src/Generated/Models/Model.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -48,8 +48,8 @@ internal partial class Model /// or is null. internal Model(string id, DateTimeOffset created, string ownedBy) { - if (id is null) throw new ArgumentNullException(nameof(id)); - if (ownedBy is null) throw new ArgumentNullException(nameof(ownedBy)); + Argument.AssertNotNull(id, nameof(id)); + Argument.AssertNotNull(ownedBy, nameof(ownedBy)); Id = id; Created = created; diff --git a/.dotnet/src/Generated/Models/ModifyAssistantRequest.Serialization.cs b/.dotnet/src/Generated/Models/ModifyAssistantRequest.Serialization.cs index 41c39aac7..9e6843435 100644 --- a/.dotnet/src/Generated/Models/ModifyAssistantRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/ModifyAssistantRequest.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -19,12 +21,12 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReader } writer.WriteStartObject(); - if (OptionalProperty.IsDefined(Model)) + if (Optional.IsDefined(Model)) { writer.WritePropertyName("model"u8); writer.WriteStringValue(Model); } - if (OptionalProperty.IsDefined(Name)) + if (Optional.IsDefined(Name)) { if (Name != null) { @@ -36,7 +38,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReader writer.WriteNull("name"); } } - if (OptionalProperty.IsDefined(Description)) + if (Optional.IsDefined(Description)) { if (Description != null) { @@ -48,7 +50,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReader writer.WriteNull("description"); } } - if (OptionalProperty.IsDefined(Instructions)) + if (Optional.IsDefined(Instructions)) { if (Instructions != null) { @@ -60,7 +62,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReader writer.WriteNull("instructions"); } } - if (OptionalProperty.IsCollectionDefined(Tools)) + if (Optional.IsCollectionDefined(Tools)) { writer.WritePropertyName("tools"u8); writer.WriteStartArray(); @@ -82,7 +84,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReader } writer.WriteEndArray(); } - if (OptionalProperty.IsCollectionDefined(FileIds)) + if (Optional.IsCollectionDefined(FileIds)) { writer.WritePropertyName("file_ids"u8); writer.WriteStartArray(); @@ -92,7 +94,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReader } writer.WriteEndArray(); } - if (OptionalProperty.IsCollectionDefined(Metadata)) + if (Optional.IsCollectionDefined(Metadata)) { if (Metadata != null) { @@ -148,13 +150,13 @@ internal static ModifyAssistantRequest DeserializeModifyAssistantRequest(JsonEle { return null; } - OptionalProperty model = default; - OptionalProperty name = default; - OptionalProperty description = default; - OptionalProperty instructions = default; - OptionalProperty> tools = default; - OptionalProperty> fileIds = default; - OptionalProperty> metadata = default; + string model = default; + string name = default; + string description = default; + string instructions = default; + IList tools = default; + IList fileIds = default; + IDictionary metadata = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -249,7 +251,15 @@ internal static ModifyAssistantRequest DeserializeModifyAssistantRequest(JsonEle } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new ModifyAssistantRequest(model.Value, name.Value, description.Value, instructions.Value, OptionalProperty.ToList(tools), OptionalProperty.ToList(fileIds), OptionalProperty.ToDictionary(metadata), serializedAdditionalRawData); + return new ModifyAssistantRequest( + model, + name, + description, + instructions, + tools ?? new ChangeTrackingList(), + fileIds ?? new ChangeTrackingList(), + metadata ?? new ChangeTrackingDictionary(), + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -290,5 +300,13 @@ internal static ModifyAssistantRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeModifyAssistantRequest(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ModifyAssistantRequest.cs b/.dotnet/src/Generated/Models/ModifyAssistantRequest.cs index ae45a5a00..a6e7b82a2 100644 --- a/.dotnet/src/Generated/Models/ModifyAssistantRequest.cs +++ b/.dotnet/src/Generated/Models/ModifyAssistantRequest.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -44,9 +44,9 @@ internal partial class ModifyAssistantRequest /// Initializes a new instance of . public ModifyAssistantRequest() { - Tools = new OptionalList(); - FileIds = new OptionalList(); - Metadata = new OptionalDictionary(); + Tools = new ChangeTrackingList(); + FileIds = new ChangeTrackingList(); + Metadata = new ChangeTrackingDictionary(); } /// Initializes a new instance of . diff --git a/.dotnet/src/Generated/Models/ModifyMessageRequest.Serialization.cs b/.dotnet/src/Generated/Models/ModifyMessageRequest.Serialization.cs index bf8d29430..22d68d73a 100644 --- a/.dotnet/src/Generated/Models/ModifyMessageRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/ModifyMessageRequest.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -19,7 +21,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWr } writer.WriteStartObject(); - if (OptionalProperty.IsCollectionDefined(Metadata)) + if (Optional.IsCollectionDefined(Metadata)) { if (Metadata != null) { @@ -75,7 +77,7 @@ internal static ModifyMessageRequest DeserializeModifyMessageRequest(JsonElement { return null; } - OptionalProperty> metadata = default; + IDictionary metadata = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -100,7 +102,7 @@ internal static ModifyMessageRequest DeserializeModifyMessageRequest(JsonElement } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new ModifyMessageRequest(OptionalProperty.ToDictionary(metadata), serializedAdditionalRawData); + return new ModifyMessageRequest(metadata ?? new ChangeTrackingDictionary(), serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -141,5 +143,13 @@ internal static ModifyMessageRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeModifyMessageRequest(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ModifyMessageRequest.cs b/.dotnet/src/Generated/Models/ModifyMessageRequest.cs index 72cc4c5bc..9fac04db8 100644 --- a/.dotnet/src/Generated/Models/ModifyMessageRequest.cs +++ b/.dotnet/src/Generated/Models/ModifyMessageRequest.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -44,7 +44,7 @@ internal partial class ModifyMessageRequest /// Initializes a new instance of . public ModifyMessageRequest() { - Metadata = new OptionalDictionary(); + Metadata = new ChangeTrackingDictionary(); } /// Initializes a new instance of . diff --git a/.dotnet/src/Generated/Models/ModifyRunRequest.Serialization.cs b/.dotnet/src/Generated/Models/ModifyRunRequest.Serialization.cs index 40da11ec2..c984d804a 100644 --- a/.dotnet/src/Generated/Models/ModifyRunRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/ModifyRunRequest.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -19,7 +21,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriter } writer.WriteStartObject(); - if (OptionalProperty.IsCollectionDefined(Metadata)) + if (Optional.IsCollectionDefined(Metadata)) { if (Metadata != null) { @@ -75,7 +77,7 @@ internal static ModifyRunRequest DeserializeModifyRunRequest(JsonElement element { return null; } - OptionalProperty> metadata = default; + IDictionary metadata = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -100,7 +102,7 @@ internal static ModifyRunRequest DeserializeModifyRunRequest(JsonElement element } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new ModifyRunRequest(OptionalProperty.ToDictionary(metadata), serializedAdditionalRawData); + return new ModifyRunRequest(metadata ?? new ChangeTrackingDictionary(), serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -141,5 +143,13 @@ internal static ModifyRunRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeModifyRunRequest(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ModifyRunRequest.cs b/.dotnet/src/Generated/Models/ModifyRunRequest.cs index 6def465a0..9cbe9b5fa 100644 --- a/.dotnet/src/Generated/Models/ModifyRunRequest.cs +++ b/.dotnet/src/Generated/Models/ModifyRunRequest.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -44,7 +44,7 @@ internal partial class ModifyRunRequest /// Initializes a new instance of . public ModifyRunRequest() { - Metadata = new OptionalDictionary(); + Metadata = new ChangeTrackingDictionary(); } /// Initializes a new instance of . diff --git a/.dotnet/src/Generated/Models/ModifyThreadRequest.Serialization.cs b/.dotnet/src/Generated/Models/ModifyThreadRequest.Serialization.cs index 5c6618494..cd64524a1 100644 --- a/.dotnet/src/Generated/Models/ModifyThreadRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/ModifyThreadRequest.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -19,7 +21,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWri } writer.WriteStartObject(); - if (OptionalProperty.IsCollectionDefined(Metadata)) + if (Optional.IsCollectionDefined(Metadata)) { if (Metadata != null) { @@ -75,7 +77,7 @@ internal static ModifyThreadRequest DeserializeModifyThreadRequest(JsonElement e { return null; } - OptionalProperty> metadata = default; + IDictionary metadata = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -100,7 +102,7 @@ internal static ModifyThreadRequest DeserializeModifyThreadRequest(JsonElement e } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new ModifyThreadRequest(OptionalProperty.ToDictionary(metadata), serializedAdditionalRawData); + return new ModifyThreadRequest(metadata ?? new ChangeTrackingDictionary(), serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -141,5 +143,13 @@ internal static ModifyThreadRequest FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeModifyThreadRequest(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ModifyThreadRequest.cs b/.dotnet/src/Generated/Models/ModifyThreadRequest.cs index df90174fa..346f01a71 100644 --- a/.dotnet/src/Generated/Models/ModifyThreadRequest.cs +++ b/.dotnet/src/Generated/Models/ModifyThreadRequest.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -44,7 +44,7 @@ internal partial class ModifyThreadRequest /// Initializes a new instance of . public ModifyThreadRequest() { - Metadata = new OptionalDictionary(); + Metadata = new ChangeTrackingDictionary(); } /// Initializes a new instance of . diff --git a/.dotnet/src/Generated/Models/OpenAIFile.Serialization.cs b/.dotnet/src/Generated/Models/OpenAIFile.Serialization.cs index 8243b7143..bd066a711 100644 --- a/.dotnet/src/Generated/Models/OpenAIFile.Serialization.cs +++ b/.dotnet/src/Generated/Models/OpenAIFile.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -40,7 +42,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOption writer.WriteStringValue(Purpose.ToString()); writer.WritePropertyName("status"u8); writer.WriteStringValue(Status.ToString()); - if (OptionalProperty.IsDefined(StatusDetails)) + if (Optional.IsDefined(StatusDetails)) { writer.WritePropertyName("status_details"u8); writer.WriteStringValue(StatusDetails); @@ -90,7 +92,7 @@ internal static OpenAIFile DeserializeOpenAIFile(JsonElement element, ModelReade OpenAIFileObject @object = default; OpenAIFilePurpose purpose = default; OpenAIFileStatus status = default; - OptionalProperty statusDetails = default; + string statusDetails = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -146,7 +148,16 @@ internal static OpenAIFile DeserializeOpenAIFile(JsonElement element, ModelReade } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new OpenAIFile(id, bytes, createdAt, filename, @object, purpose, status, statusDetails.Value, serializedAdditionalRawData); + return new OpenAIFile( + id, + bytes, + createdAt, + filename, + @object, + purpose, + status, + statusDetails, + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -187,5 +198,13 @@ internal static OpenAIFile FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeOpenAIFile(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/OpenAIFile.cs b/.dotnet/src/Generated/Models/OpenAIFile.cs index 697be44f8..e310ef98a 100644 --- a/.dotnet/src/Generated/Models/OpenAIFile.cs +++ b/.dotnet/src/Generated/Models/OpenAIFile.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -57,8 +57,8 @@ internal partial class OpenAIFile /// or is null. internal OpenAIFile(string id, long? bytes, DateTimeOffset createdAt, string filename, OpenAIFilePurpose purpose, OpenAIFileStatus status) { - if (id is null) throw new ArgumentNullException(nameof(id)); - if (filename is null) throw new ArgumentNullException(nameof(filename)); + Argument.AssertNotNull(id, nameof(id)); + Argument.AssertNotNull(filename, nameof(filename)); Id = id; Bytes = bytes; diff --git a/.dotnet/src/Generated/Models/RunCompletionUsage.Serialization.cs b/.dotnet/src/Generated/Models/RunCompletionUsage.Serialization.cs index b1cdb73da..6c064dc0a 100644 --- a/.dotnet/src/Generated/Models/RunCompletionUsage.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunCompletionUsage.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -132,5 +134,13 @@ internal static RunCompletionUsage FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeRunCompletionUsage(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/RunObject.Serialization.cs b/.dotnet/src/Generated/Models/RunObject.Serialization.cs index 70aa2431b..08d10f0d4 100644 --- a/.dotnet/src/Generated/Models/RunObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunObject.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -124,7 +126,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOptions writer.WriteStringValue(item); } writer.WriteEndArray(); - if (Metadata != null && OptionalProperty.IsCollectionDefined(Metadata)) + if (Metadata != null && Optional.IsCollectionDefined(Metadata)) { writer.WritePropertyName("metadata"u8); writer.WriteStartObject(); @@ -246,7 +248,7 @@ internal static RunObject DeserializeRunObject(JsonElement element, ModelReaderW requiredAction = null; continue; } - requiredAction = RunObjectRequiredAction.DeserializeRunObjectRequiredAction(property.Value); + requiredAction = RunObjectRequiredAction.DeserializeRunObjectRequiredAction(property.Value, options); continue; } if (property.NameEquals("last_error"u8)) @@ -256,7 +258,7 @@ internal static RunObject DeserializeRunObject(JsonElement element, ModelReaderW lastError = null; continue; } - lastError = RunObjectLastError.DeserializeRunObjectLastError(property.Value); + lastError = RunObjectLastError.DeserializeRunObjectLastError(property.Value, options); continue; } if (property.NameEquals("expires_at"u8)) @@ -360,7 +362,7 @@ internal static RunObject DeserializeRunObject(JsonElement element, ModelReaderW { if (property.Value.ValueKind == JsonValueKind.Null) { - metadata = new OptionalDictionary(); + metadata = new ChangeTrackingDictionary(); continue; } Dictionary dictionary = new Dictionary(); @@ -378,7 +380,7 @@ internal static RunObject DeserializeRunObject(JsonElement element, ModelReaderW usage = null; continue; } - usage = RunCompletionUsage.DeserializeRunCompletionUsage(property.Value); + usage = RunCompletionUsage.DeserializeRunCompletionUsage(property.Value, options); continue; } if (options.Format != "W") @@ -387,7 +389,27 @@ internal static RunObject DeserializeRunObject(JsonElement element, ModelReaderW } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new RunObject(id, @object, createdAt, threadId, assistantId, status, requiredAction, lastError, expiresAt, startedAt, cancelledAt, failedAt, completedAt, model, instructions, tools, fileIds, metadata, usage, serializedAdditionalRawData); + return new RunObject( + id, + @object, + createdAt, + threadId, + assistantId, + status, + requiredAction, + lastError, + expiresAt, + startedAt, + cancelledAt, + failedAt, + completedAt, + model, + instructions, + tools, + fileIds, + metadata, + usage, + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -428,5 +450,13 @@ internal static RunObject FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeRunObject(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/RunObject.cs b/.dotnet/src/Generated/Models/RunObject.cs index 680ffe5ea..dfa4a9104 100644 --- a/.dotnet/src/Generated/Models/RunObject.cs +++ b/.dotnet/src/Generated/Models/RunObject.cs @@ -1,9 +1,9 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; +using OpenAI; namespace OpenAI.Internal.Models { @@ -80,13 +80,13 @@ internal partial class RunObject /// , , , , , or is null. internal RunObject(string id, DateTimeOffset createdAt, string threadId, string assistantId, RunObjectStatus status, RunObjectRequiredAction requiredAction, RunObjectLastError lastError, DateTimeOffset? expiresAt, DateTimeOffset? startedAt, DateTimeOffset? cancelledAt, DateTimeOffset? failedAt, DateTimeOffset? completedAt, string model, string instructions, IEnumerable tools, IEnumerable fileIds, IReadOnlyDictionary metadata, RunCompletionUsage usage) { - if (id is null) throw new ArgumentNullException(nameof(id)); - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (model is null) throw new ArgumentNullException(nameof(model)); - if (instructions is null) throw new ArgumentNullException(nameof(instructions)); - if (tools is null) throw new ArgumentNullException(nameof(tools)); - if (fileIds is null) throw new ArgumentNullException(nameof(fileIds)); + Argument.AssertNotNull(id, nameof(id)); + Argument.AssertNotNull(threadId, nameof(threadId)); + Argument.AssertNotNull(assistantId, nameof(assistantId)); + Argument.AssertNotNull(model, nameof(model)); + Argument.AssertNotNull(instructions, nameof(instructions)); + Argument.AssertNotNull(tools, nameof(tools)); + Argument.AssertNotNull(fileIds, nameof(fileIds)); Id = id; CreatedAt = createdAt; diff --git a/.dotnet/src/Generated/Models/RunObjectLastError.Serialization.cs b/.dotnet/src/Generated/Models/RunObjectLastError.Serialization.cs index 6466b1546..99ff3ab89 100644 --- a/.dotnet/src/Generated/Models/RunObjectLastError.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunObjectLastError.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -124,5 +126,13 @@ internal static RunObjectLastError FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeRunObjectLastError(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/RunObjectLastError.cs b/.dotnet/src/Generated/Models/RunObjectLastError.cs index b824da830..185f4fcfa 100644 --- a/.dotnet/src/Generated/Models/RunObjectLastError.cs +++ b/.dotnet/src/Generated/Models/RunObjectLastError.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -47,7 +47,7 @@ internal partial class RunObjectLastError /// is null. internal RunObjectLastError(RunObjectLastErrorCode code, string message) { - if (message is null) throw new ArgumentNullException(nameof(message)); + Argument.AssertNotNull(message, nameof(message)); Code = code; Message = message; diff --git a/.dotnet/src/Generated/Models/RunObjectRequiredAction.Serialization.cs b/.dotnet/src/Generated/Models/RunObjectRequiredAction.Serialization.cs index b20e400db..b89e61f9b 100644 --- a/.dotnet/src/Generated/Models/RunObjectRequiredAction.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunObjectRequiredAction.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -74,7 +76,7 @@ internal static RunObjectRequiredAction DeserializeRunObjectRequiredAction(JsonE } if (property.NameEquals("submit_tool_outputs"u8)) { - submitToolOutputs = RunObjectRequiredActionSubmitToolOutputs.DeserializeRunObjectRequiredActionSubmitToolOutputs(property.Value); + submitToolOutputs = RunObjectRequiredActionSubmitToolOutputs.DeserializeRunObjectRequiredActionSubmitToolOutputs(property.Value, options); continue; } if (options.Format != "W") @@ -124,5 +126,13 @@ internal static RunObjectRequiredAction FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeRunObjectRequiredAction(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/RunObjectRequiredAction.cs b/.dotnet/src/Generated/Models/RunObjectRequiredAction.cs index c3515dfbd..67b3a12d2 100644 --- a/.dotnet/src/Generated/Models/RunObjectRequiredAction.cs +++ b/.dotnet/src/Generated/Models/RunObjectRequiredAction.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -46,7 +46,7 @@ internal partial class RunObjectRequiredAction /// is null. internal RunObjectRequiredAction(RunObjectRequiredActionSubmitToolOutputs submitToolOutputs) { - if (submitToolOutputs is null) throw new ArgumentNullException(nameof(submitToolOutputs)); + Argument.AssertNotNull(submitToolOutputs, nameof(submitToolOutputs)); SubmitToolOutputs = submitToolOutputs; } diff --git a/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.Serialization.cs b/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.Serialization.cs index 79032ea03..796357c84 100644 --- a/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -74,7 +76,7 @@ internal static RunObjectRequiredActionSubmitToolOutputs DeserializeRunObjectReq List array = new List(); foreach (var item in property.Value.EnumerateArray()) { - array.Add(RunToolCallObject.DeserializeRunToolCallObject(item)); + array.Add(RunToolCallObject.DeserializeRunToolCallObject(item, options)); } toolCalls = array; continue; @@ -126,5 +128,13 @@ internal static RunObjectRequiredActionSubmitToolOutputs FromResponse(PipelineRe using var document = JsonDocument.Parse(response.Content); return DeserializeRunObjectRequiredActionSubmitToolOutputs(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.cs b/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.cs index 044c28ed8..a97134507 100644 --- a/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.cs +++ b/.dotnet/src/Generated/Models/RunObjectRequiredActionSubmitToolOutputs.cs @@ -1,9 +1,9 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; +using OpenAI; namespace OpenAI.Internal.Models { @@ -47,7 +47,7 @@ internal partial class RunObjectRequiredActionSubmitToolOutputs /// is null. internal RunObjectRequiredActionSubmitToolOutputs(IEnumerable toolCalls) { - if (toolCalls is null) throw new ArgumentNullException(nameof(toolCalls)); + Argument.AssertNotNull(toolCalls, nameof(toolCalls)); ToolCalls = toolCalls.ToList(); } diff --git a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.Serialization.cs b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.Serialization.cs index 60be54dde..470744c95 100644 --- a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -74,7 +76,7 @@ internal static RunStepDetailsMessageCreationObject DeserializeRunStepDetailsMes } if (property.NameEquals("message_creation"u8)) { - messageCreation = RunStepDetailsMessageCreationObjectMessageCreation.DeserializeRunStepDetailsMessageCreationObjectMessageCreation(property.Value); + messageCreation = RunStepDetailsMessageCreationObjectMessageCreation.DeserializeRunStepDetailsMessageCreationObjectMessageCreation(property.Value, options); continue; } if (options.Format != "W") @@ -124,5 +126,13 @@ internal static RunStepDetailsMessageCreationObject FromResponse(PipelineRespons using var document = JsonDocument.Parse(response.Content); return DeserializeRunStepDetailsMessageCreationObject(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.cs b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.cs index 1de631b8d..14f926190 100644 --- a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.cs +++ b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObject.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -46,7 +46,7 @@ internal partial class RunStepDetailsMessageCreationObject /// is null. internal RunStepDetailsMessageCreationObject(RunStepDetailsMessageCreationObjectMessageCreation messageCreation) { - if (messageCreation is null) throw new ArgumentNullException(nameof(messageCreation)); + Argument.AssertNotNull(messageCreation, nameof(messageCreation)); MessageCreation = messageCreation; } diff --git a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.Serialization.cs b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.Serialization.cs index b1f56e27c..67a374c66 100644 --- a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -116,5 +118,13 @@ internal static RunStepDetailsMessageCreationObjectMessageCreation FromResponse( using var document = JsonDocument.Parse(response.Content); return DeserializeRunStepDetailsMessageCreationObjectMessageCreation(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.cs b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.cs index a7e725f0a..c0915a420 100644 --- a/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.cs +++ b/.dotnet/src/Generated/Models/RunStepDetailsMessageCreationObjectMessageCreation.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -46,7 +46,7 @@ internal partial class RunStepDetailsMessageCreationObjectMessageCreation /// is null. internal RunStepDetailsMessageCreationObjectMessageCreation(string messageId) { - if (messageId is null) throw new ArgumentNullException(nameof(messageId)); + Argument.AssertNotNull(messageId, nameof(messageId)); MessageId = messageId; } diff --git a/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.Serialization.cs b/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.Serialization.cs index c38c64703..6ad4f9fa3 100644 --- a/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -153,5 +155,13 @@ internal static RunStepDetailsToolCallsObject FromResponse(PipelineResponse resp using var document = JsonDocument.Parse(response.Content); return DeserializeRunStepDetailsToolCallsObject(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.cs b/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.cs index 37fb29ed7..00a388c37 100644 --- a/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.cs +++ b/.dotnet/src/Generated/Models/RunStepDetailsToolCallsObject.cs @@ -1,9 +1,9 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; +using OpenAI; namespace OpenAI.Internal.Models { @@ -50,7 +50,7 @@ internal partial class RunStepDetailsToolCallsObject /// is null. internal RunStepDetailsToolCallsObject(IEnumerable toolCalls) { - if (toolCalls is null) throw new ArgumentNullException(nameof(toolCalls)); + Argument.AssertNotNull(toolCalls, nameof(toolCalls)); ToolCalls = toolCalls.ToList(); } diff --git a/.dotnet/src/Generated/Models/RunStepObject.Serialization.cs b/.dotnet/src/Generated/Models/RunStepObject.Serialization.cs index b824f8e76..b9656d7d0 100644 --- a/.dotnet/src/Generated/Models/RunStepObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunStepObject.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -89,7 +91,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOpt { writer.WriteNull("completed_at"); } - if (Metadata != null && OptionalProperty.IsCollectionDefined(Metadata)) + if (Metadata != null && Optional.IsCollectionDefined(Metadata)) { writer.WritePropertyName("metadata"u8); writer.WriteStartObject(); @@ -223,7 +225,7 @@ internal static RunStepObject DeserializeRunStepObject(JsonElement element, Mode lastError = null; continue; } - lastError = RunStepObjectLastError.DeserializeRunStepObjectLastError(property.Value); + lastError = RunStepObjectLastError.DeserializeRunStepObjectLastError(property.Value, options); continue; } if (property.NameEquals("expires_at"u8)) @@ -270,7 +272,7 @@ internal static RunStepObject DeserializeRunStepObject(JsonElement element, Mode { if (property.Value.ValueKind == JsonValueKind.Null) { - metadata = new OptionalDictionary(); + metadata = new ChangeTrackingDictionary(); continue; } Dictionary dictionary = new Dictionary(); @@ -288,7 +290,7 @@ internal static RunStepObject DeserializeRunStepObject(JsonElement element, Mode usage = null; continue; } - usage = RunCompletionUsage.DeserializeRunCompletionUsage(property.Value); + usage = RunCompletionUsage.DeserializeRunCompletionUsage(property.Value, options); continue; } if (options.Format != "W") @@ -297,7 +299,24 @@ internal static RunStepObject DeserializeRunStepObject(JsonElement element, Mode } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new RunStepObject(id, @object, createdAt, assistantId, threadId, runId, type, status, stepDetails, lastError, expiresAt, cancelledAt, failedAt, completedAt, metadata, usage, serializedAdditionalRawData); + return new RunStepObject( + id, + @object, + createdAt, + assistantId, + threadId, + runId, + type, + status, + stepDetails, + lastError, + expiresAt, + cancelledAt, + failedAt, + completedAt, + metadata, + usage, + serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -338,5 +357,13 @@ internal static RunStepObject FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeRunStepObject(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/RunStepObject.cs b/.dotnet/src/Generated/Models/RunStepObject.cs index ebd98f23f..2827c4f8d 100644 --- a/.dotnet/src/Generated/Models/RunStepObject.cs +++ b/.dotnet/src/Generated/Models/RunStepObject.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -70,11 +70,11 @@ internal partial class RunStepObject /// , , , or is null. internal RunStepObject(string id, DateTimeOffset createdAt, string assistantId, string threadId, string runId, RunStepObjectType type, RunStepObjectStatus status, BinaryData stepDetails, RunStepObjectLastError lastError, DateTimeOffset? expiresAt, DateTimeOffset? cancelledAt, DateTimeOffset? failedAt, DateTimeOffset? completedAt, IReadOnlyDictionary metadata, RunCompletionUsage usage) { - if (id is null) throw new ArgumentNullException(nameof(id)); - if (assistantId is null) throw new ArgumentNullException(nameof(assistantId)); - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (runId is null) throw new ArgumentNullException(nameof(runId)); - if (stepDetails is null) throw new ArgumentNullException(nameof(stepDetails)); + Argument.AssertNotNull(id, nameof(id)); + Argument.AssertNotNull(assistantId, nameof(assistantId)); + Argument.AssertNotNull(threadId, nameof(threadId)); + Argument.AssertNotNull(runId, nameof(runId)); + Argument.AssertNotNull(stepDetails, nameof(stepDetails)); Id = id; CreatedAt = createdAt; diff --git a/.dotnet/src/Generated/Models/RunStepObjectLastError.Serialization.cs b/.dotnet/src/Generated/Models/RunStepObjectLastError.Serialization.cs index bced34068..832446fd7 100644 --- a/.dotnet/src/Generated/Models/RunStepObjectLastError.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunStepObjectLastError.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -124,5 +126,13 @@ internal static RunStepObjectLastError FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeRunStepObjectLastError(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/RunStepObjectLastError.cs b/.dotnet/src/Generated/Models/RunStepObjectLastError.cs index 32d41e0fd..ea325cd55 100644 --- a/.dotnet/src/Generated/Models/RunStepObjectLastError.cs +++ b/.dotnet/src/Generated/Models/RunStepObjectLastError.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -47,7 +47,7 @@ internal partial class RunStepObjectLastError /// is null. internal RunStepObjectLastError(RunStepObjectLastErrorCode code, string message) { - if (message is null) throw new ArgumentNullException(nameof(message)); + Argument.AssertNotNull(message, nameof(message)); Code = code; Message = message; diff --git a/.dotnet/src/Generated/Models/RunToolCallObject.Serialization.cs b/.dotnet/src/Generated/Models/RunToolCallObject.Serialization.cs index 8c1145c63..ae09f2a8a 100644 --- a/.dotnet/src/Generated/Models/RunToolCallObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunToolCallObject.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -82,7 +84,7 @@ internal static RunToolCallObject DeserializeRunToolCallObject(JsonElement eleme } if (property.NameEquals("function"u8)) { - function = RunToolCallObjectFunction.DeserializeRunToolCallObjectFunction(property.Value); + function = RunToolCallObjectFunction.DeserializeRunToolCallObjectFunction(property.Value, options); continue; } if (options.Format != "W") @@ -132,5 +134,13 @@ internal static RunToolCallObject FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeRunToolCallObject(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/RunToolCallObject.cs b/.dotnet/src/Generated/Models/RunToolCallObject.cs index 83c3a699c..dd632156c 100644 --- a/.dotnet/src/Generated/Models/RunToolCallObject.cs +++ b/.dotnet/src/Generated/Models/RunToolCallObject.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -50,8 +50,8 @@ internal partial class RunToolCallObject /// or is null. internal RunToolCallObject(string id, RunToolCallObjectFunction function) { - if (id is null) throw new ArgumentNullException(nameof(id)); - if (function is null) throw new ArgumentNullException(nameof(function)); + Argument.AssertNotNull(id, nameof(id)); + Argument.AssertNotNull(function, nameof(function)); Id = id; Function = function; diff --git a/.dotnet/src/Generated/Models/RunToolCallObjectFunction.Serialization.cs b/.dotnet/src/Generated/Models/RunToolCallObjectFunction.Serialization.cs index d7af27898..3837aaa2e 100644 --- a/.dotnet/src/Generated/Models/RunToolCallObjectFunction.Serialization.cs +++ b/.dotnet/src/Generated/Models/RunToolCallObjectFunction.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -124,5 +126,13 @@ internal static RunToolCallObjectFunction FromResponse(PipelineResponse response using var document = JsonDocument.Parse(response.Content); return DeserializeRunToolCallObjectFunction(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/RunToolCallObjectFunction.cs b/.dotnet/src/Generated/Models/RunToolCallObjectFunction.cs index 15f52388a..0a867e576 100644 --- a/.dotnet/src/Generated/Models/RunToolCallObjectFunction.cs +++ b/.dotnet/src/Generated/Models/RunToolCallObjectFunction.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -47,8 +47,8 @@ internal partial class RunToolCallObjectFunction /// or is null. internal RunToolCallObjectFunction(string name, string arguments) { - if (name is null) throw new ArgumentNullException(nameof(name)); - if (arguments is null) throw new ArgumentNullException(nameof(arguments)); + Argument.AssertNotNull(name, nameof(name)); + Argument.AssertNotNull(arguments, nameof(arguments)); Name = name; Arguments = arguments; diff --git a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.Serialization.cs b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.Serialization.cs index a4b178b12..d38502d9b 100644 --- a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.Serialization.cs +++ b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -74,7 +76,7 @@ internal static SubmitToolOutputsRunRequest DeserializeSubmitToolOutputsRunReque List array = new List(); foreach (var item in property.Value.EnumerateArray()) { - array.Add(SubmitToolOutputsRunRequestToolOutput.DeserializeSubmitToolOutputsRunRequestToolOutput(item)); + array.Add(SubmitToolOutputsRunRequestToolOutput.DeserializeSubmitToolOutputsRunRequestToolOutput(item, options)); } toolOutputs = array; continue; @@ -126,5 +128,13 @@ internal static SubmitToolOutputsRunRequest FromResponse(PipelineResponse respon using var document = JsonDocument.Parse(response.Content); return DeserializeSubmitToolOutputsRunRequest(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.cs b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.cs index 76e994a43..2bed85b35 100644 --- a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.cs +++ b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequest.cs @@ -1,9 +1,9 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; using System.Linq; +using OpenAI; namespace OpenAI.Internal.Models { @@ -47,7 +47,7 @@ internal partial class SubmitToolOutputsRunRequest /// is null. public SubmitToolOutputsRunRequest(IEnumerable toolOutputs) { - if (toolOutputs is null) throw new ArgumentNullException(nameof(toolOutputs)); + Argument.AssertNotNull(toolOutputs, nameof(toolOutputs)); ToolOutputs = toolOutputs.ToList(); } diff --git a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutput.Serialization.cs b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutput.Serialization.cs index ab9abfeb1..c18a1644b 100644 --- a/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutput.Serialization.cs +++ b/.dotnet/src/Generated/Models/SubmitToolOutputsRunRequestToolOutput.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -19,12 +21,12 @@ void IJsonModel.Write(Utf8JsonWriter writ } writer.WriteStartObject(); - if (OptionalProperty.IsDefined(ToolCallId)) + if (Optional.IsDefined(ToolCallId)) { writer.WritePropertyName("tool_call_id"u8); writer.WriteStringValue(ToolCallId); } - if (OptionalProperty.IsDefined(Output)) + if (Optional.IsDefined(Output)) { writer.WritePropertyName("output"u8); writer.WriteStringValue(Output); @@ -67,8 +69,8 @@ internal static SubmitToolOutputsRunRequestToolOutput DeserializeSubmitToolOutpu { return null; } - OptionalProperty toolCallId = default; - OptionalProperty output = default; + string toolCallId = default; + string output = default; IDictionary serializedAdditionalRawData = default; Dictionary additionalPropertiesDictionary = new Dictionary(); foreach (var property in element.EnumerateObject()) @@ -89,7 +91,7 @@ internal static SubmitToolOutputsRunRequestToolOutput DeserializeSubmitToolOutpu } } serializedAdditionalRawData = additionalPropertiesDictionary; - return new SubmitToolOutputsRunRequestToolOutput(toolCallId.Value, output.Value, serializedAdditionalRawData); + return new SubmitToolOutputsRunRequestToolOutput(toolCallId, output, serializedAdditionalRawData); } BinaryData IPersistableModel.Write(ModelReaderWriterOptions options) @@ -130,5 +132,13 @@ internal static SubmitToolOutputsRunRequestToolOutput FromResponse(PipelineRespo using var document = JsonDocument.Parse(response.Content); return DeserializeSubmitToolOutputsRunRequestToolOutput(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ThreadObject.Serialization.cs b/.dotnet/src/Generated/Models/ThreadObject.Serialization.cs index c87050e03..cb9c70752 100644 --- a/.dotnet/src/Generated/Models/ThreadObject.Serialization.cs +++ b/.dotnet/src/Generated/Models/ThreadObject.Serialization.cs @@ -2,9 +2,11 @@ using System; using OpenAI.ClientShared.Internal; +using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; using System.Text.Json; +using OpenAI; namespace OpenAI.Internal.Models { @@ -25,7 +27,7 @@ void IJsonModel.Write(Utf8JsonWriter writer, ModelReaderWriterOpti writer.WriteStringValue(Object.ToString()); writer.WritePropertyName("created_at"u8); writer.WriteNumberValue(CreatedAt, "U"); - if (Metadata != null && OptionalProperty.IsCollectionDefined(Metadata)) + if (Metadata != null && Optional.IsCollectionDefined(Metadata)) { writer.WritePropertyName("metadata"u8); writer.WriteStartObject(); @@ -105,7 +107,7 @@ internal static ThreadObject DeserializeThreadObject(JsonElement element, ModelR { if (property.Value.ValueKind == JsonValueKind.Null) { - metadata = new OptionalDictionary(); + metadata = new ChangeTrackingDictionary(); continue; } Dictionary dictionary = new Dictionary(); @@ -163,5 +165,13 @@ internal static ThreadObject FromResponse(PipelineResponse response) using var document = JsonDocument.Parse(response.Content); return DeserializeThreadObject(document.RootElement); } + + /// Convert into a Utf8JsonRequestBody. + internal virtual BinaryContent ToRequestBody() + { + var content = new Utf8JsonRequestBody(); + content.JsonWriter.WriteObjectValue(this); + return content; + } } } diff --git a/.dotnet/src/Generated/Models/ThreadObject.cs b/.dotnet/src/Generated/Models/ThreadObject.cs index b4cf5143d..4176811ee 100644 --- a/.dotnet/src/Generated/Models/ThreadObject.cs +++ b/.dotnet/src/Generated/Models/ThreadObject.cs @@ -1,8 +1,8 @@ // using System; -using OpenAI.ClientShared.Internal; using System.Collections.Generic; +using OpenAI; namespace OpenAI.Internal.Models { @@ -52,7 +52,7 @@ internal partial class ThreadObject /// is null. internal ThreadObject(string id, DateTimeOffset createdAt, IReadOnlyDictionary metadata) { - if (id is null) throw new ArgumentNullException(nameof(id)); + Argument.AssertNotNull(id, nameof(id)); Id = id; CreatedAt = createdAt; diff --git a/.dotnet/src/Generated/ModelsOps.cs b/.dotnet/src/Generated/ModelsOps.cs index 3110695ec..6ae259a43 100644 --- a/.dotnet/src/Generated/ModelsOps.cs +++ b/.dotnet/src/Generated/ModelsOps.cs @@ -81,16 +81,18 @@ public virtual ClientResult GetModels() public virtual async Task GetModelsAsync(RequestOptions options) { options ??= new RequestOptions(); - using PipelineMessage message = CreateGetModelsRequest(options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; - - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + // using var scope = ClientDiagnostics.CreateSpan("ModelsOps.GetModels"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateGetModelsRequest(options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -115,16 +117,18 @@ public virtual async Task GetModelsAsync(RequestOptions options) public virtual ClientResult GetModels(RequestOptions options) { options ??= new RequestOptions(); - using PipelineMessage message = CreateGetModelsRequest(options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; - - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + // using var scope = ClientDiagnostics.CreateSpan("ModelsOps.GetModels"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateGetModelsRequest(options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -136,8 +140,7 @@ public virtual ClientResult GetModels(RequestOptions options) /// is an empty string, and was expected to be non-empty. public virtual async Task> RetrieveAsync(string model) { - if (model is null) throw new ArgumentNullException(nameof(model)); - if (string.IsNullOrEmpty(model)) throw new ArgumentException(nameof(model)); + Argument.AssertNotNullOrEmpty(model, nameof(model)); ClientResult result = await RetrieveAsync(model, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(Model.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -152,8 +155,7 @@ public virtual async Task> RetrieveAsync(string model) /// is an empty string, and was expected to be non-empty. public virtual ClientResult Retrieve(string model) { - if (model is null) throw new ArgumentNullException(nameof(model)); - if (string.IsNullOrEmpty(model)) throw new ArgumentException(nameof(model)); + Argument.AssertNotNullOrEmpty(model, nameof(model)); ClientResult result = Retrieve(model, DefaultRequestContext); return ClientResult.FromValue(Model.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -183,19 +185,21 @@ public virtual ClientResult Retrieve(string model) /// The response returned from the service. public virtual async Task RetrieveAsync(string model, RequestOptions options) { - if (model is null) throw new ArgumentNullException(nameof(model)); - if (string.IsNullOrEmpty(model)) throw new ArgumentException(nameof(model)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateRetrieveRequest(model, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(model, nameof(model)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("ModelsOps.Retrieve"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateRetrieveRequest(model, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -222,19 +226,21 @@ public virtual async Task RetrieveAsync(string model, RequestOptio /// The response returned from the service. public virtual ClientResult Retrieve(string model, RequestOptions options) { - if (model is null) throw new ArgumentNullException(nameof(model)); - if (string.IsNullOrEmpty(model)) throw new ArgumentException(nameof(model)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateRetrieveRequest(model, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(model, nameof(model)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("ModelsOps.Retrieve"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateRetrieveRequest(model, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Delete a fine-tuned model. You must have the Owner role in your organization to delete a model. @@ -243,8 +249,7 @@ public virtual ClientResult Retrieve(string model, RequestOptions options) /// is an empty string, and was expected to be non-empty. public virtual async Task> DeleteAsync(string model) { - if (model is null) throw new ArgumentNullException(nameof(model)); - if (string.IsNullOrEmpty(model)) throw new ArgumentException(nameof(model)); + Argument.AssertNotNullOrEmpty(model, nameof(model)); ClientResult result = await DeleteAsync(model, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(DeleteModelResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -256,8 +261,7 @@ public virtual async Task> DeleteAsync(string /// is an empty string, and was expected to be non-empty. public virtual ClientResult Delete(string model) { - if (model is null) throw new ArgumentNullException(nameof(model)); - if (string.IsNullOrEmpty(model)) throw new ArgumentException(nameof(model)); + Argument.AssertNotNullOrEmpty(model, nameof(model)); ClientResult result = Delete(model, DefaultRequestContext); return ClientResult.FromValue(DeleteModelResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -286,19 +290,21 @@ public virtual ClientResult Delete(string model) /// The response returned from the service. public virtual async Task DeleteAsync(string model, RequestOptions options) { - if (model is null) throw new ArgumentNullException(nameof(model)); - if (string.IsNullOrEmpty(model)) throw new ArgumentException(nameof(model)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateDeleteRequest(model, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(model, nameof(model)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("ModelsOps.Delete"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateDeleteRequest(model, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -324,19 +330,21 @@ public virtual async Task DeleteAsync(string model, RequestOptions /// The response returned from the service. public virtual ClientResult Delete(string model, RequestOptions options) { - if (model is null) throw new ArgumentNullException(nameof(model)); - if (string.IsNullOrEmpty(model)) throw new ArgumentException(nameof(model)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateDeleteRequest(model, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(model, nameof(model)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("ModelsOps.Delete"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateDeleteRequest(model, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } internal PipelineMessage CreateGetModelsRequest(RequestOptions options) diff --git a/.dotnet/src/Generated/Moderations.cs b/.dotnet/src/Generated/Moderations.cs index ef4c93f63..0e76f8341 100644 --- a/.dotnet/src/Generated/Moderations.cs +++ b/.dotnet/src/Generated/Moderations.cs @@ -44,7 +44,7 @@ internal Moderations(ClientPipeline pipeline, ApiKeyCredential credential, Uri e /// is null. public virtual async Task> CreateModerationAsync(CreateModerationRequest content) { - if (content is null) throw new ArgumentNullException(nameof(content)); + Argument.AssertNotNull(content, nameof(content)); using BinaryContent content0 = BinaryContent.Create(content); ClientResult result = await CreateModerationAsync(content0, DefaultRequestContext).ConfigureAwait(false); @@ -56,7 +56,7 @@ public virtual async Task> CreateModerati /// is null. public virtual ClientResult CreateModeration(CreateModerationRequest content) { - if (content is null) throw new ArgumentNullException(nameof(content)); + Argument.AssertNotNull(content, nameof(content)); using BinaryContent content0 = BinaryContent.Create(content); ClientResult result = CreateModeration(content0, DefaultRequestContext); @@ -85,18 +85,21 @@ public virtual ClientResult CreateModeration(CreateMod /// The response returned from the service. public virtual async Task CreateModerationAsync(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateModerationRequest(content, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Moderations.CreateModeration"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateCreateModerationRequest(content, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -121,18 +124,21 @@ public virtual async Task CreateModerationAsync(BinaryContent cont /// The response returned from the service. public virtual ClientResult CreateModeration(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateModerationRequest(content, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Moderations.CreateModeration"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateCreateModerationRequest(content, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } internal PipelineMessage CreateCreateModerationRequest(BinaryContent content, RequestOptions options) diff --git a/.dotnet/src/Generated/OpenAIClient.cs b/.dotnet/src/Generated/OpenAIClient.cs index 014c7aada..7fe8c431f 100644 --- a/.dotnet/src/Generated/OpenAIClient.cs +++ b/.dotnet/src/Generated/OpenAIClient.cs @@ -39,8 +39,8 @@ protected OpenAIClient() /// or is null. public OpenAIClient(Uri endpoint, ApiKeyCredential credential, OpenAIClientOptions options) { - if (endpoint is null) throw new ArgumentNullException(nameof(endpoint)); - if (credential is null) throw new ArgumentNullException(nameof(credential)); + Argument.AssertNotNull(endpoint, nameof(endpoint)); + Argument.AssertNotNull(credential, nameof(credential)); options ??= new OpenAIClientOptions(); _credential = credential; var authenticationPolicy = ApiKeyAuthenticationPolicy.CreateBearerAuthorizationPolicy(_credential); diff --git a/.dotnet/src/Generated/OpenAIModelFactory.cs b/.dotnet/src/Generated/OpenAIModelFactory.cs index cc63a0fba..5722c2d7a 100644 --- a/.dotnet/src/Generated/OpenAIModelFactory.cs +++ b/.dotnet/src/Generated/OpenAIModelFactory.cs @@ -127,7 +127,25 @@ public static CreateCompletionRequest CreateCompletionRequest(CreateCompletionRe { logitBias ??= new Dictionary(); - return new CreateCompletionRequest(model, prompt, bestOf, echo, frequencyPenalty, logitBias, logprobs, maxTokens, n, presencePenalty, seed, stop, stream, suffix, temperature, topP, user, serializedAdditionalRawData: null); + return new CreateCompletionRequest( + model, + prompt, + bestOf, + echo, + frequencyPenalty, + logitBias, + logprobs, + maxTokens, + n, + presencePenalty, + seed, + stop, + stream, + suffix, + temperature, + topP, + user, + serializedAdditionalRawData: null); } /// Initializes a new instance of . @@ -148,7 +166,15 @@ public static CreateCompletionResponse CreateCompletionResponse(string id = null { choices ??= new List(); - return new CreateCompletionResponse(id, choices?.ToList(), created, model, systemFingerprint, @object, usage, serializedAdditionalRawData: null); + return new CreateCompletionResponse( + id, + choices?.ToList(), + created, + model, + systemFingerprint, + @object, + usage, + serializedAdditionalRawData: null); } /// Initializes a new instance of . @@ -221,7 +247,13 @@ public static CreateCompletionResponseChoiceLogprobs CreateCompletionResponseCho /// A new instance for mocking. public static CreateFineTuningJobRequest CreateFineTuningJobRequest(CreateFineTuningJobRequestModel model = default, string trainingFile = null, CreateFineTuningJobRequestHyperparameters hyperparameters = null, string suffix = null, string validationFile = null) { - return new CreateFineTuningJobRequest(model, trainingFile, hyperparameters, suffix, validationFile, serializedAdditionalRawData: null); + return new CreateFineTuningJobRequest( + model, + trainingFile, + hyperparameters, + suffix, + validationFile, + serializedAdditionalRawData: null); } /// Initializes a new instance of . @@ -271,7 +303,22 @@ public static FineTuningJob FineTuningJob(string id = null, DateTimeOffset creat { resultFiles ??= new List(); - return new FineTuningJob(id, createdAt, error, fineTunedModel, finishedAt, hyperparameters, model, @object, organizationId, resultFiles?.ToList(), status, trainedTokens, trainingFile, validationFile, serializedAdditionalRawData: null); + return new FineTuningJob( + id, + createdAt, + error, + fineTunedModel, + finishedAt, + hyperparameters, + model, + @object, + organizationId, + resultFiles?.ToList(), + status, + trainedTokens, + trainingFile, + validationFile, + serializedAdditionalRawData: null); } /// Initializes a new instance of . @@ -333,7 +380,13 @@ public static ListFineTuningJobEventsResponse ListFineTuningJobEventsResponse(IE /// A new instance for mocking. public static FineTuningJobEvent FineTuningJobEvent(string id = null, DateTimeOffset createdAt = default, FineTuningJobEventLevel level = default, string message = null, FineTuningJobEventObject @object = default) { - return new FineTuningJobEvent(id, createdAt, level, message, @object, serializedAdditionalRawData: null); + return new FineTuningJobEvent( + id, + createdAt, + level, + message, + @object, + serializedAdditionalRawData: null); } /// Initializes a new instance of . @@ -390,7 +443,18 @@ public static MessageObject MessageObject(string id = null, MessageObjectObject fileIds ??= new List(); metadata ??= new Dictionary(); - return new MessageObject(id, @object, createdAt, threadId, role, content?.ToList(), assistantId, runId, fileIds?.ToList(), metadata, serializedAdditionalRawData: null); + return new MessageObject( + id, + @object, + createdAt, + threadId, + role, + content?.ToList(), + assistantId, + runId, + fileIds?.ToList(), + metadata, + serializedAdditionalRawData: null); } /// Initializes a new instance of . @@ -404,7 +468,13 @@ public static ListMessagesResponse ListMessagesResponse(ListMessagesResponseObje { data ??= new List(); - return new ListMessagesResponse(@object, data?.ToList(), firstId, lastId, hasMore, serializedAdditionalRawData: null); + return new ListMessagesResponse( + @object, + data?.ToList(), + firstId, + lastId, + hasMore, + serializedAdditionalRawData: null); } /// Initializes a new instance of . @@ -418,7 +488,13 @@ public static ListMessageFilesResponse ListMessageFilesResponse(ListMessageFiles { data ??= new List(); - return new ListMessageFilesResponse(@object, data?.ToList(), firstId, lastId, hasMore, serializedAdditionalRawData: null); + return new ListMessageFilesResponse( + @object, + data?.ToList(), + firstId, + lastId, + hasMore, + serializedAdditionalRawData: null); } /// Initializes a new instance of . @@ -491,7 +567,14 @@ public static CreateThreadAndRunRequest CreateThreadAndRunRequest(string assista tools ??= new List(); metadata ??= new Dictionary(); - return new CreateThreadAndRunRequest(assistantId, thread, model, instructions, tools?.ToList(), metadata, serializedAdditionalRawData: null); + return new CreateThreadAndRunRequest( + assistantId, + thread, + model, + instructions, + tools?.ToList(), + metadata, + serializedAdditionalRawData: null); } /// Initializes a new instance of . @@ -537,7 +620,27 @@ public static RunObject RunObject(string id = null, RunObjectObject @object = de fileIds ??= new List(); metadata ??= new Dictionary(); - return new RunObject(id, @object, createdAt, threadId, assistantId, status, requiredAction, lastError, expiresAt, startedAt, cancelledAt, failedAt, completedAt, model, instructions, tools?.ToList(), fileIds?.ToList(), metadata, usage, serializedAdditionalRawData: null); + return new RunObject( + id, + @object, + createdAt, + threadId, + assistantId, + status, + requiredAction, + lastError, + expiresAt, + startedAt, + cancelledAt, + failedAt, + completedAt, + model, + instructions, + tools?.ToList(), + fileIds?.ToList(), + metadata, + usage, + serializedAdditionalRawData: null); } /// Initializes a new instance of . @@ -630,7 +733,14 @@ public static CreateRunRequest CreateRunRequest(string assistantId = null, strin tools ??= new List(); metadata ??= new Dictionary(); - return new CreateRunRequest(assistantId, model, instructions, additionalInstructions, tools?.ToList(), metadata, serializedAdditionalRawData: null); + return new CreateRunRequest( + assistantId, + model, + instructions, + additionalInstructions, + tools?.ToList(), + metadata, + serializedAdditionalRawData: null); } /// Initializes a new instance of . @@ -644,7 +754,13 @@ public static ListRunsResponse ListRunsResponse(ListRunsResponseObject @object = { data ??= new List(); - return new ListRunsResponse(@object, data?.ToList(), firstId, lastId, hasMore, serializedAdditionalRawData: null); + return new ListRunsResponse( + @object, + data?.ToList(), + firstId, + lastId, + hasMore, + serializedAdditionalRawData: null); } /// Initializes a new instance of . @@ -658,7 +774,13 @@ public static ListRunStepsResponse ListRunStepsResponse(ListRunStepsResponseObje { data ??= new List(); - return new ListRunStepsResponse(@object, data?.ToList(), firstId, lastId, hasMore, serializedAdditionalRawData: null); + return new ListRunStepsResponse( + @object, + data?.ToList(), + firstId, + lastId, + hasMore, + serializedAdditionalRawData: null); } /// Initializes a new instance of . @@ -693,7 +815,24 @@ public static RunStepObject RunStepObject(string id = null, RunStepObjectObject { metadata ??= new Dictionary(); - return new RunStepObject(id, @object, createdAt, assistantId, threadId, runId, type, status, stepDetails, lastError, expiresAt, cancelledAt, failedAt, completedAt, metadata, usage, serializedAdditionalRawData: null); + return new RunStepObject( + id, + @object, + createdAt, + assistantId, + threadId, + runId, + type, + status, + stepDetails, + lastError, + expiresAt, + cancelledAt, + failedAt, + completedAt, + metadata, + usage, + serializedAdditionalRawData: null); } /// Initializes a new instance of . diff --git a/.dotnet/src/Generated/Runs.cs b/.dotnet/src/Generated/Runs.cs index 66d2cfc1c..2ef98a2c1 100644 --- a/.dotnet/src/Generated/Runs.cs +++ b/.dotnet/src/Generated/Runs.cs @@ -44,7 +44,7 @@ internal Runs(ClientPipeline pipeline, ApiKeyCredential credential, Uri endpoint /// is null. public virtual async Task> CreateThreadAndRunAsync(CreateThreadAndRunRequest threadAndRun) { - if (threadAndRun is null) throw new ArgumentNullException(nameof(threadAndRun)); + Argument.AssertNotNull(threadAndRun, nameof(threadAndRun)); using BinaryContent content = BinaryContent.Create(threadAndRun); ClientResult result = await CreateThreadAndRunAsync(content, DefaultRequestContext).ConfigureAwait(false); @@ -56,7 +56,7 @@ public virtual async Task> CreateThreadAndRunAsync(Creat /// is null. public virtual ClientResult CreateThreadAndRun(CreateThreadAndRunRequest threadAndRun) { - if (threadAndRun is null) throw new ArgumentNullException(nameof(threadAndRun)); + Argument.AssertNotNull(threadAndRun, nameof(threadAndRun)); using BinaryContent content = BinaryContent.Create(threadAndRun); ClientResult result = CreateThreadAndRun(content, DefaultRequestContext); @@ -85,18 +85,21 @@ public virtual ClientResult CreateThreadAndRun(CreateThreadAndRunRequ /// The response returned from the service. public virtual async Task CreateThreadAndRunAsync(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateThreadAndRunRequest(content, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Runs.CreateThreadAndRun"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateCreateThreadAndRunRequest(content, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -121,18 +124,21 @@ public virtual async Task CreateThreadAndRunAsync(BinaryContent co /// The response returned from the service. public virtual ClientResult CreateThreadAndRun(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateThreadAndRunRequest(content, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Runs.CreateThreadAndRun"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateCreateThreadAndRunRequest(content, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Create a run. @@ -142,9 +148,8 @@ public virtual ClientResult CreateThreadAndRun(BinaryContent content, RequestOpt /// is an empty string, and was expected to be non-empty. public virtual async Task> CreateRunAsync(string threadId, CreateRunRequest run) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (run is null) throw new ArgumentNullException(nameof(run)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNull(run, nameof(run)); using BinaryContent content = BinaryContent.Create(run); ClientResult result = await CreateRunAsync(threadId, content, DefaultRequestContext).ConfigureAwait(false); @@ -158,9 +163,8 @@ public virtual async Task> CreateRunAsync(string threadI /// is an empty string, and was expected to be non-empty. public virtual ClientResult CreateRun(string threadId, CreateRunRequest run) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (run is null) throw new ArgumentNullException(nameof(run)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNull(run, nameof(run)); using BinaryContent content = BinaryContent.Create(run); ClientResult result = CreateRun(threadId, content, DefaultRequestContext); @@ -191,20 +195,22 @@ public virtual ClientResult CreateRun(string threadId, CreateRunReque /// The response returned from the service. public virtual async Task CreateRunAsync(string threadId, BinaryContent content, RequestOptions options = null) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateRunRequest(threadId, content, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Runs.CreateRun"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateCreateRunRequest(threadId, content, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -231,20 +237,22 @@ public virtual async Task CreateRunAsync(string threadId, BinaryCo /// The response returned from the service. public virtual ClientResult CreateRun(string threadId, BinaryContent content, RequestOptions options = null) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateRunRequest(threadId, content, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Runs.CreateRun"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateCreateRunRequest(threadId, content, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Returns a list of runs belonging to a thread. @@ -271,8 +279,7 @@ public virtual ClientResult CreateRun(string threadId, BinaryContent content, Re /// is an empty string, and was expected to be non-empty. public virtual async Task> GetRunsAsync(string threadId, int? limit = null, ListOrder? order = null, string after = null, string before = null) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); ClientResult result = await GetRunsAsync(threadId, limit, order?.ToString(), after, before, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(ListRunsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -302,8 +309,7 @@ public virtual async Task> GetRunsAsync(string th /// is an empty string, and was expected to be non-empty. public virtual ClientResult GetRuns(string threadId, int? limit = null, ListOrder? order = null, string after = null, string before = null) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); ClientResult result = GetRuns(threadId, limit, order?.ToString(), after, before, DefaultRequestContext); return ClientResult.FromValue(ListRunsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -350,19 +356,21 @@ public virtual ClientResult GetRuns(string threadId, int? limi /// The response returned from the service. public virtual async Task GetRunsAsync(string threadId, int? limit, string order, string after, string before, RequestOptions options) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateGetRunsRequest(threadId, limit, order, after, before, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Runs.GetRuns"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateGetRunsRequest(threadId, limit, order, after, before, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -406,19 +414,21 @@ public virtual async Task GetRunsAsync(string threadId, int? limit /// The response returned from the service. public virtual ClientResult GetRuns(string threadId, int? limit, string order, string after, string before, RequestOptions options) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateGetRunsRequest(threadId, limit, order, after, before, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Runs.GetRuns"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateGetRunsRequest(threadId, limit, order, after, before, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Retrieves a run. @@ -428,10 +438,8 @@ public virtual ClientResult GetRuns(string threadId, int? limit, string order, s /// or is an empty string, and was expected to be non-empty. public virtual async Task> GetRunAsync(string threadId, string runId) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (runId is null) throw new ArgumentNullException(nameof(runId)); - if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(runId, nameof(runId)); ClientResult result = await GetRunAsync(threadId, runId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -444,10 +452,8 @@ public virtual async Task> GetRunAsync(string threadId, /// or is an empty string, and was expected to be non-empty. public virtual ClientResult GetRun(string threadId, string runId) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (runId is null) throw new ArgumentNullException(nameof(runId)); - if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(runId, nameof(runId)); ClientResult result = GetRun(threadId, runId, DefaultRequestContext); return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -477,21 +483,22 @@ public virtual ClientResult GetRun(string threadId, string runId) /// The response returned from the service. public virtual async Task GetRunAsync(string threadId, string runId, RequestOptions options) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (runId is null) throw new ArgumentNullException(nameof(runId)); - if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateGetRunRequest(threadId, runId, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(runId, nameof(runId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Runs.GetRun"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateGetRunRequest(threadId, runId, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -518,21 +525,22 @@ public virtual async Task GetRunAsync(string threadId, string runI /// The response returned from the service. public virtual ClientResult GetRun(string threadId, string runId, RequestOptions options) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (runId is null) throw new ArgumentNullException(nameof(runId)); - if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateGetRunRequest(threadId, runId, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(runId, nameof(runId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Runs.GetRun"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateGetRunRequest(threadId, runId, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Modifies a run. @@ -543,11 +551,9 @@ public virtual ClientResult GetRun(string threadId, string runId, RequestOptions /// or is an empty string, and was expected to be non-empty. public virtual async Task> ModifyRunAsync(string threadId, string runId, ModifyRunRequest run) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (runId is null) throw new ArgumentNullException(nameof(runId)); - if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - if (run is null) throw new ArgumentNullException(nameof(run)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(runId, nameof(runId)); + Argument.AssertNotNull(run, nameof(run)); using BinaryContent content = BinaryContent.Create(run); ClientResult result = await ModifyRunAsync(threadId, runId, content, DefaultRequestContext).ConfigureAwait(false); @@ -562,11 +568,9 @@ public virtual async Task> ModifyRunAsync(string threadI /// or is an empty string, and was expected to be non-empty. public virtual ClientResult ModifyRun(string threadId, string runId, ModifyRunRequest run) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (runId is null) throw new ArgumentNullException(nameof(runId)); - if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - if (run is null) throw new ArgumentNullException(nameof(run)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(runId, nameof(runId)); + Argument.AssertNotNull(run, nameof(run)); using BinaryContent content = BinaryContent.Create(run); ClientResult result = ModifyRun(threadId, runId, content, DefaultRequestContext); @@ -598,22 +602,23 @@ public virtual ClientResult ModifyRun(string threadId, string runId, /// The response returned from the service. public virtual async Task ModifyRunAsync(string threadId, string runId, BinaryContent content, RequestOptions options = null) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (runId is null) throw new ArgumentNullException(nameof(runId)); - if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateModifyRunRequest(threadId, runId, content, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(runId, nameof(runId)); + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Runs.ModifyRun"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateModifyRunRequest(threadId, runId, content, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -641,22 +646,23 @@ public virtual async Task ModifyRunAsync(string threadId, string r /// The response returned from the service. public virtual ClientResult ModifyRun(string threadId, string runId, BinaryContent content, RequestOptions options = null) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (runId is null) throw new ArgumentNullException(nameof(runId)); - if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateModifyRunRequest(threadId, runId, content, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(runId, nameof(runId)); + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Runs.ModifyRun"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateModifyRunRequest(threadId, runId, content, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Cancels a run that is `in_progress`. @@ -666,10 +672,8 @@ public virtual ClientResult ModifyRun(string threadId, string runId, BinaryConte /// or is an empty string, and was expected to be non-empty. public virtual async Task> CancelRunAsync(string threadId, string runId) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (runId is null) throw new ArgumentNullException(nameof(runId)); - if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(runId, nameof(runId)); ClientResult result = await CancelRunAsync(threadId, runId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -682,10 +686,8 @@ public virtual async Task> CancelRunAsync(string threadI /// or is an empty string, and was expected to be non-empty. public virtual ClientResult CancelRun(string threadId, string runId) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (runId is null) throw new ArgumentNullException(nameof(runId)); - if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(runId, nameof(runId)); ClientResult result = CancelRun(threadId, runId, DefaultRequestContext); return ClientResult.FromValue(RunObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -715,21 +717,22 @@ public virtual ClientResult CancelRun(string threadId, string runId) /// The response returned from the service. public virtual async Task CancelRunAsync(string threadId, string runId, RequestOptions options) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (runId is null) throw new ArgumentNullException(nameof(runId)); - if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCancelRunRequest(threadId, runId, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(runId, nameof(runId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Runs.CancelRun"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateCancelRunRequest(threadId, runId, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -756,21 +759,22 @@ public virtual async Task CancelRunAsync(string threadId, string r /// The response returned from the service. public virtual ClientResult CancelRun(string threadId, string runId, RequestOptions options) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (runId is null) throw new ArgumentNullException(nameof(runId)); - if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCancelRunRequest(threadId, runId, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(runId, nameof(runId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Runs.CancelRun"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateCancelRunRequest(threadId, runId, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -785,11 +789,9 @@ public virtual ClientResult CancelRun(string threadId, string runId, RequestOpti /// or is an empty string, and was expected to be non-empty. public virtual async Task> SubmitToolOuputsToRunAsync(string threadId, string runId, SubmitToolOutputsRunRequest submitToolOutputsRun) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (runId is null) throw new ArgumentNullException(nameof(runId)); - if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - if (submitToolOutputsRun is null) throw new ArgumentNullException(nameof(submitToolOutputsRun)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(runId, nameof(runId)); + Argument.AssertNotNull(submitToolOutputsRun, nameof(submitToolOutputsRun)); using BinaryContent content = BinaryContent.Create(submitToolOutputsRun); ClientResult result = await SubmitToolOuputsToRunAsync(threadId, runId, content, DefaultRequestContext).ConfigureAwait(false); @@ -808,11 +810,9 @@ public virtual async Task> SubmitToolOuputsToRunAsync(st /// or is an empty string, and was expected to be non-empty. public virtual ClientResult SubmitToolOuputsToRun(string threadId, string runId, SubmitToolOutputsRunRequest submitToolOutputsRun) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (runId is null) throw new ArgumentNullException(nameof(runId)); - if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - if (submitToolOutputsRun is null) throw new ArgumentNullException(nameof(submitToolOutputsRun)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(runId, nameof(runId)); + Argument.AssertNotNull(submitToolOutputsRun, nameof(submitToolOutputsRun)); using BinaryContent content = BinaryContent.Create(submitToolOutputsRun); ClientResult result = SubmitToolOuputsToRun(threadId, runId, content, DefaultRequestContext); @@ -846,22 +846,23 @@ public virtual ClientResult SubmitToolOuputsToRun(string threadId, st /// The response returned from the service. public virtual async Task SubmitToolOuputsToRunAsync(string threadId, string runId, BinaryContent content, RequestOptions options = null) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (runId is null) throw new ArgumentNullException(nameof(runId)); - if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateSubmitToolOuputsToRunRequest(threadId, runId, content, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(runId, nameof(runId)); + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Runs.SubmitToolOuputsToRun"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateSubmitToolOuputsToRunRequest(threadId, runId, content, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -891,22 +892,23 @@ public virtual async Task SubmitToolOuputsToRunAsync(string thread /// The response returned from the service. public virtual ClientResult SubmitToolOuputsToRun(string threadId, string runId, BinaryContent content, RequestOptions options = null) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (runId is null) throw new ArgumentNullException(nameof(runId)); - if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateSubmitToolOuputsToRunRequest(threadId, runId, content, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(runId, nameof(runId)); + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Runs.SubmitToolOuputsToRun"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateSubmitToolOuputsToRunRequest(threadId, runId, content, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Returns a list of run steps belonging to a run. @@ -934,10 +936,8 @@ public virtual ClientResult SubmitToolOuputsToRun(string threadId, string runId, /// or is an empty string, and was expected to be non-empty. public virtual async Task> GetRunStepsAsync(string threadId, string runId, int? limit = null, ListOrder? order = null, string after = null, string before = null) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (runId is null) throw new ArgumentNullException(nameof(runId)); - if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(runId, nameof(runId)); ClientResult result = await GetRunStepsAsync(threadId, runId, limit, order?.ToString(), after, before, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(ListRunStepsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -968,10 +968,8 @@ public virtual async Task> GetRunStepsAsync(s /// or is an empty string, and was expected to be non-empty. public virtual ClientResult GetRunSteps(string threadId, string runId, int? limit = null, ListOrder? order = null, string after = null, string before = null) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (runId is null) throw new ArgumentNullException(nameof(runId)); - if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(runId, nameof(runId)); ClientResult result = GetRunSteps(threadId, runId, limit, order?.ToString(), after, before, DefaultRequestContext); return ClientResult.FromValue(ListRunStepsResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -1019,21 +1017,22 @@ public virtual ClientResult GetRunSteps(string threadId, s /// The response returned from the service. public virtual async Task GetRunStepsAsync(string threadId, string runId, int? limit, string order, string after, string before, RequestOptions options) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (runId is null) throw new ArgumentNullException(nameof(runId)); - if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateGetRunStepsRequest(threadId, runId, limit, order, after, before, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(runId, nameof(runId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Runs.GetRunSteps"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateGetRunStepsRequest(threadId, runId, limit, order, after, before, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -1078,21 +1077,22 @@ public virtual async Task GetRunStepsAsync(string threadId, string /// The response returned from the service. public virtual ClientResult GetRunSteps(string threadId, string runId, int? limit, string order, string after, string before, RequestOptions options) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (runId is null) throw new ArgumentNullException(nameof(runId)); - if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateGetRunStepsRequest(threadId, runId, limit, order, after, before, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(runId, nameof(runId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Runs.GetRunSteps"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateGetRunStepsRequest(threadId, runId, limit, order, after, before, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Retrieves a run step. @@ -1103,12 +1103,9 @@ public virtual ClientResult GetRunSteps(string threadId, string runId, int? limi /// , or is an empty string, and was expected to be non-empty. public virtual async Task> GetRunStepAsync(string threadId, string runId, string stepId) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (runId is null) throw new ArgumentNullException(nameof(runId)); - if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - if (stepId is null) throw new ArgumentNullException(nameof(stepId)); - if (string.IsNullOrEmpty(stepId)) throw new ArgumentException(nameof(stepId)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(runId, nameof(runId)); + Argument.AssertNotNullOrEmpty(stepId, nameof(stepId)); ClientResult result = await GetRunStepAsync(threadId, runId, stepId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(RunStepObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -1122,12 +1119,9 @@ public virtual async Task> GetRunStepAsync(string th /// , or is an empty string, and was expected to be non-empty. public virtual ClientResult GetRunStep(string threadId, string runId, string stepId) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (runId is null) throw new ArgumentNullException(nameof(runId)); - if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - if (stepId is null) throw new ArgumentNullException(nameof(stepId)); - if (string.IsNullOrEmpty(stepId)) throw new ArgumentException(nameof(stepId)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(runId, nameof(runId)); + Argument.AssertNotNullOrEmpty(stepId, nameof(stepId)); ClientResult result = GetRunStep(threadId, runId, stepId, DefaultRequestContext); return ClientResult.FromValue(RunStepObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -1158,23 +1152,23 @@ public virtual ClientResult GetRunStep(string threadId, string ru /// The response returned from the service. public virtual async Task GetRunStepAsync(string threadId, string runId, string stepId, RequestOptions options) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (runId is null) throw new ArgumentNullException(nameof(runId)); - if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - if (stepId is null) throw new ArgumentNullException(nameof(stepId)); - if (string.IsNullOrEmpty(stepId)) throw new ArgumentException(nameof(stepId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateGetRunStepRequest(threadId, runId, stepId, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(runId, nameof(runId)); + Argument.AssertNotNullOrEmpty(stepId, nameof(stepId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Runs.GetRunStep"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateGetRunStepRequest(threadId, runId, stepId, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -1202,23 +1196,23 @@ public virtual async Task GetRunStepAsync(string threadId, string /// The response returned from the service. public virtual ClientResult GetRunStep(string threadId, string runId, string stepId, RequestOptions options) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (runId is null) throw new ArgumentNullException(nameof(runId)); - if (string.IsNullOrEmpty(runId)) throw new ArgumentException(nameof(runId)); - if (stepId is null) throw new ArgumentNullException(nameof(stepId)); - if (string.IsNullOrEmpty(stepId)) throw new ArgumentException(nameof(stepId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateGetRunStepRequest(threadId, runId, stepId, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNullOrEmpty(runId, nameof(runId)); + Argument.AssertNotNullOrEmpty(stepId, nameof(stepId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Runs.GetRunStep"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateGetRunStepRequest(threadId, runId, stepId, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } internal PipelineMessage CreateCreateThreadAndRunRequest(BinaryContent content, RequestOptions options) diff --git a/.dotnet/src/Generated/Threads.cs b/.dotnet/src/Generated/Threads.cs index 8e2ac77e4..bc2d4cbd0 100644 --- a/.dotnet/src/Generated/Threads.cs +++ b/.dotnet/src/Generated/Threads.cs @@ -44,7 +44,7 @@ internal Threads(ClientPipeline pipeline, ApiKeyCredential credential, Uri endpo /// is null. public virtual async Task> CreateThreadAsync(CreateThreadRequest thread) { - if (thread is null) throw new ArgumentNullException(nameof(thread)); + Argument.AssertNotNull(thread, nameof(thread)); using BinaryContent content = BinaryContent.Create(thread); ClientResult result = await CreateThreadAsync(content, DefaultRequestContext).ConfigureAwait(false); @@ -56,7 +56,7 @@ public virtual async Task> CreateThreadAsync(CreateTh /// is null. public virtual ClientResult CreateThread(CreateThreadRequest thread) { - if (thread is null) throw new ArgumentNullException(nameof(thread)); + Argument.AssertNotNull(thread, nameof(thread)); using BinaryContent content = BinaryContent.Create(thread); ClientResult result = CreateThread(content, DefaultRequestContext); @@ -85,18 +85,21 @@ public virtual ClientResult CreateThread(CreateThreadRequest threa /// The response returned from the service. public virtual async Task CreateThreadAsync(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateThreadRequest(content, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Threads.CreateThread"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateCreateThreadRequest(content, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -121,18 +124,21 @@ public virtual async Task CreateThreadAsync(BinaryContent content, /// The response returned from the service. public virtual ClientResult CreateThread(BinaryContent content, RequestOptions options = null) { - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateCreateThreadRequest(content, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Threads.CreateThread"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateCreateThreadRequest(content, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Retrieves a thread. @@ -141,8 +147,7 @@ public virtual ClientResult CreateThread(BinaryContent content, RequestOptions o /// is an empty string, and was expected to be non-empty. public virtual async Task> GetThreadAsync(string threadId) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); ClientResult result = await GetThreadAsync(threadId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(ThreadObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -154,8 +159,7 @@ public virtual async Task> GetThreadAsync(string thre /// is an empty string, and was expected to be non-empty. public virtual ClientResult GetThread(string threadId) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); ClientResult result = GetThread(threadId, DefaultRequestContext); return ClientResult.FromValue(ThreadObject.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -184,19 +188,21 @@ public virtual ClientResult GetThread(string threadId) /// The response returned from the service. public virtual async Task GetThreadAsync(string threadId, RequestOptions options) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateGetThreadRequest(threadId, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Threads.GetThread"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateGetThreadRequest(threadId, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -222,19 +228,21 @@ public virtual async Task GetThreadAsync(string threadId, RequestO /// The response returned from the service. public virtual ClientResult GetThread(string threadId, RequestOptions options) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateGetThreadRequest(threadId, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Threads.GetThread"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateGetThreadRequest(threadId, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Modifies a thread. @@ -244,9 +252,8 @@ public virtual ClientResult GetThread(string threadId, RequestOptions options) /// is an empty string, and was expected to be non-empty. public virtual async Task> ModifyThreadAsync(string threadId, ModifyThreadRequest thread) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (thread is null) throw new ArgumentNullException(nameof(thread)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNull(thread, nameof(thread)); using BinaryContent content = BinaryContent.Create(thread); ClientResult result = await ModifyThreadAsync(threadId, content, DefaultRequestContext).ConfigureAwait(false); @@ -260,9 +267,8 @@ public virtual async Task> ModifyThreadAsync(string t /// is an empty string, and was expected to be non-empty. public virtual ClientResult ModifyThread(string threadId, ModifyThreadRequest thread) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (thread is null) throw new ArgumentNullException(nameof(thread)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNull(thread, nameof(thread)); using BinaryContent content = BinaryContent.Create(thread); ClientResult result = ModifyThread(threadId, content, DefaultRequestContext); @@ -293,20 +299,22 @@ public virtual ClientResult ModifyThread(string threadId, ModifyTh /// The response returned from the service. public virtual async Task ModifyThreadAsync(string threadId, BinaryContent content, RequestOptions options = null) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateModifyThreadRequest(threadId, content, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Threads.ModifyThread"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateModifyThreadRequest(threadId, content, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -333,20 +341,22 @@ public virtual async Task ModifyThreadAsync(string threadId, Binar /// The response returned from the service. public virtual ClientResult ModifyThread(string threadId, BinaryContent content, RequestOptions options = null) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - if (content is null) throw new ArgumentNullException(nameof(content)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateModifyThreadRequest(threadId, content, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); + Argument.AssertNotNull(content, nameof(content)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Threads.ModifyThread"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateModifyThreadRequest(threadId, content, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// Delete a thread. @@ -355,8 +365,7 @@ public virtual ClientResult ModifyThread(string threadId, BinaryContent content, /// is an empty string, and was expected to be non-empty. public virtual async Task> DeleteThreadAsync(string threadId) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); ClientResult result = await DeleteThreadAsync(threadId, DefaultRequestContext).ConfigureAwait(false); return ClientResult.FromValue(DeleteThreadResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -368,8 +377,7 @@ public virtual async Task> DeleteThreadAsync( /// is an empty string, and was expected to be non-empty. public virtual ClientResult DeleteThread(string threadId) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); ClientResult result = DeleteThread(threadId, DefaultRequestContext); return ClientResult.FromValue(DeleteThreadResponse.FromResponse(result.GetRawResponse()), result.GetRawResponse()); @@ -398,19 +406,21 @@ public virtual ClientResult DeleteThread(string threadId) /// The response returned from the service. public virtual async Task DeleteThreadAsync(string threadId, RequestOptions options) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateDeleteThreadRequest(threadId, options); - await _pipeline.SendAsync(message).ConfigureAwait(false); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Threads.DeleteThread"\); + // scope.Start(); + try { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + using PipelineMessage message = CreateDeleteThreadRequest(threadId, options); + return ClientResult.FromResponse(await _pipeline.ProcessMessageAsync(message, options).ConfigureAwait(false)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } /// @@ -436,19 +446,21 @@ public virtual async Task DeleteThreadAsync(string threadId, Reque /// The response returned from the service. public virtual ClientResult DeleteThread(string threadId, RequestOptions options) { - if (threadId is null) throw new ArgumentNullException(nameof(threadId)); - if (string.IsNullOrEmpty(threadId)) throw new ArgumentException(nameof(threadId)); - options ??= new RequestOptions(); - using PipelineMessage message = CreateDeleteThreadRequest(threadId, options); - _pipeline.Send(message); - PipelineResponse response = message.Response!; + Argument.AssertNotNullOrEmpty(threadId, nameof(threadId)); - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + options ??= new RequestOptions(); + // using var scope = ClientDiagnostics.CreateSpan("Threads.DeleteThread"\); + // scope.Start(); + try { - throw new ClientResultException(response); + using PipelineMessage message = CreateDeleteThreadRequest(threadId, options); + return ClientResult.FromResponse(_pipeline.ProcessMessage(message, options)); + } + catch (Exception e) + { + // scope.Failed(e); + throw; } - - return ClientResult.FromResponse(response); } internal PipelineMessage CreateCreateThreadRequest(BinaryContent content, RequestOptions options) diff --git a/main.tsp b/main.tsp index d7bbdec33..293beba5b 100644 --- a/main.tsp +++ b/main.tsp @@ -29,8 +29,7 @@ using TypeSpec.Http; license: { name: "MIT", url: "https://github.com/openai/openai-openapi/blob/master/LICENSE", - }, - version: "2.0.0", + } }) @server("https://api.openai.com/v1", "OpenAI Endpoint") @useAuth(BearerAuth) diff --git a/package-lock.json b/package-lock.json index 1c8159a55..a752dc7f5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,58 +9,58 @@ "version": "0.1.0", "dependencies": { "@azure-tools/typespec-csharp": "latest", - "@typespec/compiler": "^0.52.0", - "@typespec/http": "^0.52.0", - "@typespec/openapi": "^0.52.0", - "@typespec/openapi3": "^0.52.0", - "@typespec/rest": "^0.52.0", - "@typespec/versioning": "^0.52.0" + "@typespec/compiler": "^0.54.0", + "@typespec/http": "^0.54.0", + "@typespec/openapi": "^0.54.0", + "@typespec/openapi3": "^0.54.0", + "@typespec/rest": "^0.54.0", + "@typespec/versioning": "^0.54.0" } }, "node_modules/@autorest/csharp": { - "version": "3.0.0-beta.20240202.1", - "resolved": "https://registry.npmjs.org/@autorest/csharp/-/csharp-3.0.0-beta.20240202.1.tgz", - "integrity": "sha512-us+dLFipCJbR0uDLiUg7nFsVpV2bJB6CWSTKc30WbE8HvrX0inYxm97LcDw3k3EiOM5frQGSYetWJgXbyuW+jw==" + "version": "3.0.0-beta.20240312.2", + "resolved": "https://registry.npmjs.org/@autorest/csharp/-/csharp-3.0.0-beta.20240312.2.tgz", + "integrity": "sha512-7Q4eyNvY+/l/Ga1j4jDo1Mr0TzwDPvi2957fGwiW4zHd0Hl/sTC8wNrjdiZtpfhkJUuzJ6CAJJE84wYuhbh3hQ==" }, "node_modules/@azure-tools/typespec-azure-core": { - "version": "0.38.0", - "resolved": "https://registry.npmjs.org/@azure-tools/typespec-azure-core/-/typespec-azure-core-0.38.0.tgz", - "integrity": "sha512-ASM+njC2lpzPykzw2OicWIaAOH+OBe3bVMrufEnINBjlr7owAtudvjrTLLWmAVMBciL/YOF579KdyjxTbaxJ5A==", + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@azure-tools/typespec-azure-core/-/typespec-azure-core-0.40.0.tgz", + "integrity": "sha512-l5U47zXKYQKFbipRQLpjG4EwvPJg0SogdFEe5a3rRr7mUy8sWPkciHpngLZVOd2cKZQD5m7nqwfWL798I9TJnQ==", "peer": true, "engines": { "node": ">=18.0.0" }, "peerDependencies": { - "@typespec/compiler": "~0.52.0", - "@typespec/http": "~0.52.0", - "@typespec/rest": "~0.52.0" + "@typespec/compiler": "~0.54.0", + "@typespec/http": "~0.54.0", + "@typespec/rest": "~0.54.0" } }, "node_modules/@azure-tools/typespec-client-generator-core": { - "version": "0.38.0", - "resolved": "https://registry.npmjs.org/@azure-tools/typespec-client-generator-core/-/typespec-client-generator-core-0.38.0.tgz", - "integrity": "sha512-DUDIHJikz3Ai8uPk3vKFoMkkGPUxoD5DbGdwkN/pQxaL6Aze8HV4LGEOGtvaIu0SsGjCX9G3XPAXoBoupYgXbw==", + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@azure-tools/typespec-client-generator-core/-/typespec-client-generator-core-0.40.0.tgz", + "integrity": "sha512-Nm/OfDtSWBr1lylISbXR37B9QKWlZHK1j4T8L439Y1v3VcvJsC/0F5PLemY0odHpOYZNwu2uevJjAeM5W56wlw==", "peer": true, "dependencies": { - "change-case": "~5.3.0", + "change-case": "~5.4.2", "pluralize": "^8.0.0" }, "engines": { "node": ">=18.0.0" }, "peerDependencies": { - "@typespec/compiler": "~0.52.0", - "@typespec/http": "~0.52.0", - "@typespec/rest": "~0.52.0", - "@typespec/versioning": "~0.52.0" + "@typespec/compiler": "~0.54.0", + "@typespec/http": "~0.54.0", + "@typespec/rest": "~0.54.0", + "@typespec/versioning": "~0.54.0" } }, "node_modules/@azure-tools/typespec-csharp": { - "version": "0.2.0-beta.20240202.1", - "resolved": "https://registry.npmjs.org/@azure-tools/typespec-csharp/-/typespec-csharp-0.2.0-beta.20240202.1.tgz", - "integrity": "sha512-V+AvsqS7OMUcYIdIcVEyhS3i2MVP/rPZqCzDpIOJAcH/4oK4dHVz4RcgB/7+fM+PY7agWrM3zvR5XTkAeBqL9A==", + "version": "0.2.0-beta.20240312.2", + "resolved": "https://registry.npmjs.org/@azure-tools/typespec-csharp/-/typespec-csharp-0.2.0-beta.20240312.2.tgz", + "integrity": "sha512-F1TAiBpg8U/TIDoz4RgBkh4QNzWkZenQInY8vNpCP6Xpg7y9SA8yWlpqNwOfni9icWbtJFKEEv3bxocmOFANQQ==", "dependencies": { - "@autorest/csharp": "3.0.0-beta.20240202.1", + "@autorest/csharp": "3.0.0-beta.20240312.2", "json-serialize-refs": "0.1.0-0", "winston": "^3.8.2" }, @@ -69,6 +69,7 @@ "@azure-tools/typespec-client-generator-core": ">=0.36.0 <1.0.0", "@typespec/compiler": ">=0.50.0 <1.0.0", "@typespec/http": ">=0.50.0 <1.0.0", + "@typespec/openapi": ">=0.50.0 <1.0.0", "@typespec/rest": ">=0.50.0 <1.0.0", "@typespec/versioning": ">=0.50.0 <1.0.0" } @@ -157,9 +158,9 @@ } }, "node_modules/@sindresorhus/merge-streams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-1.0.0.tgz", - "integrity": "sha512-rUV5WyJrJLoloD4NDN1V1+LDMDWOa4OTsT4yYJwQNpTU6FWxkxHpL7eu4w+DmiH8x/EAM1otkPE1+LaspIbplw==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", "engines": { "node": ">=18" }, @@ -173,21 +174,21 @@ "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==" }, "node_modules/@typespec/compiler": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@typespec/compiler/-/compiler-0.52.0.tgz", - "integrity": "sha512-36cZ5RWxRjL4SUe41KjPh3j3RQibpUoOzHcSllQJ3ByTSZdXv1zckMHLiRfaAbTXUADSAn2GMs4ZO3s8GdOGIQ==", + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@typespec/compiler/-/compiler-0.54.0.tgz", + "integrity": "sha512-lxMqlvUq5m1KZUjg+IoM/gEwY+yeSjjnpUsz6wmzjK4cO9cIY4wPJdrZwe8jUc2UFOoqKXN3AK8N1UWxA+w9Dg==", "dependencies": { "@babel/code-frame": "~7.23.5", "ajv": "~8.12.0", - "change-case": "~5.3.0", + "change-case": "~5.4.2", "globby": "~14.0.0", "mustache": "~4.2.0", "picocolors": "~1.0.0", - "prettier": "~3.1.1", + "prettier": "~3.2.5", "prompts": "~2.4.2", - "semver": "^7.5.4", - "vscode-languageserver": "~9.0.0", - "vscode-languageserver-textdocument": "~1.0.8", + "semver": "^7.6.0", + "vscode-languageserver": "~9.0.1", + "vscode-languageserver-textdocument": "~1.0.11", "yaml": "~2.3.4", "yargs": "~17.7.2" }, @@ -200,32 +201,32 @@ } }, "node_modules/@typespec/http": { - "version": "0.52.1", - "resolved": "https://registry.npmjs.org/@typespec/http/-/http-0.52.1.tgz", - "integrity": "sha512-2i7t6eSKi96F/zt1w0yJvhRhubYej0F9o8jDRhPA+TZI6SAxcv/Vyi+lkKnkOcu90HPH7b8T+YNizudb00BO6A==", + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@typespec/http/-/http-0.54.0.tgz", + "integrity": "sha512-/hZd9pkjJh3ogOekyKzZnpVV2kXzxtWDiTt3Gekc6iHTGk/CE1JpRFts8xwXoI5d3FqYotfb4w5ztVw62WjOcA==", "engines": { "node": ">=18.0.0" }, "peerDependencies": { - "@typespec/compiler": "~0.52.0" + "@typespec/compiler": "~0.54.0" } }, "node_modules/@typespec/openapi": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@typespec/openapi/-/openapi-0.52.0.tgz", - "integrity": "sha512-2Otnu9glehxvp6TU7NOHEniBDDKufV03XTmeVGgGEmu/j+cveAMg8lA1/O0RBpS2oHGsCFnMEuPcR8M1c0LI+Q==", + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@typespec/openapi/-/openapi-0.54.0.tgz", + "integrity": "sha512-QJkwq3whcqKb29ScMD5IQzqvDmPQyLAubRl82Zj6kVMCqabRwegOX9aN+K0083nci65zt9rflZbv9bKY5GRy/A==", "engines": { "node": ">=18.0.0" }, "peerDependencies": { - "@typespec/compiler": "~0.52.0", - "@typespec/http": "~0.52.0" + "@typespec/compiler": "~0.54.0", + "@typespec/http": "~0.54.0" } }, "node_modules/@typespec/openapi3": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@typespec/openapi3/-/openapi3-0.52.0.tgz", - "integrity": "sha512-PPhNdpKQD2iHJemOaRUhnaeFWa4ApW4HtcZI+jrg4hyNSIwDYxL0OwwRohKjRUKM98iacpXvEh+5rKtkPiY2Qw==", + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@typespec/openapi3/-/openapi3-0.54.0.tgz", + "integrity": "sha512-ryqa6iNWA3Vb2TcyTUD0NrRecGVY5MGaEuAdBJnnEEPcE6CSQY0j0dFZXzRLBUd4LiR332B4Y7Brkq6MjRdrNg==", "dependencies": { "yaml": "~2.3.4" }, @@ -233,33 +234,33 @@ "node": ">=18.0.0" }, "peerDependencies": { - "@typespec/compiler": "~0.52.0", - "@typespec/http": "~0.52.0", - "@typespec/openapi": "~0.52.0", - "@typespec/versioning": "~0.52.0" + "@typespec/compiler": "~0.54.0", + "@typespec/http": "~0.54.0", + "@typespec/openapi": "~0.54.0", + "@typespec/versioning": "~0.54.0" } }, "node_modules/@typespec/rest": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@typespec/rest/-/rest-0.52.0.tgz", - "integrity": "sha512-dLsY0fS60IVaAt4eCRcvEqorX/miPVV33du3dETTYYmbHtfEbvBKgTj/m6OH4noey7oaihlvLz5kYyLv8Am7zA==", + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@typespec/rest/-/rest-0.54.0.tgz", + "integrity": "sha512-F1hq/Per9epPJQ8Ey84mAtrgrZeLu6fDMIxNao1XlTfDEFZuYgFuCSyg0pyIi0Xg7KUBMvrvSv83WoF3mN2szw==", "engines": { "node": ">=18.0.0" }, "peerDependencies": { - "@typespec/compiler": "~0.52.0", - "@typespec/http": "~0.52.0" + "@typespec/compiler": "~0.54.0", + "@typespec/http": "~0.54.0" } }, "node_modules/@typespec/versioning": { - "version": "0.52.0", - "resolved": "https://registry.npmjs.org/@typespec/versioning/-/versioning-0.52.0.tgz", - "integrity": "sha512-Vr4WHaZiDOxJqRp8/u6X0R45E+rFKEprYmSZX0o5bzetj0cVjOIEbQZvDJCif1Uz0S3K0KKfqf/kYmdYWMJ7Dw==", + "version": "0.54.0", + "resolved": "https://registry.npmjs.org/@typespec/versioning/-/versioning-0.54.0.tgz", + "integrity": "sha512-IlGpveOJ0WBTbn3w8nfzgSNhJWNd0+H+bo1Ljrjpeb9SFQmS8bX2fDf0vqsHVl50XgvKIZxgOpEXN5TmuzNnRw==", "engines": { "node": ">=18.0.0" }, "peerDependencies": { - "@typespec/compiler": "~0.52.0" + "@typespec/compiler": "~0.54.0" } }, "node_modules/ajv": { @@ -326,9 +327,9 @@ } }, "node_modules/change-case": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/change-case/-/change-case-5.3.0.tgz", - "integrity": "sha512-Eykca0fGS/xYlx2fG5NqnGSnsWauhSGiSXYhB1kO6E909GUfo8S54u4UZNS7lMJmgZumZ2SUpWaoLgAcfQRICg==" + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-5.4.3.tgz", + "integrity": "sha512-4cdyvorTy/lViZlVzw2O8/hHCLUuHqp4KpSSP3DlauhFCf3LdnfF+p5s0EAhjKsU7bqrMzu7iQArYfoPiHO2nw==" }, "node_modules/cliui": { "version": "8.0.1", @@ -394,9 +395,9 @@ "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "engines": { "node": ">=6" } @@ -430,9 +431,9 @@ } }, "node_modules/fastq": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.0.tgz", - "integrity": "sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dependencies": { "reusify": "^1.0.4" } @@ -478,11 +479,11 @@ } }, "node_modules/globby": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.0.tgz", - "integrity": "sha512-/1WM/LNHRAOH9lZta77uGbq0dAEQM+XjNesWwhlERDVenqothRbnzTrL3/LrIoEPPjeUHC3vrS6TwoyxeHs7MQ==", + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.1.tgz", + "integrity": "sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==", "dependencies": { - "@sindresorhus/merge-streams": "^1.0.0", + "@sindresorhus/merge-streams": "^2.1.0", "fast-glob": "^3.3.2", "ignore": "^5.2.4", "path-type": "^5.0.0", @@ -701,9 +702,9 @@ } }, "node_modules/prettier": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz", - "integrity": "sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==", + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", "bin": { "prettier": "bin/prettier.cjs" }, @@ -727,9 +728,9 @@ } }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "engines": { "node": ">=6" } @@ -841,9 +842,9 @@ } }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -986,39 +987,39 @@ } }, "node_modules/vscode-languageserver": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.0.tgz", - "integrity": "sha512-npT72Iu28Tjsm94MsCbwJmIu5ycCF3UEPj3Eb3725T1Hqf4d+Vj2W4GC+F8l4n9yNItJuvE/AHYvomvAs9Dj8A==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", + "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", "dependencies": { - "vscode-languageserver-protocol": "3.17.4" + "vscode-languageserver-protocol": "3.17.5" }, "bin": { "installServerIntoExtension": "bin/installServerIntoExtension" } }, "node_modules/vscode-languageserver-protocol": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.4.tgz", - "integrity": "sha512-IpaHLPft+UBWf4dOIH15YEgydTbXGz52EMU2h16SfFpYu/yOQt3pY14049mtpJu+4CBHn+hq7S67e7O0AwpRqQ==", + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", "dependencies": { "vscode-jsonrpc": "8.2.0", - "vscode-languageserver-types": "3.17.4" + "vscode-languageserver-types": "3.17.5" } }, "node_modules/vscode-languageserver-textdocument": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.8.tgz", - "integrity": "sha512-1bonkGqQs5/fxGT5UchTgjGVnfysL0O8v1AYMBjqTbWQTFn721zaPGDYFkOKtfDgFiSgXM3KwaG3FMGfW4Ed9Q==" + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz", + "integrity": "sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==" }, "node_modules/vscode-languageserver-types": { - "version": "3.17.4", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.4.tgz", - "integrity": "sha512-9YXi5pA3XF2V+NUQg6g+lulNS0ncRCKASYdK3Cs7kiH9sVFXWq27prjkC/B8M/xJLRPPRSPCHVMuBTgRNFh2sQ==" + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==" }, "node_modules/winston": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.11.0.tgz", - "integrity": "sha512-L3yR6/MzZAOl0DsysUXHVjOwv8mKZ71TrA/41EIduGpOOV5LQVodqN+QdQ6BS6PJ/RdIshZhq84P/fStEZkk7g==", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.12.0.tgz", + "integrity": "sha512-OwbxKaOlESDi01mC9rkM0dQqQt2I8DAUMRLZ/HpbwvDXm85IryEHgoogy5fziQy38PntgZsLlhAYHz//UPHZ5w==", "dependencies": { "@colors/colors": "^1.6.0", "@dabh/diagnostics": "^2.0.2", @@ -1030,16 +1031,16 @@ "safe-stable-stringify": "^2.3.1", "stack-trace": "0.0.x", "triple-beam": "^1.3.0", - "winston-transport": "^4.5.0" + "winston-transport": "^4.7.0" }, "engines": { "node": ">= 12.0.0" } }, "node_modules/winston-transport": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.6.0.tgz", - "integrity": "sha512-wbBA9PbPAHxKiygo7ub7BYRiKxms0tpfU2ljtWzb3SjRjv5yl6Ozuy/TkXf00HTAt+Uylo3gSkNwzc4ME0wiIg==", + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.7.0.tgz", + "integrity": "sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==", "dependencies": { "logform": "^2.3.2", "readable-stream": "^3.6.0", diff --git a/package.json b/package.json index f43e693fb..40565051c 100644 --- a/package.json +++ b/package.json @@ -4,12 +4,12 @@ "type": "module", "dependencies": { "@azure-tools/typespec-csharp": "latest", - "@typespec/compiler": "^0.52.0", - "@typespec/http": "^0.52.0", - "@typespec/openapi": "^0.52.0", - "@typespec/openapi3": "^0.52.0", - "@typespec/rest": "^0.52.0", - "@typespec/versioning": "^0.52.0" + "@typespec/compiler": "^0.54.0", + "@typespec/http": "^0.54.0", + "@typespec/openapi": "^0.54.0", + "@typespec/openapi3": "^0.54.0", + "@typespec/rest": "^0.54.0", + "@typespec/versioning": "^0.54.0" }, "private": true } diff --git a/tsp-output/@typespec/openapi3/openapi.yaml b/tsp-output/@typespec/openapi3/openapi.yaml index 394ac492c..172e5a50d 100644 --- a/tsp-output/@typespec/openapi3/openapi.yaml +++ b/tsp-output/@typespec/openapi3/openapi.yaml @@ -1,8 +1,8 @@ openapi: 3.0.0 info: title: OpenAI API - version: 2.0.0 description: The OpenAI REST API. Please see https://platform.openai.com/docs/api-reference for more details. + version: 0.0.0 tags: - name: Audio - name: Assistants @@ -1798,8 +1798,7 @@ components: maxLength: 32768 description: The system instructions that the assistant uses. The maximum length is 32768 characters. tools: - allOf: - - $ref: '#/components/schemas/CreateAssistantRequestToolsItem' + $ref: '#/components/schemas/CreateAssistantRequestToolsItem' description: |- A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. Tools can be of types `code_interpreter`, `retrieval`, or `function`. @@ -1897,8 +1896,7 @@ components: type: string description: The text that was part of this audio segment. tokens: - allOf: - - $ref: '#/components/schemas/TokenArrayItem' + $ref: '#/components/schemas/TokenArrayItem' description: The token IDs matching the text in this audio segment. temperature: type: number @@ -2376,8 +2374,7 @@ components: maxLength: 32768 description: The system instructions that the assistant uses. The maximum length is 32768 characters. tools: - allOf: - - $ref: '#/components/schemas/CreateAssistantRequestToolsItem' + $ref: '#/components/schemas/CreateAssistantRequestToolsItem' description: |- A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. Tools can be of types `code_interpreter`, `retrieval`, or `function`. @@ -4823,8 +4820,7 @@ components: maxLength: 32768 description: The system instructions that the assistant uses. The maximum length is 32768 characters. tools: - allOf: - - $ref: '#/components/schemas/CreateAssistantRequestToolsItem' + $ref: '#/components/schemas/CreateAssistantRequestToolsItem' description: |- A list of tool enabled on the assistant. There can be a maximum of 128 tools per assistant. Tools can be of types `code_interpreter`, `retrieval`, or `function`. @@ -5112,8 +5108,7 @@ components: type: string description: The instructions that the [assistant](/docs/api-reference/assistants) used for this run. tools: - allOf: - - $ref: '#/components/schemas/CreateRunRequestToolsItem' + $ref: '#/components/schemas/CreateRunRequestToolsItem' description: The list of tools that the [assistant](/docs/api-reference/assistants) used for this run. file_ids: type: array @@ -5210,8 +5205,7 @@ components: type: string description: The input to the Code Interpreter tool call. outputs: - allOf: - - $ref: '#/components/schemas/RunStepDetailsToolCallsCodeOutputs' + $ref: '#/components/schemas/RunStepDetailsToolCallsCodeOutputs' description: |- The outputs from the Code Interpreter tool call. Code Interpreter can output one or more items, including text (`logs`) or images (`image`). Each of these are represented by a @@ -5311,8 +5305,7 @@ components: - tool_calls description: Always `tool_calls`. tool_calls: - allOf: - - $ref: '#/components/schemas/RunStepDetailsToolCallsObjectToolCallsItem' + $ref: '#/components/schemas/RunStepDetailsToolCallsObjectToolCallsItem' description: |- An array of tool calls the run step was involved in. These can be associated with one of three types of tools: `code_interpreter`, `retrieval`, or `function`. diff --git a/tspconfig.yaml b/tspconfig.yaml index 3788a1428..652d57a6e 100644 --- a/tspconfig.yaml +++ b/tspconfig.yaml @@ -1,4 +1,3 @@ options: "@azure-tools/typespec-csharp": - branded: false generate-test-project: true \ No newline at end of file From 21bd3c9de5467cd4bcb849fb842c33585507fe05 Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado <45773732+joseharriaga@users.noreply.github.com> Date: Fri, 15 Mar 2024 13:58:43 -0700 Subject: [PATCH 36/50] Fix protocol method sample (#24) --- .dotnet/README.md | 3 ++- .dotnet/tests/Samples/Chat/Sample04_Protocol.cs | 3 ++- .dotnet/tests/Samples/Chat/Sample04_ProtocolAsync.cs | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.dotnet/README.md b/.dotnet/README.md index d41e003da..c6ab493c2 100644 --- a/.dotnet/README.md +++ b/.dotnet/README.md @@ -558,7 +558,8 @@ BinaryData input = BinaryData.FromString(""" } """); -ClientResult result = client.CompleteChat(BinaryContent.Create(input)); +using BinaryContent content = BinaryContent.Create(input); +ClientResult result = client.CompleteChat(content); BinaryData output = result.GetRawResponse().Content; using JsonDocument outputAsJson = JsonDocument.Parse(output.ToString()); diff --git a/.dotnet/tests/Samples/Chat/Sample04_Protocol.cs b/.dotnet/tests/Samples/Chat/Sample04_Protocol.cs index 099ddbbe7..53eb49224 100644 --- a/.dotnet/tests/Samples/Chat/Sample04_Protocol.cs +++ b/.dotnet/tests/Samples/Chat/Sample04_Protocol.cs @@ -26,7 +26,8 @@ public void Sample04_Protocol() } """); - ClientResult result = client.CompleteChat(BinaryContent.Create(input)); + using BinaryContent content = BinaryContent.Create(input); + ClientResult result = client.CompleteChat(content); BinaryData output = result.GetRawResponse().Content; using JsonDocument outputAsJson = JsonDocument.Parse(output.ToString()); diff --git a/.dotnet/tests/Samples/Chat/Sample04_ProtocolAsync.cs b/.dotnet/tests/Samples/Chat/Sample04_ProtocolAsync.cs index 6d066ee17..b11e5789c 100644 --- a/.dotnet/tests/Samples/Chat/Sample04_ProtocolAsync.cs +++ b/.dotnet/tests/Samples/Chat/Sample04_ProtocolAsync.cs @@ -27,7 +27,8 @@ public async Task Sample04_ProtocolAsync() } """); - ClientResult result = await client.CompleteChatAsync(BinaryContent.Create(input)); + using BinaryContent content = BinaryContent.Create(input); + ClientResult result = await client.CompleteChatAsync(content); BinaryData output = result.GetRawResponse().Content; using JsonDocument outputAsJson = JsonDocument.Parse(output.ToString()); From 6d6ea7868c4537f550b33278f6e14c8595810999 Mon Sep 17 00:00:00 2001 From: Patrick Hallisey Date: Fri, 15 Mar 2024 16:12:03 -0700 Subject: [PATCH 37/50] Add unit tests with secrets (#23) --- .dotnet/tests/OpenAI.Tests.csproj | 2 +- .dotnet/tests/TestScenarios/GitHubTests.cs | 23 ++++++++++ .github/README.md | 17 ++++++++ .github/workflows/main.yml | 50 +++++++++++++++++++--- .gitignore | 1 + 5 files changed, 87 insertions(+), 6 deletions(-) create mode 100644 .dotnet/tests/TestScenarios/GitHubTests.cs create mode 100644 .github/README.md diff --git a/.dotnet/tests/OpenAI.Tests.csproj b/.dotnet/tests/OpenAI.Tests.csproj index 9bb493c12..2556909e3 100644 --- a/.dotnet/tests/OpenAI.Tests.csproj +++ b/.dotnet/tests/OpenAI.Tests.csproj @@ -1,6 +1,6 @@ - net7.0 + net8.0 $(NoWarn);CS1591 latest diff --git a/.dotnet/tests/TestScenarios/GitHubTests.cs b/.dotnet/tests/TestScenarios/GitHubTests.cs new file mode 100644 index 000000000..3a3644f22 --- /dev/null +++ b/.dotnet/tests/TestScenarios/GitHubTests.cs @@ -0,0 +1,23 @@ +using NUnit.Framework; +using System; + +namespace OpenAI.Tests; + +public partial class GitHubTests +{ + [Test(Description = "Test that we can use a GitHub secret")] + [Category("Online")] + public void CanUseGitHubSecret() + { + string gitHubSecretString = Environment.GetEnvironmentVariable("SECRET_VALUE"); + Assert.That(gitHubSecretString, Is.Not.Null.Or.Empty); + } + + [Test(Description = "That that we can run some tests without secrets")] + [Category("Offline")] + public void CanTestWithoutSecretAccess() + { + int result = 2 + 1; + Assert.That(result, Is.EqualTo(3)); + } +} diff --git a/.github/README.md b/.github/README.md new file mode 100644 index 000000000..df5b3494c --- /dev/null +++ b/.github/README.md @@ -0,0 +1,17 @@ +The workflows in this repository try to follow existing, basic samples with little customization. + +## main.yml +We use a basic dotnet build/test/pack workflow +https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net + +- Build the solution using the dotnet cli + - Strong name the assemblies using a key stored in the repository + https://github.com/dotnet/runtime/blob/main/docs/project/strong-name-signing.md +- Test the built libraries + - Use a repository secret to hold the OpenAI token used for live testing + https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions +- Package the built libraries +- Publish the package as a GitHub Release +- Publish the package to a GitHub NuGet registry + https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-nuget-registry +- Publish a single build artifact containing test results and a nuget package \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 02d8fa18a..2d11478b2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,4 +1,5 @@ name: Build and Test + on: workflow_dispatch: push: @@ -10,6 +11,9 @@ on: jobs: build: # Test, pack and publish the Open AI nuget package as a build artifact runs-on: ubuntu-latest + env: + # if we're in a manually queued run, + version_suffix_args: ${{ format('--version-suffix="alpha.{0}"', github.run_number) }} steps: - name: Setup .NET uses: actions/setup-dotnet@v1 @@ -19,15 +23,51 @@ jobs: - name: Checkout code uses: actions/checkout@v2 + - name: Build + run: dotnet build + -c Release + ${{ env.version_suffix_args }} + working-directory: .dotnet + + - name: Test + run: dotnet test + --no-build + --configuration Release + --filter="TestCategory~${{ github.event_name == 'pull_request' && 'Offline' || 'Online' }}" + --logger "trx;LogFileName=${{github.workspace}}/artifacts/test-results/full.trx" + env: + SECRET_VALUE: ${{ secrets.OPENAI_TOKEN }} + working-directory: .dotnet + - name: Pack run: dotnet pack - -c Release - -o "${{github.workspace}}/packages" - ${{ github.ref != 'refs/heads/main' && format('--version-suffix="alpha.{0}"', github.run_number) || '' }} + --no-build + --configuration Release + --output "${{github.workspace}}/artifacts/packages" + ${{ env.version_suffix_args }} working-directory: .dotnet - name: Upload artifact uses: actions/upload-artifact@v2 with: - name: package - path: packages/*.nupkg + name: build-artifacts + path: ${{github.workspace}}/artifacts + + - name: NuGet Autenticate + if: github.event_name != 'pull_request' + run: dotnet nuget add source + "https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json" + --name "github" + --username ${{ github.actor }} + --password ${{ secrets.GITHUB_TOKEN }} + --store-password-in-clear-text + working-directory: .dotnet + + - name: Publish + if: github.event_name != 'pull_request' + run: dotnet nuget push + ${{github.workspace}}/artifacts/packages/*.nupkg + --source "github" + --api-key ${{ secrets.GITHUB_TOKEN }} + --skip-duplicate + working-directory: .dotnet diff --git a/.gitignore b/.gitignore index 5a3c43f3f..f71e3dc8e 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ launchSettings.json .assets # Build results +/artifacts binaries/ [Dd]ebug*/ [Rr]elease/ From c25a062f1dfe399248bdff7f51224d03ed6c4110 Mon Sep 17 00:00:00 2001 From: Patrick Hallisey Date: Fri, 15 Mar 2024 16:33:58 -0700 Subject: [PATCH 38/50] Add release workflow (#25) --- .github/workflows/main.yml | 1 - .github/workflows/release.yml | 64 +++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2d11478b2..521ae2598 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -12,7 +12,6 @@ jobs: build: # Test, pack and publish the Open AI nuget package as a build artifact runs-on: ubuntu-latest env: - # if we're in a manually queued run, version_suffix_args: ${{ format('--version-suffix="alpha.{0}"', github.run_number) }} steps: - name: Setup .NET diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..f296f9c90 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,64 @@ +name: Release package + +on: + workflow_dispatch: + release: + types: [created] + +jobs: + deploy: + runs-on: ubuntu-latest + permissions: + packages: write + contents: read + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-dotnet@v3 + with: + dotnet-version: '8.x' # SDK Version to use. + + - name: Build + run: dotnet build + -c Release + working-directory: .dotnet + + - name: Test + run: dotnet test + --no-build + --configuration Release + --filter="TestCategory~Online" + --logger "trx;LogFileName=${{github.workspace}}/artifacts/test-results/full.trx" + env: + SECRET_VALUE: ${{ secrets.OPENAI_TOKEN }} + working-directory: .dotnet + + - name: Pack + run: dotnet pack + --no-build + --configuration Release + --output "${{github.workspace}}/artifacts/packages" + working-directory: .dotnet + + - name: Upload artifact + uses: actions/upload-artifact@v2 + with: + name: build-artifacts + path: ${{github.workspace}}/artifacts + + - name: NuGet Autenticate + run: dotnet nuget add source + "https://nuget.pkg.github.com/${{ github.repository_owner }}/index.json" + --name "github" + --username ${{ github.actor }} + --password ${{ secrets.GITHUB_TOKEN }} + --store-password-in-clear-text + working-directory: .dotnet + + - name: Publish + run: dotnet nuget push + ${{github.workspace}}/artifacts/packages/*.nupkg + --source "github" + --api-key ${{ secrets.GITHUB_TOKEN }} + --skip-duplicate + working-directory: .dotnet + From 1d447d9e8accfee878316f7135a4771dbce3609a Mon Sep 17 00:00:00 2001 From: Patrick Hallisey Date: Mon, 18 Mar 2024 10:49:33 -0700 Subject: [PATCH 39/50] When building a release, upload nuget package as a release asset (#27) * Upload the nuget package as a release asset * Remove workflow_dispatch trigger from release * Use `published` type for release event triggering * Add contents: write permission to release workflow --- .github/workflows/release.yml | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f296f9c90..16bc44f93 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,16 +1,16 @@ name: Release package on: - workflow_dispatch: release: - types: [created] + types: [published] + jobs: deploy: runs-on: ubuntu-latest permissions: packages: write - contents: read + contents: write steps: - uses: actions/checkout@v4 - uses: actions/setup-dotnet@v3 @@ -39,6 +39,13 @@ jobs: --output "${{github.workspace}}/artifacts/packages" working-directory: .dotnet + # Append the nuget package to the github release that triggered this workflow + - name: Upload release asset + run: gh release upload ${{ github.event.release.tag_name }} + ${{github.workspace}}/artifacts/packages/*.nupkg + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Upload artifact uses: actions/upload-artifact@v2 with: From 3957379e9d4fa592c1399500c7372ffb74962455 Mon Sep 17 00:00:00 2001 From: Patrick Hallisey Date: Mon, 18 Mar 2024 12:16:25 -0700 Subject: [PATCH 40/50] Add release url to nuget package (#28) --- .github/workflows/release.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 16bc44f93..b2bd412ec 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,11 +32,14 @@ jobs: SECRET_VALUE: ${{ secrets.OPENAI_TOKEN }} working-directory: .dotnet + # Pack the client nuget package and include urls back to the repository and release tag - name: Pack run: dotnet pack --no-build --configuration Release --output "${{github.workspace}}/artifacts/packages" + /p:RepositoryUrl="${{ github.repository }}" + /p:PackageProjectUrl="${{ github.repository }}/tree/${{ github.event.release.tag_name }}" working-directory: .dotnet # Append the nuget package to the github release that triggered this workflow From bc4d02f067575bc421fff92c65bcfe8185ade0f8 Mon Sep 17 00:00:00 2001 From: Patrick Hallisey Date: Mon, 18 Mar 2024 12:22:44 -0700 Subject: [PATCH 41/50] Use major version 0 (#29) --- .dotnet/src/Directory.Build.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.dotnet/src/Directory.Build.props b/.dotnet/src/Directory.Build.props index 14f9c42e7..cc9c20924 100644 --- a/.dotnet/src/Directory.Build.props +++ b/.dotnet/src/Directory.Build.props @@ -1,7 +1,7 @@ - 1.0.0 - beta.1 + 0.1.0 + beta.0 true OpenAI.snk From ddbba588015a3303417d5e51e4cca450384bad75 Mon Sep 17 00:00:00 2001 From: Patrick Hallisey Date: Mon, 18 Mar 2024 12:33:05 -0700 Subject: [PATCH 42/50] Use better package urls (#30) --- .dotnet/src/Directory.Build.props | 2 +- .github/workflows/release.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.dotnet/src/Directory.Build.props b/.dotnet/src/Directory.Build.props index cc9c20924..21f972465 100644 --- a/.dotnet/src/Directory.Build.props +++ b/.dotnet/src/Directory.Build.props @@ -1,7 +1,7 @@ 0.1.0 - beta.0 + beta.1 true OpenAI.snk diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b2bd412ec..8e25a5651 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -38,8 +38,8 @@ jobs: --no-build --configuration Release --output "${{github.workspace}}/artifacts/packages" - /p:RepositoryUrl="${{ github.repository }}" - /p:PackageProjectUrl="${{ github.repository }}/tree/${{ github.event.release.tag_name }}" + /p:RepositoryUrl="https://github.com/${{ github.repository }}" + /p:PackageProjectUrl="https://github.com/${{ github.repository }}/tree/${{ github.event.release.tag_name }}" working-directory: .dotnet # Append the nuget package to the github release that triggered this workflow From fed67d6ca455cb71ad06b4089828ea5735129540 Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado <45773732+joseharriaga@users.noreply.github.com> Date: Mon, 18 Mar 2024 16:07:46 -0700 Subject: [PATCH 43/50] Add ModifyMessage methods to AssistantClient (#31) * Added `ModifyMessage` and `ModifyMessageAsync` protocol and convenience methods to `AssistantClient`. * Fixed typo: `GetAssistantFileAssociation` --> `GetAssistantFileAssociations` * Fixed typo: `GetAssistantFileAssociationAsync` --> `GetAssistantFileAssociationsAsync` * Added missing usages of `ConfigureAwait(false)` in `AssistantClient`. --- .../Assistants/AssistantClient.Protocol.cs | 22 ++++- .../src/Custom/Assistants/AssistantClient.cs | 90 ++++++++++--------- .../Assistants/MessageModificationOptions.cs | 21 +++++ .../Assistants/ThreadModificationOptions.cs | 3 - 4 files changed, 89 insertions(+), 47 deletions(-) create mode 100644 .dotnet/src/Custom/Assistants/MessageModificationOptions.cs diff --git a/.dotnet/src/Custom/Assistants/AssistantClient.Protocol.cs b/.dotnet/src/Custom/Assistants/AssistantClient.Protocol.cs index 1ac71c23b..826d90bf8 100644 --- a/.dotnet/src/Custom/Assistants/AssistantClient.Protocol.cs +++ b/.dotnet/src/Custom/Assistants/AssistantClient.Protocol.cs @@ -120,7 +120,7 @@ public virtual async Task GetAssistantFileAssociationAsync( /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual ClientResult GetAssistantFileAssociation( + public virtual ClientResult GetAssistantFileAssociations( string assistantId, int? maxResults, string createdSortOrder, @@ -131,7 +131,7 @@ public virtual ClientResult GetAssistantFileAssociation( /// [EditorBrowsable(EditorBrowsableState.Never)] - public virtual async Task GetAssistantFileAssociationAsync( + public virtual async Task GetAssistantFileAssociationsAsync( string assistantId, int? maxResults, string createdSortOrder, @@ -246,6 +246,24 @@ public virtual async Task GetMessageAsync( RequestOptions options) => await MessageShim.GetMessageAsync(threadId, messageId, options).ConfigureAwait(false); + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult ModifyMessage( + string threadId, + string messageId, + BinaryContent content, + RequestOptions options) + => MessageShim.ModifyMessage(threadId, messageId, content, options); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual async Task ModifyMessageAsync( + string threadId, + string messageId, + BinaryContent content, + RequestOptions options) + => await MessageShim.ModifyMessageAsync(threadId, messageId, content, options).ConfigureAwait(false); + /// [EditorBrowsable(EditorBrowsableState.Never)] public virtual ClientResult GetMessages( diff --git a/.dotnet/src/Custom/Assistants/AssistantClient.cs b/.dotnet/src/Custom/Assistants/AssistantClient.cs index 9fbbc76f0..a8ebe12e7 100644 --- a/.dotnet/src/Custom/Assistants/AssistantClient.cs +++ b/.dotnet/src/Custom/Assistants/AssistantClient.cs @@ -1,4 +1,3 @@ -using OpenAI.ClientShared.Internal; using System; using System.ClientModel; using System.ClientModel.Primitives; @@ -113,8 +112,7 @@ public virtual async Task> CreateAssistantAsync( AssistantCreationOptions options = null) { Internal.Models.CreateAssistantRequest request = CreateInternalCreateAssistantRequest(modelName, options); - ClientResult internalResult - = await Shim.CreateAssistantAsync(request).ConfigureAwait(false); + ClientResult internalResult = await Shim.CreateAssistantAsync(request).ConfigureAwait(false); return ClientResult.FromValue(new Assistant(internalResult.Value), internalResult.GetRawResponse()); } @@ -127,8 +125,7 @@ public virtual ClientResult GetAssistant(string assistantId) public virtual async Task> GetAssistantAsync( string assistantId) { - ClientResult internalResult - = await Shim.GetAssistantAsync(assistantId).ConfigureAwait(false); + ClientResult internalResult = await Shim.GetAssistantAsync(assistantId).ConfigureAwait(false); return ClientResult.FromValue(new Assistant(internalResult.Value), internalResult.GetRawResponse()); } @@ -174,8 +171,7 @@ public virtual async Task> ModifyAssistantAsync( AssistantModificationOptions options) { Internal.Models.ModifyAssistantRequest request = CreateInternalModifyAssistantRequest(options); - ClientResult internalResult - = await Shim.ModifyAssistantAsync(assistantId, request).ConfigureAwait(false); + ClientResult internalResult = await Shim.ModifyAssistantAsync(assistantId, request).ConfigureAwait(false); return ClientResult.FromValue(new Assistant(internalResult.Value), internalResult.GetRawResponse()); } @@ -189,8 +185,7 @@ public virtual ClientResult DeleteAssistant( public virtual async Task> DeleteAssistantAsync( string assistantId) { - ClientResult internalResponse - = await Shim.DeleteAssistantAsync(assistantId).ConfigureAwait(false); + ClientResult internalResponse = await Shim.DeleteAssistantAsync(assistantId).ConfigureAwait(false); return ClientResult.FromValue(internalResponse.Value.Deleted, internalResponse.GetRawResponse()); } @@ -207,8 +202,7 @@ public virtual async Task> CreateAssistan string assistantId, string fileId) { - ClientResult internalResult - = await Shim.CreateAssistantFileAsync(assistantId, new(fileId)).ConfigureAwait(false); + ClientResult internalResult = await Shim.CreateAssistantFileAsync(assistantId, new(fileId)).ConfigureAwait(false); return ClientResult.FromValue(new AssistantFileAssociation(internalResult.Value), internalResult.GetRawResponse()); } @@ -224,8 +218,7 @@ public virtual async Task> GetAssistantFi string assistantId, string fileId) { - ClientResult internalResult - = await Shim.GetAssistantFileAsync(assistantId, fileId).ConfigureAwait(false); + ClientResult internalResult = await Shim.GetAssistantFileAsync(assistantId, fileId).ConfigureAwait(false); return ClientResult.FromValue(new AssistantFileAssociation(internalResult.Value), internalResult.GetRawResponse()); } @@ -275,8 +268,7 @@ public virtual async Task> RemoveAssistantFileAssociationAsyn string assistantId, string fileId) { - ClientResult internalResult - = await Shim.DeleteAssistantFileAsync(assistantId, fileId).ConfigureAwait(false); + ClientResult internalResult = await Shim.DeleteAssistantFileAsync(assistantId, fileId).ConfigureAwait(false); return ClientResult.FromValue(internalResult.Value.Deleted, internalResult.GetRawResponse()); } @@ -292,8 +284,7 @@ public virtual async Task> CreateThreadAsync( ThreadCreationOptions options = null) { Internal.Models.CreateThreadRequest request = CreateInternalCreateThreadRequest(options); - ClientResult internalResult - = await ThreadShim.CreateThreadAsync(request).ConfigureAwait(false); + ClientResult internalResult = await ThreadShim.CreateThreadAsync(request).ConfigureAwait(false); return ClientResult.FromValue(new AssistantThread(internalResult.Value), internalResult.GetRawResponse()); } @@ -306,8 +297,7 @@ public virtual ClientResult GetThread(string threadId) public virtual async Task> GetThreadAsync( string threadId) { - ClientResult internalResult - = await ThreadShim.GetThreadAsync(threadId).ConfigureAwait(false); + ClientResult internalResult = await ThreadShim.GetThreadAsync(threadId).ConfigureAwait(false); return ClientResult.FromValue(new AssistantThread(internalResult.Value), internalResult.GetRawResponse()); } @@ -329,8 +319,7 @@ public virtual async Task> ModifyThreadAsync( Internal.Models.ModifyThreadRequest request = new( options.Metadata, serializedAdditionalRawData: null); - ClientResult internalResult - = await ThreadShim.ModifyThreadAsync(threadId, request); + ClientResult internalResult = await ThreadShim.ModifyThreadAsync(threadId, request).ConfigureAwait(false); return ClientResult.FromValue(new AssistantThread(internalResult.Value), internalResult.GetRawResponse()); } @@ -342,8 +331,7 @@ public virtual ClientResult DeleteThread(string threadId) public virtual async Task> DeleteThreadAsync(string threadId) { - ClientResult internalResult - = await ThreadShim.DeleteThreadAsync(threadId).ConfigureAwait(false); + ClientResult internalResult = await ThreadShim.DeleteThreadAsync(threadId).ConfigureAwait(false); return ClientResult.FromValue(internalResult.Value.Deleted, internalResult.GetRawResponse()); } @@ -375,8 +363,7 @@ public virtual async Task> CreateMessageAsync( options.FileIds, options.Metadata, serializedAdditionalRawData: null); - ClientResult internalResult - = await MessageShim.CreateMessageAsync(threadId, request).ConfigureAwait(false); + ClientResult internalResult = await MessageShim.CreateMessageAsync(threadId, request).ConfigureAwait(false); return ClientResult.FromValue(new ThreadMessage(internalResult.Value), internalResult.GetRawResponse()); } @@ -392,8 +379,31 @@ public virtual async Task> GetMessageAsync( string threadId, string messageId) { - ClientResult internalResult - = await MessageShim.GetMessageAsync(threadId, messageId).ConfigureAwait(false); + ClientResult internalResult = await MessageShim.GetMessageAsync(threadId, messageId).ConfigureAwait(false); + return ClientResult.FromValue(new ThreadMessage(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual ClientResult ModifyMessage( + string threadId, + string messageId, + MessageModificationOptions options) + { + Internal.Models.ModifyMessageRequest request = new( + options.Metadata, + serializedAdditionalRawData: null); + ClientResult internalResult = MessageShim.ModifyMessage(threadId, messageId, request); + return ClientResult.FromValue(new ThreadMessage(internalResult.Value), internalResult.GetRawResponse()); + } + + public virtual async Task> ModifyMessageAsync( + string threadId, + string messageId, + MessageModificationOptions options) + { + Internal.Models.ModifyMessageRequest request = new( + options.Metadata, + serializedAdditionalRawData: null); + ClientResult internalResult = await MessageShim.ModifyMessageAsync(threadId, messageId, request).ConfigureAwait(false); return ClientResult.FromValue(new ThreadMessage(internalResult.Value), internalResult.GetRawResponse()); } @@ -444,8 +454,7 @@ public virtual async Task> GetMessageFileAs string messageId, string fileId) { - ClientResult internalResult - = await MessageShim.GetMessageFileAsync(threadId, messageId, fileId).ConfigureAwait(false); + ClientResult internalResult = await MessageShim.GetMessageFileAsync(threadId, messageId, fileId).ConfigureAwait(false); return ClientResult.FromValue(new MessageFileAssociation(internalResult.Value), internalResult.GetRawResponse()); } @@ -501,8 +510,7 @@ public virtual async Task> CreateRunAsync( RunCreationOptions options = null) { Internal.Models.CreateRunRequest request = CreateInternalCreateRunRequest(assistantId, options); - ClientResult internalResult - = await RunShim.CreateRunAsync(threadId, request).ConfigureAwait(false); + ClientResult internalResult = await RunShim.CreateRunAsync(threadId, request).ConfigureAwait(false); return ClientResult.FromValue(new ThreadRun(internalResult.Value), internalResult.GetRawResponse()); } @@ -524,8 +532,7 @@ public virtual async Task> CreateThreadAndRunAsync( { Internal.Models.CreateThreadAndRunRequest request = CreateInternalCreateThreadAndRunRequest(assistantId, threadOptions, runOptions); - ClientResult internalResult - = await RunShim.CreateThreadAndRunAsync(request).ConfigureAwait(false); + ClientResult internalResult = await RunShim.CreateThreadAndRunAsync(request).ConfigureAwait(false); return ClientResult.FromValue(new ThreadRun(internalResult.Value), internalResult.GetRawResponse()); } @@ -537,8 +544,7 @@ public virtual ClientResult GetRun(string threadId, string runId) public virtual async Task> GetRunAsync(string threadId, string runId) { - ClientResult internalResult - = await RunShim.GetRunAsync(threadId, runId).ConfigureAwait(false); + ClientResult internalResult = await RunShim.GetRunAsync(threadId, runId).ConfigureAwait(false); return ClientResult.FromValue(new ThreadRun(internalResult.Value), internalResult.GetRawResponse()); } @@ -584,8 +590,7 @@ public virtual ClientResult ModifyRun(string threadId, string runId, public virtual async Task> ModifyRunAsync(string threadId, string runId, RunModificationOptions options) { Internal.Models.ModifyRunRequest request = new(options.Metadata, serializedAdditionalRawData: null); - ClientResult internalResult - = await RunShim.ModifyRunAsync(threadId, runId, request).ConfigureAwait(false); + ClientResult internalResult = await RunShim.ModifyRunAsync(threadId, runId, request).ConfigureAwait(false); return ClientResult.FromValue(new ThreadRun(internalResult.Value), internalResult.GetRawResponse()); } @@ -597,8 +602,7 @@ public virtual ClientResult CancelRun(string threadId, string runId) public virtual async Task> CancelRunAsync(string threadId, string runId) { - ClientResult internalResult - = await RunShim.CancelRunAsync(threadId, runId); + ClientResult internalResult = await RunShim.CancelRunAsync(threadId, runId).ConfigureAwait(false); return ClientResult.FromValue(true, internalResult.GetRawResponse()); } @@ -646,7 +650,8 @@ internal static Internal.Models.CreateAssistantRequest CreateInternalCreateAssis serializedAdditionalRawData: null); } - internal static Internal.Models.ModifyAssistantRequest CreateInternalModifyAssistantRequest(AssistantModificationOptions options) + internal static Internal.Models.ModifyAssistantRequest CreateInternalModifyAssistantRequest( + AssistantModificationOptions options) { return new Internal.Models.ModifyAssistantRequest( options.Model, @@ -659,7 +664,8 @@ internal static Internal.Models.ModifyAssistantRequest CreateInternalModifyAssis serializedAdditionalRawData: null); } - internal static Internal.Models.CreateThreadRequest CreateInternalCreateThreadRequest(ThreadCreationOptions options) + internal static Internal.Models.CreateThreadRequest CreateInternalCreateThreadRequest( + ThreadCreationOptions options) { options ??= new(); return new Internal.Models.CreateThreadRequest( @@ -762,7 +768,7 @@ internal virtual async Task>> GetListQueryPageAsyn where T : class where U : class { - ClientResult internalResult = await internalAsyncFunc.Invoke(); + ClientResult internalResult = await internalAsyncFunc.Invoke().ConfigureAwait(false); ListQueryPage convertedValue = ListQueryPage.Create(internalResult.Value) as ListQueryPage; return ClientResult.FromValue(convertedValue, internalResult.GetRawResponse()); } diff --git a/.dotnet/src/Custom/Assistants/MessageModificationOptions.cs b/.dotnet/src/Custom/Assistants/MessageModificationOptions.cs new file mode 100644 index 000000000..947eccb6d --- /dev/null +++ b/.dotnet/src/Custom/Assistants/MessageModificationOptions.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; + +namespace OpenAI.Assistants; + +/// +/// Represents additional options available when modifying an existing . +/// +public partial class MessageModificationOptions +{ + /// + /// A replacement for the optional key/value mapping of additional, supplemental data items to attach to the + /// . This information may be useful for storing custom details in a structured format. + /// + /// + /// + /// Keys can be a maximum of 64 characters in length. + /// Values can be a maximum of 512 characters in length. + /// + /// + public IDictionary Metadata { get; } = new ChangeTrackingDictionary(); +} \ No newline at end of file diff --git a/.dotnet/src/Custom/Assistants/ThreadModificationOptions.cs b/.dotnet/src/Custom/Assistants/ThreadModificationOptions.cs index b36224468..8e47015d3 100644 --- a/.dotnet/src/Custom/Assistants/ThreadModificationOptions.cs +++ b/.dotnet/src/Custom/Assistants/ThreadModificationOptions.cs @@ -1,6 +1,3 @@ -using OpenAI.ClientShared.Internal; -using System.ClientModel.Internal; - using System.Collections.Generic; namespace OpenAI.Assistants; From 6374f6dfbc5284b982e47cb80320c1429482ea1b Mon Sep 17 00:00:00 2001 From: Anne Thompson Date: Tue, 19 Mar 2024 18:48:34 -0700 Subject: [PATCH 44/50] Move OpenAI to use latest multipart/form-data proposal (#32) * Add convenience methods for image edits and variations * investigation * WIP * rework to depend on local implementation of ClientModel * go back to using BCL type * WIP * WIP * file client * update for filename * Add model implementation prototype * backup WIP * unlink demo client * refactor * move content creation routine to model * null * revert * cleanup * revert * Add clean generated client using System.ClientModel 1.0.0-beta.2 * delete files not used for diff * move to public clientmodel package * Create transcription * Create translation * tidy * tidy * Add Stream overloads for audio service methods * file endpoints * nits * nits * image edits * image variations * nits * stream overloads for file upload * stream overloads for image operations * nits * update for Content-Length * rework file name APIs * rework file name APIs * Update from @joseharriaga Co-authored-by: Jose Arriaga Maldonado <45773732+joseharriaga@users.noreply.github.com> * Update from @joseharriaga Co-authored-by: Jose Arriaga Maldonado <45773732+joseharriaga@users.noreply.github.com> * Update from @joseharriaga Co-authored-by: Jose Arriaga Maldonado <45773732+joseharriaga@users.noreply.github.com> * Update from @joseharriaga Co-authored-by: Jose Arriaga Maldonado <45773732+joseharriaga@users.noreply.github.com> * Update from @joseharriaga Co-authored-by: Jose Arriaga Maldonado <45773732+joseharriaga@users.noreply.github.com> * Update from @joseharriaga Co-authored-by: Jose Arriaga Maldonado <45773732+joseharriaga@users.noreply.github.com> --------- Co-authored-by: Jose Arriaga Maldonado Co-authored-by: Jose Arriaga Maldonado <45773732+joseharriaga@users.noreply.github.com> --- .dotnet/src/Custom/Audio/AudioClient.cs | 363 ++++++++---- .../src/Custom/Audio/AudioTranscription.cs | 6 + .../Custom/Audio/AudioTranscriptionOptions.cs | 79 ++- .dotnet/src/Custom/Audio/AudioTranslation.cs | 9 +- .../Custom/Audio/AudioTranslationOptions.cs | 49 +- .dotnet/src/Custom/Files/FileClient.cs | 170 ++++-- .dotnet/src/Custom/Files/UploadFileOptions.cs | 42 ++ .../Custom/Images/GeneratedImageCollection.cs | 21 + .dotnet/src/Custom/Images/ImageClient.cs | 526 +++++++++--------- .dotnet/src/Custom/Images/ImageEditOptions.cs | 94 +++- .../Custom/Images/ImageVariationOptions.cs | 69 ++- .dotnet/src/OpenAI.csproj | 4 +- .../Utility/MultipartFormDataBinaryContent.cs | 155 ++++++ .../System.ClientModel.MultipartContent.cs | 367 ------------ ...em.ClientModel.MultipartFormDataContent.cs | 117 ---- .dotnet/tests/OpenAI.Tests.csproj | 2 +- .../Images/Sample02_SimpleImageEdit.cs | 3 +- .../Images/Sample02_SimpleImageEditAsync.cs | 3 +- .../Images/Sample03_SimpleImageVariation.cs | 2 +- .../Sample03_SimpleImageVariationAsync.cs | 2 +- 20 files changed, 1175 insertions(+), 908 deletions(-) create mode 100644 .dotnet/src/Custom/Files/UploadFileOptions.cs create mode 100644 .dotnet/src/Utility/MultipartFormDataBinaryContent.cs delete mode 100644 .dotnet/src/Utility/System.ClientModel.MultipartContent.cs delete mode 100644 .dotnet/src/Utility/System.ClientModel.MultipartFormDataContent.cs diff --git a/.dotnet/src/Custom/Audio/AudioClient.cs b/.dotnet/src/Custom/Audio/AudioClient.cs index 12ca6eb4f..748928db4 100644 --- a/.dotnet/src/Custom/Audio/AudioClient.cs +++ b/.dotnet/src/Custom/Audio/AudioClient.cs @@ -1,10 +1,10 @@ -using OpenAI.ClientShared.Internal; +using OpenAI.Internal; using System; using System.ClientModel; using System.ClientModel.Primitives; -using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices.ComTypes; using System.Text; -using System.Text.Json; using System.Threading.Tasks; namespace OpenAI.Audio; @@ -144,173 +144,306 @@ public virtual Task> GenerateSpeechFromTextAsync( return Shim.CreateSpeechAsync(request); } - public virtual ClientResult TranscribeAudio(BinaryData audioBytes, string filename, AudioTranscriptionOptions options = null) + // convenience method - sync; Stream overload + // TODO: add refdoc comment + public virtual ClientResult TranscribeAudio(Stream fileStream, string fileName, AudioTranscriptionOptions options = null) { - PipelineMessage message = CreateInternalTranscriptionRequestMessage(audioBytes, filename, options); - Shim.Pipeline.Send(message); - return GetTranscriptionResultFromResponse(message.Response); + Argument.AssertNotNull(fileStream, nameof(fileStream)); + Argument.AssertNotNull(fileName, nameof(fileName)); + + options ??= new(); + + using MultipartFormDataBinaryContent content = options.ToMultipartContent(fileStream, fileName, _clientConnector.Model); + + ClientResult result = TranscribeAudio(content, content.ContentType); + + PipelineResponse response = result.GetRawResponse(); + + AudioTranscription value = AudioTranscription.Deserialize(response.Content!); + + return ClientResult.FromValue(value, response); + } + + // convenience method - sync + // TODO: add refdoc comment + public virtual ClientResult TranscribeAudio(BinaryData audioBytes, string fileName, AudioTranscriptionOptions options = null) + { + Argument.AssertNotNull(audioBytes, nameof(audioBytes)); + Argument.AssertNotNull(fileName, nameof(fileName)); + + options ??= new(); + + using MultipartFormDataBinaryContent content = options.ToMultipartContent(audioBytes, fileName, _clientConnector.Model); + + ClientResult result = TranscribeAudio(content, content.ContentType); + + PipelineResponse response = result.GetRawResponse(); + + AudioTranscription value = AudioTranscription.Deserialize(response.Content!); + + return ClientResult.FromValue(value, response); } - public virtual async Task> TranscribeAudioAsync(BinaryData audioBytes, string filename, AudioTranscriptionOptions options = null) + // convenience method - async + // TODO: add refdoc comment + public virtual async Task> TranscribeAudioAsync(Stream fileStream, string filename, AudioTranscriptionOptions options = null) { - PipelineMessage message = CreateInternalTranscriptionRequestMessage(audioBytes, filename, options); - await Shim.Pipeline.SendAsync(message).ConfigureAwait(false); - return GetTranscriptionResultFromResponse(message.Response); + Argument.AssertNotNull(fileStream, nameof(fileStream)); + Argument.AssertNotNull(filename, nameof(filename)); + + options ??= new(); + + using MultipartFormDataBinaryContent content = options.ToMultipartContent(fileStream, filename, _clientConnector.Model); + + ClientResult result = await TranscribeAudioAsync(content, content.ContentType).ConfigureAwait(false); + + PipelineResponse response = result.GetRawResponse(); + + AudioTranscription value = AudioTranscription.Deserialize(response.Content!); + + return ClientResult.FromValue(value, response); + } + + // convenience method - async + // TODO: add refdoc comment + public virtual async Task> TranscribeAudioAsync(BinaryData audioBytes, string fileName, AudioTranscriptionOptions options = null) + { + Argument.AssertNotNull(audioBytes, nameof(audioBytes)); + Argument.AssertNotNull(fileName, nameof(fileName)); + + options ??= new(); + + using MultipartFormDataBinaryContent content = options.ToMultipartContent(audioBytes, fileName, _clientConnector.Model); + + ClientResult result = await TranscribeAudioAsync(content, content.ContentType).ConfigureAwait(false); + + PipelineResponse response = result.GetRawResponse(); + + AudioTranscription value = AudioTranscription.Deserialize(response.Content!); + + return ClientResult.FromValue(value, response); } - public virtual ClientResult TranslateAudio(BinaryData audioBytes, string filename, AudioTranslationOptions options = null) + // protocol method - sync + // TODO: add refdoc comment + public virtual ClientResult TranscribeAudio(BinaryContent content, string contentType, RequestOptions options = null) { - PipelineMessage message = CreateInternalTranslationRequestMessage(audioBytes, filename, options); + Argument.AssertNotNull(content, nameof(content)); + Argument.AssertNotNull(contentType, nameof(contentType)); + + options ??= new RequestOptions(); + + using PipelineMessage message = CreateCreateTranscriptionRequest(content, contentType, options); + Shim.Pipeline.Send(message); - return GetTranslationResultFromResponse(message.Response); + + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + { + throw new ClientResultException(response); + } + + return ClientResult.FromResponse(response); } - public virtual async Task> TranslateAudioAsync(BinaryData audioBytes, string filename, AudioTranslationOptions options = null) + // protocol method - async + // TODO: add refdoc comment + public virtual async Task TranscribeAudioAsync(BinaryContent content, string contentType, RequestOptions options = null) { - PipelineMessage message = CreateInternalTranslationRequestMessage(audioBytes, filename, options); - await Shim.Pipeline.SendAsync(message).ConfigureAwait(false); - return GetTranslationResultFromResponse(message.Response); + Argument.AssertNotNull(content, nameof(content)); + Argument.AssertNotNull(contentType, nameof(contentType)); + + options ??= new RequestOptions(); + + using PipelineMessage message = CreateCreateTranscriptionRequest(content, contentType, options); + + Shim.Pipeline.Send(message); + + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + { + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + } + + return ClientResult.FromResponse(response); } - private PipelineMessage CreateInternalTranscriptionRequestMessage(BinaryData audioBytes, string filename, AudioTranscriptionOptions options) + private PipelineMessage CreateCreateTranscriptionRequest(BinaryContent content, string contentType, RequestOptions options) { PipelineMessage message = Shim.Pipeline.CreateMessage(); message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; request.Method = "POST"; + UriBuilder uriBuilder = new(_clientConnector.Endpoint.AbsoluteUri); + StringBuilder path = new(); path.Append("/audio/transcriptions"); uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; - MultipartFormDataContent requestContent = CreateInternalTranscriptionRequestContent(audioBytes, filename, options); - requestContent.ApplyToRequest(request); + request.Headers.Set("Content-Type", contentType); + + request.Content = content; + + message.Apply(options); return message; } - private PipelineMessage CreateInternalTranslationRequestMessage(BinaryData audioBytes, string filename, AudioTranslationOptions options) + // convenience method - sync; Stream overload + // TODO: add refdoc comment + public virtual ClientResult TranslateAudio(Stream fileStream, string fileName, AudioTranslationOptions options = null) { - PipelineMessage message = Shim.Pipeline.CreateMessage(); - message.ResponseClassifier = ResponseErrorClassifier200; - PipelineRequest request = message.Request; - request.Method = "POST"; - UriBuilder uriBuilder = new(_clientConnector.Endpoint.AbsoluteUri); - StringBuilder path = new(); - path.Append("/audio/translations"); - uriBuilder.Path += path.ToString(); - request.Uri = uriBuilder.Uri; + Argument.AssertNotNull(fileStream, nameof(fileStream)); + Argument.AssertNotNull(fileName, nameof(fileName)); + + options ??= new(); - MultipartFormDataContent requestContent = CreateInternalTranscriptionRequestContent(audioBytes, filename, options); - requestContent.ApplyToRequest(request); + using MultipartFormDataBinaryContent content = options.ToMultipartContent(fileStream, fileName, _clientConnector.Model); - return message; + ClientResult result = TranslateAudio(content, content.ContentType); + + PipelineResponse response = result.GetRawResponse(); + + AudioTranslation value = AudioTranslation.Deserialize(response.Content!); + + return ClientResult.FromValue(value, response); } - private MultipartFormDataContent CreateInternalTranscriptionRequestContent(BinaryData audioBytes, string filename, AudioTranscriptionOptions options) + // convenience method - sync + // TODO: add refdoc comment + public virtual ClientResult TranslateAudio(BinaryData audioBytes, string fileName, AudioTranslationOptions options = null) { + Argument.AssertNotNull(audioBytes, nameof(audioBytes)); + Argument.AssertNotNull(fileName, nameof(fileName)); + options ??= new(); - return CreateInternalTranscriptionRequestContent( - audioBytes, - filename, - options.Language, - options.Prompt, - options.ResponseFormat, - options.Temperature, - options.EnableWordTimestamps, - options.EnableSegmentTimestamps); + + using MultipartFormDataBinaryContent content = options.ToMultipartContent(audioBytes, fileName, _clientConnector.Model); + + ClientResult result = TranslateAudio(content, content.ContentType); + + PipelineResponse response = result.GetRawResponse(); + + AudioTranslation value = AudioTranslation.Deserialize(response.Content!); + + return ClientResult.FromValue(value, response); } - private MultipartFormDataContent CreateInternalTranscriptionRequestContent(BinaryData audioBytes, string filename, AudioTranslationOptions options) + // convenience method - async; Stream overload + // TODO: add refdoc comment + public virtual async Task> TranslateAudioAsync(Stream fileStream, string fileName, AudioTranslationOptions options = null) { + Argument.AssertNotNull(fileStream, nameof(fileStream)); + Argument.AssertNotNull(fileName, nameof(fileName)); + options ??= new(); - return CreateInternalTranscriptionRequestContent( - audioBytes, - filename, - language: null, - options.Prompt, - options.ResponseFormat, - options.Temperature, - enableWordTimestamps: null, - enableSegmentTimestamps: null); + + using MultipartFormDataBinaryContent content = options.ToMultipartContent(fileStream, fileName, _clientConnector.Model); + + ClientResult result = await TranslateAudioAsync(content, content.ContentType).ConfigureAwait(false); + + PipelineResponse response = result.GetRawResponse(); + + AudioTranslation value = AudioTranslation.Deserialize(response.Content!); + + return ClientResult.FromValue(value, response); } - private MultipartFormDataContent CreateInternalTranscriptionRequestContent( - BinaryData audioBytes, - string filename, - string language = null, - string prompt = null, - AudioTranscriptionFormat? transcriptionFormat = null, - float? temperature = null, - bool? enableWordTimestamps = null, - bool? enableSegmentTimestamps = null) + // convenience method - async + // TODO: add refdoc comment + public virtual async Task> TranslateAudioAsync(BinaryData audioBytes, string fileName, AudioTranslationOptions options = null) { - MultipartFormDataContent content = new(); - content.Add(MultipartContent.Create(BinaryData.FromString(_clientConnector.Model)), name: "model", []); - if (Optional.IsDefined(language)) - { - content.Add(MultipartContent.Create(BinaryData.FromString(language)), name: "language", []); - } - if (Optional.IsDefined(prompt)) - { - content.Add(MultipartContent.Create(BinaryData.FromString(prompt)), name: "prompt", []); - } - if (Optional.IsDefined(transcriptionFormat)) - { - content.Add(MultipartContent.Create(BinaryData.FromString(transcriptionFormat switch - { - AudioTranscriptionFormat.Simple => "json", - AudioTranscriptionFormat.Detailed => "verbose_json", - AudioTranscriptionFormat.Srt => "srt", - AudioTranscriptionFormat.Vtt => "vtt", - _ => throw new ArgumentException(nameof(transcriptionFormat)), - })), - name: "response_format", - []); - } - if (Optional.IsDefined(temperature)) - { - content.Add(MultipartContent.Create(BinaryData.FromString($"{temperature}")), name: "temperature", []); - } - if (Optional.IsDefined(enableWordTimestamps) || Optional.IsDefined(enableSegmentTimestamps)) - { - List granularities = []; - if (enableWordTimestamps == true) - { - granularities.Add("word"); - } - if (enableSegmentTimestamps == true) - { - granularities.Add("segment"); - } - content.Add(MultipartContent.Create(BinaryData.FromObjectAsJson(granularities)), name: "timestamp_granularities", []); - } - content.Add(MultipartContent.Create(audioBytes), name: "file", fileName: filename, []); + Argument.AssertNotNull(audioBytes, nameof(audioBytes)); + Argument.AssertNotNull(fileName, nameof(fileName)); + + options ??= new(); + + using MultipartFormDataBinaryContent content = options.ToMultipartContent(audioBytes, fileName, _clientConnector.Model); - return content; + ClientResult result = await TranslateAudioAsync(content, content.ContentType).ConfigureAwait(false); + + PipelineResponse response = result.GetRawResponse(); + + AudioTranslation value = AudioTranslation.Deserialize(response.Content!); + + return ClientResult.FromValue(value, response); } - private static ClientResult GetTranscriptionResultFromResponse(PipelineResponse response) + // protocol method - sync + // TODO: add refdoc comment + public virtual ClientResult TranslateAudio(BinaryContent content, string contentType, RequestOptions options = null) { - if (response.IsError) + Argument.AssertNotNull(content, nameof(content)); + Argument.AssertNotNull(contentType, nameof(contentType)); + + options ??= new RequestOptions(); + + using PipelineMessage message = CreateCreateTranslationRequest(content, contentType, options); + + Shim.Pipeline.Send(message); + + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { throw new ClientResultException(response); } - using JsonDocument responseDocument = JsonDocument.Parse(response.Content); - return ClientResult.FromValue(AudioTranscription.DeserializeAudioTranscription(responseDocument.RootElement), response); + return ClientResult.FromResponse(response); } - private static ClientResult GetTranslationResultFromResponse(PipelineResponse response) + // protocol method - async + // TODO: add refdoc comment + public virtual async Task TranslateAudioAsync(BinaryContent content, string contentType, RequestOptions options = null) { - if (response.IsError) + Argument.AssertNotNull(content, nameof(content)); + Argument.AssertNotNull(contentType, nameof(contentType)); + + options ??= new RequestOptions(); + + using PipelineMessage message = CreateCreateTranslationRequest(content, contentType, options); + + Shim.Pipeline.Send(message); + + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - throw new ClientResultException(response); + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } - using JsonDocument responseDocument = JsonDocument.Parse(response.Content); - return ClientResult.FromValue(AudioTranslation.DeserializeAudioTranscription(responseDocument.RootElement), response); + return ClientResult.FromResponse(response); + } + + private PipelineMessage CreateCreateTranslationRequest(BinaryContent content, string contentType, RequestOptions options) + { + PipelineMessage message = Shim.Pipeline.CreateMessage(); + message.ResponseClassifier = ResponseErrorClassifier200; + + PipelineRequest request = message.Request; + request.Method = "POST"; + + UriBuilder uriBuilder = new(_clientConnector.Endpoint.AbsoluteUri); + + StringBuilder path = new(); + path.Append("/audio/translations"); + uriBuilder.Path += path.ToString(); + + request.Uri = uriBuilder.Uri; + + request.Headers.Set("Content-Type", contentType); + + request.Content = content; + + message.Apply(options); + + return message; } private Internal.Models.CreateSpeechRequest CreateInternalTtsRequest( @@ -346,7 +479,7 @@ private Internal.Models.CreateSpeechRequest CreateInternalTtsRequest( options?.SpeedMultiplier, serializedAdditionalRawData: null); } + private static PipelineMessageClassifier _responseErrorClassifier200; private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); - } diff --git a/.dotnet/src/Custom/Audio/AudioTranscription.cs b/.dotnet/src/Custom/Audio/AudioTranscription.cs index 5f55ef9cb..efd5a0e8d 100644 --- a/.dotnet/src/Custom/Audio/AudioTranscription.cs +++ b/.dotnet/src/Custom/Audio/AudioTranscription.cs @@ -22,6 +22,12 @@ internal AudioTranscription(string language, TimeSpan? duration, string text, IR Segments = segments; } + internal static AudioTranscription Deserialize(BinaryData content) + { + using JsonDocument responseDocument = JsonDocument.Parse(content); + return DeserializeAudioTranscription(responseDocument.RootElement); + } + internal static AudioTranscription DeserializeAudioTranscription(JsonElement element, ModelReaderWriterOptions options = default) { string language = null; diff --git a/.dotnet/src/Custom/Audio/AudioTranscriptionOptions.cs b/.dotnet/src/Custom/Audio/AudioTranscriptionOptions.cs index 2b473f74d..6d4c3ab12 100644 --- a/.dotnet/src/Custom/Audio/AudioTranscriptionOptions.cs +++ b/.dotnet/src/Custom/Audio/AudioTranscriptionOptions.cs @@ -1,14 +1,89 @@ +using OpenAI.Internal; using System; using System.Collections.Generic; +using System.IO; +using System.Text.Json; namespace OpenAI.Audio; public partial class AudioTranscriptionOptions { public string Language { get; set; } - public string Prompt { get; set; } + public string Prompt { get; set; } public AudioTranscriptionFormat? ResponseFormat { get; set; } public float? Temperature { get; set; } public bool? EnableWordTimestamps { get; set; } public bool? EnableSegmentTimestamps { get; set; } -} \ No newline at end of file + + internal MultipartFormDataBinaryContent ToMultipartContent(Stream fileStream, string fileName, string model) + { + MultipartFormDataBinaryContent content = new(); + + content.Add(fileStream, "file", fileName); + + AddContent(model, content); + + return content; + } + + internal MultipartFormDataBinaryContent ToMultipartContent(BinaryData audioBytes, string fileName, string model) + { + MultipartFormDataBinaryContent content = new(); + + content.Add(audioBytes, "file", fileName); + + AddContent(model, content); + + return content; + } + + private void AddContent(string model, MultipartFormDataBinaryContent content) + { + content.Add(model, "model"); + + if (Language is not null) + { + content.Add(Language, "language"); + } + + if (Prompt is not null) + { + content.Add(Prompt, "prompt"); + } + + if (ResponseFormat is not null) + { + string value = ResponseFormat switch + { + AudioTranscriptionFormat.Simple => "json", + AudioTranscriptionFormat.Detailed => "verbose_json", + AudioTranscriptionFormat.Srt => "srt", + AudioTranscriptionFormat.Vtt => "vtt", + _ => throw new ArgumentException(nameof(ResponseFormat)) + }; + + content.Add(value, "response_format"); + } + + if (Temperature is not null) + { + content.Add(Temperature.Value, "temperature"); + } + + if (EnableWordTimestamps is not null || EnableSegmentTimestamps is not null) + { + List granularities = []; + if (EnableWordTimestamps.Value) + { + granularities.Add("word"); + } + if (EnableSegmentTimestamps.Value) + { + granularities.Add("segment"); + } + + byte[] data = JsonSerializer.SerializeToUtf8Bytes(granularities); + content.Add(data, "timestamp_granularities"); + } + } +} diff --git a/.dotnet/src/Custom/Audio/AudioTranslation.cs b/.dotnet/src/Custom/Audio/AudioTranslation.cs index 49de258bf..b683161b3 100644 --- a/.dotnet/src/Custom/Audio/AudioTranslation.cs +++ b/.dotnet/src/Custom/Audio/AudioTranslation.cs @@ -1,6 +1,5 @@ using System; using System.ClientModel.Primitives; -using System.Collections.Generic; using System.Text.Json; namespace OpenAI.Audio; @@ -14,7 +13,13 @@ internal AudioTranslation(string text) Text = text; } - internal static AudioTranslation DeserializeAudioTranscription(JsonElement element, ModelReaderWriterOptions options = default) + internal static AudioTranslation Deserialize(BinaryData content) + { + using JsonDocument responseDocument = JsonDocument.Parse(content); + return DeserializeAudioTranslation(responseDocument.RootElement); + } + + internal static AudioTranslation DeserializeAudioTranslation(JsonElement element, ModelReaderWriterOptions options = default) { string text = null; diff --git a/.dotnet/src/Custom/Audio/AudioTranslationOptions.cs b/.dotnet/src/Custom/Audio/AudioTranslationOptions.cs index 38e05a047..50f8a89e0 100644 --- a/.dotnet/src/Custom/Audio/AudioTranslationOptions.cs +++ b/.dotnet/src/Custom/Audio/AudioTranslationOptions.cs @@ -1,5 +1,6 @@ +using OpenAI.Internal; using System; -using System.Collections.Generic; +using System.IO; namespace OpenAI.Audio; @@ -8,4 +9,50 @@ public partial class AudioTranslationOptions public string Prompt { get; set; } public AudioTranscriptionFormat? ResponseFormat { get; set; } public float? Temperature { get; set; } + + internal MultipartFormDataBinaryContent ToMultipartContent(Stream fileStream, string fileName, string model) + { + MultipartFormDataBinaryContent content = new(); + + content.Add(fileStream, "file", fileName); + + AddContent(model, content); + + return content; + } + + internal MultipartFormDataBinaryContent ToMultipartContent(BinaryData audioBytes, string fileName, string model) + { + MultipartFormDataBinaryContent content = new(); + + content.Add(audioBytes, "file", fileName); + + AddContent(model, content); + + return content; + } + + private void AddContent(string model, MultipartFormDataBinaryContent content) + { + content.Add(model, "model"); + + if (Prompt is not null) + { + content.Add(Prompt, "prompt"); + } + + if (ResponseFormat is not null) + { + string value = ResponseFormat switch + { + AudioTranscriptionFormat.Simple => "json", + AudioTranscriptionFormat.Detailed => "verbose_json", + AudioTranscriptionFormat.Srt => "srt", + AudioTranscriptionFormat.Vtt => "vtt", + _ => throw new ArgumentException(nameof(ResponseFormat)) + }; + + content.Add(value, "response_format"); + } + } } \ No newline at end of file diff --git a/.dotnet/src/Custom/Files/FileClient.cs b/.dotnet/src/Custom/Files/FileClient.cs index a1cdb9ea8..815d6490e 100644 --- a/.dotnet/src/Custom/Files/FileClient.cs +++ b/.dotnet/src/Custom/Files/FileClient.cs @@ -1,7 +1,9 @@ +using OpenAI.Internal; using System; using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; +using System.IO; using System.Text; using System.Threading.Tasks; @@ -92,24 +94,126 @@ public FileClient(OpenAIClientOptions options = null) : this(endpoint: null, credential: null, options) { } - public virtual ClientResult UploadFile(BinaryData file, string filename, OpenAIFilePurpose purpose) + // convenience method - sync; Stream overload + // TODO: add refdoc comment + public virtual ClientResult UploadFile(Stream fileStream, string fileName, OpenAIFilePurpose purpose) { - if (file is null) throw new ArgumentNullException(nameof(file)); - if (string.IsNullOrWhiteSpace(filename)) throw new ArgumentException(nameof(filename)); + Argument.AssertNotNull(fileStream, nameof(fileStream)); + Argument.AssertNotNull(fileName, nameof(fileName)); - PipelineMessage uploadMessage = CreateInternalUploadMessage(file, filename, purpose); - Shim.Pipeline.Send(uploadMessage); - return GetUploadResultFromResponse(uploadMessage.Response); + using MultipartFormDataBinaryContent content = UploadFileOptions.ToMultipartContent(fileStream, fileName, purpose); + + ClientResult result = UploadFile(content, content.ContentType); + + PipelineResponse response = result.GetRawResponse(); + + Internal.Models.OpenAIFile internalFile = Internal.Models.OpenAIFile.FromResponse(response); + OpenAIFileInfo fileInfo = new(internalFile); + + return ClientResult.FromValue(fileInfo, response); + } + + // convenience method - sync + // TODO: add refdoc comment + public virtual ClientResult UploadFile(BinaryData file, string fileName, OpenAIFilePurpose purpose) + { + Argument.AssertNotNull(file, nameof(file)); + Argument.AssertNotNull(fileName, nameof(fileName)); + + using MultipartFormDataBinaryContent content = UploadFileOptions.ToMultipartContent(file, fileName, purpose); + + ClientResult result = UploadFile(content, content.ContentType); + + PipelineResponse response = result.GetRawResponse(); + + Internal.Models.OpenAIFile internalFile = Internal.Models.OpenAIFile.FromResponse(response); + OpenAIFileInfo fileInfo = new(internalFile); + + return ClientResult.FromValue(fileInfo, response); + } + + // convenience method - async; Stream overload + // TODO: add refdoc comment + public virtual async Task> UploadFileAsync(Stream file, string fileName, OpenAIFilePurpose purpose) + { + Argument.AssertNotNull(file, nameof(file)); + Argument.AssertNotNull(fileName, nameof(fileName)); + + using MultipartFormDataBinaryContent content = UploadFileOptions.ToMultipartContent(file, fileName, purpose); + + ClientResult result = await UploadFileAsync(content, content.ContentType).ConfigureAwait(false); + + PipelineResponse response = result.GetRawResponse(); + + Internal.Models.OpenAIFile internalFile = Internal.Models.OpenAIFile.FromResponse(response); + OpenAIFileInfo fileInfo = new(internalFile); + + return ClientResult.FromValue(fileInfo, response); + } + + // convenience method - async + // TODO: add refdoc comment + public virtual async Task> UploadFileAsync(BinaryData file, string fileName, OpenAIFilePurpose purpose) + { + Argument.AssertNotNull(file, nameof(file)); + Argument.AssertNotNull(fileName, nameof(fileName)); + + using MultipartFormDataBinaryContent content = UploadFileOptions.ToMultipartContent(file, fileName, purpose); + + ClientResult result = await UploadFileAsync(content, content.ContentType).ConfigureAwait(false); + + PipelineResponse response = result.GetRawResponse(); + + Internal.Models.OpenAIFile internalFile = Internal.Models.OpenAIFile.FromResponse(response); + OpenAIFileInfo fileInfo = new(internalFile); + + return ClientResult.FromValue(fileInfo, response); } - public virtual async Task> UploadFileAsync(BinaryData file, string filename, OpenAIFilePurpose purpose) + // protocol method - sync + // TODO: add refdoc comment + public virtual ClientResult UploadFile(BinaryContent content, string contentType, RequestOptions options = null) { - if (file is null) throw new ArgumentNullException(nameof(file)); - if (string.IsNullOrWhiteSpace(filename)) throw new ArgumentException(nameof(filename)); + Argument.AssertNotNull(content, nameof(content)); + Argument.AssertNotNull(contentType, nameof(contentType)); - PipelineMessage uploadMessage = CreateInternalUploadMessage(file, filename, purpose); - await Shim.Pipeline.SendAsync(uploadMessage).ConfigureAwait(false); - return GetUploadResultFromResponse(uploadMessage.Response); + options ??= new RequestOptions(); + + using PipelineMessage message = CreateUploadFileRequest(content, contentType, options); + + Shim.Pipeline.Send(message); + + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + { + throw new ClientResultException(response); + } + + return ClientResult.FromResponse(response); + } + + // protocol method - async + // TODO: add refdoc comment + public virtual async Task UploadFileAsync(BinaryContent content, string contentType, RequestOptions options = null) + { + Argument.AssertNotNull(content, nameof(content)); + Argument.AssertNotNull(contentType, nameof(contentType)); + + options ??= new RequestOptions(); + + using PipelineMessage message = CreateUploadFileRequest(content, contentType, options); + + Shim.Pipeline.Send(message); + + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + { + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + } + + return ClientResult.FromResponse(response); } public virtual ClientResult GetFileInfo(string fileId) @@ -213,53 +317,33 @@ public virtual async Task DeleteFileAsync(string fileId) _ = Shim.DeleteFileAsync(fileId); } - internal PipelineMessage CreateInternalUploadMessage(BinaryData fileData, string filename, OpenAIFilePurpose purpose) + private PipelineMessage CreateUploadFileRequest(BinaryContent content, string contentType, RequestOptions options) { - MultipartFormDataContent content = new(); - content.Add(BinaryContent.Create(fileData), - name: "file", - fileName: filename, - headers: []); - content.Add(MultipartContent.Create( - BinaryData.FromString(purpose switch - { - OpenAIFilePurpose.FineTuning => "fine-tune", - OpenAIFilePurpose.Assistants => "assistants", - _ => throw new ArgumentException($"Unsupported purpose for file upload: {purpose}"), - })), - name: "\"purpose\"", - headers: []); - PipelineMessage message = Shim.Pipeline.CreateMessage(); message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; request.Method = "POST"; + UriBuilder uriBuilder = new(_clientConnector.Endpoint.AbsoluteUri); + StringBuilder path = new(); path.Append("/files"); uriBuilder.Path += path.ToString(); + request.Uri = uriBuilder.Uri; + request.Headers.Set("Accept", "application/json"); + request.Headers.Set("Content-Type", contentType); + request.Content = content; - content.ApplyToRequest(request); + message.Apply(options); return message; } - internal ClientResult GetUploadResultFromResponse(PipelineResponse response) - { - if (response.IsError) - { - throw new ClientResultException(response); - } - - Internal.Models.OpenAIFile internalFile = Internal.Models.OpenAIFile.FromResponse(response); - OpenAIFileInfo fileInfo = new(internalFile); - return ClientResult.FromValue(fileInfo, response); - } - - internal static Internal.Models.OpenAIFilePurpose? ToInternalFilePurpose(OpenAIFilePurpose? purpose) + private static Internal.Models.OpenAIFilePurpose? ToInternalFilePurpose(OpenAIFilePurpose? purpose) { if (purpose == null) { @@ -274,7 +358,7 @@ internal ClientResult GetUploadResultFromResponse(PipelineRespon _ => throw new ArgumentException($"Unsupported file purpose: {purpose}"), }; } + private static PipelineMessageClassifier _responseErrorClassifier200; private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); - } diff --git a/.dotnet/src/Custom/Files/UploadFileOptions.cs b/.dotnet/src/Custom/Files/UploadFileOptions.cs new file mode 100644 index 000000000..4b3b6c2d1 --- /dev/null +++ b/.dotnet/src/Custom/Files/UploadFileOptions.cs @@ -0,0 +1,42 @@ +using OpenAI.Internal; +using System; +using System.IO; + +namespace OpenAI.Files; + +internal class UploadFileOptions +{ + internal static MultipartFormDataBinaryContent ToMultipartContent(Stream fileStream, string fileName, OpenAIFilePurpose purpose) + { + MultipartFormDataBinaryContent content = new(); + + content.Add(fileStream, "file", fileName); + + AddContent(purpose, content); + + return content; + } + + internal static MultipartFormDataBinaryContent ToMultipartContent(BinaryData fileData, string fileName, OpenAIFilePurpose purpose) + { + MultipartFormDataBinaryContent content = new(); + + content.Add(fileData, "file", fileName); + + AddContent(purpose, content); + + return content; + } + + private static void AddContent(OpenAIFilePurpose purpose, MultipartFormDataBinaryContent content) + { + string purposeValue = purpose switch + { + OpenAIFilePurpose.FineTuning => "fine-tune", + OpenAIFilePurpose.Assistants => "assistants", + _ => throw new ArgumentException($"Unsupported purpose for file upload: {purpose}"), + }; + + content.Add(purposeValue, "\"purpose\""); + } +} diff --git a/.dotnet/src/Custom/Images/GeneratedImageCollection.cs b/.dotnet/src/Custom/Images/GeneratedImageCollection.cs index 78d217f1a..9f286e260 100644 --- a/.dotnet/src/Custom/Images/GeneratedImageCollection.cs +++ b/.dotnet/src/Custom/Images/GeneratedImageCollection.cs @@ -1,5 +1,7 @@ +using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Text.Json; namespace OpenAI.Images; @@ -9,4 +11,23 @@ namespace OpenAI.Images; public class GeneratedImageCollection : ReadOnlyCollection { internal GeneratedImageCollection(IList list) : base(list) { } + + internal static GeneratedImageCollection Deserialize(BinaryData content) + { + using JsonDocument responseDocument = JsonDocument.Parse(content); + return Deserialize(responseDocument.RootElement); + } + + internal static GeneratedImageCollection Deserialize(JsonElement element) + { + Internal.Models.ImagesResponse response = Internal.Models.ImagesResponse.DeserializeImagesResponse(element); + + List images = []; + for (int i = 0; i < response.Data.Count; i++) + { + images.Add(new GeneratedImage(response, i)); + } + + return new GeneratedImageCollection(images); + } } \ No newline at end of file diff --git a/.dotnet/src/Custom/Images/ImageClient.cs b/.dotnet/src/Custom/Images/ImageClient.cs index 5e29e045b..5dbdacec6 100644 --- a/.dotnet/src/Custom/Images/ImageClient.cs +++ b/.dotnet/src/Custom/Images/ImageClient.cs @@ -1,12 +1,11 @@ -using OpenAI.Audio; -using OpenAI.ClientShared.Internal; +using OpenAI.Internal; using System; using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; +using System.IO; using System.Runtime.InteropServices.ComTypes; using System.Text; -using System.Text.Json; using System.Threading.Tasks; namespace OpenAI.Images; @@ -172,7 +171,7 @@ public virtual async Task> GenerateImages { Internal.Models.CreateImageRequest request = CreateInternalImageRequest(prompt, imageCount, options); ClientResult response = await Shim.CreateImageAsync(request).ConfigureAwait(false); - + List images = []; for (int i = 0; i < response.Value.Data.Count; i++) { @@ -182,106 +181,317 @@ public virtual async Task> GenerateImages return ClientResult.FromValue(new GeneratedImageCollection(images), response.GetRawResponse()); } + + // convenience method - sync; Stream overload + // TODO: add refdoc comment + public virtual ClientResult GenerateImageEdits( + Stream fileStream, + string fileName, + string prompt, + int? imageCount = null, + ImageEditOptions options = null) + { + Argument.AssertNotNull(fileStream, nameof(fileStream)); + Argument.AssertNotNull(fileName, nameof(fileName)); + Argument.AssertNotNull(prompt, nameof(prompt)); + + if (options?.MaskBytes is not null) + { + Argument.AssertNotNull(options.MaskFileName, nameof(options.MaskFileName)); + } + + options ??= new(); + + using MultipartFormDataBinaryContent content = options.ToMultipartContent(fileStream, fileName, prompt, _clientConnector.Model, imageCount); + + ClientResult result = GenerateImageEdits(content, content.ContentType); + + PipelineResponse response = result.GetRawResponse(); + + GeneratedImageCollection value = GeneratedImageCollection.Deserialize(response.Content!); + + return ClientResult.FromValue(value, response); + } + + // convenience method - sync + // TODO: add refdoc comment public virtual ClientResult GenerateImageEdits( BinaryData imageBytes, + string fileName, string prompt, int? imageCount = null, ImageEditOptions options = null) { - PipelineMessage message = CreateInternalImageEditsPipelineMessage(imageBytes, prompt, imageCount, options); - Shim.Pipeline.Send(message); + Argument.AssertNotNull(imageBytes, nameof(imageBytes)); + Argument.AssertNotNull(fileName, nameof(fileName)); + Argument.AssertNotNull(prompt, nameof(prompt)); - if (message.Response.IsError) + if (options?.MaskBytes is not null) { - throw new ClientResultException(message.Response); + Argument.AssertNotNull(options.MaskFileName, nameof(options.MaskFileName)); } - using JsonDocument responseDocument = JsonDocument.Parse(message.Response.Content); - Internal.Models.ImagesResponse response = Internal.Models.ImagesResponse.DeserializeImagesResponse(responseDocument.RootElement); + options ??= new(); + + using MultipartFormDataBinaryContent content = options.ToMultipartContent(imageBytes, fileName, prompt, _clientConnector.Model, imageCount); - List images = []; - for (int i = 0; i < response.Data.Count; i++) + ClientResult result = GenerateImageEdits(content, content.ContentType); + + PipelineResponse response = result.GetRawResponse(); + + GeneratedImageCollection value = GeneratedImageCollection.Deserialize(response.Content!); + + return ClientResult.FromValue(value, response); + } + + // convenience method - async; Stream overload + // TODO: add refdoc comment + public virtual async Task> GenerateImageEditsAsync( + Stream fileStream, + string fileName, + string prompt, + int? imageCount = null, + ImageEditOptions options = null) + { + Argument.AssertNotNull(fileStream, nameof(fileStream)); + Argument.AssertNotNull(fileName, nameof(fileName)); + Argument.AssertNotNull(prompt, nameof(prompt)); + + if (options?.MaskBytes is not null) { - images.Add(new GeneratedImage(response, i)); + Argument.AssertNotNull(options.MaskFileName, nameof(options.MaskFileName)); } - return ClientResult.FromValue(new GeneratedImageCollection(images), message.Response); + options ??= new(); + + using MultipartFormDataBinaryContent content = options.ToMultipartContent(fileStream, fileName, prompt, _clientConnector.Model, imageCount); + + ClientResult result = await GenerateImageEditsAsync(content, content.ContentType).ConfigureAwait(false); + + PipelineResponse response = result.GetRawResponse(); + + GeneratedImageCollection value = GeneratedImageCollection.Deserialize(response.Content!); + + return ClientResult.FromValue(value, response); } + // convenience method - async + // TODO: add refdoc comment public virtual async Task> GenerateImageEditsAsync( BinaryData imageBytes, + string fileName, string prompt, int? imageCount = null, ImageEditOptions options = null) { - PipelineMessage message = CreateInternalImageEditsPipelineMessage(imageBytes, prompt, imageCount, options); - await Shim.Pipeline.SendAsync(message).ConfigureAwait(false); + Argument.AssertNotNull(imageBytes, nameof(imageBytes)); + Argument.AssertNotNull(fileName, nameof(fileName)); + Argument.AssertNotNull(prompt, nameof(prompt)); - if (message.Response.IsError) + if (options?.MaskBytes is not null) { - throw new ClientResultException(message.Response); + Argument.AssertNotNull(options.MaskFileName, nameof(options.MaskFileName)); } - using JsonDocument responseDocument = JsonDocument.Parse(message.Response.Content); - Internal.Models.ImagesResponse response = Internal.Models.ImagesResponse.DeserializeImagesResponse(responseDocument.RootElement); + options ??= new(); - List images = []; - for (int i = 0; i < response.Data.Count; i++) + using MultipartFormDataBinaryContent content = options.ToMultipartContent(imageBytes, fileName, prompt, _clientConnector.Model, imageCount); + + ClientResult result = await GenerateImageEditsAsync(content, content.ContentType).ConfigureAwait(false); + + PipelineResponse response = result.GetRawResponse(); + + GeneratedImageCollection value = GeneratedImageCollection.Deserialize(response.Content!); + + return ClientResult.FromValue(value, response); + } + + // protocol method - sync + // TODO: add refdoc comment + public virtual ClientResult GenerateImageEdits(BinaryContent content, string contentType, RequestOptions options = null) + { + Argument.AssertNotNull(content, nameof(content)); + Argument.AssertNotNull(contentType, nameof(contentType)); + + options ??= new RequestOptions(); + + using PipelineMessage message = CreateCreateImageEditsRequest(content, contentType, options); + + Shim.Pipeline.Send(message); + + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - images.Add(new GeneratedImage(response, i)); + throw new ClientResultException(response); } - return ClientResult.FromValue(new GeneratedImageCollection(images), message.Response); + return ClientResult.FromResponse(response); } + // protocol method - async + // TODO: add refdoc comment + public virtual async Task GenerateImageEditsAsync(BinaryContent content, string contentType, RequestOptions options = null) + { + Argument.AssertNotNull(content, nameof(content)); + Argument.AssertNotNull(contentType, nameof(contentType)); + + options ??= new RequestOptions(); + + using PipelineMessage message = CreateCreateImageEditsRequest(content, contentType, options); + + Shim.Pipeline.Send(message); + + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + { + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + } + + return ClientResult.FromResponse(response); + } + + // convenience method - sync + // TODO: add refdoc comment + public virtual ClientResult GenerateImageVariations( + Stream fileStream, + string fileName, + int? imageCount = null, + ImageVariationOptions options = null) + { + Argument.AssertNotNull(fileStream, nameof(fileStream)); + Argument.AssertNotNull(fileName, nameof(fileName)); + + options ??= new(); + + using MultipartFormDataBinaryContent content = options.ToMultipartContent(fileStream, fileName, _clientConnector.Model, imageCount); + + ClientResult result = GenerateImageVariations(content, content.ContentType); + + PipelineResponse response = result.GetRawResponse(); + + GeneratedImageCollection value = GeneratedImageCollection.Deserialize(response.Content!); + + return ClientResult.FromValue(value, response); + } + + // convenience method - sync + // TODO: add refdoc comment public virtual ClientResult GenerateImageVariations( BinaryData imageBytes, + string fileName, int? imageCount = null, ImageVariationOptions options = null) { - PipelineMessage message = CreateInternalImageVariationsPipelineMessage(imageBytes, imageCount, options); - Shim.Pipeline.Send(message); + Argument.AssertNotNull(imageBytes, nameof(imageBytes)); + Argument.AssertNotNull(fileName, nameof(fileName)); - if (message.Response.IsError) - { - throw new ClientResultException(message.Response); - } + options ??= new(); - using JsonDocument responseDocument = JsonDocument.Parse(message.Response.Content); - Internal.Models.ImagesResponse response = Internal.Models.ImagesResponse.DeserializeImagesResponse(responseDocument.RootElement); + using MultipartFormDataBinaryContent content = options.ToMultipartContent(imageBytes, fileName, _clientConnector.Model, imageCount); - List images = []; - for (int i = 0; i < response.Data.Count; i++) - { - images.Add(new GeneratedImage(response, i)); - } + ClientResult result = GenerateImageVariations(content, content.ContentType); - return ClientResult.FromValue(new GeneratedImageCollection(images), message.Response); + PipelineResponse response = result.GetRawResponse(); + + GeneratedImageCollection value = GeneratedImageCollection.Deserialize(response.Content!); + + return ClientResult.FromValue(value, response); } + // convenience method - async; Stream overload + // TODO: add refdoc comment + public virtual async Task> GenerateImageVariationsAsync( + Stream fileStream, + string fileName, + int? imageCount = null, + ImageVariationOptions options = null) + { + Argument.AssertNotNull(fileStream, nameof(fileStream)); + Argument.AssertNotNull(fileName, nameof(fileName)); + + options ??= new(); + + using MultipartFormDataBinaryContent content = options.ToMultipartContent(fileStream, fileName, _clientConnector.Model, imageCount); + + ClientResult result = await GenerateImageVariationsAsync(content, content.ContentType).ConfigureAwait(false); + + PipelineResponse response = result.GetRawResponse(); + + GeneratedImageCollection value = GeneratedImageCollection.Deserialize(response.Content!); + + return ClientResult.FromValue(value, response); + } + + // convenience method - async + // TODO: add refdoc comment public virtual async Task> GenerateImageVariationsAsync( BinaryData imageBytes, + string fileName, int? imageCount = null, ImageVariationOptions options = null) { - PipelineMessage message = CreateInternalImageVariationsPipelineMessage(imageBytes, imageCount, options); - await Shim.Pipeline.SendAsync(message).ConfigureAwait(false); + Argument.AssertNotNull(imageBytes, nameof(imageBytes)); + Argument.AssertNotNull(fileName, nameof(fileName)); + + options ??= new(); + + using MultipartFormDataBinaryContent content = options.ToMultipartContent(imageBytes, fileName, _clientConnector.Model, imageCount); + + ClientResult result = await GenerateImageVariationsAsync(content, content.ContentType).ConfigureAwait(false); + + PipelineResponse response = result.GetRawResponse(); + + GeneratedImageCollection value = GeneratedImageCollection.Deserialize(response.Content!); + + return ClientResult.FromValue(value, response); + } + + // protocol method - sync + // TODO: add refdoc comment + public virtual ClientResult GenerateImageVariations(BinaryContent content, string contentType, RequestOptions options = null) + { + Argument.AssertNotNull(content, nameof(content)); + Argument.AssertNotNull(contentType, nameof(contentType)); + + options ??= new RequestOptions(); + + using PipelineMessage message = CreateImageVariationsRequest(content, contentType, options); + + Shim.Pipeline.Send(message); + + PipelineResponse response = message.Response!; - if (message.Response.IsError) + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - throw new ClientResultException(message.Response); + throw new ClientResultException(response); } - using JsonDocument responseDocument = JsonDocument.Parse(message.Response.Content); - Internal.Models.ImagesResponse response = Internal.Models.ImagesResponse.DeserializeImagesResponse(responseDocument.RootElement); + return ClientResult.FromResponse(response); + } - List images = []; - for (int i = 0; i < response.Data.Count; i++) + // protocol method - async + // TODO: add refdoc comment + public virtual async Task GenerateImageVariationsAsync(BinaryContent content, string contentType, RequestOptions options = null) + { + Argument.AssertNotNull(content, nameof(content)); + Argument.AssertNotNull(contentType, nameof(contentType)); + + options ??= new RequestOptions(); + + using PipelineMessage message = CreateImageVariationsRequest(content, contentType, options); + + Shim.Pipeline.Send(message); + + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) { - images.Add(new GeneratedImage(response, i)); + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); } - return ClientResult.FromValue(new GeneratedImageCollection(images), message.Response); + return ClientResult.FromResponse(response); } private Internal.Models.CreateImageRequest CreateInternalImageRequest( @@ -349,240 +559,56 @@ private Internal.Models.CreateImageRequest CreateInternalImageRequest( serializedAdditionalRawData: null); } - private PipelineMessage CreateInternalImageEditsPipelineMessage( - BinaryData imageBytes, - string prompt, - int? imageCount = null, - ImageEditOptions options = null) + private PipelineMessage CreateCreateImageEditsRequest(BinaryContent content, string contentType, RequestOptions options) { PipelineMessage message = Shim.Pipeline.CreateMessage(); message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; request.Method = "POST"; + UriBuilder uriBuilder = new(_clientConnector.Endpoint.AbsoluteUri); + StringBuilder path = new(); path.Append("/images/edits"); uriBuilder.Path += path.ToString(); - request.Uri = uriBuilder.Uri; - - options ??= new(); - MultipartFormDataContent requestContent = CreateInternalImageEditsMultipartFormDataContent( - imageBytes, - prompt, - options.MaskBytes, - imageCount, - options.ResponseFormat, - options.Size, - options.User); - requestContent.ApplyToRequest(request); - return message; - } - - private MultipartFormDataContent CreateInternalImageEditsMultipartFormDataContent( - BinaryData imageBytes, - string prompt, - BinaryData maskBytes, - int? imageCount, - ImageResponseFormat? imageResponseFormat, - ImageSize? imageSize, - string user) - { - MultipartFormDataContent content = new(); - - content.Add(MultipartContent.Create(imageBytes), name: "image", fileName: "image.png", headers: []); - - content.Add(MultipartContent.Create(BinaryData.FromString(prompt)), name: "prompt", headers: []); - - content.Add(MultipartContent.Create(BinaryData.FromString(_clientConnector.Model)), name: "model", headers: []); - - if (Optional.IsDefined(maskBytes)) - { - content.Add(MultipartContent.Create(maskBytes), name: "mask", fileName: "mask.png", headers: []); - } - - if (Optional.IsDefined(imageCount)) - { - content.Add(MultipartContent.Create(BinaryData.FromString(imageCount.ToString())), name: "n", headers: []); - } + request.Uri = uriBuilder.Uri; - if (Optional.IsDefined(imageResponseFormat)) - { - content.Add(MultipartContent.Create( - BinaryData.FromString( - imageResponseFormat switch - { - ImageResponseFormat.Uri => "url", - ImageResponseFormat.Bytes => "b64_json", - _ => throw new ArgumentException(nameof(imageResponseFormat)), - }) - ), - name: "response_format", - headers: []); - } + request.Headers.Set("Content-Type", contentType); - if (Optional.IsDefined(imageSize)) - { - content.Add(MultipartContent.Create( - BinaryData.FromString( - imageSize switch - { - ImageSize.Size256x256 => "256x256", - ImageSize.Size512x512 => "512x512", - ImageSize.Size1024x1024 => "1024x1024", - // TODO: 1024x1792 and 1792x1024 are currently not supported in image edits. - ImageSize.Size1024x1792 => "1024x1792", - ImageSize.Size1792x1024 => "1792x1024", - _ => throw new ArgumentException(nameof(imageSize)) - }) - ), - name: "size", - headers: []); - } + request.Content = content; - if (Optional.IsDefined(user)) - { - content.Add(MultipartContent.Create(BinaryData.FromString(user)), "user", []); - } + message.Apply(options); - return content; + return message; } - private PipelineMessage CreateInternalImageVariationsPipelineMessage( - BinaryData imageBytes, - int? imageCount = null, - ImageVariationOptions options = null) + private PipelineMessage CreateImageVariationsRequest(BinaryContent content, string contentType, RequestOptions options) { PipelineMessage message = Shim.Pipeline.CreateMessage(); message.ResponseClassifier = ResponseErrorClassifier200; + PipelineRequest request = message.Request; request.Method = "POST"; + UriBuilder uriBuilder = new(_clientConnector.Endpoint.AbsoluteUri); + StringBuilder path = new(); path.Append("/images/variations"); uriBuilder.Path += path.ToString(); - request.Uri = uriBuilder.Uri; - - options ??= new(); - MultipartFormDataContent requestContent = CreateInternalImageVariationsMultipartFormDataContent( - imageBytes, - imageCount, - options.ResponseFormat, - options.Size, - options.User); - requestContent.ApplyToRequest(request); - - return message; - } - - private MultipartFormDataContent CreateInternalImageVariationsMultipartFormDataContent( - BinaryData imageBytes, - int? imageCount, - ImageResponseFormat? imageResponseFormat, - ImageSize? imageSize, - string user) - { - MultipartFormDataContent content = new(); - - content.Add(MultipartContent.Create(imageBytes), name: "image", fileName: "image.png", headers: []); - - content.Add(MultipartContent.Create(BinaryData.FromString(_clientConnector.Model)), name: "model", headers: []); - if (Optional.IsDefined(imageCount)) - { - content.Add(MultipartContent.Create(BinaryData.FromString(imageCount.ToString())), name: "n", headers: []); - } + request.Uri = uriBuilder.Uri; - if (Optional.IsDefined(imageResponseFormat)) - { - content.Add(MultipartContent.Create( - BinaryData.FromString( - imageResponseFormat switch - { - ImageResponseFormat.Uri => "url", - ImageResponseFormat.Bytes => "b64_json", - _ => throw new ArgumentException(nameof(imageResponseFormat)), - }) - ), - name: "response_format", - headers: []); - } + request.Headers.Set("Content-Type", contentType); - if (Optional.IsDefined(imageSize)) - { - content.Add(MultipartContent.Create( - BinaryData.FromString( - imageSize switch - { - ImageSize.Size256x256 => "256x256", - ImageSize.Size512x512 => "512x512", - ImageSize.Size1024x1024 => "1024x1024", - // TODO: 1024x1792 and 1792x1024 are currently not supported in image variations. - ImageSize.Size1024x1792 => "1024x1792", - ImageSize.Size1792x1024 => "1792x1024", - _ => throw new ArgumentException(nameof(imageSize)) - }) - ), - name: "size", - headers: []); - } + request.Content = content; - if (Optional.IsDefined(user)) - { - content.Add(MultipartContent.Create(BinaryData.FromString(user)), "user", []); - } + message.Apply(options); - return content; + return message; } private static PipelineMessageClassifier _responseErrorClassifier200; private static PipelineMessageClassifier ResponseErrorClassifier200 => _responseErrorClassifier200 ??= PipelineMessageClassifier.Create(stackalloc ushort[] { 200 }); - - private Internal.Models.CreateImageEditRequest CreateInternalImageEditRequest( - BinaryData imageBytes, - string prompt, - int? imageCount = null, - ImageEditOptions options = null) - { - options ??= new(); - - - Internal.Models.CreateImageEditRequestSize? internalSize = null; - if (options.Size != null) - { - internalSize = options.Size switch - { - - ImageSize.Size256x256 => Internal.Models.CreateImageEditRequestSize._256x256, - ImageSize.Size512x512 => Internal.Models.CreateImageEditRequestSize._512x512, - ImageSize.Size1024x1024 => Internal.Models.CreateImageEditRequestSize._1024x1024, - // TODO: 1024x1792 and 1792x1024 are currently not supported in image edits. - ImageSize.Size1024x1792 => new Internal.Models.CreateImageEditRequestSize("1024x1792"), - ImageSize.Size1792x1024 => new Internal.Models.CreateImageEditRequestSize("1792x1024"), - _ => throw new ArgumentException(nameof(options.Size)), - }; - } - - Internal.Models.CreateImageEditRequestResponseFormat? internalFormat = null; - if (options.ResponseFormat != null) - { - internalFormat = options.ResponseFormat switch - { - ImageResponseFormat.Bytes => Internal.Models.CreateImageEditRequestResponseFormat.B64Json, - ImageResponseFormat.Uri => Internal.Models.CreateImageEditRequestResponseFormat.Url, - _ => throw new ArgumentException(nameof(options.ResponseFormat)), - }; - } - - return new Internal.Models.CreateImageEditRequest( - imageBytes, - prompt, - options.MaskBytes, - _clientConnector.Model, - imageCount, - internalSize, - internalFormat, - options.User, - serializedAdditionalRawData: null); - } } diff --git a/.dotnet/src/Custom/Images/ImageEditOptions.cs b/.dotnet/src/Custom/Images/ImageEditOptions.cs index 8412a42ce..2a816428f 100644 --- a/.dotnet/src/Custom/Images/ImageEditOptions.cs +++ b/.dotnet/src/Custom/Images/ImageEditOptions.cs @@ -1,4 +1,6 @@ -using System; +using OpenAI.Internal; +using System; +using System.IO; namespace OpenAI.Images; @@ -10,12 +12,98 @@ public partial class ImageEditOptions /// public BinaryData MaskBytes { get; set; } - /// - public ImageSize? Size { get; set; } + // The generator will need to add file-name to models for properties that + // represent files in order to enable setting the header. + /// + /// TODO + /// + public string MaskFileName { get; set; } /// public ImageResponseFormat? ResponseFormat { get; set; } + /// + public ImageSize? Size { get; set; } + /// public string User { get; set; } + + internal MultipartFormDataBinaryContent ToMultipartContent(Stream fileStream, + string fileName, + string prompt, + string model, + int? imageCount) + { + MultipartFormDataBinaryContent content = new(); + + content.Add(fileStream, "image", fileName); + + AddContent(model, prompt, imageCount, content); + + return content; + } + + internal MultipartFormDataBinaryContent ToMultipartContent(BinaryData imageBytes, + string fileName, + string prompt, + string model, + int? imageCount) + { + MultipartFormDataBinaryContent content = new(); + + content.Add(imageBytes, "image", fileName); + + AddContent(model, prompt, imageCount, content); + + return content; + } + + private void AddContent(string model, string prompt, int? imageCount, MultipartFormDataBinaryContent content) + { + content.Add(prompt, "prompt"); + content.Add(model, "model"); + + if (MaskBytes is not null) + { + content.Add(MaskBytes.ToArray(), "mask", MaskFileName); + } + + if (imageCount is not null) + { + content.Add(imageCount.Value, "n"); + } + + if (ResponseFormat is not null) + { + string format = ResponseFormat switch + { + ImageResponseFormat.Uri => "url", + ImageResponseFormat.Bytes => "b64_json", + _ => throw new ArgumentException(nameof(ResponseFormat)), + }; + + content.Add(format, "response_format"); + } + + if (Size is not null) + { + string imageSize = Size switch + { + ImageSize.Size256x256 => "256x256", + ImageSize.Size512x512 => "512x512", + ImageSize.Size1024x1024 => "1024x1024", + // TODO: 1024x1792 and 1792x1024 are currently not supported in image edits. + ImageSize.Size1024x1792 => "1024x1792", + ImageSize.Size1792x1024 => "1792x1024", + _ => throw new ArgumentException(nameof(imageSize)) + }; + + content.Add(imageSize, "size"); + } + + if (User is not null) + { + content.Add(User, "user"); + } + } } \ No newline at end of file diff --git a/.dotnet/src/Custom/Images/ImageVariationOptions.cs b/.dotnet/src/Custom/Images/ImageVariationOptions.cs index 129c14cb7..cb72dfcc7 100644 --- a/.dotnet/src/Custom/Images/ImageVariationOptions.cs +++ b/.dotnet/src/Custom/Images/ImageVariationOptions.cs @@ -1,4 +1,6 @@ -using System; +using OpenAI.Internal; +using System; +using System.IO; namespace OpenAI.Images; @@ -15,4 +17,69 @@ public partial class ImageVariationOptions /// public string User { get; set; } + + internal MultipartFormDataBinaryContent ToMultipartContent(Stream fileStream, string fileName, string model, int? imageCount) + { + MultipartFormDataBinaryContent content = new(); + + content.Add(fileStream, "image", fileName); + + AddContent(model, imageCount, content); + + return content; + } + + internal MultipartFormDataBinaryContent ToMultipartContent(BinaryData imageBytes, string fileName, string model, int? imageCount) + { + MultipartFormDataBinaryContent content = new(); + + content.Add(imageBytes, "image", fileName); + + AddContent(model, imageCount, content); + + return content; + } + + private void AddContent(string model, int? imageCount, MultipartFormDataBinaryContent content) + { + content.Add(model, "model"); + + if (imageCount is not null) + { + content.Add(imageCount.Value, "n"); + } + + if (ResponseFormat is not null) + { + string format = ResponseFormat switch + { + ImageResponseFormat.Uri => "url", + ImageResponseFormat.Bytes => "b64_json", + _ => throw new ArgumentException(nameof(ResponseFormat)), + }; + + content.Add(format, "response_format"); + } + + if (Size is not null) + { + string imageSize = Size switch + { + ImageSize.Size256x256 => "256x256", + ImageSize.Size512x512 => "512x512", + ImageSize.Size1024x1024 => "1024x1024", + // TODO: 1024x1792 and 1792x1024 are currently not supported in image edits. + ImageSize.Size1024x1792 => "1024x1792", + ImageSize.Size1792x1024 => "1792x1024", + _ => throw new ArgumentException(nameof(imageSize)) + }; + + content.Add(imageSize, "size"); + } + + if (User is not null) + { + content.Add(User, "user"); + } + } } \ No newline at end of file diff --git a/.dotnet/src/OpenAI.csproj b/.dotnet/src/OpenAI.csproj index 39523f012..34cbabc5e 100644 --- a/.dotnet/src/OpenAI.csproj +++ b/.dotnet/src/OpenAI.csproj @@ -1,4 +1,4 @@ - + This is the OpenAI client library for developing .NET applications with rich experience. SDK Code Generation OpenAI @@ -9,7 +9,7 @@ - + diff --git a/.dotnet/src/Utility/MultipartFormDataBinaryContent.cs b/.dotnet/src/Utility/MultipartFormDataBinaryContent.cs new file mode 100644 index 000000000..adce9e4f1 --- /dev/null +++ b/.dotnet/src/Utility/MultipartFormDataBinaryContent.cs @@ -0,0 +1,155 @@ +using System; +using System.ClientModel; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Threading; +using System.Threading.Tasks; + +namespace OpenAI.Internal; + +internal class MultipartFormDataBinaryContent : BinaryContent +{ + private readonly MultipartFormDataContent _multipartContent; + + private static Random _random = new(); + private static readonly char[] _boundaryValues = "0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz".ToCharArray(); + + public MultipartFormDataBinaryContent() + { + _multipartContent = new MultipartFormDataContent(CreateBoundary()); + } + + public string ContentType + { + get + { + Debug.Assert(_multipartContent.Headers.ContentType is not null); + + return _multipartContent.Headers.ContentType!.ToString(); + } + } + + internal HttpContent HttpContent => _multipartContent; + + public void Add(Stream stream, string name, string fileName = default) + { + Add(new StreamContent(stream), name, fileName); + } + + public void Add(string content, string name, string fileName = default) + { + Add(new StringContent(content), name, fileName); + } + + public void Add(int content, string name, string fileName = default) + { + // https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings#GFormatString + string value = content.ToString("G", CultureInfo.InvariantCulture); + Add(new StringContent(value), name, fileName); + } + + public void Add(double content, string name, string fileName = default) + { + // https://learn.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings#GFormatString + string value = content.ToString("G", CultureInfo.InvariantCulture); + Add(new StringContent(value), name, fileName); + } + + public void Add(byte[] content, string name, string fileName = default) + { + Add(new ByteArrayContent(content), name, fileName); + } + + public void Add(BinaryData content, string name, string fileName = default) + { + Add(new ByteArrayContent(content.ToArray()), name, fileName); + } + + private void Add(HttpContent content, string name, string fileName) + { + if (fileName is not null) + { + AddFileNameHeader(content, name, fileName); + } + + _multipartContent.Add(content, name); + } + + private static void AddFileNameHeader(HttpContent content, string name, string filename) + { + // Add the content header manually because the default implementation + // adds a `filename*` parameter to the header, which RFC 7578 says not + // to do. We are following up with the BCL team per correctness. + ContentDispositionHeaderValue header = new("form-data") + { + Name = name, + FileName = filename + }; + content.Headers.ContentDisposition = header; + } + + private static string CreateBoundary() + { + Span chars = new char[70]; + + byte[] random = new byte[70]; + _random.NextBytes(random); + + // The following will sample evenly from the possible values. + // This is important to ensuring that the odds of creating a boundary + // that occurs in any content part are astronomically small. + int mask = 255 >> 2; + + Debug.Assert(_boundaryValues.Length - 1 == mask); + + for (int i = 0; i < 70; i++) + { + chars[i] = _boundaryValues[random[i] & mask]; + } + + return chars.ToString(); + } + + public override bool TryComputeLength(out long length) + { + // We can't call the protected method on HttpContent + + if (_multipartContent.Headers.ContentLength is long contentLength) + { + length = contentLength; + return true; + } + + length = 0; + return false; + } + + public override void WriteTo(Stream stream, CancellationToken cancellationToken = default) + { + // TODO: polyfill sync-over-async for netstandard2.0 for Azure clients. + // Tracked by https://github.com/Azure/azure-sdk-for-net/issues/42674 + +#if NET6_0_OR_GREATER + _multipartContent.CopyTo(stream, default, cancellationToken); +#else + _multipartContent.CopyToAsync(stream).GetAwaiter().GetResult(); +#endif + } + + public override async Task WriteToAsync(Stream stream, CancellationToken cancellationToken = default) + { +#if NET6_0_OR_GREATER + await _multipartContent.CopyToAsync(stream, cancellationToken).ConfigureAwait(false); +#else + await _multipartContent.CopyToAsync(stream).ConfigureAwait(false); +#endif + } + + public override void Dispose() + { + _multipartContent.Dispose(); + } +} diff --git a/.dotnet/src/Utility/System.ClientModel.MultipartContent.cs b/.dotnet/src/Utility/System.ClientModel.MultipartContent.cs deleted file mode 100644 index 6342d7552..000000000 --- a/.dotnet/src/Utility/System.ClientModel.MultipartContent.cs +++ /dev/null @@ -1,367 +0,0 @@ - - -using System.ClientModel.Primitives; -using System.Collections.Generic; -using System.IO; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace System.ClientModel; - -// Placeholder implementation adapted from: -// https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/core/Azure.Core/src/Shared/Multipart/MultipartContent.cs - -internal partial class MultipartContent : BinaryContent -{ - #region Fields - - private const string CrLf = "\r\n"; - private const string ColonSP = ": "; - - private static readonly int s_crlfLength = GetEncodedLength(CrLf); - private static readonly int s_dashDashLength = GetEncodedLength("--"); - private static readonly int s_colonSpaceLength = GetEncodedLength(ColonSP); - - private readonly List _nestedContent; - private readonly string _subtype; - private readonly string _boundary; - internal readonly Dictionary _headers; - - #endregion Fields - - #region Construction - - public MultipartContent() - : this("mixed", GetDefaultBoundary()) - { } - - public MultipartContent(string subtype) - : this(subtype, GetDefaultBoundary()) - { } - - /// - /// Initializes a new instance of the class. - /// - /// The multipart sub type. - /// The boundary string for the multipart form data content. - public MultipartContent(string subtype, string boundary) - { - ValidateBoundary(boundary); - _subtype = subtype; - - // see https://www.ietf.org/rfc/rfc1521.txt page 29. - _boundary = boundary.Contains(":") ? $"\"{boundary}\"" : boundary; - _headers = new Dictionary - { - ["content-type"] = $"multipart/{_subtype}; boundary={_boundary}" - }; - - _nestedContent = new List(); - } - - private static void ValidateBoundary(string boundary) - { - // NameValueHeaderValue is too restrictive for boundary. - // Instead validate it ourselves and then quote it. - if (string.IsNullOrWhiteSpace(boundary)) throw new ArgumentException(nameof(boundary)); - - // cspell:disable - // RFC 2046 Section 5.1.1 - // boundary := 0*69 bcharsnospace - // bchars := bcharsnospace / " " - // bcharsnospace := DIGIT / ALPHA / "'" / "(" / ")" / "+" / "_" / "," / "-" / "." / "/" / ":" / "=" / "?" - // cspell:enable - if (boundary.Length > 70) - { - throw new ArgumentOutOfRangeException(nameof(boundary), boundary, $"The field cannot be longer than {70} characters."); - } - // Cannot end with space. - if (boundary.EndsWith(" ", StringComparison.InvariantCultureIgnoreCase)) - { - throw new ArgumentException($"The format of value '{boundary}' is invalid.", nameof(boundary)); - } - - const string AllowedMarks = @"'()+_,-./:=? "; - - foreach (char ch in boundary) - { - if (('0' <= ch && ch <= '9') || // Digit. - ('a' <= ch && ch <= 'z') || // alpha. - ('A' <= ch && ch <= 'Z') || // ALPHA. - AllowedMarks.Contains(char.ToString(ch))) // Marks. - { - // Valid. - } - else - { - throw new ArgumentException($"The format of value '{boundary}' is invalid.", nameof(boundary)); - } - } - } - - private static string GetDefaultBoundary() - { - return Guid.NewGuid().ToString(); - } - - /// - /// Add content type header to the request. - /// - /// The request. - public void ApplyToRequest(PipelineRequest request) - { - request.Headers.Set("content-type", $"multipart/{_subtype}; boundary={_boundary}"); - request.Content = this; - } - - /// - /// Add HTTP content to a collection of RequestContent objects that - /// get serialized to multipart/form-data MIME type. - /// - /// The Request content to add to the collection. - public virtual void Add(BinaryContent content) - { - if (content is null) throw new ArgumentNullException(nameof(content)); - AddInternal(content, null); - } - - /// - /// Add HTTP content to a collection of RequestContent objects that - /// get serialized to multipart/form-data MIME type. - /// - /// The Request content to add to the collection. - /// The headers to add to the collection. - public virtual void Add(BinaryContent content, Dictionary headers) - { - if (content is null) throw new ArgumentNullException(nameof(content)); - if (headers is null) throw new ArgumentNullException(nameof(headers)); - - AddInternal(content, headers); - } - - private void AddInternal(BinaryContent content, Dictionary headers) - { - headers ??= []; - _nestedContent.Add(new MultipartRequestContent(content, headers)); - } - - #endregion Construction - - #region Dispose - - /// - /// Frees resources held by the object. - /// - public override void Dispose() - { - foreach (MultipartRequestContent content in _nestedContent) - { - content.RequestContent.Dispose(); - } - _nestedContent.Clear(); - } - - #endregion Dispose - - #region Serialization - - // for-each content - // write "--" + boundary - // for-each content header - // write header: header-value - // write content.WriteTo[Async] - // write "--" + boundary + "--" - // Can't be canceled directly by the user. If the overall request is canceled - // then the stream will be closed an exception thrown. - /// - /// - /// - /// - /// - /// - public override void WriteTo(Stream stream, CancellationToken cancellationToken) - { - if (stream is null) throw new ArgumentNullException(nameof(stream)); - - try - { - // Write start boundary. - EncodeStringToStream(stream, "--" + _boundary + CrLf); - - // Write each nested content. - var output = new StringBuilder(); - for (int contentIndex = 0; contentIndex < _nestedContent.Count; contentIndex++) - { - // Write divider, headers, and content. - BinaryContent content = _nestedContent[contentIndex].RequestContent; - Dictionary headers = _nestedContent[contentIndex].Headers; - EncodeStringToStream(stream, SerializeHeadersToString(output, contentIndex, headers)); - content.WriteTo(stream, cancellationToken); - } - - // Write footer boundary. - EncodeStringToStream(stream, CrLf + "--" + _boundary + "--" + CrLf); - } - catch (Exception) - { - throw; - } - } - - // for-each content - // write "--" + boundary - // for-each content header - // write header: header-value - // write content.WriteTo[Async] - // write "--" + boundary + "--" - // Can't be canceled directly by the user. If the overall request is canceled - // then the stream will be closed an exception thrown. - /// - /// - /// - /// - /// - /// - public override Task WriteToAsync(Stream stream, CancellationToken cancellation) => - SerializeToStreamAsync(stream, cancellation); - - private async Task SerializeToStreamAsync(Stream stream, CancellationToken cancellationToken) - { - if (stream is null) throw new ArgumentNullException(nameof(stream)); - try - { - // Write start boundary. - await EncodeStringToStreamAsync(stream, "--" + _boundary + CrLf, cancellationToken).ConfigureAwait(false); - - // Write each nested content. - var output = new StringBuilder(); - for (int contentIndex = 0; contentIndex < _nestedContent.Count; contentIndex++) - { - // Write divider, headers, and content. - BinaryContent content = _nestedContent[contentIndex].RequestContent; - Dictionary headers = _nestedContent[contentIndex].Headers; - await EncodeStringToStreamAsync(stream, SerializeHeadersToString(output, contentIndex, headers), cancellationToken).ConfigureAwait(false); - await content.WriteToAsync(stream, cancellationToken).ConfigureAwait(false); - } - - // Write footer boundary. - await EncodeStringToStreamAsync(stream, CrLf + "--" + _boundary + "--" + CrLf, cancellationToken).ConfigureAwait(false); - } - catch (Exception) - { - throw; - } - } - - private string SerializeHeadersToString(StringBuilder scratch, int contentIndex, Dictionary headers) - { - scratch.Clear(); - - // Add divider. - if (contentIndex != 0) // Write divider for all but the first content. - { - scratch.Append(CrLf + "--"); // const strings - scratch.Append(_boundary); - scratch.Append(CrLf); - } - - // Add headers. - foreach (KeyValuePair header in headers) - { - scratch.Append(header.Key); - scratch.Append(": "); - scratch.Append(header.Value); - scratch.Append(CrLf); - } - - // Extra CRLF to end headers (even if there are no headers). - scratch.Append(CrLf); - - return scratch.ToString(); - } - - private static void EncodeStringToStream(Stream stream, string input) - { - byte[] buffer = Encoding.Default.GetBytes(input); - stream.Write(buffer, 0, buffer.Length); - } - - private static Task EncodeStringToStreamAsync(Stream stream, string input, CancellationToken cancellationToken) - { - byte[] buffer = Encoding.Default.GetBytes(input); - return stream.WriteAsync(buffer, 0, buffer.Length, cancellationToken); - } - - /// - /// Attempts to compute the length of the underlying content, if available. - /// - /// The length of the underlying data. - public override bool TryComputeLength(out long length) - { - int boundaryLength = GetEncodedLength(_boundary); - - long currentLength = 0; - long internalBoundaryLength = s_crlfLength + s_dashDashLength + boundaryLength + s_crlfLength; - - // Start Boundary. - currentLength += s_dashDashLength + boundaryLength + s_crlfLength; - - bool first = true; - foreach (MultipartRequestContent content in _nestedContent) - { - if (first) - { - first = false; // First boundary already written. - } - else - { - // Internal Boundary. - currentLength += internalBoundaryLength; - } - - // Headers. - foreach (KeyValuePair headerPair in content.Headers) - { - currentLength += GetEncodedLength(headerPair.Key) + s_colonSpaceLength; - currentLength += GetEncodedLength(headerPair.Value); - currentLength += s_crlfLength; - } - - currentLength += s_crlfLength; - - // Content. - if (!content.RequestContent.TryComputeLength(out long tempContentLength)) - { - length = 0; - return false; - } - currentLength += tempContentLength; - } - - // Terminating boundary. - currentLength += s_crlfLength + s_dashDashLength + boundaryLength + s_dashDashLength + s_crlfLength; - - length = currentLength; - return true; - } - - private static int GetEncodedLength(string input) - { - return Encoding.Default.GetByteCount(input); - } - - #endregion Serialization - - private class MultipartRequestContent - { - public readonly BinaryContent RequestContent; - public Dictionary Headers; - - public MultipartRequestContent(BinaryContent content, Dictionary headers) - { - RequestContent = content; - Headers = headers; - } - } -} \ No newline at end of file diff --git a/.dotnet/src/Utility/System.ClientModel.MultipartFormDataContent.cs b/.dotnet/src/Utility/System.ClientModel.MultipartFormDataContent.cs deleted file mode 100644 index 9faceac1c..000000000 --- a/.dotnet/src/Utility/System.ClientModel.MultipartFormDataContent.cs +++ /dev/null @@ -1,117 +0,0 @@ -using System.Collections.Generic; - -namespace System.ClientModel; - -// Placeholder implementation adapted from: -// https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/core/Azure.Core/src/Shared/Multipart/MultipartFormDataContent.cs - -internal partial class MultipartFormDataContent : MultipartContent -{ - // Copyright (c) Microsoft Corporation. All rights reserved. - // Licensed under the MIT License. - -#nullable disable - - #region Fields - - private const string FormData = "form-data"; - - #endregion Fields - - #region Construction - - /// - /// Initializes a new instance of the class. - /// - public MultipartFormDataContent() : base(FormData) - { } - - /// - /// Initializes a new instance of the class. - /// - /// The boundary string for the multipart form data content. - public MultipartFormDataContent(string boundary) : base(FormData, boundary) - { } - - #endregion Construction - - /// - /// Add HTTP content to a collection of RequestContent objects that - /// get serialized to multipart/form-data MIME type. - /// - /// The Request content to add to the collection. - public override void Add(BinaryContent content) - { - if (content is null) throw new ArgumentNullException(nameof(content)); - AddInternal(content, null, null, null); - } - - /// - /// Add HTTP content to a collection of RequestContent objects that - /// get serialized to multipart/form-data MIME type. - /// - /// The Request content to add to the collection. - /// The headers to add to the collection. - public override void Add(BinaryContent content, Dictionary headers) - { - if (content is null) throw new ArgumentNullException(nameof(content)); - if (headers is null) throw new ArgumentNullException(nameof(headers)); - - AddInternal(content, headers, null, null); - } - - /// - /// Add HTTP content to a collection of RequestContent objects that - /// get serialized to multipart/form-data MIME type. - /// - /// The Request content to add to the collection. - /// The name for the request content to add. - /// The headers to add to the collection. - public void Add(BinaryContent content, string name, Dictionary headers) - { - if (content is null) throw new ArgumentNullException(nameof(content)); - if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException(nameof(name)); - - AddInternal(content, headers, name, null); - } - - /// - /// Add HTTP content to a collection of RequestContent objects that - /// get serialized to multipart/form-data MIME type. - /// - /// The Request content to add to the collection. - /// The name for the request content to add. - /// The file name for the request content to add to the collection. - /// The headers to add to the collection. - public void Add(BinaryContent content, string name, string fileName, Dictionary headers) - { - if (content is null) throw new ArgumentNullException(nameof(content)); - if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException(nameof(name)); - if (string.IsNullOrWhiteSpace(fileName)) throw new ArgumentException(nameof(fileName)); - - AddInternal(content, headers, name, fileName); - } - - private void AddInternal(BinaryContent content, Dictionary headers, string name, string fileName) - { - headers ??= []; - - if (!headers.ContainsKey("Content-Disposition")) - { - var value = FormData; - - if (name != null) - { - value = value + "; name=" + name; - } - if (fileName != null) - { - value = value + "; filename=" + fileName; - } - - headers.Add("Content-Disposition", value); - } - - base.Add(content, headers); - } -} \ No newline at end of file diff --git a/.dotnet/tests/OpenAI.Tests.csproj b/.dotnet/tests/OpenAI.Tests.csproj index 2556909e3..6ec3f6166 100644 --- a/.dotnet/tests/OpenAI.Tests.csproj +++ b/.dotnet/tests/OpenAI.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/.dotnet/tests/Samples/Images/Sample02_SimpleImageEdit.cs b/.dotnet/tests/Samples/Images/Sample02_SimpleImageEdit.cs index 174645ec2..81b0f486c 100644 --- a/.dotnet/tests/Samples/Images/Sample02_SimpleImageEdit.cs +++ b/.dotnet/tests/Samples/Images/Sample02_SimpleImageEdit.cs @@ -24,11 +24,12 @@ public void Sample02_SimpleImageEdit() ImageEditOptions options = new() { MaskBytes = maskBytes, + MaskFileName = "edit_sample_mask.png", Size = ImageSize.Size1024x1024, ResponseFormat = ImageResponseFormat.Bytes }; - GeneratedImageCollection image = client.GenerateImageEdits(imageBytes, prompt, 1, options); + GeneratedImageCollection image = client.GenerateImageEdits(imageBytes, "edit_sample_image.png", prompt, 1, options); BinaryData bytes = image[0].ImageBytes; using FileStream stream = File.OpenWrite($"{Guid.NewGuid()}.png"); diff --git a/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs b/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs index ac8b7373d..a143ba328 100644 --- a/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs +++ b/.dotnet/tests/Samples/Images/Sample02_SimpleImageEditAsync.cs @@ -25,11 +25,12 @@ public async Task Sample02_SimpleImageEditAsync() ImageEditOptions options = new() { MaskBytes = maskBytes, + MaskFileName = "edit_sample_mask.png", Size = ImageSize.Size1024x1024, ResponseFormat = ImageResponseFormat.Bytes }; - GeneratedImageCollection image = await client.GenerateImageEditsAsync(imageBytes, prompt, 1, options); + GeneratedImageCollection image = await client.GenerateImageEditsAsync(imageBytes, "edit_sample_image.png", prompt, 1, options); BinaryData bytes = image[0].ImageBytes; using FileStream stream = File.OpenWrite($"{Guid.NewGuid()}.png"); diff --git a/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariation.cs b/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariation.cs index 1ec803cd4..409dd3cef 100644 --- a/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariation.cs +++ b/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariation.cs @@ -22,7 +22,7 @@ public void Sample03_SimpleImageVariation() ResponseFormat = ImageResponseFormat.Bytes }; - GeneratedImageCollection image = client.GenerateImageVariations(imageBytes, 1, options); + GeneratedImageCollection image = client.GenerateImageVariations(imageBytes, "variation_sample_image.png", 1, options); BinaryData bytes = image[0].ImageBytes; using FileStream stream = File.OpenWrite($"{Guid.NewGuid()}.png"); diff --git a/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariationAsync.cs b/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariationAsync.cs index 6f2aba398..257abc1fe 100644 --- a/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariationAsync.cs +++ b/.dotnet/tests/Samples/Images/Sample03_SimpleImageVariationAsync.cs @@ -23,7 +23,7 @@ public async Task Sample03_SimpleImageVariationAsync() ResponseFormat = ImageResponseFormat.Bytes }; - GeneratedImageCollection image = await client.GenerateImageVariationsAsync(imageBytes, 1, options); + GeneratedImageCollection image = await client.GenerateImageVariationsAsync(imageBytes, "variation_sample_image.png", 1, options); BinaryData bytes = image[0].ImageBytes; using FileStream stream = File.OpenWrite($"{Guid.NewGuid()}.png"); From 7b8ea024c0879ee136da5b1041215a98a44669d1 Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado <45773732+joseharriaga@users.noreply.github.com> Date: Tue, 19 Mar 2024 19:23:22 -0700 Subject: [PATCH 45/50] Update System.ClientModel to version 1.1.0-alpha.20240319.1 (#35) --- .dotnet/scripts/Add-Customizations.ps1 | 4 ++++ .dotnet/scripts/Update-ClientModel.ps1 | 4 ++-- .dotnet/src/OpenAI.csproj | 4 ++-- .dotnet/tests/OpenAI.Tests.csproj | 15 ++++++--------- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/.dotnet/scripts/Add-Customizations.ps1 b/.dotnet/scripts/Add-Customizations.ps1 index 30e795553..4b4d4cd92 100644 --- a/.dotnet/scripts/Add-Customizations.ps1 +++ b/.dotnet/scripts/Add-Customizations.ps1 @@ -28,9 +28,13 @@ function Set-LangVersionToLatest { $root = Split-Path $PSScriptRoot -Parent $filePath = Join-Path -Path $root -ChildPath "tests\OpenAI.Tests.csproj" $xml = [xml](Get-Content -Path $filePath) + + $xml.Project.PropertyGroup.TargetFramework = "net8.0" + $element = $xml.CreateElement("LangVersion") $element.InnerText = "latest" $xml.Project.PropertyGroup.AppendChild($element) | Out-Null + $xml.Save($filePath) } diff --git a/.dotnet/scripts/Update-ClientModel.ps1 b/.dotnet/scripts/Update-ClientModel.ps1 index 6502789ba..698ed7b05 100644 --- a/.dotnet/scripts/Update-ClientModel.ps1 +++ b/.dotnet/scripts/Update-ClientModel.ps1 @@ -6,13 +6,13 @@ function Update-SystemClientModelPackage { $directory = Join-Path -Path $root -ChildPath "src" Set-Location -Path $directory dotnet remove "OpenAI.csproj" package "System.ClientModel" - dotnet add "OpenAI.csproj" package "System.ClientModel" --version "1.1.0-alpha.20240305.1" --source "https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-net/nuget/v3/index.json" + dotnet add "OpenAI.csproj" package "System.ClientModel" --version "1.1.0-alpha.20240319.1" --source "https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-net/nuget/v3/index.json" # Update System.ClientModel package in OpenAI.Tests.csproj $directory = Join-Path -Path $root -ChildPath "tests" Set-Location -Path $directory dotnet remove "OpenAI.Tests.csproj" package "System.ClientModel" - dotnet add "OpenAI.Tests.csproj" package "System.ClientModel" --version "1.1.0-alpha.20240305.1" --source "https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-net/nuget/v3/index.json" + dotnet add "OpenAI.Tests.csproj" package "System.ClientModel" --version "1.1.0-alpha.20240319.1" --source "https://pkgs.dev.azure.com/azure-sdk/public/_packaging/azure-sdk-for-net/nuget/v3/index.json" Set-Location -Path $current } diff --git a/.dotnet/src/OpenAI.csproj b/.dotnet/src/OpenAI.csproj index 34cbabc5e..cd5fa6d55 100644 --- a/.dotnet/src/OpenAI.csproj +++ b/.dotnet/src/OpenAI.csproj @@ -1,4 +1,4 @@ - + This is the OpenAI client library for developing .NET applications with rich experience. SDK Code Generation OpenAI @@ -9,7 +9,7 @@ - + diff --git a/.dotnet/tests/OpenAI.Tests.csproj b/.dotnet/tests/OpenAI.Tests.csproj index 6ec3f6166..9958ed4e7 100644 --- a/.dotnet/tests/OpenAI.Tests.csproj +++ b/.dotnet/tests/OpenAI.Tests.csproj @@ -14,25 +14,22 @@ - + - - PreserveNewest - - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest - + PreserveNewest From b5032d561a5add0d830c305884a928a9994645a2 Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado <45773732+joseharriaga@users.noreply.github.com> Date: Tue, 19 Mar 2024 19:41:42 -0700 Subject: [PATCH 46/50] Add Directory.Build.targets to test project to copy assets to output directory (#36) --- .dotnet/tests/Directory.Build.targets | 7 +++++++ .dotnet/tests/OpenAI.Tests.csproj | 20 -------------------- 2 files changed, 7 insertions(+), 20 deletions(-) create mode 100644 .dotnet/tests/Directory.Build.targets diff --git a/.dotnet/tests/Directory.Build.targets b/.dotnet/tests/Directory.Build.targets new file mode 100644 index 000000000..9108ca3f9 --- /dev/null +++ b/.dotnet/tests/Directory.Build.targets @@ -0,0 +1,7 @@ + + + + PreserveNewest + + + \ No newline at end of file diff --git a/.dotnet/tests/OpenAI.Tests.csproj b/.dotnet/tests/OpenAI.Tests.csproj index 9958ed4e7..59b95785f 100644 --- a/.dotnet/tests/OpenAI.Tests.csproj +++ b/.dotnet/tests/OpenAI.Tests.csproj @@ -16,24 +16,4 @@ - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - \ No newline at end of file From bab92c701d5804e87091a4221e559f0bfdbb52e9 Mon Sep 17 00:00:00 2001 From: Jose Arriaga Maldonado <45773732+joseharriaga@users.noreply.github.com> Date: Tue, 19 Mar 2024 23:12:17 -0700 Subject: [PATCH 47/50] Apply EditorBrowsableState.Never to multipart/form-data protocol methods (#37) --- .../src/Custom/Audio/AudioClient.Protocol.cs | 180 +++++++++++++++++- .dotnet/src/Custom/Audio/AudioClient.cs | 92 --------- .../src/Custom/Files/FileClient.Protocol.cs | 105 +++++++++- .dotnet/src/Custom/Files/FileClient.cs | 46 ----- .../src/Custom/Images/ImageClient.Protocol.cs | 180 +++++++++++++++++- .dotnet/src/Custom/Images/ImageClient.cs | 93 --------- .dotnet/tests/Assets/hola_mundo.m4a | Bin 202099 -> 0 bytes .dotnet/tests/Assets/multilingual.wav | Bin 0 -> 4038734 bytes .../tests/TestScenarios/FileClientTests.cs | 8 + .../tests/TestScenarios/TranslationTests.cs | 4 +- 10 files changed, 472 insertions(+), 236 deletions(-) delete mode 100644 .dotnet/tests/Assets/hola_mundo.m4a create mode 100644 .dotnet/tests/Assets/multilingual.wav diff --git a/.dotnet/src/Custom/Audio/AudioClient.Protocol.cs b/.dotnet/src/Custom/Audio/AudioClient.Protocol.cs index 527e5b672..d4998eb39 100644 --- a/.dotnet/src/Custom/Audio/AudioClient.Protocol.cs +++ b/.dotnet/src/Custom/Audio/AudioClient.Protocol.cs @@ -1,6 +1,8 @@ -using System.ClientModel; +using System; +using System.ClientModel; using System.ClientModel.Primitives; using System.ComponentModel; +using System.IO; using System.Threading.Tasks; namespace OpenAI.Audio; @@ -16,4 +18,180 @@ public virtual ClientResult GenerateSpeechFromText(BinaryContent content, Reques [EditorBrowsable(EditorBrowsableState.Never)] public virtual async Task GenerateSpeechFromTextAsync(BinaryContent content, RequestOptions options = null) => await Shim.CreateSpeechAsync(content, options).ConfigureAwait(false); + + /// + /// [Protocol Method] Transcribes audio into the input language. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler or convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The content type of the request. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult TranscribeAudio(BinaryContent content, string contentType, RequestOptions options = null) + { + Argument.AssertNotNull(content, nameof(content)); + Argument.AssertNotNullOrEmpty(contentType, nameof(contentType)); + + options ??= new RequestOptions(); + + using PipelineMessage message = CreateCreateTranscriptionRequest(content, contentType, options); + + Shim.Pipeline.Send(message); + + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + { + throw new ClientResultException(response); + } + + return ClientResult.FromResponse(response); + } + + /// + /// [Protocol Method] Transcribes audio into the input language. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler or convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The content type of the request. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. + /// or is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual async Task TranscribeAudioAsync(BinaryContent content, string contentType, RequestOptions options = null) + { + Argument.AssertNotNull(content, nameof(content)); + Argument.AssertNotNullOrEmpty(contentType, nameof(contentType)); + + options ??= new RequestOptions(); + + using PipelineMessage message = CreateCreateTranscriptionRequest(content, contentType, options); + + Shim.Pipeline.Send(message); + + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + { + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + } + + return ClientResult.FromResponse(response); + } + + /// + /// [Protocol Method] Translates audio into English. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler or convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The content type of the request. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult TranslateAudio(BinaryContent content, string contentType, RequestOptions options = null) + { + Argument.AssertNotNull(content, nameof(content)); + Argument.AssertNotNullOrEmpty(contentType, nameof(contentType)); + + options ??= new RequestOptions(); + + using PipelineMessage message = CreateCreateTranslationRequest(content, contentType, options); + + Shim.Pipeline.Send(message); + + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + { + throw new ClientResultException(response); + } + + return ClientResult.FromResponse(response); + } + + /// + /// [Protocol Method] Translates audio into English. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler or convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The content type of the request. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual async Task TranslateAudioAsync(BinaryContent content, string contentType, RequestOptions options = null) + { + Argument.AssertNotNull(content, nameof(content)); + Argument.AssertNotNullOrEmpty(contentType, nameof(contentType)); + + options ??= new RequestOptions(); + + using PipelineMessage message = CreateCreateTranslationRequest(content, contentType, options); + + Shim.Pipeline.Send(message); + + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + { + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + } + + return ClientResult.FromResponse(response); + } } \ No newline at end of file diff --git a/.dotnet/src/Custom/Audio/AudioClient.cs b/.dotnet/src/Custom/Audio/AudioClient.cs index 748928db4..2fdf68170 100644 --- a/.dotnet/src/Custom/Audio/AudioClient.cs +++ b/.dotnet/src/Custom/Audio/AudioClient.cs @@ -224,52 +224,6 @@ public virtual async Task> TranscribeAudioAsync return ClientResult.FromValue(value, response); } - // protocol method - sync - // TODO: add refdoc comment - public virtual ClientResult TranscribeAudio(BinaryContent content, string contentType, RequestOptions options = null) - { - Argument.AssertNotNull(content, nameof(content)); - Argument.AssertNotNull(contentType, nameof(contentType)); - - options ??= new RequestOptions(); - - using PipelineMessage message = CreateCreateTranscriptionRequest(content, contentType, options); - - Shim.Pipeline.Send(message); - - PipelineResponse response = message.Response!; - - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) - { - throw new ClientResultException(response); - } - - return ClientResult.FromResponse(response); - } - - // protocol method - async - // TODO: add refdoc comment - public virtual async Task TranscribeAudioAsync(BinaryContent content, string contentType, RequestOptions options = null) - { - Argument.AssertNotNull(content, nameof(content)); - Argument.AssertNotNull(contentType, nameof(contentType)); - - options ??= new RequestOptions(); - - using PipelineMessage message = CreateCreateTranscriptionRequest(content, contentType, options); - - Shim.Pipeline.Send(message); - - PipelineResponse response = message.Response!; - - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) - { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); - } - - return ClientResult.FromResponse(response); - } - private PipelineMessage CreateCreateTranscriptionRequest(BinaryContent content, string contentType, RequestOptions options) { PipelineMessage message = Shim.Pipeline.CreateMessage(); @@ -375,52 +329,6 @@ public virtual async Task> TranslateAudioAsync(Bi return ClientResult.FromValue(value, response); } - // protocol method - sync - // TODO: add refdoc comment - public virtual ClientResult TranslateAudio(BinaryContent content, string contentType, RequestOptions options = null) - { - Argument.AssertNotNull(content, nameof(content)); - Argument.AssertNotNull(contentType, nameof(contentType)); - - options ??= new RequestOptions(); - - using PipelineMessage message = CreateCreateTranslationRequest(content, contentType, options); - - Shim.Pipeline.Send(message); - - PipelineResponse response = message.Response!; - - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) - { - throw new ClientResultException(response); - } - - return ClientResult.FromResponse(response); - } - - // protocol method - async - // TODO: add refdoc comment - public virtual async Task TranslateAudioAsync(BinaryContent content, string contentType, RequestOptions options = null) - { - Argument.AssertNotNull(content, nameof(content)); - Argument.AssertNotNull(contentType, nameof(contentType)); - - options ??= new RequestOptions(); - - using PipelineMessage message = CreateCreateTranslationRequest(content, contentType, options); - - Shim.Pipeline.Send(message); - - PipelineResponse response = message.Response!; - - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) - { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); - } - - return ClientResult.FromResponse(response); - } - private PipelineMessage CreateCreateTranslationRequest(BinaryContent content, string contentType, RequestOptions options) { PipelineMessage message = Shim.Pipeline.CreateMessage(); diff --git a/.dotnet/src/Custom/Files/FileClient.Protocol.cs b/.dotnet/src/Custom/Files/FileClient.Protocol.cs index 263efec6c..d7298b1dc 100644 --- a/.dotnet/src/Custom/Files/FileClient.Protocol.cs +++ b/.dotnet/src/Custom/Files/FileClient.Protocol.cs @@ -1,12 +1,115 @@ -using System.ClientModel; +using System; +using System.ClientModel; using System.ClientModel.Primitives; using System.ComponentModel; +using System.IO; using System.Threading.Tasks; namespace OpenAI.Files; public partial class FileClient { + /// + /// [Protocol Method] Upload a file that can be used across various endpoints. The size of all the files uploaded by + /// one organization can be up to 100 GB. + /// + /// The size of individual files can be a maximum of 512 MB or 2 million tokens for Assistants. See + /// the [Assistants Tools guide](/docs/assistants/tools) to learn more about the types of files + /// supported. The Fine-tuning API only supports `.jsonl` files. + /// + /// Please [contact us](https://help.openai.com/) if you need to increase these storage limits. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler or convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The content type of the request. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult UploadFile(BinaryContent content, string contentType, RequestOptions options = null) + { + Argument.AssertNotNull(content, nameof(content)); + Argument.AssertNotNullOrEmpty(contentType, nameof(contentType)); + + options ??= new RequestOptions(); + + using PipelineMessage message = CreateUploadFileRequest(content, contentType, options); + + Shim.Pipeline.Send(message); + + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + { + throw new ClientResultException(response); + } + + return ClientResult.FromResponse(response); + } + + /// + /// [Protocol Method] Upload a file that can be used across various endpoints. The size of all the files uploaded by + /// one organization can be up to 100 GB. + /// + /// The size of individual files can be a maximum of 512 MB or 2 million tokens for Assistants. See + /// the [Assistants Tools guide](/docs/assistants/tools) to learn more about the types of files + /// supported. The Fine-tuning API only supports `.jsonl` files. + /// + /// Please [contact us](https://help.openai.com/) if you need to increase these storage limits. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler or convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The content type of the request. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual async Task UploadFileAsync(BinaryContent content, string contentType, RequestOptions options = null) + { + Argument.AssertNotNull(content, nameof(content)); + Argument.AssertNotNullOrEmpty(contentType, nameof(contentType)); + + options ??= new RequestOptions(); + + using PipelineMessage message = CreateUploadFileRequest(content, contentType, options); + + Shim.Pipeline.Send(message); + + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + { + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + } + + return ClientResult.FromResponse(response); + } + /// [EditorBrowsable(EditorBrowsableState.Never)] public virtual ClientResult GetFileInfo(string fileId, RequestOptions options) diff --git a/.dotnet/src/Custom/Files/FileClient.cs b/.dotnet/src/Custom/Files/FileClient.cs index 815d6490e..26b4530ab 100644 --- a/.dotnet/src/Custom/Files/FileClient.cs +++ b/.dotnet/src/Custom/Files/FileClient.cs @@ -170,52 +170,6 @@ public virtual async Task> UploadFileAsync(BinaryDa return ClientResult.FromValue(fileInfo, response); } - // protocol method - sync - // TODO: add refdoc comment - public virtual ClientResult UploadFile(BinaryContent content, string contentType, RequestOptions options = null) - { - Argument.AssertNotNull(content, nameof(content)); - Argument.AssertNotNull(contentType, nameof(contentType)); - - options ??= new RequestOptions(); - - using PipelineMessage message = CreateUploadFileRequest(content, contentType, options); - - Shim.Pipeline.Send(message); - - PipelineResponse response = message.Response!; - - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) - { - throw new ClientResultException(response); - } - - return ClientResult.FromResponse(response); - } - - // protocol method - async - // TODO: add refdoc comment - public virtual async Task UploadFileAsync(BinaryContent content, string contentType, RequestOptions options = null) - { - Argument.AssertNotNull(content, nameof(content)); - Argument.AssertNotNull(contentType, nameof(contentType)); - - options ??= new RequestOptions(); - - using PipelineMessage message = CreateUploadFileRequest(content, contentType, options); - - Shim.Pipeline.Send(message); - - PipelineResponse response = message.Response!; - - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) - { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); - } - - return ClientResult.FromResponse(response); - } - public virtual ClientResult GetFileInfo(string fileId) { ClientResult internalResult = Shim.RetrieveFile(fileId); diff --git a/.dotnet/src/Custom/Images/ImageClient.Protocol.cs b/.dotnet/src/Custom/Images/ImageClient.Protocol.cs index b95c9b4d0..61fc82eb1 100644 --- a/.dotnet/src/Custom/Images/ImageClient.Protocol.cs +++ b/.dotnet/src/Custom/Images/ImageClient.Protocol.cs @@ -1,6 +1,8 @@ -using System.ClientModel.Primitives; +using System; +using System.ClientModel.Primitives; using System.ClientModel; using System.ComponentModel; +using System.IO; using System.Threading.Tasks; namespace OpenAI.Images; @@ -16,4 +18,180 @@ public virtual ClientResult GenerateImage(BinaryContent content, RequestOptions [EditorBrowsable(EditorBrowsableState.Never)] public virtual async Task GenerateImageAsync(BinaryContent content, RequestOptions options = null) => await Shim.CreateImageAsync(content, options).ConfigureAwait(false); + + /// + /// [Protocol Method] Creates an edited or extended image given an original image and a prompt. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler or convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The content type of the request. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult GenerateImageEdits(BinaryContent content, string contentType, RequestOptions options = null) + { + Argument.AssertNotNull(content, nameof(content)); + Argument.AssertNotNullOrEmpty(contentType, nameof(contentType)); + + options ??= new RequestOptions(); + + using PipelineMessage message = CreateCreateImageEditsRequest(content, contentType, options); + + Shim.Pipeline.Send(message); + + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + { + throw new ClientResultException(response); + } + + return ClientResult.FromResponse(response); + } + + /// + /// [Protocol Method] Creates an edited or extended image given an original image and a prompt. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler or convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The content type of the request. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual async Task GenerateImageEditsAsync(BinaryContent content, string contentType, RequestOptions options = null) + { + Argument.AssertNotNull(content, nameof(content)); + Argument.AssertNotNullOrEmpty(contentType, nameof(contentType)); + + options ??= new RequestOptions(); + + using PipelineMessage message = CreateCreateImageEditsRequest(content, contentType, options); + + Shim.Pipeline.Send(message); + + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + { + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + } + + return ClientResult.FromResponse(response); + } + + /// + /// [Protocol Method] Creates an edited or extended image given an original image and a prompt. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler or convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The content type of the request. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual ClientResult GenerateImageVariations(BinaryContent content, string contentType, RequestOptions options = null) + { + Argument.AssertNotNull(content, nameof(content)); + Argument.AssertNotNullOrEmpty(contentType, nameof(contentType)); + + options ??= new RequestOptions(); + + using PipelineMessage message = CreateImageVariationsRequest(content, contentType, options); + + Shim.Pipeline.Send(message); + + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + { + throw new ClientResultException(response); + } + + return ClientResult.FromResponse(response); + } + + /// + /// [Protocol Method] Creates an edited or extended image given an original image and a prompt. + /// + /// + /// + /// This protocol method allows explicit creation of the request and processing of the response for advanced scenarios. + /// + /// + /// + /// + /// Please try the simpler or convenience overload with strongly typed models first. + /// + /// + /// + /// + /// The content to send as the body of the request. + /// The content type of the request. + /// The request options, which can override default behaviors of the client pipeline on a per-call basis. + /// is null. + /// is an empty string, and was expected to be non-empty. + /// Service returned a non-success status code. + /// The response returned from the service. + [EditorBrowsable(EditorBrowsableState.Never)] + public virtual async Task GenerateImageVariationsAsync(BinaryContent content, string contentType, RequestOptions options = null) + { + Argument.AssertNotNull(content, nameof(content)); + Argument.AssertNotNullOrEmpty(contentType, nameof(contentType)); + + options ??= new RequestOptions(); + + using PipelineMessage message = CreateImageVariationsRequest(content, contentType, options); + + Shim.Pipeline.Send(message); + + PipelineResponse response = message.Response!; + + if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) + { + throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); + } + + return ClientResult.FromResponse(response); + } } diff --git a/.dotnet/src/Custom/Images/ImageClient.cs b/.dotnet/src/Custom/Images/ImageClient.cs index 5dbdacec6..f233db58e 100644 --- a/.dotnet/src/Custom/Images/ImageClient.cs +++ b/.dotnet/src/Custom/Images/ImageClient.cs @@ -181,7 +181,6 @@ public virtual async Task> GenerateImages return ClientResult.FromValue(new GeneratedImageCollection(images), response.GetRawResponse()); } - // convenience method - sync; Stream overload // TODO: add refdoc comment public virtual ClientResult GenerateImageEdits( @@ -306,52 +305,6 @@ public virtual async Task> GenerateImageE return ClientResult.FromValue(value, response); } - // protocol method - sync - // TODO: add refdoc comment - public virtual ClientResult GenerateImageEdits(BinaryContent content, string contentType, RequestOptions options = null) - { - Argument.AssertNotNull(content, nameof(content)); - Argument.AssertNotNull(contentType, nameof(contentType)); - - options ??= new RequestOptions(); - - using PipelineMessage message = CreateCreateImageEditsRequest(content, contentType, options); - - Shim.Pipeline.Send(message); - - PipelineResponse response = message.Response!; - - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) - { - throw new ClientResultException(response); - } - - return ClientResult.FromResponse(response); - } - - // protocol method - async - // TODO: add refdoc comment - public virtual async Task GenerateImageEditsAsync(BinaryContent content, string contentType, RequestOptions options = null) - { - Argument.AssertNotNull(content, nameof(content)); - Argument.AssertNotNull(contentType, nameof(contentType)); - - options ??= new RequestOptions(); - - using PipelineMessage message = CreateCreateImageEditsRequest(content, contentType, options); - - Shim.Pipeline.Send(message); - - PipelineResponse response = message.Response!; - - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) - { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); - } - - return ClientResult.FromResponse(response); - } - // convenience method - sync // TODO: add refdoc comment public virtual ClientResult GenerateImageVariations( @@ -448,52 +401,6 @@ public virtual async Task> GenerateImageV return ClientResult.FromValue(value, response); } - // protocol method - sync - // TODO: add refdoc comment - public virtual ClientResult GenerateImageVariations(BinaryContent content, string contentType, RequestOptions options = null) - { - Argument.AssertNotNull(content, nameof(content)); - Argument.AssertNotNull(contentType, nameof(contentType)); - - options ??= new RequestOptions(); - - using PipelineMessage message = CreateImageVariationsRequest(content, contentType, options); - - Shim.Pipeline.Send(message); - - PipelineResponse response = message.Response!; - - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) - { - throw new ClientResultException(response); - } - - return ClientResult.FromResponse(response); - } - - // protocol method - async - // TODO: add refdoc comment - public virtual async Task GenerateImageVariationsAsync(BinaryContent content, string contentType, RequestOptions options = null) - { - Argument.AssertNotNull(content, nameof(content)); - Argument.AssertNotNull(contentType, nameof(contentType)); - - options ??= new RequestOptions(); - - using PipelineMessage message = CreateImageVariationsRequest(content, contentType, options); - - Shim.Pipeline.Send(message); - - PipelineResponse response = message.Response!; - - if (response.IsError && options.ErrorOptions == ClientErrorBehaviors.Default) - { - throw await ClientResultException.CreateAsync(response).ConfigureAwait(false); - } - - return ClientResult.FromResponse(response); - } - private Internal.Models.CreateImageRequest CreateInternalImageRequest( string prompt, int? imageCount = null, diff --git a/.dotnet/tests/Assets/hola_mundo.m4a b/.dotnet/tests/Assets/hola_mundo.m4a deleted file mode 100644 index 7bc01b755379aa13d424ac61492bdeb9514fa584..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 202099 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 z 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 diff --git a/.dotnet/tests/Assets/multilingual.wav b/.dotnet/tests/Assets/multilingual.wav new file mode 100644 index 0000000000000000000000000000000000000000..847f3463a065574b8ed946eb5db9806331134242 GIT binary patch literal 4038734 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

g^MR8YEk-TI^ZH|O%_^`Lz_Cw(-8kM)f*#)m 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

Dz6<(&E=^uU@xLUXSsQf&q!wv(iR z&Ho>e2(t-4@)q$AWb$U>BDNQN5^W&Y*AZDEIf212T`Ux)iZ`VkV3{g`^!NbyN++SQ zwhH#V6w+9p2(-L*=zLrtuL8k(IFV1RrFtqis-~znX;x{EYnOrNs8px+nd6(|9~!VX zV0utQ$nen8u#OQYBGaO=m?kkdV;;u@#B_`~SZjXl{Mgg6ZR1+RO^8j4JsukoyDz3R z>Qh8Q_=B*&Li+{P3D^QW;68r&z)C@UqkK&I6vKI+1%`Us398Y`X7HSgq4p5v*g{l= ztP`JdGhols#Cs2JkfnAX`)u3j8ei*p%L&UQ*aCF5W>{WXFFQDw+r8Nv!42n%_s!xP8Q#r4QGymZ=x|%z^1~UE&vEjLtsi6fDFSin9Bt#70R2`N@XrkTrq7c zolZAMvr%24aD$ti!{?E!fJ4~;O%+Qa>Ci(6lpcX^X%{Ebo83B?hv#y`1cVFrKJZL( zPj|j_?03EKT=x9sigH+L)>$mo{mtpta_c7Z%?hrpvixAhr}C%ey(>Rd235Q+W6Q8| z61tLN#jnaU(06}S`JjAnMQ-Jo>ZR74ntN7H%~nSj$6&`3S3B4M4P}O~lKZjiig!N8 z@SA}&^h$JyBO#Tx92tmTC+m~*@#WZK;41tdbPaof^Lh_?4_^ftu58H7@Ni$r68~YpKxXL_vmO#ijbW!H!*=p-rXB6$ zKIKmJzK7{ihWAg8&Qk_??Dlk9U?-jfrowx7E#RNlrV~6(+zR(tc>AE9Q?6s43+!b` zFdgB}G7b3aU>GFjNk~JYo8pkNqhdS|mzt0aB%+@vNo~AlgSvyRy-$^~2lTH}eRn~N z&tcqYy6VgOhWU;4Q~C}9PRAo-4A_Fsneu!rhOfX`+-KOOI}UrtW}0!TF;rJ#HjxEJ z(C6e;eO6rjEYr0$POb5C0AR%iPeZ;lsjzg?$eV2>CboZfJ3M-SCi*U4b0~ z>jbXzt7|-I{OQ*@AUJ>scVLy_QOe2jTy0Y zY#Ai>N`+b8^PVH#3*h+L&Rn9mxCc0G_F~6&_jHe+tCjszO}m<|wrWR?GuYA4u5|RX z@3e~5Qq@OufBRQ3*slg>`aq{I5L$!WGodMIafNyd*bwG``!7!`E=2@CqBvgKFUO!` zu=7Y?$%+gl>*4E#di+&z(ni3Ea4fnKQi@%$f!Ge@s5}duK-kD1_+aTX?9JDSG(7uE z(kM>FM0>6}dwKM*)gR4RJ?&|aI}>iQwY(mnxIJTg^Ou+@?%A$mK*;Lrae2CXFLATQ z<6Ljp)6V18@CO+WQ!JiBe5E^luDJPsK0KmWwN#0s8S)IORFkAirWUArY6<0C>=Qml z>Czm~rKv}vxOf=iXiSQbci9B>Blja&s_k~n&Dt{D6Znx-jt~@4C zo{J>NjA#^gF`qo2yn`hSzlnC0o`R9B1>_E^m>~KOI!2g>JOhWo7M#I^V8_MBQ6`N7GvWpZ+G(3VkE}X`M;)T>VIg=o>3N=tiUgSXB#=bnr=AkbWZL zSz{mW?ka9Vii8BdxBMDi!1s03uDR>^j$9@tNl|orNEzP)ue;Vc)U}�dn;q?_v)J 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 OLZQFYC%h9Dfks9IvH0V z*Jdad9EM);EGV!~^Avif!e8|f^wOG$V?-as-aVL9HW8s2EVaOivkydG`m!rXl`~qEJ8Xb+n@^-|+W58NAMYL9NUTF~jS7A!;!Mvb`cvJYr z)4&SW_P+5n_grv~ai_WVIafQnIIfh`gErs}TYbA?)7fel%S9E7nc{&(rHe`xkFurP z8rWaj&%uS`vCVC(V7pb6Ty)!Zsbr9&t)sDH68^lfe=LqGUSj)b9}bP!bIytGnjX?q z!yV*W=)CT{>uTsNEBO*l>Cfy34GG1U|LM-?BEf#1>>K4jB_PGpB6vo~KOv<<{tLDS z*9oZ{@+~+q_)l=H&=sZLmzr8CIrMSJvS2dkx@EhiEmS)i1bqzJ9^58mTgbx@bEtpl z(U4vtMZtrDV}jcSPYpgDd^31HG(P-;23qa}JT}Fc+WSj>4&Ovyug?TSJe-i%awFKc z^f>g>_F=Ye!7Okm@eR4S2@ZoRQESdZ?%D-4-g$H@Mqs6|bPV`*iR@pr$Odrz@3L#4 zM^cK7#@e%hQ^#^kp>#Eni__ROZ#CC7gS3Od{<^6DVwmY0Y8>bvV!CeH5zx<^XkKN$ zW3FyFVCft9#xlPswL_f1y+ivH`3vBo!ki+!&fNPQ3OXs#?{B{!n0 zm5rTo8m@>3P`~{rS%m}qYp=gog`>)Lm(>;P?&1Cl=I=-+4B+f1i~AQhE>0@yQ|QPy z=FiD{U{!PDb8qG7a~fn%$@-c(Ewg9loXpRe|7N|(w&eD=*3JvfTWjrRooOw!{>kf5 zpexeb!b?6m5}iw&3!MKtXFLDrtmnGvUgd2sTof@yN5or&u0mCCL-wJ6@DP}&N5plq zJY50jT}^1${>H3)GIxW^fHUI)F#T$Mnr@l)wkA{4913H{wS%;mG@+Uq zTqkx9R4ikW2aYGQP~p9TH{cy8Ma9c&q?2N@utT^Y^c7yi$C%@zyeUwexewJV+HtRB zT**^=zAd?UU(u<;tp)Y+z1B9?*SVi_PGwiiK9p4|b6a{!TKlxLR5Gni+K9AeX=~H^ zr5V$Hrk+lXO|6wmq}@yFmNqkWb?VZzcInm99cc^G`(+%-n3j={5uf=jYfkpFto2zL z*|&53@|x!FDM&87QDnB2*j)}^_atvSaheiLzNCgSZMcV;{n}SLollxyJ5y=1DXu3Oo~w%UdCL0 zC8oZ|z)*;g4vC|I)d}JIdq;T>ct3ip;R+Aq_w#Fk*+~;iaPEJVeq;V*P&>h&aw!wX zy$2(9ntlxwtVjF4_x1G~2}RH9#-qmh{+CU=0uloprlF>E|FQm|{$>0Z__sDy3|JWu z1HDwUsRPz_D`SD*9KVZxNybL_`UB%R<5_%Wps&*~#1LWVraz~R(F}sx@CGK4szAJv z6UD*&InP!1GuK?Fvt*(@)K*ZmzOYh(Hb2ceJNHv|be20~WybD|%9$54<1&|I#An22 z>`u>5D^B}g`nmMZ>37n0rsbs7O#hV@o%Sd7PwJ#pW9pjJ5owzAN9pA=U0DrsR_0vK zX^?w3SI#|SP05Qdcvm=~c&k0jaoyDjI;h`(R{0^iqyfrKbv9;_P2e6HiT%EYc}DL* zK6Vm$`A+66bQD){oMybHi$)I)eRWpDoT2;C_mOwJrjIfbV+P;vC;f`5Pvwzw(3Olp z?e_w@%;8F7`MRiup7bzJRdmu?g@3Yod=v6-UmCtP#06VtM(R;b+T^Ewessd1*tb zks-H(ng_ly+e}Z5zkU1q_!?g8nrX*zPnn&#zE#niDo3Vbinm_vuQY-;{V*U>f~E6f z51gk1pno=B;Q6h*>Rsfm=)LV(?Ro6c!1F5%ye5mcfp-{qOxvM+_d$3k-jr_2v|0@v z-~_4wiZ+|T^-j_5(Hnj0_)hfOZ9L*X(zL?V(Nq!VOH0!>lPO?Dz}-V|mF%+k&EA1#9xMbDP3x;!0*=MuiMAJt;Nj&*EPne(d~S{O!fJ>~FSjMc-1s zjrx}Ub^q7yUp*<$QdXz*NLim!_Ur$?8otJ-luwCE8J}WLA-?&4Z}el!&!k^9fA9Wn z{FC!1CT&*w-3(7=-|U#&9BWv9NI`I6`J(A?Pl+vwbT)AR@x(xxc06)d4Q32C;jGC? z1LeBv1R@kpig(bX8i`I{6IA(qs4jFa{h8heo_Y-QK+{Ph8G>4F9{Nc>sNM=O*((Pw zsE;&B*y(NK8RFjLD(|ZA8VzPtg0q<;qNKHbv#qVIpKXopKby&3+Row;W)HFdux+)) z!4s@aabocy+iUygk^skB$7!ePOmW_Io^zgddf>G1(lyRq%aiR{;jPXK{8!Quq-Fp)SdsZ3Qv|)2``ix=t1GLoW0(%TgwlwetNlDsoLOY-=wIDr zGvx+I=9iY4fm~3PAUen=XmL<*@TB0!!6QPhg(QXS57`;gGNd^^?i$L6PAIjd6klp~ z>8qv7hTROSQD#q>A7#Fj2`c-t?5=X{!ncQS3Qq_(hhHf7sGO~wvs`p|&u~q6n{uV# zv(!F}3VT?3bm=@iLkqZN^bdIzJSNx>Tnf7M-k?=M8G(L*LoH6^3#ZKM&ArU7fR+Ir zO~d?m8}kwGTl+TlX>5qoFV-E`&enu+IY1k)r6$4a`T#muG(4IlI7imQgl?YL3Y^cX z;$l?%J8^bThK6apR0sWyPa-891=es9a`5GN)CU?_6!(jpMHvb`L*;|OVfg@!H9`J_ z-uW829JGZJR}areH|wtB8suEyI9zhw{>2t$+m0-z zP4R)Eq{4><=kxV>Lvjr{<+4v_Ey_yB8lL5wwK(%`#-em{TGpR0zq#MfetrMt{AK!G z<#+4frGD@EHQ?9sU%P&-`*q+K{X66LpFcBFZK>nZW~GfxTak7utsreddi#tQ4MU3QU^ZvpOp(4~ahru<~AG666T+ySLAH1fP(NmdmY-R2Qyny>@J3ytcp?;=* zk-m-Iqbt&d>qqOq>Hjf^h88|UeKz}~_*i}J`+V}5<~!D}H`I}r`Fs2;n^@BuC?vC{ zR8xSNwftk*W?5#LZ0Tn)SQeX0n>A*8z%#@tKEM(1Z-6$SiK&nOVdG%qIOB1nYOL&E z9c~nQ|G~zmerx;|_+9l2Fvc4n8VC4a@;~U`#y{PdX4Lza7@rtV8xP{|5dXdYEll%G z9Lb7qHm;(rhyaTIyH^Se95)EC&O322BgD2{)6=cq|EN z5>hcl8}cPME7&)r5?sfgg}e!w9C8P_`>~*=K^p^aL5Kg9d7jx3a4g_ZK$n26rg#35 zkuv)G)$<+fv&mqErekS+k?xvKqw{E7+%I-CW5sOkAbE}ajc&>r%qOm*=0B{|g9or5 zl(>fogN5^gP7D-pfi-%^`^yvM>FPe?8sn-2GbbJlQ9bSNe7OJ0_qQE%=n~+284bkyHFpKi0Z%LMBd_Xh&2Q$<@rU_?JlqcWWN!#7`6rHt0~kx)W$UhvKFb@+xt^SZuY1HW;| zG&}np^y_Lg`G58wY+7sDWZGpqXj%`Iyyd39dR?gjAI--s{(;p4b1dC0&&?Cfoy?2P z-^>*(lPvQr^)1Qf#^yr-J^_>RK?WH)YjDA6mEL%za5W@{^d+o z)5Czl=5q6af>*Cgej@9IOE~?D`MG=$PvU3p@YV4gmr#kd0w<{g zZ{q9ot*~}qdG{ihiuINtx@kNQ+`HXv+!?N8t{$#b=X9sp>2{QLHgYz`ZYqIBac?+a zbSe30p9N*M<@N{AzoAOz+Be#+qt`IH$WeF~E}7p8?-VX8tXH_V;Ca3?uVLN|Yl5}2 zb+q-W)oZPo7nXO-+SpnLepmynC#{ir7xNnCC+0uNPs@Lqe=h$cG#A|kJE4m=qUdSS zo1)!ClZrYNEi7tWtQL>AZHFJmJ=B}+;|9XB0y;fbVm#kwM0ja{F> zHkF|{`NUHO`}G|(Y+1e-SIf+gfrft`)YPH`26&4%(C|6PU*bi+jW7Tz__c9e4nfZ$ z3B4G9DGvOu_mU6h2pYKx=2uW$RO(}@pNlRz1)b~PYL;3W=QIP9&m&BWb@VVeTy_Wk zjL!S^*{A143nYG-Wh%h0f^CU{3rOI_a{xUrbDJ) z0knCbd8hf&|Hs=#mI;;(mh+Y`mVm&Tfl-0o0 zqL8&AbI^C$1_!y_(7PTJ(lx{pyeqg3G7wLYPjErdt)N*!#-OCYY>R46z{(zg-xF)* zv3fnGMWzneKO**0q5n1iIna6gYTRa=4b|BH8M_z><1xQjtmxam{d`~ejDnVZIjG1# zH1swU>z6`_s*!G~HVwVRNzfaaujz>T;x4qswxOGNjrj-4%axgEram6!(aYV1$%r53 z9U>-(jWJ)o4V*w_bVZUe`A{&W)hk`(9q=^$CVmw^i^s)v*bx#qw=3W_(;abs8Tk5% zd@ZPT%)}j@=p9B!MMr1HaHt8I z9f>8G_L}zf$Vb<}VT!c3fb#Jy`$l_`eJAvQd)RNfjgtSlT@6jyAqwXxxDc9V!}C+`=Z>w%A?v$P&fA-98$w zEU)bYOU5|1g7G^F-S@|yfnZCY^p*n8<|gnzow0W-h<*6#qjXmsifV`zoj41d zio?ZSK!U_dy`bK&h^H|jf+n8W2}*o(q)^O!SYT;Mcy>1gZYmV&+IwXglViQw30Hq2 z&v!C5 zhu;7{%5T4~(RYSVn9n!EKZYs>)=;AVr9Z6irYH5=bw1Dvp02H=eFO!l>6{I-yKU@b zsNE|}HuIUe{+FA=3+ z+sC!$Bp@^wv*Vy)kihoE&iDw|`DaXfW-x5)U_o3#gM!L<^noU*zA(P{2VN))=`O9yOqO*$Dr(l*eM;xm$iH z7l11kflio5c3_eXb#zQxszJ~FG#FI>VATc#(@_L`^(bhEBr89`HE4wySsrjk8!%r# zi_f$Lx1c{Jo(F-@`buOIe}KfuAsUh=$#7&iZ7_?_F;y}DFURy}t}>M|lknj#a$}%n zwNfi-Yw2QjeW4@zT{l`EV6Yh;`E>F<;Y<0&`|b3*<5%K0+?ZnQ>hJd7VNy&}kl6&o zyQGu(EIP;2Evqc2Egvm(;Ml+?fsVk?py;50ATH<|{9T#^3YKHo2Rkjd5c_Xi##y4^ z&^XHcC7?sV1Je|&>uILFI4wq+T>c&4u{a4{FKvATeHlDLeJS4+a58$Nf2>P^ifz1x z=iYMrx!!Pq=*gaAa%eO7wSVB^R)x$XK42d63A5}TKrsBo1oaYdIf?2DbsxAqsle_; zKsmZHQI}{6RCqVc^yd(>G5bD2`W%Np5GtolEg=^5BYY!jA5XRs>j%fGz1p;QITH4g%9BH;Ny0m(20xWIaH zD)9I3#oF+Xc!SBzRxjzD>PdDR-J@J*o%xQsj*TV8lEe10_ANHn)~EPTk-lhL;r)U# z1S_qzOW?HaonMG&TytV8@tZB zYPk=%>%$%Gl$Yjf^PQ1>jfbaYCf{GUBN#E8Per9(QHntI-UO(F>QW=bW>oqY<}=0c?oP;X7ZwDAWzx;@DOwFPb%up<8Ofu91j zd@UvxN?QxT*u4PXrz^aP(HhFZJ&HBB@lh01fwmf~hEhI( zJ}HKMhMlMj<`|aaqfLgXhMtBxh5+Odd3v*X=mJHrdZ zDZ@6yLc?aljYZnE4*?Hj5o&()CO8FNU9tv3SMnM0}1~#XWS^{puDfCkg1E(|w6ORxuapwaO zV+5kCtEz?GnF{>cF5sf>soQ}_JE@chPNlB=8*Udxk_A)XayW@;`K%NoZ4(=dUxfr@ zrULJQR|g^3_{W$&fAThk=2#<7y89UN@*VE!s9E*yotP8daJGRb@pwmh^qFCX0{=G+ zvYim9)~1*2fSN5)l4^f%|7!Oy8Bmf~avmI>Y-FYU~_za9mz3kmFtWEr{LSglm|7Hxeg61$C~t z4Be?Q;uLX@_@Agj*1S(jhbFZXNUiOdx=)stN`FK>h|x)(WOfqWJ|WyQd!^~WhZ5K-s{P(qSB-8{lp^1_-QsN{W&Nyx&c5<7X-T zfbFdg%x^^{4BuyyU&uQU%gV_az-LU88cM485-6<>A}RhSoB$W0ols8jqPE@7F99Z{ zA@2*PhTEv+`gp5*eW6|O+w;Zq7WwgY&r$UM$9m#C^*zy0iL2@9=o#*r=~?613MKKG zz_#?mbiS`=hUYlk35?#B-bu))*Lv4`lf37=Z@oI?RL}UTsEUiAXg&(H#xe0ZGLgFA zY`M`reE~Fbe`Ojt2osd9N@L9L`vZS=TFC~+r4)8}CiedzWEw?s8dNE?_>PI-MXdu~ zvlDp2UvVw>%U7_vBa{)yo}VHQIfCcvfS=%H3i)^ft`CR4>O}Nc2jkxcY9%Py3N{;I%RttG_Ad%RPse(|&d(I~EL_HS8I9xg@ju*pX0a)v@2;1a$-m zi*&{Yj*bU;?+vg${F&{jYe%3vyo5fB+LmHuFeXj_tziboH4==6nc#xDXp#N^AE=FR z*-1of73mhtGUhzsqIJPGXFSyYib#BETI`yl=SP9qFC zXH9g}Z-_I2v>zfK6cr%QmI8zJ6X*6SDIAm5-eOmHK$FsX3A%IgANcy^0V%i<*?OKN zfG-%VJO=Z^2Y72Ebd$E>l`K;#VP8Z83(G5Ofx#Bko9O)P!s@t+`NqHUHq1EsA;#?k zR(6uo9PFt=u#($It)%Hvlwu+GV*i$d|AU{BgKp?}6<0}@;3SZYKL0eJ#||L|%*Fe^h&gg2AgYgI#Wn+)yC1UY|FDK1 zW8L2e|8NKR8WVt~UO_wu4z4}s7d3z`Oaia>GcxLY@CE*;f7JTGAlLb;O$8Rk3ov>| z(K0n3SlsrAR2!&Vs)VXZw}j4dOLjHWn_0rdGsWnq!~?OLMxRB670w)^djp+&2)##L~a1{xpXi z^bcZWSujTL0*`hBdN3K3hVF^AToo?r_wk+4SmPR|Hd7IvzPp$Q%x<6nXVXiWV@w}r zH8Y=$;y$sF>@>zo7sD^^A!P2 z65H^c_*J?t)e_Tzy6Yg{B2Hsv3{+HaS79BPA$No}0x8rMFDos;U`SDVLCd<4upHCj ze9v9s095B=$e*MyDas2_QE!23+BVS#SM!^i24pf1W#9r{C*Bgzi4CQNih-KS*l8Ql zR{kLz6Wc?{AzAq#jFKZrg8s;SW8Q(&oC{9*RCtSj`ipXity+D=RYhvN;o zj(N|zQ17&%r&E=<$+`{9N4Y0aQ`1XR195XH&TT6*6KbPz%tx{_oyZQSJ3y@g-2~p;3 z96f?^DysAb81fd%7orI|Z_fxFR2KY*8-!IhK{X=?9PA6g^7cgZokG7NrYjnCHCY3@ zE||Lw$HPSJ0L@l93TUb@M0^LB$;D8wsfj*MYpw?Sf!KkoX`=o|{!7i{LbV6Dy6AL# zXH&4pO0(;j@>FSZJ~af20Z;#8{Lm#bQ5A_P$lvCY$LNlXj-C&HtO@Eiauv0Jj8XmY zN^_`MoS9jqwBa+{qrCse(OE!MnYLZ{bO)TEySp0{yTz`tySsJl?!r#&?rt4aKt!eU zba!|B_xCTCYt5{2q@MSA@7Vj=znz;s=MhElbeDUFx)}CMd%0T-mH1@P$M<)gaenor zKo(>JqTEe$HMyAJ)X4H$fG#x9>F?$tdZI2O{<;S^?pY_>ERIdCi|&4iNvK1J)2=m+ z#o*3YyAHdBjuqBqTdfO&*zB!wC%Q@<*X?H*!9Gdf@;B#(91npuF>wzUIMb&yVc3H ztpcjf4Y*C0fscGNP(!DI?y}wK07jDNe@rr`22|ljNH|*!GrxQX*|Epdh32EWyZ=Cr z#7y@$=o~3-U?6&f-FHFd`rd&CoueCAo;widF-(-mz1MpZwG`0+)mICU1NWj_`j}RRk{AT=yH-DfcwQK=fZ=j;x1C zMNc@>^BvtBNuE`(C4cW-4g~xlR1@g`YJr1*MZJV%mzx4h2kLEC+oRQ;b!h8Ay*i-V=+e#bB^g@pnj^i)(2WEx@(f`{yeeuY_% zR}w1;S1}q;#3P`~ScW}^%f)7a9<>(q<*~RwSR1MZnF%b4MW_^HcjRT%e#{$~1g^wf z0nPaiWIkwJKf*Ti2Po7}f_LCJY8>)E_gmKms3TcGNICB53-|k9ug&utIM7DWO@9Ta z!ZP^zB)URihWi~jp95W6T)kXU(9Yeq#n?M-3xOJY!1=?)hJF4TpaZ;j46uK6EQd)N z-QxjH=r+$a&~A`GnY+im!!-)(o7JGjHG5}+QstAghXe0A>)}Bs+rzWP{m1R_L?C7Z z%i#v}s^fqVV|Gu0>hz;$F=8FE${Psp_vMHR&neI^`+%oyCFm09pkFn4T;LNP?N!59 z!17c=F2);2f9D}rt|!hL;W0S-!|C7Pd}Wha`#MVD*HCLB@jkwc9>+x4%jAGql* zgU`_cbL@pMEi$@GfkZPCw91#EoAL29L56H^V2hM{STyZUDE~TjX`1B3gjQAVx{i@1XX`LMNhSkQGqrZuRs7%Gxb-GG;Ei z0NfZGkl;=C3Rj*`OT2F6aLiBmXiw2|fsJGb z@ZJ9^4sa0c0AffGC_n;Gdw||I&AR}(80z=G&{KB+BP9qb zkE6&6$UbzVV==oiGq4*mPQ)3{LdZGJK-@r-0mVNa{U2%}B&PlYOe}``iOb~P2n3aV zK>ueU=OSytMRW?j2L?pDr-yqURJNnsOCjM?;f;mw{1I7Bp18^(Ey+-pEV^T~C@?FE|JTbL&2LR$7c`$|U%O!0=h@NOBXYR*BXRx)%I zzk&NQ(lH6LnZ5uaiv?a)qNm#Z9%}fbu20}^YjgR7*K;s@Y#ek1zCf_+<~|2$di%kt zv&7ByEQQ&|b>O2+M&x;SxB;TtCCEPL>#d8gD8x??# zL3JT0h#}rG;1TJ-yMzKwPY4o&Dn_NDo+9&*9{35NygraB0Fzzt`n-c~vY(d>tcjK2 zo|3?mat;(k$K01-diV|!$s4_0FxNT{-TX_)YQjM$x(A3cUO1T=@ULtFhl0%;?X3WU zzZY0Cqk*v1hP;gkgIRDAB<+j@Z{T=DCUAM8;iMEmKe-Mw5C}jdR6ckk+fawl-@zSq z6>8#AObs~ee8Jn&18)6Epp`j+wL=Aw0{5vuW*$_=3&Fh|i1NoQ!R~^o#%u74twvK& zZNNu+2B~xmNGm2__~^61OiJ)RgsB1tQVX>3wX1<^@xRYxB=}?hgQvL@5f1*-t)OuG z2lU~`fRU01&(3MM0WN@Rx!rT!n+#RO81ELKTHwJeS>%ld&-!L?-i`I90llUKPVP*k z8ctCQxLB9M#(uZwl6#0}uJ^8YgE!l|6VA{e=;<$mcbV^P0_AxRm}8Gd^1=NIQAoXk@I+U@9qjA=3f?uN^Ru%Ia7>)O?SHv zfqVQ0P`i$}n%y1lc$n^_!*9EeRYzq#eS=Q!_};Y@{oSPU%mM^F`llLg*0 z-+*p&8nUIKP9`eSpjN>G)(#FXO5I2+uh-5~!+0(x>0egvV2;D*d{2jLSj znRpu?g%2c{VDh{MzYA|A1dxh}!|{J{0?1LAg5QJBAod|WfnD=g*fQtfujA5ic`!}; z0Nag|xZW`1h{lCr4+0;g5W2m2=z8cSLs99#gKPqClmx*Bdd>=PQul_tq7mMf|JwwW z0tG1#JW>YeUoX1&;OhAdoRbUAK&RG`>wN9RKxQJ%L9`R?LtyS13913DV*=>qdxDBG z$fb1Ng`R4(qtcFc+TktL52jgbVAjBa85Re!IfudQV3KPm)Tig&hvAI4VG~ zn7(o0y_*R+OMjeH*951@zS2IW+@*q9VMV>|;N8Jl)d>xdnlp{2i&r;t~pM`X$&wSt2 zj8ahP2w5GhPpsvz;oZ(oWSwK?f#Pf{YX`HQ5zE{FyWu95nIZFyXFTu~(8iL_5swqs z5^oc3>lGH z0paTqQ2#wZ+4ux`l>2QCJNUXFBMAkX7@F;s^_Xp?W1?#Zkb@=y8}TS`12W-_whn~= z;+Y7h1qyUDb|lV(|4JN1nngT8=tZm{9VYiBza^k#ZLpYuL{1`UK#HL zH<0^+^NQ1(i{SO*J>@vEtIB6b7Y6) z2NWNa{%W+QPIFbeLC4i=3_gZt-9^2h@ue}?9B1=)Qr$G~Ib;i(gQ*6;-ZZQex0*nM zq`3&vR&p98n`|TG;Qb(-n@YGyXeQn!T_hEet`hBpfdndK$PvN6rG@!lAtYT)Lq7sS zAs2NDc8b>!+dO?-=V3Azu zigu1h0UPOTRftNW+^$lp&uSj2d#E-j*~(#xe)3DQLo#3aFZpJ+|t!t37F}(m^BMjkvK*MquKYE zuM3o$8$p3nLBCA@mwuAIn_de~4uQIktRc=KMi9Ap5w;l<0GZchR5(HbZ?1_j^}LH{ zMgD>vEDg9{Vk_3Q{wl(au5Y<8DeOr61&6HV_G_)lyB2j%+w$nr?ky?{q|grl^;5vMUYVkvgXZ zW@JkocO6*Bi5>Wg*XVhrZ9IC_>ya!3fR@1wDaxTAuqhsbrt&i zG+aPx56Wki|K5SD&Lj*NK70!$JH%c6{ zC;nk#V9KcU4Oy#lqH^!#KFo80Sc{PRA_te7lJ_)UT(G_{qi{~a?flJobvfIz-)FUF zp2;Ak_er%U5faK`%~6O5RY+FwyC7}Qv*76=148BmX9X{4Faw2PI5HqH=zrE49CP40&%_!_5c|$SvrQQKwgJ_2kpKMZ{l9gJC1Zu}N*@JnBy|bp7&(j7 zNH~p8#qGf~L0_~Us65}`9K3J_I(CDQ?wZ+QC=bwTTq7I|}eGo#tm{IunG%Y)|GO@A6g zntYqiHXdyJ(Wq+FHGXRR)A+aPQOl9GdF|udf418@o_7j6dv^Wp%Hbq(WL<@vd~SDM zPyTp8FQK2vN8CelPI^Jc0&P1{Ib3yB-3YqgB<)Ns8JwN9`l*HtV_#Ff2@mPoDb^5M zA6vL>wQU$|m5UvL4hmF!4Gxs!kWB$uBUkMU!0F6@89@Nd*N%c-rp4m{HqUkFYJNMz zKz;DsnFI?ds!D;H7`ra;FIm@VE_G7(g{bi-Ff3TmiL)aA1hK&l41s)385F8##3Qvsm zkA5EWJT4${bFw8Bl`%H+Ojbp9P4seKq?u^)sTj^yP%QD|&dNVBPN7BEf`=tA& z#wBYK=Om6ue4Q{MerTLC_P^Nvu}@<@#5|6@9A}S9h~E|;mhd9sM8doHOK}CUAESpx z&5pgcZ{WD$bHB8Ztw}C*HBkbnn_i}>rne75IDGJ*j6~< zYM7oa!v4nI!~KgNiN67x;~MZZ-^NUVbDx0XA$Ni&+6~=uAdqzWB5wd^vaoIKu|-}k zJ0d+H86m&+Ue` z;ccAOh}O+5nJs6UFE%}G{HIY3=Xp+Z-(4EWRR3GfR&{e=G z;ZEc&=bsbw5QRxvqzXA+6{oIIw`wZ2F}lUNTAd608UN_6>Xzu6^e+7w!$YISq%&`| z1X=xTS#TrMfm`?4;rG8g85GkCLHQWs&V*SK-~9^uopkRj?|+Ds(2@OzxP^EGG$>#1 zd-q4smN8uyoCeTQFSmz-YF}Y}09)k2)}0oo`5rjEr6h( z^#t`>Rh}vs^qy-$|5>iC(0H{g^eCg)RBiFGX&|Y5HcXd4!St=%>F2D2likNv3VYva z;N->w{U8y!8C8W2z<$R05Lb}9QxDS)(U1AqeAAfq%zLZ|KevBw(2fvGm?-i?3^_h6 zk&*l?WpSD;y*QJQy)MU;b1*kL?`{KRZBdmw8Da|mOC@4r4z>0~;Q_Ja~Y z`3h=WY>S5})+_MuVG!FMC*kj>fnsL(o5p)PL=y-cTSG5{;tIxsF z6z*K>U_v_YN4v!S#2#f|ZmY2RTXmMLmgnYr(;DMNy-s^eb4`6;wOzSJ(IhXCAC`Hf z8>Dekr1YL7K{7|2B1#h03bF-J`~u!VE`|GvbCFZUY2Xay_;OZoW^#UZ4et8Vnb5hm zV`ICl&CyoXwxVrn8?QB?)z)HYA-3LXo!;ixj_df;kHeIyN+CCbudQ)Gi=^JTemgM6^!8mKSFt1Rja&`XZd_cNFc zTOm{SUn9b_8mI!jjNJ?zeTHF>!Pk&yP#Yx1a??*!rdeU0X{oeKwf?o*tWDrZ8e+L^ z=9_*P?-=gurMfxbMNfrWE|%YrljN&qqh$MJ z9N7SPXRKF@R;H<%RP)sRH9NI`bSZ{9<81R@%T4PRyTB=O2g9>t2i|-+kWID&*QwSU z4zuAjm%{K&m6$s<@eQ}7MLE?FSs-$1w7JYB8sAJ$83tv zN_v=bHmyCKomrUmA&Zw~%_3)evIb}6X1>fgl;M-HGu@W9Fl~6+h%{W9JvBdVP+D%9 zBK2V^K5brFV%q-H>nR_S$0tW7(~{36horDl3RCu^yiAEs9i4h9WnnTY>2rcCUK4jV z_EOCI=rvKrkpU5!FrTm?p|?V|hx80N5=;!<7W6VOCh&MbmH!ZbiC=fW@9eScvn(1* z%cQXev8J%DvevQ5ep+@TyNb>Ro{#y=^y%sIlRky+ zM_*4{3VzjVkcIsRyj%l`T*4yYarlGZxe*-2{V{LBJvSVf*k@r|ybDu-9)zkyO!7|h zT!5SBiSv+SvwbhPCo9by(*;w232T(=6ZMaEEFDYRq&}}&qwK4&$nHzWO1eZ9LZx80 zV4+~IV25C-pj_}v;1)y(nZiavFTqIuKAsP67njN9ajtU?!Z{wssqUK9hjc6D&Ba<}tp`G*A0;BQ?jB#7!o zo5V>Hz9d;1ERB?&mHsE=%LgdFD&{N4D%FaI3SX#5Z^-;*ZBm2OF6}R?l{Lt8vP$_Y z#bsrMYKhucvshEC!E2Q2@!)K-DK9GYvU}1Wk~5MLDO2VrAE+=YTner7hAz`2)o>Ww~mF8n1b%d9Qt}E73pF=NnW8jOm#9U+Y=>D`%^lipWAy zFsHFP9FcH=FpF>(-wQtz-yeS!M+aT@V%&JxSM?^XqS$E%eTB>__6vVy;QC-%$mx*b zp{=3)!fuAq!S#70VtHhJ)cKe@aqPs&$vsn9>3cG!XF4+xS#g<|j6Z3sQwvk#l7}U= zCZ;DAC)CFWB)m>&OB|TIFJ*e_o7ApUaq95Y1t~4b>|{q`USdarG+|=m>_m3r&cvlj z5y@T2CsVvBLsA!|PEIXOJ)5#Jd3aJpqAorJs*-)N!((U1UX9I;J0ABXZbf`TLQw)T z;ZA%(d~;k>Tz2e_n71((Vot`aiNVLbjD8aRA^LoDQgmySA*v&4N)#sQO61pw+u2_!~seh{usMf3Kszu6ginsFKGNq(l z{8_X^I7~2}f0d`>`g1clYq~8DL5ZM>-;E#1FXNx#JNP37XyFji za&e&Kr{tydwrq*~ue=`k7aZ9pS*WZK&Ws7F zd6{Caf)3xKiSlK#Inp+$uw;^@(lXh3xl-X!_Ex{sNVILb>-tjQEE;m0Q0M?4Mvq1aVN22m{QM8dT67zh zNH|JjP^Zuj`j#^Z>}hNy`y06EZZWf&=@$|-Y-wYf4{}G`2gOzKCprMY5!&WWc_M6WsW!9G)&TO z(A8^wwFR0Z>Hzh2)hnez(MNGc?u1h_MY=`OCPo3XqNmU#cq|wzND>?nED`n){Ri*< z;o@Clv$zPR5W~cB(HGH0QFqZ@Awjr85F)ViPw>fn6u6gP^O1rw!3n`@!CJv5{x4oD zH-=lySkr={yPV z75|uEk#L9TfEXzWlAwVLvqQ8+*jo_KU(e%m7jS!X)3~#_;XD!VB)_+SCwMB{AgTbT z=oD~F=ZG6cqeNZ8FT(4>Wy1NwE5b3N!D5y8isXTGqU?z5sqB$#t&A)EBzYmmi-*FW zB#YLH{KY@SQIh+Tr_xojKeC~6ltQDBE7z+kRBu)7Dk*5^2dh$5BUH~-ht(%FSF~jP zDMPif&UDUfH&ZMhpuWBc@4Zdn$l7SUWc+H3GpS8!7Kt_8(c&87-HyD6F2{!AX@pFI z9e*1C7T&7G*twW(plHoNZ$%Hn+`zuamy!NbhR`c~S2Jnsv3{??BjfOvVh}M)Vo{_!`Z7;3f*1#VpZWZtzosQqN0R3d2jXL}Y3QjyOZ*A^%dNo24gh6D9@N%G z*vRkmJcVuSW>AMHZPnn+e`%g&3N?}pW%{SOzgn(_ttnK`RXtJOP>hyG%M6m&;x{6@ z@ThQ~@C2|}DuqPRdJ$WEN^B4_BzMIY(L#|#SPXaYO}>CPj3?zj;BMl^a(_epah~&q zW9RsA!?`%_0ge~CJ5DF1b5h6i_K5aoAY545X0`iv*gIM~7j$X6$~ht2Iow&?Fs_!P z=QufmTn6_NryD1SR66!;5w3gto!JZ%cWAOTh&=OYB+0tcTUxFE=cuP8$F zR@7ZQLyQwY6ulDZMWx~e;xh3l@i}oLR25~CO%ko-jr5f4mfWc5p*p61srg6y8s;gJ zft$5KuhY*n+&3IEoQC>hvQc5oH3^NojhBrS(=FJh9Do{qxMiQ^i^XHXTE&(cV2B+D zhxtv*H0xN~So;dcUC4#l4~*Mmp!L#0;@5fnLP8+1l9)@HK(Z0B#Qwl!8%Q`$$R(PI zIPzvnDQ%+9Hby3EGkbxbkAF%)d*Hm_-65HwmqG`Hg@xCJFOHB!9En6mSH(<>OH1gU z)IDWODapaB@apnB~Oa)6~8NHmdq|$U2?rdP~s}Vb#s)Ux`lOnUxF{WTYRW^ zcCoDJQDJt0Hg8R?Ap2(4luS+f-L!eB15$1$7bX9fl%F&vaS+_zN8&!jnqsgp??y(= zkEjW|7W!`pIe2rR2r7?Eb_#1DvxdQ9tn;<{Wcje^l`u8wN0t$(1T@YMvmBKH)cp^T zgY%zRhWUY@KFpvLstJo9~gROr8BL;wudY%r zQD0I0t1MKkmJg6SWJ_ccX@BVp$p}fOc$GK--sf$?DB(i5i#z%6`S*Y#ae{xDf0Mry zDvD4+cR_(*E>zpw1YZRA1TzH1g1>wQe=1ML?cfr54sJE~9-Mn7uY&iTcbPYo_Z4o} zLT&?R2GlNByHniK=>GJI==(^FB%Q?=8;j(y@JUrjXo5S13UBRJtz3q6=eyig?Ag=rVBT^91~!!k?nmk`5_Deozsh zDpRKebD&1^NV7?kr4fTS+ogW5snI6s&4y0XbIX2Pm}9sz9`rNaT^8q6phWh7Sqctx z_)DF^u2$Cz(6k+cih=>^83oD(`A#Ct5a9g#V6!2WG8d|j8E_=`A%ajWe$REUkrOG`zw0` z8^vD69t_^*2?04l(%@sEtnjjkzmfBzm&SC9jgCXdyW+DFE0Zpz zOyQ0KbN+>VcK+BrLGHHP+8i--r9HBCXD-i}pDs$9o_04iIQ3deYRdWK%}I>JU-2X3 z%42+@??*;Pl!tW>9T{>ecvDb*U_n5kzm5HoRm)6aRxmnz)jn1_o<5i6rp}{sDHW9Q zKmb@v9!4HP?nll8w~~`Ik@T1tOZ-CEO9+8!2@{+l+i?io0#Hq^1z+Ajkeo9C60r!L zjlgP2gbdjYj<0sMeUB}`w$>`Ne6&1-J0-$$!7Me=OibfY!wvmW-9+syO_5roR4S}; zi_9VANR;Bf;>n^Rz|f)zdh$zo%ee!%rQ91F0_T30qSM;Z8|E9I+a|VA+l;O3HeKuK z)^V+IFs-(<%xxjSFJ&_x=tKIJk*)Vz*SE&DX0=Xlt!*6%XYo;6_x1(QQ?70w)PAq6 zy|t?a(=w;Iyy;e>s$o^bl7_1dRShE=1Dm!qbv2D@?$wNH_G#8N?Q6ECwSNr4kP3^e$(zY3`Ct8>-_?G@Hl`WfF*S39W zFYc`FTF33irwG4`LM7d$XJiU_y<(+Osa&k;0lnWMjZnkUmgrv?5==MD>DCIH)lLCU z&U)}9mBCr=0V>Hn=Q%jd2VBXZuxRrf_7Xv#v;o0`(E!MebjwQ z`-b-2(`RY#;9l!`sJqFF5(~m|k7O=MvnN+4HpcT}A4i{$42&2QULRH#h6~FLI}qj@ z{ysb|;(EkCkq0B^N3MzViyRoy7(O(-Pgqo_B)9@*B-aBH{oU+PwvG9WvDJ5m&o=ra zS|@cXHJ93#`jXlob|)EhJ)PlO&rq-s{zZW^gHfSm{X@9hT&i}>L!zi`Bd;RqKY4!c<^Xf;`kExHZFRnjP-%#(@FstEaLqemx z@j=t2=7TN0S_ikCX}{7@*EyXdg?WmtApAx zwS98ifYvcBi<=vowl`TD$22+`b~e1I$JM|6yWy|p&)`4Tf2->H)zRzH>bBMu{T}w` z>fb>PsHUgQwXGQ))4R@dV+F577RfVNwBo7~sU~U|+5{a@FVMRTJ4~xBgKeMeGn~iW z4lf&Z1e_7g*gD)sd;;MLp@T4sNF?Qg0$~B^E_f@Ck(39CjmQ)?z^6b{~k$k-%BABNza$?1#e>6DiB+W0Z5+uW~*W zc}j!&HVu3=lr`ehsH8DB$DA7D9345DIjVdFdwABcw`DnHPli4o8dHM>eEQfi0ZOsLx_WN`%8KU^f*&onJ3CTp2CmI zjhr03ip`@hBIRL!AdId>_TiSh#s@GLeWu-^D%^!LRRniea?@ZG39{Vxn2*TTQn6kdhqiy@%|DDZ=j}390LR`?8}0eM6NI z>tf!-UrCauoJ`}U|Huf){G7o}znPYnIw`qlV)ytyvB>DU2z3}Tv}Z6Ts4bw*f3W{a zze2Wx`IwR5dy+1pipWl4I>8V35N$#@+zhA0>SxN(tx~O#6^I(R*&T12PuCBt>#Y9v zE%$5Sr^W9*Z`xj6c{%-MpO?K~M!YJ2O?vzO-TV)$KMwyi?sLSKsxMouCw_UNF=<80(bTbN3F(~ls0>MZ zd^#rWUCNN;6N#tdU&hA9tcY3=u`+CF2qtK)zk=15@s1uw?N9oPe~%r8z74spCTElV zv^BsiFyQo|+QsT%)eprf`AyjeX|fan6P`cf=i)+1lVrEFLRPBCRn5^n)A<_jnDcB! zjuh7x&rZl%`Hg1d77)gfzL4iqx6=cC`!aB>P`~_umqBAfnGrXltK!|sTQgE~$wfCy z=k+}@=-x2EnoQtMshp{qOIf&Y@qwk~%MzBYUlO>e&;0MR=S@E_Nj>i5sPtj_L6&|| zy?>Y5OZpTc3VP*T%*o3R$ZE>ila5a_C94wk@%EUdk-1^#f_nPZ`;MbNAehj2udidK z`KIop1w(f-1@$#WU0!5k-yqF{ZDOu7H@;K=Z!QIgoT ziS;Qf(!XXRb2z#A`O^HZ{EhjdyxLq;&W+5(^yewniGAX>L_G|{2ABH>us-;3s58jD ziEHpruoxhPMj}4|EqV|nY4^81HMbi~+U2T;vV8GWzPIyXYjNYg-`bi!->-ey^x@8% z=$9qW-aKCN@a_G|do%8hzqjdL!2Q(^Mm}2b*u zEGQXX{HX9qeoXGrtd_KhZP8dIja@u)*9BDf~-Rv ztKE=1gMNyuB{k4$8Tb4~24#koMVVuj32TzcY1GWB?CH5T^2Qc?DO_H3zG!pNp`t5A z=|%4gD+)&!h8B)0>{&=G{I{^ANLKWx_+d#=H*GgZ_vTV!k6op=x*zOTQ9QZ8o82dU zOVYGhQTT?S6821=9h7Cnt+ zQ92-HGSOckP4@(NPlJ*D5P!UA$gDAX&mkgFI7|WVF5w??2Cd4cnE8Wk@;@9{6SOn< zL-5hyk3qWv`vx5I8_G&ztnv}jGN=>DJfez#A)xRHkcUhMX3_xgaL+3}Xoad_3b}Nj_@^L?C+a%bv9C?glGohQ_@H4>{lvf6zh!@> z|F+aUubWqwU#I+a?N`OGbH8T&V*ffN_5G@(D(MewReaT=s`%=# znzcWB!^va*6*g>dZfQN*f#j&T6oF3IU;IT9C}YdVDlRB*sVJILz!nWK7!50oqfAuL zc9of8O)lea<7?w`BTPmN)%sp~KYhM_ul~8gWGb}Iut&HyLB$;i*--@V4)+r07+Zhy zDZ^B4xN4sKp=6?nAhhxwyr(a!ftWOztq|g4h$87kwr43)DjL4&qz< zRICX+6vdwIE`>eEsx-wI_v`68jphU}%xKzI+8;Wl{;=_;`Ly+<{g!j4y9Cm@7ehL` z65E8EO7H_(#$EC`${p%s+7e(uX8OKkyk<7ABz}y*?LjTUmqMq9KaD7l^hO3pWkyLN zk&(*qf5Ya7Obgl{(9KT@^Y86IkiJMwq!v>hR1Pfe(;gop=aI%~_zNXCgV^?wIEN1Bqef&P8^WCDPPQuU3y& z$R*o_={#NM?zYj*9~*Z4efGPwuA%nZ&sp&6#m}7DjkPapd;W6#T3t7(4h>IL&94!^ z%4_%kd{?u#236y(npQ=q`t^fVHMDAN)v@Z#pLc7^>nwjxHprUqw@>8c3yLMf6t6Tc z!x76*yToa-hdhdZlV+{2e*S@B%&$1=_ZDhHOUVhuscv6 zbTwENWC%PQhz%qJ{D6~ph$#T};0@oIJ_qP!^la#_IzgdHp&SO5=5OKw!Xf-q+(B#( z295rKTngUdcJMVsx_>~13>v1yddPNMi%=sOpb{N`ZN%vbxnu(MB5j|Ko-vtS;C~n9 zFW-W*Lbrx34(}VGj2swqE3Q4^cT#i8we$yB{G11Q;)0>Y%eobo-t2LwXTM&xy$19i z+`G0HuGjA#rKRh;g%yt|IFfrk>uCDf?gj1vt%4G_MN~V$NL+EX^KD6;PA+3eh z1Ew-@w3W19z-8jl)bM+8hh#oYVgYWGPZP~q)Pm+_>p*##78z> zF-PT5Kh#R}36PoapJl9dGLR^)Sh3a!%Q^EC(<)<|;fi6Dfn|{EOAQN+=S@Vj-4t(j zn1z=0KtRrQR5^RQ?Vdk~M$}VG6LvQ)8ovaejvt0IU{;|Cs1R_4w?h)$L~shkK+cUC zWrbw-XPEie*^q7Aj+u|yf}VsTA;&|8bq^O0c3YwLp|;c3XVzj+xQlJO?0$}24y$7U zJgpdam3shq5S`xs2(R}VI3(_P8X%owq$|z&#eTrH-n!Cq4D_m}je*Ah408>84Ph|- z4mMXl{C<;ii7NHdU)USgIA}2=DTrgK`YVPX=|& z5)oCRmM)MtC_+_@ssdo>Ee1y95mmWTtXQo0ArF#IksXtIB)5QengqMq&Ek7vw4_`z zOBy88%Ze1Yl?m!on(NwH-CP68w84zB-m+~3N7ie1qIWi82DmEkpx0sUVEyrZ37d#V zNo&b|R4Tp5$L7QFIIg-h8(ol1+O&!&H+*ZZh_&oOL35%0&$VsTjaSv^>xtT`+adlEYjW}Pei*7)}d zUM>Fx?X9)bw{Cv&GtAB6Yr8rXZBFsO}o z(-QL|Gs-f-GT#ykStCEqM}f2Z+T>^Y4m41I<6G#Wn9@{a8s>oRHm;)=00*4$3u(9qLcIjmE*i z?tE;%wD7g)E0BgN0uW)K2Ryg%^m(zRA?KmB(@qbVKwkyp+>o+6<7k3kQ^ zdU0gJe8NZqi7*&{8M_Sq2)Pw;2}n$*ArXxR*@E+d&fJdjM=wTCz%*i);Q54Mr0?Wf zN(V(iW|R2%SJ+GFTgYXgPve2=xDK6)or!bdyNH*`anysfRG(ain7Ng;1~|+ikoED@ zCy}Q3pJsx9#bsfxqI{62ywf~G-Mw5>fylTVoZy8XsW%9<4s#l}lyI3SBAy|BB$#l? znEibj%Ie#AP`k_UQZo&jyxuW!)*F~pi|pbdEL|b0e;V_W|?7D2Y8B6G~^mVkcR5#4&<`Z`k zF5!3KmSOi`&Y^dKUzvh<0$UjdDB9<{JHd&51RR3BzzuTFrx>?YT}Ry8xk%iyiB-~Fe4#1!4rQyJ|I3T zju87IIy35V#F%h;7%${>aB`3v5@;s-*MN#^9=kic1UAEOnV%W6eb3W}Qa6$+@G^`q zD$JYins0Ymewc0>ZtE^;&Vp9%KRI3gTXs^GCHp2#ly;Yp#TCM-g4O(EymIbIPDK}@ z>rm(2j(acx{|+4f_Z=%c=XLGmoa5f+ec^Y4(qo30Esc`M*j;h6)**cRx*Er2|&3wnQ%{s}(2leb<`!+{_GYC}QVoyJW2Du-7 z7qb(40Vl^3i4x*LQYm=@#h-S99_))`;@KWQeZbeCVIkK;e})|izZC8h-Xm;e=szK= zf>#C23Va%{EFd$W(!b0f;ot1{%I~hA3AW?iq`SMx8_d!MLz`TrK`RVLvgA)C^vvzLdVy zL2$0;`iOjcF+)J_SI9>CHTrG#H~Wta*c-4mfEh5C*7p-M@#`E6`*!OC^I_v6eWmt*X1cnYszkY5(JqgahscVh zHImbkCz8q1rLybtU?op=S2I}`WDpuJnoF$>wxz&MVFLGz5B#(7;QycMdhI&v{@|Gb z?hO)l8?X|J$rY3g+7mj{cRK^kn$Di=hxb3>U+2Hhzt%6#@7@0sB9ZJk_HOnib{M;m zHJAB>QR~|TSuLOGX81Zc08_Y*eiD>0baG!}AN(oo8c6uP0#)!i#By*8OI&V8p#6^Z z9}C@VGRh6H27-ZYXw~o6=jw$zt8Tphm%iL^6}*6Av(&N>c;I7fZMHu4!}fRfp^iPy zx4;XkanA&v$1`s_VmrbYX-EEt+KjHiXu$j4hOdM-uN(BCA>h7P4X&Y;lp&PAWD*%g zdIVgNVq6dGJj?~i)NY1!*%Oe&oCdu@9cX<&xb6b~F3qvRe$}?anrR6$Cz)`@C;DvN zbIm_$qUwoako=2ugoGykEc`CmD%d4>1a)CI(LnKf$rCAAehappA!@I>OS1*ucfYlD zT8wVHE?j?0pKZVyeN0K99FMYz?RT6D-1%MxvJ-U;vj?|`kVv{sMpDnwcKZxw+-H7g zU1bmTyXv>lPr{zh*0WBrHpA~47LuLB9su9({j4USc&=v%eaHCL`K<6E`V65@r1hox zQYhr{q_;!_F@i7#UyB=r+XZ=QgMsoRN5pw2y0I>a4qDiE(ig~W{hQ|b(`(E{W;{h3~~uw2FO9&>>3P7p6kG~7y@MQ zIgW>r*S-k;>v}jpjounW9r6!qD-bBE(P5b9n1$Fx+(+DG{02fL@i<9N3I$zMcXAWy zJ8?E41m6nou@Xq&d0{P@) z>_IlNHQ7>PE;4O378 z@7pqM10a>>3t|MeN}BccC8 zr_(X?dfGYIKDE;@^u=@qobM!Gz3%`Zu5SSEB%X1=_l?gyND^>S?vQ^IyYLuX4@@iS zK5{0a)Vta937*&nr_GV*7-?T`+ism;nQK-7!BYma{p;W;oMoJB#6wOC+wfe!1Zd_{ zfCha}k2S0_I1NXP@uo`CO0%zJm&Iv0Y8_@9WS{2P;?%kRc>W^pq55HdU}xi9gdwD9 zzJP9^Wz(inpHciFH|7B3#&AK|1g|?>Fm^0x zECb+4C_~wiRmh9Ls0cw;0H?1vR1s6$@UwR8wT}hI#%*)7>7bztHoXi@7kG~*DKnHM z$}LKi>VxW@`j^J7jn)q^Of!ywd@rMUq2(+nQD$4lTSi)XSTevrdCFpq*jh3Fdf5A+MvvXgciaXW+izLSYArBn*O`=T|}j@XDh}r$Ocam7GucLfJ?i zO&dU;;IqT`5@R-`nY>}nWIkZ5^=+r8&~{N8NV&w*cmX`wgV6m@Ww6m(fYnJ z=yW*B9fgi6AV*ql)wXB0m$na(pHXG&w0(!Z{R9aw0VTMDx$vgB^v;%bvm4iZ}yucz`4k=HO z=)UNo=t49OxCGg#zu^8~h8zR#_Wvc}K0@9@9zX^mCn5I#e}|OnKIq~(#{rvp2Yhut z;HsJj9o0ifGv>Oc04rMw{K{G2_r426K~1m+y#QSTEFJ<{fO-myv?ZwRkhOXYbraZR22?i8 z37?_^Kx^I({-R@86A%C=;#T6W;?%f4_`UeAcpDx|5aAEwyKri(7ZV82`zA*sZyO{g zSO1T%1>X}a@(R#0dP9cwZ3G9r0UwdGQ4UDx`2l3Lp+HA_j_JhkfG|4;=x8i76BUe1 zLKJvMfNSzKq#@#*{*EE`D%(n19=MXwHiuPgeF8b8dDZ}{)zW6^wAcVYXol&M#GJK#Qbo^-8&B-`g+U*rPRYcw0X5%&tc0K4yvG7kEpiAzz{~t@|03Fx%w()~e>;|<{+eq#9*8JDDZQI7J?OWTn zZ6lnFkG@~KzBMaplT0RO&ffdw^FB{4);^Ap7;m^YAAFYAysdpMIBn)J*`EczjjC`H zWP)coKdgZk_(wX!KG8{xB3IcYS2C?anc8d0V6F%5=Cav~T`yv>S#Fufn{%13FzaqH z?SRkL4ujohX^!-d6brjX5q9)TsRde^`_cZ=%~>sJ=BYgU5bPQ{alkvRgX-{|@ZR@S z@}$6#R>E_@)65&fdugQv<7;wj3*qt{3`1H1jPECnRBGHRimvzZ`u$P1KA=~F-Es=- z#V^z&FrrLU_o8yWOzWe!HEP1|7X-h@1ehXipe8E7Iit(((Y-y%iQNmQ-Vyl;`Ntsk z#c{Nq--tt)e_J6mpo;#}cxZe4~sk)fD{U(yeRw89($(Fz_zZ*TIxH2lkAA z^yctq^wayps2ONX_7gM?CpFx7d5r+$-Ius7e;~ z^zh8&e(9cp-mk3WRbOVN&rZT1Sp>GodoZI`g$rVvb{7WyQt*Qog|l{{Pzi>gd(wV+ z4$449VCr0r4%>6vaKC*1$^L5t;sf^u<_Q`Tv@K|J(Bz=nL3abCz^H(D>}n-jC#rdQ zEN9ThZAy>efoU#!!RO%I{7)()-A9Lcy^ul_)mHDSHB;LwQ&IMK>ambPtZ})WZJoaz zyBt%PFBd5IFi#p8!m+ao^uI2gR+2S1zZ{9o9eEVr-(HuW(bc8F9u=1KppdFdd zB$_;Ox_nPw!-Rh}m^pf(nl}x`i;bv;>;iXQqxu3Xg@n zC`r#|UTh}%@^!^*)NQB1S^EHH9}iqV_s~nd47bj67&;d+``48T!0SpBidaY0%&e$27`Z$GjX?zjjP;)`S(fwe6#Al3xM;{r;AK z@~~OUFt2y=|LWJwZ!t_I8Z#zA=JN3TKa{F7rI|@wB7_RFU;yf(Um}}$ul7{Gfl~VE z>+ZYEMB5q^EV|(j%b^-n#+l-{?%3y84rj+&{%1IC==M^{b9)?DvmbjAAoPbw)3ux|}F zOO}b2XBIf}tc|S0P;55a{;{2~6~H&i{@wf!`io4FO$?YCFfQPK0U-fL{9Chg2Khz! z9fTR@5xmoNKnVV{+`yyvvt+US2cGg4-c&(3zP$Vv4eb`vJJ^mc34TH@qaga%P5&^h zamO9rmnbYaK=YLKb@UBkcW-Ah^^?!4Sd}lnbH3%iPUuN|NB!m@{>kpm?CXY-Stj_d zLgDVNs6E#H(J#UxzY)FrNqr3>ox03>n-bYYYpoM7>LiA?WPQ-s(7F|;yJjh+8L+e1K&@? zk&4y4s6ImPAt!t4Kl00`e;J}HYsb_;Y}&tYClo{JrIzOfoguGlsw);edrjvP$1?bA z#yA!`J~&!Alb!ori``Sum+0Z^s&rOcXqEI>BADeuF7(%v#c(N{Xzv61?ek!W&Bt_g z8r)7#&_Q@3$YKexJ+rFM#R#dTv>Sex=J+ZHYJ<&SeQSe)jR5a#VIsra(i+hu_7grB zO^KX}>I<2RDx^+_m$a|11oQQieRi_sD)28p(^lX;9~yOFkGja;IVUWFBTE#P!<}>) zpYsGA@akGoEf-$23chG56R^ozQKGS@dS>`_SKv3ogvP=w7;{yjnYd1TBwF$8b%?;) zFfTtqnjnpUMRz&z;7`e)35lNaN?4MQvl3s>C;1{jz}wE2hoNa71n=xZtWYxVu{=s6 zCsE_>3kOjP7w$V}_`s_2c|NQFS>Od+ZoD$A zAbv&R6WFi>_>^kFMAb!e!I#|}cEW0?tB+7Op?=6d3OLl&L11#FXY7s1dMYIdRO~IHoS81XYxFHVH>M+ZB;M(9H9>xXx&0OQ>r6tyOb znmAqxz}96nErN@@oOzIWmHC+YqWQS_2=T~E^BovKs+m>T%8Qwv5@oa@PdXt@gA@FJ zQi4=UDkqhfDia~a^KWndY9E;KvcZQ_koZ^;KZsw%V5%J1iIr9HsyGnU@S{vSUxq_+ zCn^o6w2?3aGA~Aim<(Igd%e1`9p0Dm?Bd?y6EPJ$d>Gsd{rNjD$=s9RANLrO(S*nc zb6x|Orgj@<_-_vgeq>w@*07B1qDGb-PSEq@+i#fMn`N8u z>ewTy+c3j;-~nH)!SS!xCUOtql=nlyZOSgZ_y@c)zF+; zi$=I|-Ge2=^q{Z&=LIn6a5pER^J^;oR*MP)R@QD&yYc4)C<}Y#^h~ zhc4q7yjdOe#glvmsF0mxcYa6vIz{=ZY+<)HRjMnpasmat8B`-4_=*v)_XQ(j<9$i=bVawpIT>z5z&F_h+-o+zDoZ^kGadA`OjwQ58x!}u)?UEbeivocQCedy z7KXN)s3kOjDWw3437uhm+swWHrM9NZ+f~2EN!|dHTOYIzTBzrhLdtSZUR`4JNuC0p z=j0WW-0R#Yne5Mx!a;NIPwxa@gmMNB)!tadTl#!Dn^COz1-L?Yh(pQVLq)G}R%jyx zb7xcFlg~+>^j7FDy2W|0J-wF4nnKMx&DktXELBj6aG4X$U$GgV&A<74n5?mxxh(u! z79#epXj$cefv1$IJbBs!Dhht`9roLKCOJ&_lY%gXUXxDqaYMRHMyE*4s5$&VLnb?s z$VR5z8=LI%Dil;MNev|zyd-Vmd0&Xt41??art!!~A|B1lF1RJY5Gfv!#>-{laDN9U zO1kM6OxkCuU&NaB%a!G$QbuX5*ct|uI$~owO0(%yU6$s`wM?4npt+^xr6oJs7j3Nz ztp}}(u;jljvn-;eA2z$Tsjoat+JS=BeKdspQEXXZoG@Her|U2a*N{^qWPWHHh~MC?S<_L=@0-flBKZ4zu++u`HfYOFP;^4y_RW}bmjW zPH_Q|L~gwACe+XFafP>~uXGga$}Qk+{Vn|~b>iGUKuKnX*aUQ#%F66V6Q-q57NxsS z##J)uq1c3W;&43i1$ZGpqwi2&bP^w|!Vmv67Gbqnb-e?+0ZDY{Z)=xP8raAGPHBg! zDLC-gNZQuXic;dTAI2CHI`}Y zQj>ZO>%9WimOrPWpVCWlqqk8P<--iVkKSG0>fY}tB|1EAROi}x2Yb7D$9gY#gMH1& zhc^?~zd`vW3`>7SDUZTS2d+**iJ-sU2@a2~=ny^B-w}0%Qz7UEujWV82Fl{y9;mN4 zW!>QO@KPzbpnl@ibyI`Yd*pC^6vNlXx5rz=>+;<941tklt$V$DuloW#FSE%A8hfo& zy5G}zr~%h~7^`K#LOKzS%n%rFiV97MNk`x}HV7`Fq${w1Zj}njZuz#UKYpUT<$%S9 zJ@Z+HS?g09YU0-&O(TC4vWESw59NfF?zL?^RoRKwc$ge&SUXsYqhlCoby$|7n9;#;#)^^q;%V$e| zYfSk}(Lgu24K3yqFM6z3#!gt;~Lc!gyhEb^BvFDzzjW^`oU!o~KAe9d2eOr@i> zFx)t*pMdkazOvdk(09$3TPXprUN$n$V<=vHh8H}GT2~!O%ywRxh5!B!j+H?^w|Ap= z99oP2Ll-p6+tYi``wGpUgK#pxS1M^0^)LEqV~;Rjydu4pTbQz$n^=xn##x42T2PV7 zXihghHt)1#w1k?^nP!`kQEsqeDNLqjasjz5NTwJXXf4SJVz_clOo<@&;8YsV<{B)gE1s>FO7?9X9^A_8hM7N$>&h(8H*@E#xd( z;6Sd#Ii5yr-IY}tBX8w#pIEw|R0wXR9O$LZ5}&bt39NgRK3r3|QUe!U@A*USPMrg{oRUsz@GvhQ3nIfZy*9Z*MmtTKIyd++jfnfzeBxO%8b- zEvFb5j|-B4JR>u*z%YD5h!szYy}>ixly8}umY<=i6<*jUmd{k9mY8#! zi<&aa4TiF-Y7m3?-5jQDHevMg4$~QJ8O>z#28wXKMM` zD^H0$R;u%{Uz^lk>Re?dGmtSvt7}ly+=UX+ZlZ$@%#0mEVY-HIqHmRwRTY?!oQCFk zBc+)dj#|b(?X_A({i)PdCDuV8#$9Km5)Zt_LXU>6^%QlIF-(Z<)$8joQEJ!)d+|lF zz0_0omuHK$#Hmzg=aDhDBZgfmM@jeal3t-C47!2T(yNLcsd;S_PQsA%3wvjQD`}B2 zpNz9B+IWFP1=Fec=~_SixK^I)XvJiRf}l>@cmZAA8bU)Q`CFG zKwAzQ{8%dhbMbktg+7Q{YiXj#8~DO=d{va1a~H9%P)3+3d=+|%Q>2`x2y-3NBI&d^ zR{9{HHmSrG$585UNJELFUrEJaV(uY+GP;Q4<<_!U+KuOPqNdn`m^w^U$R*F~b@c`C z(;qbo8jr{#C2I)+3I0~RPlUJtey|jg zip_Z{#KIL{l~wu7ia3P`_~Ku{k3Ir!=@w!uagF{`ouW4qmKqg|iNZ3Y1^MV;V}y7O zw(tj37n-RK^}3c7{e)idJi^QpFd3Oo78yatae-&s7okrDQZU)2t{L@ z;Zpi~HDv>g;6=0^T2o_*QB=F=8?Ed?Zy}D|agUf~CK1wo*193unKJi$w78HC6}1&A z926{tqhwW|!4$5NDw*;L21+VP!W`2zSrSVbVeqtf6f~IZm+Mq6)t`DP!KRm?0(4US z;+v&>)@rH0-6K5*w28(7b+b=Y(tOW-2I?IJ)l+m`hQprz-F?#e)nn)%sjJS{Q|Om2 z^FH!^R+m5@z zX{df)d9Dr;8lwzz+cZ;(F-|B)J+r|(9Y;SW2hn6>W0v~JvkJQ(?|rU3q~^U%dE-fN z_jXV6J|e2ArH)qGDKa{d`4u<3cI8y7u}~UgE^hu;tfo%~DbhwiBaQQa6qL~qm1*k7 zjm0wN!L~7ecbOvA&6iDU(3)8fXK<2fucd+i4Ai9~10I^<;qU4vS2P`#+nc}IHu-%w z9n!a|k5JlcsE3G$q#Jro??`V`y|-{(YpN7euj=^)m)=iR$f73ttlm|gZ^}8*V`?a6 zQ8K1)Np`1x^eh(EO3RIp>S#1g5}dQ_`&}os{Xz~S2N=@1=r_DoYN9T6$M;*)<+@z| zXL#MRqRcvpo=$GDow=25kLdv3_l|VTG#(Dy^QKrjK_e_3t-sA~xdNOv|JVlDA}zYP zCv4zHEWxH(prZPT)6B44z#3Xg9<4|F%KMt@5vEgQo+E_`zSTZi8>KHprDwBr$@s4R z>&xuz?yIO1>ua->Y{Z%?d}rM*_YS5&PJ8b7w$kOfNgkHVm&vo(lUY5;wXdd5H$eOC zP4WoJMzC$Kw0J521GK_uB^@*-i+i*u)DecJCZ{SnolnwVdfP~! z$=4O>r|wY#eADUnBq~=;iPj6URaj`awZ16X{ZCt>o5VG8FX=zM5Y@=qXmkCik5I<> zp6cIBtu38Vj>v0NC#$`IUEPQ_(=_Q9Jd+owjf^1Ej2Ev7ML^0tl=n&7g>H0KVge{Pg@}8^gk6C@ApvJWh@ceiqpmMrhT?&w!-EJ={mMzgV2C^(C3y8 zW{c^d6fPX0!;%Wic{p4p@5CDP0FR;bb4{Crc7oHez!K1!e_$Fo|cF7@C)fcLx^fTg8IZ>`Ehl=}ATstf_ zkn2l@iQu}5L#P8km+w+VD=u$iUdJMJr4w>Ox+4CEmCq~A5uTygHcFTv+3*(=geYo3 z74?s3xem~8i&v#+DN$HM4dZ~JFk2LDY!m+@(|ciz(JHD%G}(A=WDqV<-yEztv2|zl z9@0wFQ28vLXp-JT^;gg6N69{2#!9KYNfV3fiOkt%GB!~4DQKLBi@KFI7u}L?bWpPz z1HrEBpr_!67T|m8fC0h=^e|=`E0{aqWOPFXz|WYDogQHLlZ zb&*8joHD{&MFqD&EZ0-sEnOByVoP?AtGSKg(o8u~j4@gf4Xn_8Mm^!N{!3k~cF}u@ z?d6)1$!G~1M3UA3%xpHQ^fr7^h*VdsNjwt7H1KIO4J|~um4vRs3@msVumh1q8o7mn|oN&nRqNIWe~?2 z&Gg~I1JfPLZ_^L40*L;PVmELpxy3`mGf*y>KKXay01zFH75~5EjU&7X=~MUzGz=n zRo6e!TUZPWXC{3xIx}yDgJ6$7(p?{n6&MXCyNg?PZa~^pJ)$=r?CRM+M=yHWfRECTx z#HiP(39O|$sc0jqsr5$ts1Xr$MPl2s>PufKUnivv=!2H9x%NVxrJ=8w_m$_Z=Zkl` zGKd(wusR1+k%V?#SM81d%1GcWccS9pBu=huG&4pUZH4LN*A1jkbjQ1h%|O$XmtTXN z*(QCGV(Az(L~(MF97QGTp=qG0i+mmp>tgaOQ)zQ4xSz92s!)yY^h)&D){1^Y24gH- zn2m+0MqRSHf7s`DIjsY^!t2@|G>!TyJ(ZTqD77kjjAiwm+8dN2`>B((mU;_)G_lro zB~fvydr-0&X`IB@^bi`0`G}Hd5m)vR&htA#XcTRcubR4mOR6aUQPi9wrBOp`Km}_b zS!#E&JM34h#eK|UuhxecA)s+=@-DfFDU&IcE+D!uXuWv!6ytny$ZeR7hr&_0r>TV$#7q+*s$Sc$K|x}mpnk8H=E zp7CL-V9`XTR^cKrkk^y+E{K~#Fp_Q^CP<@5x#$qzkzCt?v%%$RM z)QM_hZ@Pn0`Oj3rlF!^3&v=V!UTG9w3Zq%}g6yrb6eQIHgONj=PuHa>y{kLylS}$r z?Y-vJ!u4EOv<#@JU)I;EWnoWvsZ3L&w9T4}Dnvaki@J->{}*Kt8pzk#Ge=Pt2~|g+ zI47?Y8%btZp0sb6L)b%rn;YjfVXs^>D6 z3CY41L;r+IE5+kWQHpWjRGVS05>2=t6Da_*? zR}y-lkJeSl%&yri+@rSql1@i^!>+}!z6GdZ&MU39^E(PJp{w}M(w z->804bgC20HK+PeTTPW^0E$Q+u2e$L@`sRYJl6+PD}1Z@zzi8`2R&RED^_Dybe5h7 zi}V?25U1-sg**70yHsVG$&IM*#>zpGOkby>w2?f?B=<2*GJPkH_NN>2Ke+~ohH0i? zQx9acZd=8fjn`WGc=|*!c-Ud6295{s(+P#p z%glnE2g6i_p2;dI!VcvlYC?I*90x0Z^bq`%)8JwrseQD{bcD0&y|u%t8AXE|N@gl- zUU>38&J)D{}E8`8BM`cZuHdHpmy`U6<;b@0kp(6i_{=@Yl6+ud4C=dZn2o~XsO z%1o0CRWmBvy~&<6o-7_eRK|z;+ADjR37qPl>>li1=?ZbRMU!TOE6{z;-PE(dQ`wW< zQ{DRsg`Ld4yq-(0>9^N%*i;hrvhk*NmSk&1zxn>dQJ3!&AfmF-+qT*I+1k=})3(p=hkx(D zrNNU!2Z!E92ct^Rb?_y%0;GT;0nYY8 zZMqLy@2up+4!E?7oKaERsg0pNv;mI6AmZb4L>Re2wcSDmEW6M||EfG=PO!M=nJ3KG z3)XWRI-CWRvGm<;pr=|zc|*r|4v6(5;H{FqTfNgfY3^H|yYS5<&@(@T8h3UuSbcpP znC@-rn?=-rgL-LUFkP#ar@p=3ub%%rrM;zm3s5Xr$PB_sUk`Nz5lyL|Ks9EXblk?Hhyn()bbGj~P_A>@=J{S1`H?&)s`mb(|9&@s5G%x9mabebSHGr>9j+JDK(??Q7b2``Ppa=Q>w2 z(6CFG^XqM&14ry=Ccqx2KXkls4tLdbb%V30rK^DF0;ZvlaCF;=eiYc;J+P_Na#R4IUJ-G&Cyw--yML47Qz5!!bfxGb(YG^n zjM^8GEn;iLsz^svv*;bsJDFmf5E&SGBcfYGk?@|Or9<`y=Lx3 zJpytD_76A*;_;EShONGBk@W}tmkQ?V@&?Hyoj_e}zHr?5AIg}u$(3&EXV99OicWHU zkVMP%k)Z0X;zu_qy?l+mlRY)*rdIIAdOvtZd3X9wfy}O=j-(FX9>nf2Ws!PHJ*5ou zZKS((gk9OyyUClIzU&jM&@t+ePG3im41=hNJ@Fk;5~xtsV1lEmS9jk9Rlkqf#{RA* z&fd=EZpK1Uuz!x_oB}tp>I!vUg3*0zdWG~c_A2&!_K)d;Q*p+)CHh*)uFuYv&hjA3 znmQjl!{Ko+>>T3|(=Vk>O&gmwJT0redHO=fGG`iH?-oo~mUa|!{shr~+qD&3hUDz$ zsO{(vB5TKo+Xe8Rikyj#@^ZPb)J=#pD(G3U z_lasRV%7;*WRu>Lp7~R-Gp)46>R4qFa{)U&$?p2h13d6}Jcg&M$L=2MY2t0~Jq9v4 zuP4a!$$f(vq^$gWleaPUA;ed~+u9TEUIzZ_itD&15Ijv`wVPJf$O=1$3*E{{%->Uf(iuB4(SqlGW1L6&(LgP|AyrVe-S=E zVobzpnEVQbZ;lufl|On#OyAfMu{~oe#a+tS2A!J)v7cf_#D0zo&U7rJIj&yJ=I9e39J_InfW0Rg{PJ_!;;SuNbm8fWvKNdNd9rwXiK!I zHF3R_+Ve_!QNczRy`yGBeQllZBt5aIU|0)+a_H{M+ zr#sWX!&#aoy^pOi2|@Ra5q-JWA=DdOLL+Qx`*1)-Vx#hNXYnN%%# zIum*~&<)F$c0Mh_9&LA~{Y=Yb7wq3t`=s1Wo|KZpJlsV4So?IeVibFk^tI`u966je z=OM=y#|=kr=WOQ$XHjRMGXwi~xvQAFuPfep&XJK5W4Lm88hZ}7tAoU!;2uh!*a8Nm zi>EzvC5ybJeYt(%zIb1nH;=C#y}#0GxH?R2gwE$&s(EF#5N*49hA!X-@`#R9LOSWM z>3KweMBHHvXMb9S&s5-TD6@``E;8$J4J6V+yvA=~o!A`w%@D9c!~V7N-?;ufPX^qXQEI;sPHBwhCGrBnQ6^z8i8Pv`Bcr z$UYhV7kwn!6`h;O$81c%zm6-D(agT}#ZAZJ{ScsZjN7W^5RK4hAk zX=tWunf1))GVjb(G2_SBdolT9qGQ^{Y>WwwJrNrcw=H&gO!4R~QRc|?;Stz` zw-sJ+@4gzVj9;j5R@L{Q`|(^E2U@|$lv`&yb?Z^7d_)J^qJ)EBTM52+GI*bf$~)gq z?-l%ABkv*Xcw_HRPg~CscS-j>*J4+!JHcc36r_i}&HK^w+Wp3L4+}irDZ1iZm(WQJ z#fs;5wR81z%8t+WruNRvD02R{Zl?A2c@h` zsh*l4ZD-ntv>f&__VaMw>`Psgx;OPhsx8fzx{Rs&0;$tducf|3sqRPGUb}yKwe*td zODS)DPCJ}dA?;=ArPM-ciD{MWrR+OUU+j=R*giH*N;{m|JT*G?C0b5dk}D^DO8lCb zo>(X;Fu8e3w$yB??v&iAl~UKH%um*mvL@G0R+1(r4NLkjX=zd!re)71%}(x@5|_Fp z^+)RJ)b%NOIoVQL75nh??Qm@0c29%-L7obs?zb zHmGV&w2ZbSSi9MF`AGq{0$v4}0(S+j33?M;GBiA_V_46ypr&WF#5*cnkgVm!)q zze4+lT@0@ku`WD3yiWL)@OlwTB8o+<2_GLmJv=PDQrMYLQ`n#|A*^g@z0eP#pF+!q zjtdb&#sv2bvIPn-8O*}!mGnF6x6d!yZ;h>y?E%kDw}<(cW~Xg+CbBsWI`=@X1h7iHOWQEn&KmY2)?&OX1DG1YvjMzKW9MRz+Zuf1M>tX1*9{9u{h8#s9Vt9pork|&na zt~v_@L5Nb-_lXIlII!PKeV0M&MAJ`wL=Pd#lZh_DY}XoBjQb_?fW6#1VRLANl4Nyf zjPo)WyX}t84h`kc>dp{nb!I%5r+0Pej;H9;4NbpjuWhej-)hg59-5wDubQ?dwRh^u z)L*Gp)25_#OH)!mGHdHgEu1<4&$1S8Q8Z%+#i-QtIB6St%z|qEbty{z~bS z;z?eR{5a`V;_SqnNr#i3CE1eyNuHAYI=N}emXsYSnNo7YyMHPvIyoZw82%?`(v!q4 zi3y3<6XzyvPI{Y|J+VyUgT&lPV$!k1afyxbL(4fM$w`Nkv%zcLAh}5LlH|L|zmrF$ z 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

public partial class OpenAIClient { - private readonly Uri _cachedEndpoint = null; private readonly ApiKeyCredential _cachedCredential = null; private readonly OpenAIClientOptions _cachedOptions = null; @@ -31,57 +31,14 @@ public partial class OpenAIClient /// This client does not provide any model functionality directly and is purely a helper to facilitate the creation /// of the scenario-specific subclients like . /// - /// An explicitly defined endpoint that all clients created by this should use. /// An explicitly defined credential that all clients created by this should use. /// A common client options definition that all clients created by this should use. - public OpenAIClient(Uri endpoint, ApiKeyCredential credential, OpenAIClientOptions clientOptions = null) + public OpenAIClient(ApiKeyCredential credential = default, OpenAIClientOptions clientOptions = default) { - _cachedEndpoint = endpoint; _cachedCredential = credential; _cachedOptions = clientOptions; } - /// - /// Creates a new instance of will store common client configuration details to permit - /// easy reuse and propagation to multiple, scenario-specific subclients. - /// - /// - /// This client does not provide any model functionality directly and is purely a helper to facilitate the creation - /// of the scenario-specific subclients like . - /// - /// An explicitly defined endpoint that all clients created by this should use. - /// A common client options definition that all clients created by this should use. - public OpenAIClient(Uri endpoint, OpenAIClientOptions clientOptions = null) - : this(endpoint, credential: null, clientOptions) - { } - - /// - /// Creates a new instance of will store common client configuration details to permit - /// easy reuse and propagation to multiple, scenario-specific subclients. - /// - /// - /// This client does not provide any model functionality directly and is purely a helper to facilitate the creation - /// of the scenario-specific subclients like . - /// - /// An explicitly defined credential that all clients created by this should use. - /// A common client options definition that all clients created by this should use. - public OpenAIClient(ApiKeyCredential credential, OpenAIClientOptions clientOptions = null) - : this(endpoint: null, credential, clientOptions) - { } - - /// - /// Creates a new instance of will store common client configuration details to permit - /// easy reuse and propagation to multiple, scenario-specific subclients. - /// - /// - /// This client does not provide any model functionality directly and is purely a helper to facilitate the creation - /// of the scenario-specific subclients like . - /// - /// A common client options definition that all clients created by this should use. - public OpenAIClient(OpenAIClientOptions clientOptions) - : this(endpoint: null, credential: null, clientOptions) - { } - /// /// Gets a new instance of that reuses the client configuration details provided to /// the instance. @@ -91,8 +48,7 @@ public OpenAIClient(OpenAIClientOptions clientOptions) /// the same configuration details. /// /// A new . - public AssistantClient GetAssistantClient() - => new(_cachedEndpoint, _cachedCredential, _cachedOptions); + public AssistantClient GetAssistantClient() => new(_cachedCredential, _cachedOptions); /// /// Gets a new instance of that reuses the client configuration details provided to @@ -103,8 +59,7 @@ public AssistantClient GetAssistantClient() /// the same configuration details. /// /// A new . - public AudioClient GetAudioClient(string model) - => new(_cachedEndpoint, model, _cachedCredential, _cachedOptions); + public AudioClient GetAudioClient(string model) => new(model, _cachedCredential, _cachedOptions); /// /// Gets a new instance of that reuses the client configuration details provided to @@ -115,8 +70,7 @@ public AudioClient GetAudioClient(string model) /// the same configuration details. /// /// A new . - public ChatClient GetChatClient(string model) - => new(_cachedEndpoint, model, _cachedCredential, _cachedOptions); + public ChatClient GetChatClient(string model) => new(model, _cachedCredential, _cachedOptions); /// /// Gets a new instance of that reuses the client configuration details provided to @@ -127,8 +81,7 @@ public ChatClient GetChatClient(string model) /// the same configuration details. /// /// A new . - public EmbeddingClient GetEmbeddingClient(string model) - => new(_cachedEndpoint, model, _cachedCredential, _cachedOptions); + public EmbeddingClient GetEmbeddingClient(string model) => new(model, _cachedCredential, _cachedOptions); /// /// Gets a new instance of that reuses the client configuration details provided to @@ -139,8 +92,7 @@ public EmbeddingClient GetEmbeddingClient(string model) /// the same configuration details. /// /// A new . - public FileClient GetFileClient() - => new(_cachedEndpoint, _cachedCredential, _cachedOptions); + public FileClient GetFileClient() => new(_cachedCredential, _cachedOptions); /// /// Gets a new instance of that reuses the client configuration details provided to @@ -151,8 +103,7 @@ public FileClient GetFileClient() /// the same configuration details. /// /// A new . - public FineTuningManagementClient GetFineTuningManagementClient() - => new(_cachedEndpoint, _cachedCredential, _cachedOptions); + public FineTuningManagementClient GetFineTuningManagementClient() => new(_cachedCredential, _cachedOptions); /// /// Gets a new instance of that reuses the client configuration details provided to @@ -163,8 +114,7 @@ public FineTuningManagementClient GetFineTuningManagementClient() /// the same configuration details. /// /// A new . - public ImageClient GetImageClient(string model) - => new(_cachedEndpoint, model, _cachedCredential, _cachedOptions); + public ImageClient GetImageClient(string model) => new(model, _cachedCredential, _cachedOptions); /// /// Gets a new instance of that reuses the client configuration details provided to @@ -175,8 +125,7 @@ public ImageClient GetImageClient(string model) /// the same configuration details. /// /// A new . - public LegacyCompletionClient GetLegacyCompletionClient() - => new(_cachedEndpoint, _cachedCredential, _cachedOptions); + public LegacyCompletionClient GetLegacyCompletionClient() => new(_cachedCredential, _cachedOptions); /// /// Gets a new instance of that reuses the client configuration details provided to @@ -187,8 +136,7 @@ public LegacyCompletionClient GetLegacyCompletionClient() /// the same configuration details. /// /// A new . - public ModelManagementClient GetModelManagementClient() - => new(_cachedEndpoint, _cachedCredential, _cachedOptions); + public ModelManagementClient GetModelManagementClient() => new(_cachedCredential, _cachedOptions); /// /// Gets a new instance of that reuses the client configuration details provided to @@ -199,6 +147,5 @@ public ModelManagementClient GetModelManagementClient() /// the same configuration details. /// /// A new . - public ModerationClient GetModerationClient() - => new(_cachedEndpoint, _cachedCredential, _cachedOptions); + public ModerationClient GetModerationClient() => new(_cachedCredential, _cachedOptions); } diff --git a/.dotnet/src/Custom/OpenAIClientConnector.cs b/.dotnet/src/Custom/OpenAIClientConnector.cs index 348d5f48b..8ee47b1ee 100644 --- a/.dotnet/src/Custom/OpenAIClientConnector.cs +++ b/.dotnet/src/Custom/OpenAIClientConnector.cs @@ -19,13 +19,12 @@ internal partial class OpenAIClientConnector internal OpenAIClientConnector( string model, - Uri endpoint = null, ApiKeyCredential credential = null, OpenAIClientOptions options = null) { if (model is null) throw new ArgumentNullException(nameof(model)); Model = model; - Endpoint ??= new(Environment.GetEnvironmentVariable(s_OpenAIEndpointEnvironmentVariable) ?? s_defaultOpenAIV1Endpoint); + Endpoint ??= options?.Endpoint ?? new(Environment.GetEnvironmentVariable(s_OpenAIEndpointEnvironmentVariable) ?? s_defaultOpenAIV1Endpoint); credential ??= new(Environment.GetEnvironmentVariable(s_OpenAIApiKeyEnvironmentVariable) ?? string.Empty); options ??= new(); InternalClient = new(Endpoint, credential, options.InternalOptions); diff --git a/.dotnet/src/Custom/OpenAIClientOptions.cs b/.dotnet/src/Custom/OpenAIClientOptions.cs index 69eb0b2d6..8234691b5 100644 --- a/.dotnet/src/Custom/OpenAIClientOptions.cs +++ b/.dotnet/src/Custom/OpenAIClientOptions.cs @@ -1,3 +1,4 @@ +using System; using System.ClientModel; using System.ClientModel; using System.ClientModel.Primitives; @@ -10,6 +11,11 @@ namespace OpenAI; /// public partial class OpenAIClientOptions : RequestOptions { + /// + /// Gets or sets a non-default base endpoint that clients should use when connecting. + /// + public Uri Endpoint { get; set; } + // Note: this type currently proxies RequestOptions properties manually via the matching internal type. This is a // temporary extra step pending richer integration with code generation. diff --git a/.dotnet/tests/Utility/TestHelpers.cs b/.dotnet/tests/Utility/TestHelpers.cs index a9ec4198b..1d7916977 100644 --- a/.dotnet/tests/Utility/TestHelpers.cs +++ b/.dotnet/tests/Utility/TestHelpers.cs @@ -36,12 +36,12 @@ public static T GetTestClient(TestScenario scenario, string overrideModel = n options.ErrorOptions = throwOnError ? ClientErrorBehaviors.Default : ClientErrorBehaviors.NoThrow; object clientObject = scenario switch { - TestScenario.Chat => new ChatClient(overrideModel ?? "gpt-3.5-turbo", options), - TestScenario.VisionChat => new ChatClient(overrideModel ?? "gpt-4-vision-preview", options), - TestScenario.Assistants => new AssistantClient(options), - TestScenario.Images => new ImageClient(overrideModel ?? "dall-e-3", options), - TestScenario.Files => new FileClient(options), - TestScenario.Transcription => new AudioClient(overrideModel ?? "whisper-1", options), + TestScenario.Chat => new ChatClient(overrideModel ?? "gpt-3.5-turbo", credential: null, options), + TestScenario.VisionChat => new ChatClient(overrideModel ?? "gpt-4-vision-preview", credential: null, options), + TestScenario.Assistants => new AssistantClient(credential: null, options), + TestScenario.Images => new ImageClient(overrideModel ?? "dall-e-3", credential: null, options), + TestScenario.Files => new FileClient(credential: null, options), + TestScenario.Transcription => new AudioClient(overrideModel ?? "whisper-1", credential: null, options), _ => throw new NotImplementedException(), }; return (T)clientObject; From cf3b7c06d75a3739a1a49df162eefd0423b1d099 Mon Sep 17 00:00:00 2001 From: Travis Wilson <35748617+trrwilson@users.noreply.github.com> Date: Wed, 20 Mar 2024 10:29:32 -0700 Subject: [PATCH 49/50] Polyfill the C#12 "ExperimentalAttribute" and use it for AssistantClient (#17) * polyfill ExperimentalAttribute and use it for AssistantClient * polyfill update from source, parallel #if directive * PR feedback --- .../src/Custom/Assistants/AssistantClient.cs | 2 + .dotnet/src/Custom/OpenAIClient.cs | 2 + ...tics.CodeAnalysis.ExperimentalAttribute.cs | 59 +++++++++++++++++++ .../Sample01_RetrievalAugmentedGeneration.cs | 2 + ...ple01_RetrievalAugmentedGenerationAsync.cs | 2 + .../Sample02_ListAssistantsWithPagination.cs | 2 + ...ple02_ListAssistantsWithPaginationAsync.cs | 2 + .../Assistants/Sample03_FunctionCalling.cs | 2 + .../Sample03_FunctionCallingAsync.cs | 2 + .dotnet/tests/Samples/ClientSamples.cs | 2 + .dotnet/tests/TestScenarios/AssistantTests.cs | 5 +- .dotnet/tests/Utility/TestHelpers.cs | 2 + 12 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 .dotnet/src/Polyfill/System.Diagnostics.CodeAnalysis.ExperimentalAttribute.cs diff --git a/.dotnet/src/Custom/Assistants/AssistantClient.cs b/.dotnet/src/Custom/Assistants/AssistantClient.cs index 9ef7fb422..7543c0330 100644 --- a/.dotnet/src/Custom/Assistants/AssistantClient.cs +++ b/.dotnet/src/Custom/Assistants/AssistantClient.cs @@ -2,6 +2,7 @@ using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; namespace OpenAI.Assistants; @@ -9,6 +10,7 @@ namespace OpenAI.Assistants; /// /// The service client for OpenAI assistants. /// +[Experimental("OPENAI001")] public partial class AssistantClient { private OpenAIClientConnector _clientConnector; diff --git a/.dotnet/src/Custom/OpenAIClient.cs b/.dotnet/src/Custom/OpenAIClient.cs index a245cfd06..929158d5f 100644 --- a/.dotnet/src/Custom/OpenAIClient.cs +++ b/.dotnet/src/Custom/OpenAIClient.cs @@ -11,6 +11,7 @@ using OpenAI.Moderations; using System; using System.ClientModel; +using System.Diagnostics.CodeAnalysis; namespace OpenAI; @@ -48,6 +49,7 @@ public OpenAIClient(ApiKeyCredential credential = default, OpenAIClientOptions c /// the same configuration details. /// /// A new . + [Experimental("OPENAI001")] public AssistantClient GetAssistantClient() => new(_cachedCredential, _cachedOptions); /// diff --git a/.dotnet/src/Polyfill/System.Diagnostics.CodeAnalysis.ExperimentalAttribute.cs b/.dotnet/src/Polyfill/System.Diagnostics.CodeAnalysis.ExperimentalAttribute.cs new file mode 100644 index 000000000..163d98482 --- /dev/null +++ b/.dotnet/src/Polyfill/System.Diagnostics.CodeAnalysis.ExperimentalAttribute.cs @@ -0,0 +1,59 @@ +#if !NET8_0_OR_GREATER + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Diagnostics.CodeAnalysis +{ + /// + /// Indicates that an API is experimental and it may change in the future. + /// + /// + /// This attribute allows call sites to be flagged with a diagnostic that indicates that an experimental + /// feature is used. Authors can use this attribute to ship preview features in their assemblies. + /// + [AttributeUsage(AttributeTargets.Assembly | + AttributeTargets.Module | + AttributeTargets.Class | + AttributeTargets.Struct | + AttributeTargets.Enum | + AttributeTargets.Constructor | + AttributeTargets.Method | + AttributeTargets.Property | + AttributeTargets.Field | + AttributeTargets.Event | + AttributeTargets.Interface | + AttributeTargets.Delegate, Inherited = false)] + internal sealed class ExperimentalAttribute : Attribute + { + /// + /// Initializes a new instance of the class, specifying the ID that the compiler will use + /// when reporting a use of the API the attribute applies to. + /// + /// The ID that the compiler will use when reporting a use of the API the attribute applies to. + public ExperimentalAttribute(string diagnosticId) + { + DiagnosticId = diagnosticId; + } + + /// + /// Gets the ID that the compiler will use when reporting a use of the API the attribute applies to. + /// + /// The unique diagnostic ID. + /// + /// The diagnostic ID is shown in build output for warnings and errors. + /// This property represents the unique ID that can be used to suppress the warnings or errors, if needed. + /// + public string DiagnosticId { get; } + + /// + /// Gets or sets the URL for corresponding documentation. + /// The API accepts a format string instead of an actual URL, creating a generic URL that includes the diagnostic ID. + /// + /// The format string that represents a URL to corresponding documentation. + /// An example format string is https://contoso.com/obsoletion-warnings/{0}. + public string? UrlFormat { get; set; } + } +} + +#endif // !NET8_0_OR_LATER \ No newline at end of file diff --git a/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGeneration.cs b/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGeneration.cs index cc8431f19..0f7856c2f 100644 --- a/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGeneration.cs +++ b/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGeneration.cs @@ -13,6 +13,8 @@ public partial class AssistantSamples [Ignore("Compilation validation only")] public void Sample01_RetrievalAugmentedGeneration() { + // Assistants is a beta API and subject to change; acknowledge its experimental status by suppressing the matching warning. +#pragma warning disable OPENAI001 OpenAIClient openAIClient = new(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); FileClient fileClient = openAIClient.GetFileClient(); AssistantClient assistantClient = openAIClient.GetAssistantClient(); diff --git a/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGenerationAsync.cs b/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGenerationAsync.cs index 4b706a8eb..7737114fe 100644 --- a/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGenerationAsync.cs +++ b/.dotnet/tests/Samples/Assistants/Sample01_RetrievalAugmentedGenerationAsync.cs @@ -13,6 +13,8 @@ public partial class AssistantSamples [Ignore("Compilation validation only")] public async Task Sample01_RetrievalAugmentedGenerationAsync() { + // Assistants is a beta API and subject to change; acknowledge its experimental status by suppressing the matching warning. +#pragma warning disable OPENAI001 OpenAIClient openAIClient = new(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); FileClient fileClient = openAIClient.GetFileClient(); AssistantClient assistantClient = openAIClient.GetAssistantClient(); diff --git a/.dotnet/tests/Samples/Assistants/Sample02_ListAssistantsWithPagination.cs b/.dotnet/tests/Samples/Assistants/Sample02_ListAssistantsWithPagination.cs index 59f171d66..4966ce1f8 100644 --- a/.dotnet/tests/Samples/Assistants/Sample02_ListAssistantsWithPagination.cs +++ b/.dotnet/tests/Samples/Assistants/Sample02_ListAssistantsWithPagination.cs @@ -10,6 +10,8 @@ public partial class AssistantSamples [Ignore("Compilation validation only")] public void Sample02_ListAssistantsWithPagination() { + // Assistants is a beta API and subject to change; acknowledge its experimental status by suppressing the matching warning. +#pragma warning disable OPENAI001 AssistantClient client = new(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); string latestId = null; diff --git a/.dotnet/tests/Samples/Assistants/Sample02_ListAssistantsWithPaginationAsync.cs b/.dotnet/tests/Samples/Assistants/Sample02_ListAssistantsWithPaginationAsync.cs index 2e4f6db86..e834e5aa1 100644 --- a/.dotnet/tests/Samples/Assistants/Sample02_ListAssistantsWithPaginationAsync.cs +++ b/.dotnet/tests/Samples/Assistants/Sample02_ListAssistantsWithPaginationAsync.cs @@ -11,6 +11,8 @@ public partial class AssistantSamples [Ignore("Compilation validation only")] public async Task Sample02_ListAssistantsWithPaginationAsync() { + // Assistants is a beta API and subject to change; acknowledge its experimental status by suppressing the matching warning. +#pragma warning disable OPENAI001 AssistantClient client = new(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); string latestId = null; diff --git a/.dotnet/tests/Samples/Assistants/Sample03_FunctionCalling.cs b/.dotnet/tests/Samples/Assistants/Sample03_FunctionCalling.cs index e989b95b2..7e5bca6a2 100644 --- a/.dotnet/tests/Samples/Assistants/Sample03_FunctionCalling.cs +++ b/.dotnet/tests/Samples/Assistants/Sample03_FunctionCalling.cs @@ -60,6 +60,8 @@ private static string GetCurrentWeather(string location, string unit = "celsius" [Ignore("Compilation validation only")] public void Sample03_FunctionCalling() { + // Assistants is a beta API and subject to change; acknowledge its experimental status by suppressing the matching warning. +#pragma warning disable OPENAI001 AssistantClient client = new(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); #region diff --git a/.dotnet/tests/Samples/Assistants/Sample03_FunctionCallingAsync.cs b/.dotnet/tests/Samples/Assistants/Sample03_FunctionCallingAsync.cs index 44fc106b2..9333f51d0 100644 --- a/.dotnet/tests/Samples/Assistants/Sample03_FunctionCallingAsync.cs +++ b/.dotnet/tests/Samples/Assistants/Sample03_FunctionCallingAsync.cs @@ -14,6 +14,8 @@ public partial class AssistantSamples [Ignore("Compilation validation only")] public async Task Sample03_FunctionCallingAsync() { + // Assistants is a beta API and subject to change; acknowledge its experimental status by suppressing the matching warning. +#pragma warning disable OPENAI001 AssistantClient client = new(Environment.GetEnvironmentVariable("OpenAIClient_KEY")); #region diff --git a/.dotnet/tests/Samples/ClientSamples.cs b/.dotnet/tests/Samples/ClientSamples.cs index 21000a32b..fdbc3fd40 100644 --- a/.dotnet/tests/Samples/ClientSamples.cs +++ b/.dotnet/tests/Samples/ClientSamples.cs @@ -17,7 +17,9 @@ public void CreateAssistantAndFileClients() { OpenAIClient openAIClient = new(""); FileClient fileClient = openAIClient.GetFileClient(); +#pragma warning disable OPENAI001 AssistantClient assistantClient = openAIClient.GetAssistantClient(); +#pragma warning restore OPENAI001 } [Test] diff --git a/.dotnet/tests/TestScenarios/AssistantTests.cs b/.dotnet/tests/TestScenarios/AssistantTests.cs index aea1c3614..ecb3b1163 100644 --- a/.dotnet/tests/TestScenarios/AssistantTests.cs +++ b/.dotnet/tests/TestScenarios/AssistantTests.cs @@ -7,6 +7,7 @@ namespace OpenAI.Tests.Assistants; +#pragma warning disable OPENAI001 public partial class AssistantTests { [Test] @@ -143,7 +144,7 @@ private async Task CreateCommonTestAssistantAsync() private async Task DeleteRecentTestThings() { - AssistantClient client = new(); + AssistantClient client = GetTestClient(); foreach(Assistant assistant in client.GetAssistants().Value) { if (assistant.Name == s_testAssistantName @@ -159,3 +160,5 @@ private async Task DeleteRecentTestThings() private static readonly string s_testAssistantName = $".NET SDK Test Assistant - Please Delete Me"; private static readonly string s_cleanupMetadataKey = $"test_metadata_cleanup_eligible"; } + +#pragma warning restore OPENAI001 diff --git a/.dotnet/tests/Utility/TestHelpers.cs b/.dotnet/tests/Utility/TestHelpers.cs index 1d7916977..bfc847e42 100644 --- a/.dotnet/tests/Utility/TestHelpers.cs +++ b/.dotnet/tests/Utility/TestHelpers.cs @@ -38,7 +38,9 @@ public static T GetTestClient(TestScenario scenario, string overrideModel = n { TestScenario.Chat => new ChatClient(overrideModel ?? "gpt-3.5-turbo", credential: null, options), TestScenario.VisionChat => new ChatClient(overrideModel ?? "gpt-4-vision-preview", credential: null, options), +#pragma warning disable OPENAI001 TestScenario.Assistants => new AssistantClient(credential: null, options), +#pragma warning restore OPENAI001 TestScenario.Images => new ImageClient(overrideModel ?? "dall-e-3", credential: null, options), TestScenario.Files => new FileClient(credential: null, options), TestScenario.Transcription => new AudioClient(overrideModel ?? "whisper-1", credential: null, options), From e1d8bfaba38122edfdec529cba9b33b4d7f56411 Mon Sep 17 00:00:00 2001 From: Anne Thompson Date: Thu, 21 Mar 2024 08:56:23 -0700 Subject: [PATCH 50/50] Initial implementation --- .dotnet/OpenAI.sln | 34 ++----- .dotnet/src/Custom/Chat/ChatClient.cs | 15 ++- .dotnet/src/OpenAI.csproj | 5 +- .dotnet/src/Utility/StreamingResult.cs | 96 +++++-------------- .dotnet/tests/OpenAI.Tests.csproj | 2 +- .../Chat/Sample02_StreamingChatAsync.cs | 1 + 6 files changed, 44 insertions(+), 109 deletions(-) diff --git a/.dotnet/OpenAI.sln b/.dotnet/OpenAI.sln index 5d1edd8c3..c3e866e93 100644 --- a/.dotnet/OpenAI.sln +++ b/.dotnet/OpenAI.sln @@ -1,10 +1,12 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29709.97 +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34701.34 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenAI", "src\OpenAI.csproj", "{28FF4005-4467-4E36-92E7-DEA27DEB1519}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenAI", "src\OpenAI.csproj", "{28FF4005-4467-4E36-92E7-DEA27DEB1519}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenAI.Tests", "tests\OpenAI.Tests.csproj", "{1F1CD1D4-9932-4B73-99D8-C252A67D4B46}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenAI.Tests", "tests\OpenAI.Tests.csproj", "{1F1CD1D4-9932-4B73-99D8-C252A67D4B46}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.ClientModel", "..\..\azure-sdk-for-net\sdk\core\System.ClientModel\src\System.ClientModel.csproj", "{297DA5FF-1CD7-4183-8C13-45987286D33F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -12,26 +14,6 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {B0C276D1-2930-4887-B29A-D1A33E7009A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B0C276D1-2930-4887-B29A-D1A33E7009A2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B0C276D1-2930-4887-B29A-D1A33E7009A2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B0C276D1-2930-4887-B29A-D1A33E7009A2}.Release|Any CPU.Build.0 = Release|Any CPU - {8E9A77AC-792A-4432-8320-ACFD46730401}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8E9A77AC-792A-4432-8320-ACFD46730401}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8E9A77AC-792A-4432-8320-ACFD46730401}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8E9A77AC-792A-4432-8320-ACFD46730401}.Release|Any CPU.Build.0 = Release|Any CPU - {A4241C1F-A53D-474C-9E4E-075054407E74}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A4241C1F-A53D-474C-9E4E-075054407E74}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A4241C1F-A53D-474C-9E4E-075054407E74}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A4241C1F-A53D-474C-9E4E-075054407E74}.Release|Any CPU.Build.0 = Release|Any CPU - {FA8BD3F1-8616-47B6-974C-7576CDF4717E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FA8BD3F1-8616-47B6-974C-7576CDF4717E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FA8BD3F1-8616-47B6-974C-7576CDF4717E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FA8BD3F1-8616-47B6-974C-7576CDF4717E}.Release|Any CPU.Build.0 = Release|Any CPU - {85677AD3-C214-42FA-AE6E-49B956CAC8DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {85677AD3-C214-42FA-AE6E-49B956CAC8DC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {85677AD3-C214-42FA-AE6E-49B956CAC8DC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {85677AD3-C214-42FA-AE6E-49B956CAC8DC}.Release|Any CPU.Build.0 = Release|Any CPU {28FF4005-4467-4E36-92E7-DEA27DEB1519}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {28FF4005-4467-4E36-92E7-DEA27DEB1519}.Debug|Any CPU.Build.0 = Debug|Any CPU {28FF4005-4467-4E36-92E7-DEA27DEB1519}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -40,6 +22,10 @@ Global {1F1CD1D4-9932-4B73-99D8-C252A67D4B46}.Debug|Any CPU.Build.0 = Debug|Any CPU {1F1CD1D4-9932-4B73-99D8-C252A67D4B46}.Release|Any CPU.ActiveCfg = Release|Any CPU {1F1CD1D4-9932-4B73-99D8-C252A67D4B46}.Release|Any CPU.Build.0 = Release|Any CPU + {297DA5FF-1CD7-4183-8C13-45987286D33F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {297DA5FF-1CD7-4183-8C13-45987286D33F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {297DA5FF-1CD7-4183-8C13-45987286D33F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {297DA5FF-1CD7-4183-8C13-45987286D33F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/.dotnet/src/Custom/Chat/ChatClient.cs b/.dotnet/src/Custom/Chat/ChatClient.cs index 16a875c5a..f867f1b02 100644 --- a/.dotnet/src/Custom/Chat/ChatClient.cs +++ b/.dotnet/src/Custom/Chat/ChatClient.cs @@ -208,11 +208,10 @@ public virtual StreamingClientResult CompleteChatStreaming( throw new ClientResultException(response); } - ClientResult genericResult = ClientResult.FromResponse(response); - return StreamingClientResult.CreateFromResponse( - genericResult, + return StreamingEventResult.CreateFromResponse( + response, (responseForEnumeration) => SseAsyncEnumerator.EnumerateFromSseStream( - responseForEnumeration.GetRawResponse().ContentStream, + responseForEnumeration.ContentStream, e => StreamingChatUpdate.DeserializeStreamingChatUpdates(e))); } @@ -229,7 +228,6 @@ public virtual StreamingClientResult CompleteChatStreaming( /// The number of independent, alternative choices that the chat completion request should generate. /// /// Additional options for the chat completion request. - /// The cancellation token for the operation. /// A streaming result with incremental chat completion updates. public virtual async Task> CompleteChatStreamingAsync( IEnumerable messages, @@ -246,11 +244,10 @@ public virtual async Task> CompleteCh throw new ClientResultException(response); } - ClientResult genericResult = ClientResult.FromResponse(response); - return StreamingClientResult.CreateFromResponse( - genericResult, + return StreamingEventResult.CreateFromResponse( + response, (responseForEnumeration) => SseAsyncEnumerator.EnumerateFromSseStream( - responseForEnumeration.GetRawResponse().ContentStream, + responseForEnumeration.ContentStream, e => StreamingChatUpdate.DeserializeStreamingChatUpdates(e))); } diff --git a/.dotnet/src/OpenAI.csproj b/.dotnet/src/OpenAI.csproj index cd5fa6d55..6d4778553 100644 --- a/.dotnet/src/OpenAI.csproj +++ b/.dotnet/src/OpenAI.csproj @@ -9,7 +9,10 @@ - + + + + diff --git a/.dotnet/src/Utility/StreamingResult.cs b/.dotnet/src/Utility/StreamingResult.cs index a1b6ff538..b3f676732 100644 --- a/.dotnet/src/Utility/StreamingResult.cs +++ b/.dotnet/src/Utility/StreamingResult.cs @@ -1,95 +1,43 @@ -using System.ClientModel; +using System; using System.ClientModel; using System.ClientModel.Primitives; -using System.Threading; using System.Collections.Generic; -using System; +using System.Threading; namespace OpenAI; + +#pragma warning disable CS1591 // public XML comments + /// /// Represents an operation response with streaming content that can be deserialized and enumerated while the response /// is still being received. /// /// The data type representative of distinct, streamable items. -public class StreamingClientResult - : IDisposable - , IAsyncEnumerable +public class StreamingEventResult : StreamingClientResult { - private ClientResult _rawResult { get; } private IAsyncEnumerable _asyncEnumerableSource { get; } - private bool _disposedValue { get; set; } - - private StreamingClientResult() { } - - private StreamingClientResult( - ClientResult rawResult, - Func> asyncEnumerableProcessor) + + private StreamingEventResult(PipelineResponse response, + Func> asyncEnumerableProcessor) + : base(response) { - _rawResult = rawResult; - _asyncEnumerableSource = asyncEnumerableProcessor.Invoke(rawResult); + _asyncEnumerableSource = asyncEnumerableProcessor.Invoke(response); } - /// - /// Creates a new instance of using the provided underlying HTTP response. The - /// provided function will be used to resolve the response into an asynchronous enumeration of streamed response - /// items. - /// - /// The HTTP response. - /// - /// The function that will resolve the provided response into an IAsyncEnumerable. - /// - /// - /// A new instance of that will be capable of asynchronous enumeration of - /// items from the HTTP response. - /// - internal static StreamingClientResult CreateFromResponse( - ClientResult result, - Func> asyncEnumerableProcessor) + internal static StreamingEventResult CreateFromResponse( + PipelineResponse response, + Func> asyncEnumerableProcessor) { - return new(result, asyncEnumerableProcessor); + return new(response, asyncEnumerableProcessor); } - /// - /// Gets the underlying instance that this may enumerate - /// over. - /// - /// The instance attached to this . - public PipelineResponse GetRawResponse() => _rawResult.GetRawResponse(); + // TODO: Handle disposal via Enumerator? Validate that this will work. + // If it doesn't, we likely need to implement IDisposable or IAsyncDisposable + // on StreamingClientResult. - /// - /// Gets the asynchronously enumerable collection of distinct, streamable items in the response. - /// - /// - /// The return value of this method may be used with the "await foreach" statement. - /// - /// As explicitly implements , callers may - /// enumerate a instance directly instead of calling this method. - /// - /// - /// - public IAsyncEnumerable EnumerateValues() => this; - - /// - public void Dispose() - { - Dispose(disposing: true); - GC.SuppressFinalize(this); - } - - /// - protected virtual void Dispose(bool disposing) - { - if (!_disposedValue) - { - if (disposing) - { - _rawResult?.GetRawResponse()?.Dispose(); - } - _disposedValue = true; - } - } - - IAsyncEnumerator IAsyncEnumerable.GetAsyncEnumerator(CancellationToken cancellationToken) + public override IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) => _asyncEnumerableSource.GetAsyncEnumerator(cancellationToken); -} \ No newline at end of file +} + +#pragma warning restore CS1591 // public XML comments \ No newline at end of file diff --git a/.dotnet/tests/OpenAI.Tests.csproj b/.dotnet/tests/OpenAI.Tests.csproj index 59b95785f..252866ce8 100644 --- a/.dotnet/tests/OpenAI.Tests.csproj +++ b/.dotnet/tests/OpenAI.Tests.csproj @@ -6,6 +6,7 @@ latest + @@ -14,6 +15,5 @@ - \ No newline at end of file diff --git a/.dotnet/tests/Samples/Chat/Sample02_StreamingChatAsync.cs b/.dotnet/tests/Samples/Chat/Sample02_StreamingChatAsync.cs index 6ce1a96f0..14d7bfb02 100644 --- a/.dotnet/tests/Samples/Chat/Sample02_StreamingChatAsync.cs +++ b/.dotnet/tests/Samples/Chat/Sample02_StreamingChatAsync.cs @@ -1,6 +1,7 @@ using NUnit.Framework; using OpenAI.Chat; using System; +using System.ClientModel; using System.Threading.Tasks; namespace OpenAI.Samples