diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 059887474..091cfb127 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.9.1" + ".": "0.10.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index eb5d3722b..7fede91ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,34 @@ # Changelog +## 0.10.0 (2025-01-08) + +Full Changelog: [v0.9.1...v0.10.0](https://github.com/openai/openai-java/compare/v0.9.1...v0.10.0) + +### Features + +* **client:** add various convenience setters to models ([#91](https://github.com/openai/openai-java/issues/91)) ([9b3eb17](https://github.com/openai/openai-java/commit/9b3eb17270075587ac9c2701b0e41a7debf17bec)) +* **client:** allow passing null or optional for nullable fields ([#84](https://github.com/openai/openai-java/issues/84)) ([8a8f2f9](https://github.com/openai/openai-java/commit/8a8f2f9ac5f6555c372a81acc196b3ab04fd9555)) +* **client:** allow setting arbitrary JSON for top-level body params ([9b3eb17](https://github.com/openai/openai-java/commit/9b3eb17270075587ac9c2701b0e41a7debf17bec)) +* **client:** expose getters for `JsonField` of body params ([9b3eb17](https://github.com/openai/openai-java/commit/9b3eb17270075587ac9c2701b0e41a7debf17bec)) + + +### Bug Fixes + +* **client:** consistently throw on omitting required fields ([9b3eb17](https://github.com/openai/openai-java/commit/9b3eb17270075587ac9c2701b0e41a7debf17bec)) +* **client:** convert `JsonField` containing list type to mutable in builder ([9b3eb17](https://github.com/openai/openai-java/commit/9b3eb17270075587ac9c2701b0e41a7debf17bec)) + + +### Documentation + +* add params class javadocs ([#90](https://github.com/openai/openai-java/issues/90)) ([9a33c1c](https://github.com/openai/openai-java/commit/9a33c1cf22e30e1878d739acfab4258321c6a9f8)) + + +### Styles + +* **internal:** explicitly add some method return types ([9b3eb17](https://github.com/openai/openai-java/commit/9b3eb17270075587ac9c2701b0e41a7debf17bec)) +* **internal:** move headers and query params setters below others ([9b3eb17](https://github.com/openai/openai-java/commit/9b3eb17270075587ac9c2701b0e41a7debf17bec)) +* **internal:** simplify existing convenience setters on params ([9b3eb17](https://github.com/openai/openai-java/commit/9b3eb17270075587ac9c2701b0e41a7debf17bec)) + ## 0.9.1 (2025-01-06) Full Changelog: [v0.9.0...v0.9.1](https://github.com/openai/openai-java/compare/v0.9.0...v0.9.1) diff --git a/README.md b/README.md index a933422cd..20818e0aa 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ -[![Maven Central](https://img.shields.io/maven-central/v/com.openai/openai-java)](https://central.sonatype.com/artifact/com.openai/openai-java/0.9.1) +[![Maven Central](https://img.shields.io/maven-central/v/com.openai/openai-java)](https://central.sonatype.com/artifact/com.openai/openai-java/0.10.0) @@ -32,7 +32,7 @@ The REST API documentation can be foundĀ on [platform.openai.com](https://platfo ```kotlin -implementation("com.openai:openai-java:0.9.1") +implementation("com.openai:openai-java:0.10.0") ``` #### Maven @@ -41,7 +41,7 @@ implementation("com.openai:openai-java:0.9.1") com.openai openai-java - 0.9.1 + 0.10.0 ``` diff --git a/build.gradle.kts b/build.gradle.kts index cef5a8638..f901fcc35 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,7 +4,7 @@ plugins { allprojects { group = "com.openai" - version = "0.9.1" // x-release-please-version + version = "0.10.0" // x-release-please-version } diff --git a/openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OpenAIOkHttpClient.kt b/openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OpenAIOkHttpClient.kt index 0a01dc68e..025640fd1 100644 --- a/openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OpenAIOkHttpClient.kt +++ b/openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OpenAIOkHttpClient.kt @@ -13,6 +13,7 @@ import com.openai.credential.Credential import java.net.Proxy import java.time.Clock import java.time.Duration +import java.util.Optional class OpenAIOkHttpClient private constructor() { @@ -138,9 +139,13 @@ class OpenAIOkHttpClient private constructor() { clientOptions.azureServiceVersion(azureServiceVersion) } - fun organization(organization: String) = apply { clientOptions.organization(organization) } + fun organization(organization: String?) = apply { clientOptions.organization(organization) } - fun project(project: String) = apply { clientOptions.project(project) } + fun organization(organization: Optional) = organization(organization.orElse(null)) + + fun project(project: String?) = apply { clientOptions.project(project) } + + fun project(project: Optional) = project(project.orElse(null)) fun fromEnv() = apply { clientOptions.fromEnv() } diff --git a/openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OpenAIOkHttpClientAsync.kt b/openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OpenAIOkHttpClientAsync.kt index e88af6969..20753d76c 100644 --- a/openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OpenAIOkHttpClientAsync.kt +++ b/openai-java-client-okhttp/src/main/kotlin/com/openai/client/okhttp/OpenAIOkHttpClientAsync.kt @@ -13,6 +13,7 @@ import com.openai.credential.Credential import java.net.Proxy import java.time.Clock import java.time.Duration +import java.util.Optional class OpenAIOkHttpClientAsync private constructor() { @@ -138,9 +139,13 @@ class OpenAIOkHttpClientAsync private constructor() { clientOptions.azureServiceVersion(azureServiceVersion) } - fun organization(organization: String) = apply { clientOptions.organization(organization) } + fun organization(organization: String?) = apply { clientOptions.organization(organization) } - fun project(project: String) = apply { clientOptions.project(project) } + fun organization(organization: Optional) = organization(organization.orElse(null)) + + fun project(project: String?) = apply { clientOptions.project(project) } + + fun project(project: Optional) = project(project.orElse(null)) fun fromEnv() = apply { clientOptions.fromEnv() } diff --git a/openai-java-core/src/main/kotlin/com/openai/core/ClientOptions.kt b/openai-java-core/src/main/kotlin/com/openai/core/ClientOptions.kt index aa08c1c77..da2250553 100644 --- a/openai-java-core/src/main/kotlin/com/openai/core/ClientOptions.kt +++ b/openai-java-core/src/main/kotlin/com/openai/core/ClientOptions.kt @@ -14,6 +14,7 @@ import com.openai.core.http.RetryingHttpClient import com.openai.credential.BearerTokenCredential import com.openai.credential.Credential import java.time.Clock +import java.util.Optional import java.util.concurrent.Executor import java.util.concurrent.Executors import java.util.concurrent.ThreadFactory @@ -91,6 +92,30 @@ private constructor( fun baseUrl(baseUrl: String) = apply { this.baseUrl = baseUrl } + fun responseValidation(responseValidation: Boolean) = apply { + this.responseValidation = responseValidation + } + + fun maxRetries(maxRetries: Int) = apply { this.maxRetries = maxRetries } + + fun apiKey(apiKey: String) = apply { + this.credential = BearerTokenCredential.create(apiKey) + } + + fun credential(credential: Credential) = apply { this.credential = credential } + + fun azureServiceVersion(azureServiceVersion: AzureOpenAIServiceVersion) = apply { + this.azureServiceVersion = azureServiceVersion + } + + fun organization(organization: String?) = apply { this.organization = organization } + + fun organization(organization: Optional) = organization(organization.orElse(null)) + + fun project(project: String?) = apply { this.project = project } + + fun project(project: Optional) = project(project.orElse(null)) + fun headers(headers: Headers) = apply { this.headers.clear() putAllHeaders(headers) @@ -171,26 +196,6 @@ private constructor( fun removeAllQueryParams(keys: Set) = apply { queryParams.removeAll(keys) } - fun responseValidation(responseValidation: Boolean) = apply { - this.responseValidation = responseValidation - } - - fun maxRetries(maxRetries: Int) = apply { this.maxRetries = maxRetries } - - fun apiKey(apiKey: String) = apply { - this.credential = BearerTokenCredential.create(apiKey) - } - - fun credential(credential: Credential) = apply { this.credential = credential } - - fun azureServiceVersion(azureServiceVersion: AzureOpenAIServiceVersion) = apply { - this.azureServiceVersion = azureServiceVersion - } - - fun organization(organization: String) = apply { this.organization = organization } - - fun project(project: String) = apply { this.project = project } - fun fromEnv() = apply { val openAIKey = System.getenv("OPENAI_API_KEY") val openAIOrgId = System.getenv("OPENAI_ORG_ID") diff --git a/openai-java-core/src/main/kotlin/com/openai/models/Assistant.kt b/openai-java-core/src/main/kotlin/com/openai/models/Assistant.kt index ca2ff1431..4bd3cc004 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/Assistant.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/Assistant.kt @@ -71,6 +71,13 @@ private constructor( fun instructions(): Optional = Optional.ofNullable(instructions.getNullable("instructions")) + /** + * 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 maximum of 512 characters long. + */ + @JsonProperty("metadata") @ExcludeMissing fun _metadata(): JsonValue = metadata + /** * ID of the model to use. You can use the * [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all of @@ -139,25 +146,20 @@ private constructor( fun topP(): Optional = Optional.ofNullable(topP.getNullable("top_p")) /** The identifier, which can be referenced in API endpoints. */ - @JsonProperty("id") @ExcludeMissing fun _id() = id + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id /** The Unix timestamp (in seconds) for when the assistant was created. */ - @JsonProperty("created_at") @ExcludeMissing fun _createdAt() = createdAt + @JsonProperty("created_at") @ExcludeMissing fun _createdAt(): JsonField = createdAt /** The description of the assistant. The maximum length is 512 characters. */ - @JsonProperty("description") @ExcludeMissing fun _description() = description + @JsonProperty("description") @ExcludeMissing fun _description(): JsonField = description /** * The system instructions that the assistant uses. The maximum length is 256,000 characters. */ - @JsonProperty("instructions") @ExcludeMissing fun _instructions() = instructions - - /** - * 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 maximum of 512 characters long. - */ - @JsonProperty("metadata") @ExcludeMissing fun _metadata() = metadata + @JsonProperty("instructions") + @ExcludeMissing + fun _instructions(): JsonField = instructions /** * ID of the model to use. You can use the @@ -165,19 +167,19 @@ private constructor( * your available models, or see our [Model overview](https://platform.openai.com/docs/models) * for descriptions of them. */ - @JsonProperty("model") @ExcludeMissing fun _model() = model + @JsonProperty("model") @ExcludeMissing fun _model(): JsonField = model /** The name of the assistant. The maximum length is 256 characters. */ - @JsonProperty("name") @ExcludeMissing fun _name() = name + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name /** The object type, which is always `assistant`. */ - @JsonProperty("object") @ExcludeMissing fun _object_() = object_ + @JsonProperty("object") @ExcludeMissing fun _object_(): JsonField = object_ /** * 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`, `file_search`, or `function`. */ - @JsonProperty("tools") @ExcludeMissing fun _tools() = tools + @JsonProperty("tools") @ExcludeMissing fun _tools(): JsonField> = tools /** * Specifies the format that the model must output. Compatible with @@ -199,20 +201,24 @@ private constructor( * partially cut off if `finish_reason="length"`, which indicates the generation exceeded * `max_tokens` or the conversation exceeded the max context length. */ - @JsonProperty("response_format") @ExcludeMissing fun _responseFormat() = responseFormat + @JsonProperty("response_format") + @ExcludeMissing + fun _responseFormat(): JsonField = responseFormat /** * 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. */ - @JsonProperty("temperature") @ExcludeMissing fun _temperature() = temperature + @JsonProperty("temperature") @ExcludeMissing fun _temperature(): JsonField = temperature /** * A set of resources that are used by the assistant's tools. The resources are specific to the * type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the * `file_search` tool requires a list of vector store IDs. */ - @JsonProperty("tool_resources") @ExcludeMissing fun _toolResources() = toolResources + @JsonProperty("tool_resources") + @ExcludeMissing + fun _toolResources(): JsonField = toolResources /** * An alternative to sampling with temperature, called nucleus sampling, where the model @@ -221,7 +227,7 @@ private constructor( * * We generally recommend altering this or temperature but not both. */ - @JsonProperty("top_p") @ExcludeMissing fun _topP() = topP + @JsonProperty("top_p") @ExcludeMissing fun _topP(): JsonField = topP @JsonAnyGetter @ExcludeMissing @@ -256,15 +262,15 @@ private constructor( class Builder { - private var id: JsonField = JsonMissing.of() - private var createdAt: JsonField = JsonMissing.of() - private var description: JsonField = JsonMissing.of() - private var instructions: JsonField = JsonMissing.of() - private var metadata: JsonValue = JsonMissing.of() - private var model: JsonField = JsonMissing.of() - private var name: JsonField = JsonMissing.of() - private var object_: JsonField = JsonMissing.of() - private var tools: JsonField> = JsonMissing.of() + private var id: JsonField? = null + private var createdAt: JsonField? = null + private var description: JsonField? = null + private var instructions: JsonField? = null + private var metadata: JsonValue? = null + private var model: JsonField? = null + private var name: JsonField? = null + private var object_: JsonField? = null + private var tools: JsonField>? = null private var responseFormat: JsonField = JsonMissing.of() private var temperature: JsonField = JsonMissing.of() private var toolResources: JsonField = JsonMissing.of() @@ -281,7 +287,7 @@ private constructor( model = assistant.model name = assistant.name object_ = assistant.object_ - tools = assistant.tools + tools = assistant.tools.map { it.toMutableList() } responseFormat = assistant.responseFormat temperature = assistant.temperature toolResources = assistant.toolResources @@ -302,7 +308,10 @@ private constructor( fun createdAt(createdAt: JsonField) = apply { this.createdAt = createdAt } /** The description of the assistant. The maximum length is 512 characters. */ - fun description(description: String) = description(JsonField.of(description)) + fun description(description: String?) = description(JsonField.ofNullable(description)) + + /** The description of the assistant. The maximum length is 512 characters. */ + fun description(description: Optional) = description(description.orElse(null)) /** The description of the assistant. The maximum length is 512 characters. */ fun description(description: JsonField) = apply { this.description = description } @@ -311,7 +320,13 @@ private constructor( * The system instructions that the assistant uses. The maximum length is 256,000 * characters. */ - fun instructions(instructions: String) = instructions(JsonField.of(instructions)) + fun instructions(instructions: String?) = instructions(JsonField.ofNullable(instructions)) + + /** + * The system instructions that the assistant uses. The maximum length is 256,000 + * characters. + */ + fun instructions(instructions: Optional) = instructions(instructions.orElse(null)) /** * The system instructions that the assistant uses. The maximum length is 256,000 @@ -345,7 +360,10 @@ private constructor( fun model(model: JsonField) = apply { this.model = model } /** The name of the assistant. The maximum length is 256 characters. */ - fun name(name: String) = name(JsonField.of(name)) + fun name(name: String?) = name(JsonField.ofNullable(name)) + + /** The name of the assistant. The maximum length is 256 characters. */ + fun name(name: Optional) = name(name.orElse(null)) /** The name of the assistant. The maximum length is 256 characters. */ fun name(name: JsonField) = apply { this.name = name } @@ -366,7 +384,49 @@ private constructor( * 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`, `file_search`, or `function`. */ - fun tools(tools: JsonField>) = apply { this.tools = tools } + fun tools(tools: JsonField>) = apply { + this.tools = tools.map { it.toMutableList() } + } + + /** + * 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`, `file_search`, or `function`. + */ + fun addTool(tool: AssistantTool) = apply { + tools = + (tools ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(tool) + } + } + + /** + * Specifies the format that the model must output. Compatible with + * [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 + * Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 + * Turbo models since `gpt-3.5-turbo-1106`. + * + * Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs + * which ensures the model will match your supplied JSON schema. Learn more in the + * [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). + * + * Setting to `{ "type": "json_object" }` enables JSON mode, which ensures 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. + */ + fun responseFormat(responseFormat: AssistantResponseFormatOption?) = + responseFormat(JsonField.ofNullable(responseFormat)) /** * Specifies the format that the model must output. Compatible with @@ -388,8 +448,8 @@ private constructor( * partially cut off if `finish_reason="length"`, which indicates the generation exceeded * `max_tokens` or the conversation exceeded the max context length. */ - fun responseFormat(responseFormat: AssistantResponseFormatOption) = - responseFormat(JsonField.of(responseFormat)) + fun responseFormat(responseFormat: Optional) = + responseFormat(responseFormat.orElse(null)) /** * Specifies the format that the model must output. Compatible with @@ -415,12 +475,45 @@ private constructor( this.responseFormat = responseFormat } + /** `auto` is the default value */ + fun responseFormat(behavior: AssistantResponseFormatOption.Behavior) = + responseFormat(AssistantResponseFormatOption.ofBehavior(behavior)) + + fun responseFormat(responseFormatText: ResponseFormatText) = + responseFormat(AssistantResponseFormatOption.ofResponseFormatText(responseFormatText)) + + fun responseFormat(responseFormatJsonObject: ResponseFormatJsonObject) = + responseFormat( + AssistantResponseFormatOption.ofResponseFormatJsonObject(responseFormatJsonObject) + ) + + fun responseFormat(responseFormatJsonSchema: ResponseFormatJsonSchema) = + responseFormat( + AssistantResponseFormatOption.ofResponseFormatJsonSchema(responseFormatJsonSchema) + ) + + /** + * 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. + */ + fun temperature(temperature: Double?) = temperature(JsonField.ofNullable(temperature)) + /** * 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. */ - fun temperature(temperature: Double) = temperature(JsonField.of(temperature)) + fun temperature(temperature: Double) = temperature(temperature as Double?) + + /** + * 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. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun temperature(temperature: Optional) = + temperature(temperature.orElse(null) as Double?) /** * What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the @@ -434,7 +527,16 @@ private constructor( * the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, * while the `file_search` tool requires a list of vector store IDs. */ - fun toolResources(toolResources: ToolResources) = toolResources(JsonField.of(toolResources)) + fun toolResources(toolResources: ToolResources?) = + toolResources(JsonField.ofNullable(toolResources)) + + /** + * A set of resources that are used by the assistant's tools. The resources are specific to + * the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, + * while the `file_search` tool requires a list of vector store IDs. + */ + fun toolResources(toolResources: Optional) = + toolResources(toolResources.orElse(null)) /** * A set of resources that are used by the assistant's tools. The resources are specific to @@ -452,7 +554,26 @@ private constructor( * * We generally recommend altering this or temperature but not both. */ - fun topP(topP: Double) = topP(JsonField.of(topP)) + fun topP(topP: Double?) = topP(JsonField.ofNullable(topP)) + + /** + * 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. + */ + fun topP(topP: Double) = topP(topP as Double?) + + /** + * 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. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun topP(topP: Optional) = topP(topP.orElse(null) as Double?) /** * An alternative to sampling with temperature, called nucleus sampling, where the model @@ -484,15 +605,16 @@ private constructor( fun build(): Assistant = Assistant( - id, - createdAt, - description, - instructions, - metadata, - model, - name, - object_, - tools.map { it.toImmutable() }, + checkNotNull(id) { "`id` is required but was not set" }, + checkNotNull(createdAt) { "`createdAt` is required but was not set" }, + checkNotNull(description) { "`description` is required but was not set" }, + checkNotNull(instructions) { "`instructions` is required but was not set" }, + checkNotNull(metadata) { "`metadata` is required but was not set" }, + checkNotNull(model) { "`model` is required but was not set" }, + checkNotNull(name) { "`name` is required but was not set" }, + checkNotNull(object_) { "`object_` is required but was not set" }, + checkNotNull(tools) { "`tools` is required but was not set" } + .map { it.toImmutable() }, responseFormat, temperature, toolResources, @@ -577,9 +699,13 @@ private constructor( fun fileSearch(): Optional = Optional.ofNullable(fileSearch.getNullable("file_search")) - @JsonProperty("code_interpreter") @ExcludeMissing fun _codeInterpreter() = codeInterpreter + @JsonProperty("code_interpreter") + @ExcludeMissing + fun _codeInterpreter(): JsonField = codeInterpreter - @JsonProperty("file_search") @ExcludeMissing fun _fileSearch() = fileSearch + @JsonProperty("file_search") + @ExcludeMissing + fun _fileSearch(): JsonField = fileSearch @JsonAnyGetter @ExcludeMissing @@ -679,7 +805,9 @@ private constructor( * available to the `code_interpreter`` tool. There can be a maximum of 20 files * associated with the tool. */ - @JsonProperty("file_ids") @ExcludeMissing fun _fileIds() = fileIds + @JsonProperty("file_ids") + @ExcludeMissing + fun _fileIds(): JsonField> = fileIds @JsonAnyGetter @ExcludeMissing @@ -703,12 +831,12 @@ private constructor( class Builder { - private var fileIds: JsonField> = JsonMissing.of() + private var fileIds: JsonField>? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(codeInterpreter: CodeInterpreter) = apply { - fileIds = codeInterpreter.fileIds + fileIds = codeInterpreter.fileIds.map { it.toMutableList() } additionalProperties = codeInterpreter.additionalProperties.toMutableMap() } @@ -724,7 +852,27 @@ private constructor( * available to the `code_interpreter`` tool. There can be a maximum of 20 files * associated with the tool. */ - fun fileIds(fileIds: JsonField>) = apply { this.fileIds = fileIds } + fun fileIds(fileIds: JsonField>) = apply { + this.fileIds = fileIds.map { it.toMutableList() } + } + + /** + * A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made + * available to the `code_interpreter`` tool. There can be a maximum of 20 files + * associated with the tool. + */ + fun addFileId(fileId: String) = apply { + fileIds = + (fileIds ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(fileId) + } + } fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() @@ -750,7 +898,7 @@ private constructor( fun build(): CodeInterpreter = CodeInterpreter( - fileIds.map { it.toImmutable() }, + (fileIds ?: JsonMissing.of()).map { it.toImmutable() }, additionalProperties.toImmutable() ) } @@ -799,7 +947,9 @@ private constructor( * attached to this assistant. There can be a maximum of 1 vector store attached to the * assistant. */ - @JsonProperty("vector_store_ids") @ExcludeMissing fun _vectorStoreIds() = vectorStoreIds + @JsonProperty("vector_store_ids") + @ExcludeMissing + fun _vectorStoreIds(): JsonField> = vectorStoreIds @JsonAnyGetter @ExcludeMissing @@ -823,12 +973,12 @@ private constructor( class Builder { - private var vectorStoreIds: JsonField> = JsonMissing.of() + private var vectorStoreIds: JsonField>? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(fileSearch: FileSearch) = apply { - vectorStoreIds = fileSearch.vectorStoreIds + vectorStoreIds = fileSearch.vectorStoreIds.map { it.toMutableList() } additionalProperties = fileSearch.additionalProperties.toMutableMap() } @@ -848,7 +998,26 @@ private constructor( * the assistant. */ fun vectorStoreIds(vectorStoreIds: JsonField>) = apply { - this.vectorStoreIds = vectorStoreIds + this.vectorStoreIds = vectorStoreIds.map { it.toMutableList() } + } + + /** + * The ID of the + * [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) + * attached to this assistant. There can be a maximum of 1 vector store attached to + * the assistant. + */ + fun addVectorStoreId(vectorStoreId: String) = apply { + vectorStoreIds = + (vectorStoreIds ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(vectorStoreId) + } } fun additionalProperties(additionalProperties: Map) = apply { @@ -875,7 +1044,7 @@ private constructor( fun build(): FileSearch = FileSearch( - vectorStoreIds.map { it.toImmutable() }, + (vectorStoreIds ?: JsonMissing.of()).map { it.toImmutable() }, additionalProperties.toImmutable() ) } diff --git a/openai-java-core/src/main/kotlin/com/openai/models/AssistantDeleted.kt b/openai-java-core/src/main/kotlin/com/openai/models/AssistantDeleted.kt index 072e3e554..330a6adaa 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/AssistantDeleted.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/AssistantDeleted.kt @@ -37,11 +37,11 @@ private constructor( fun object_(): Object = object_.getRequired("object") - @JsonProperty("id") @ExcludeMissing fun _id() = id + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id - @JsonProperty("deleted") @ExcludeMissing fun _deleted() = deleted + @JsonProperty("deleted") @ExcludeMissing fun _deleted(): JsonField = deleted - @JsonProperty("object") @ExcludeMissing fun _object_() = object_ + @JsonProperty("object") @ExcludeMissing fun _object_(): JsonField = object_ @JsonAnyGetter @ExcludeMissing @@ -67,9 +67,9 @@ private constructor( class Builder { - private var id: JsonField = JsonMissing.of() - private var deleted: JsonField = JsonMissing.of() - private var object_: JsonField = JsonMissing.of() + private var id: JsonField? = null + private var deleted: JsonField? = null + private var object_: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -113,9 +113,9 @@ private constructor( fun build(): AssistantDeleted = AssistantDeleted( - id, - deleted, - object_, + checkNotNull(id) { "`id` is required but was not set" }, + checkNotNull(deleted) { "`deleted` is required but was not set" }, + checkNotNull(object_) { "`object_` is required but was not set" }, additionalProperties.toImmutable(), ) } diff --git a/openai-java-core/src/main/kotlin/com/openai/models/AssistantStreamEvent.kt b/openai-java-core/src/main/kotlin/com/openai/models/AssistantStreamEvent.kt index 76cc36da3..9aef75ab8 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/AssistantStreamEvent.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/AssistantStreamEvent.kt @@ -1057,12 +1057,12 @@ private constructor( * Represents a thread that contains * [messages](https://platform.openai.com/docs/api-reference/messages). */ - @JsonProperty("data") @ExcludeMissing fun _data() = data + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data - @JsonProperty("event") @ExcludeMissing fun _event() = event + @JsonProperty("event") @ExcludeMissing fun _event(): JsonField = event /** Whether to enable input audio transcription. */ - @JsonProperty("enabled") @ExcludeMissing fun _enabled() = enabled + @JsonProperty("enabled") @ExcludeMissing fun _enabled(): JsonField = enabled @JsonAnyGetter @ExcludeMissing @@ -1088,8 +1088,8 @@ private constructor( class Builder { - private var data: JsonField = JsonMissing.of() - private var event: JsonField = JsonMissing.of() + private var data: JsonField? = null + private var event: JsonField? = null private var enabled: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @@ -1144,8 +1144,8 @@ private constructor( fun build(): ThreadCreated = ThreadCreated( - data, - event, + checkNotNull(data) { "`data` is required but was not set" }, + checkNotNull(event) { "`event` is required but was not set" }, enabled, additionalProperties.toImmutable(), ) @@ -1248,9 +1248,9 @@ private constructor( * Represents an execution run on a * [thread](https://platform.openai.com/docs/api-reference/threads). */ - @JsonProperty("data") @ExcludeMissing fun _data() = data + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data - @JsonProperty("event") @ExcludeMissing fun _event() = event + @JsonProperty("event") @ExcludeMissing fun _event(): JsonField = event @JsonAnyGetter @ExcludeMissing @@ -1275,8 +1275,8 @@ private constructor( class Builder { - private var data: JsonField = JsonMissing.of() - private var event: JsonField = JsonMissing.of() + private var data: JsonField? = null + private var event: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -1323,8 +1323,8 @@ private constructor( fun build(): ThreadRunCreated = ThreadRunCreated( - data, - event, + checkNotNull(data) { "`data` is required but was not set" }, + checkNotNull(event) { "`event` is required but was not set" }, additionalProperties.toImmutable(), ) } @@ -1426,9 +1426,9 @@ private constructor( * Represents an execution run on a * [thread](https://platform.openai.com/docs/api-reference/threads). */ - @JsonProperty("data") @ExcludeMissing fun _data() = data + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data - @JsonProperty("event") @ExcludeMissing fun _event() = event + @JsonProperty("event") @ExcludeMissing fun _event(): JsonField = event @JsonAnyGetter @ExcludeMissing @@ -1453,8 +1453,8 @@ private constructor( class Builder { - private var data: JsonField = JsonMissing.of() - private var event: JsonField = JsonMissing.of() + private var data: JsonField? = null + private var event: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -1501,8 +1501,8 @@ private constructor( fun build(): ThreadRunQueued = ThreadRunQueued( - data, - event, + checkNotNull(data) { "`data` is required but was not set" }, + checkNotNull(event) { "`event` is required but was not set" }, additionalProperties.toImmutable(), ) } @@ -1604,9 +1604,9 @@ private constructor( * Represents an execution run on a * [thread](https://platform.openai.com/docs/api-reference/threads). */ - @JsonProperty("data") @ExcludeMissing fun _data() = data + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data - @JsonProperty("event") @ExcludeMissing fun _event() = event + @JsonProperty("event") @ExcludeMissing fun _event(): JsonField = event @JsonAnyGetter @ExcludeMissing @@ -1631,8 +1631,8 @@ private constructor( class Builder { - private var data: JsonField = JsonMissing.of() - private var event: JsonField = JsonMissing.of() + private var data: JsonField? = null + private var event: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -1679,8 +1679,8 @@ private constructor( fun build(): ThreadRunInProgress = ThreadRunInProgress( - data, - event, + checkNotNull(data) { "`data` is required but was not set" }, + checkNotNull(event) { "`event` is required but was not set" }, additionalProperties.toImmutable(), ) } @@ -1782,9 +1782,9 @@ private constructor( * Represents an execution run on a * [thread](https://platform.openai.com/docs/api-reference/threads). */ - @JsonProperty("data") @ExcludeMissing fun _data() = data + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data - @JsonProperty("event") @ExcludeMissing fun _event() = event + @JsonProperty("event") @ExcludeMissing fun _event(): JsonField = event @JsonAnyGetter @ExcludeMissing @@ -1809,8 +1809,8 @@ private constructor( class Builder { - private var data: JsonField = JsonMissing.of() - private var event: JsonField = JsonMissing.of() + private var data: JsonField? = null + private var event: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -1857,8 +1857,8 @@ private constructor( fun build(): ThreadRunRequiresAction = ThreadRunRequiresAction( - data, - event, + checkNotNull(data) { "`data` is required but was not set" }, + checkNotNull(event) { "`event` is required but was not set" }, additionalProperties.toImmutable(), ) } @@ -1959,9 +1959,9 @@ private constructor( * Represents an execution run on a * [thread](https://platform.openai.com/docs/api-reference/threads). */ - @JsonProperty("data") @ExcludeMissing fun _data() = data + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data - @JsonProperty("event") @ExcludeMissing fun _event() = event + @JsonProperty("event") @ExcludeMissing fun _event(): JsonField = event @JsonAnyGetter @ExcludeMissing @@ -1986,8 +1986,8 @@ private constructor( class Builder { - private var data: JsonField = JsonMissing.of() - private var event: JsonField = JsonMissing.of() + private var data: JsonField? = null + private var event: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -2034,8 +2034,8 @@ private constructor( fun build(): ThreadRunCompleted = ThreadRunCompleted( - data, - event, + checkNotNull(data) { "`data` is required but was not set" }, + checkNotNull(event) { "`event` is required but was not set" }, additionalProperties.toImmutable(), ) } @@ -2137,9 +2137,9 @@ private constructor( * Represents an execution run on a * [thread](https://platform.openai.com/docs/api-reference/threads). */ - @JsonProperty("data") @ExcludeMissing fun _data() = data + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data - @JsonProperty("event") @ExcludeMissing fun _event() = event + @JsonProperty("event") @ExcludeMissing fun _event(): JsonField = event @JsonAnyGetter @ExcludeMissing @@ -2164,8 +2164,8 @@ private constructor( class Builder { - private var data: JsonField = JsonMissing.of() - private var event: JsonField = JsonMissing.of() + private var data: JsonField? = null + private var event: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -2212,8 +2212,8 @@ private constructor( fun build(): ThreadRunIncomplete = ThreadRunIncomplete( - data, - event, + checkNotNull(data) { "`data` is required but was not set" }, + checkNotNull(event) { "`event` is required but was not set" }, additionalProperties.toImmutable(), ) } @@ -2312,9 +2312,9 @@ private constructor( * Represents an execution run on a * [thread](https://platform.openai.com/docs/api-reference/threads). */ - @JsonProperty("data") @ExcludeMissing fun _data() = data + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data - @JsonProperty("event") @ExcludeMissing fun _event() = event + @JsonProperty("event") @ExcludeMissing fun _event(): JsonField = event @JsonAnyGetter @ExcludeMissing @@ -2339,8 +2339,8 @@ private constructor( class Builder { - private var data: JsonField = JsonMissing.of() - private var event: JsonField = JsonMissing.of() + private var data: JsonField? = null + private var event: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -2387,8 +2387,8 @@ private constructor( fun build(): ThreadRunFailed = ThreadRunFailed( - data, - event, + checkNotNull(data) { "`data` is required but was not set" }, + checkNotNull(event) { "`event` is required but was not set" }, additionalProperties.toImmutable(), ) } @@ -2490,9 +2490,9 @@ private constructor( * Represents an execution run on a * [thread](https://platform.openai.com/docs/api-reference/threads). */ - @JsonProperty("data") @ExcludeMissing fun _data() = data + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data - @JsonProperty("event") @ExcludeMissing fun _event() = event + @JsonProperty("event") @ExcludeMissing fun _event(): JsonField = event @JsonAnyGetter @ExcludeMissing @@ -2517,8 +2517,8 @@ private constructor( class Builder { - private var data: JsonField = JsonMissing.of() - private var event: JsonField = JsonMissing.of() + private var data: JsonField? = null + private var event: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -2565,8 +2565,8 @@ private constructor( fun build(): ThreadRunCancelling = ThreadRunCancelling( - data, - event, + checkNotNull(data) { "`data` is required but was not set" }, + checkNotNull(event) { "`event` is required but was not set" }, additionalProperties.toImmutable(), ) } @@ -2667,9 +2667,9 @@ private constructor( * Represents an execution run on a * [thread](https://platform.openai.com/docs/api-reference/threads). */ - @JsonProperty("data") @ExcludeMissing fun _data() = data + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data - @JsonProperty("event") @ExcludeMissing fun _event() = event + @JsonProperty("event") @ExcludeMissing fun _event(): JsonField = event @JsonAnyGetter @ExcludeMissing @@ -2694,8 +2694,8 @@ private constructor( class Builder { - private var data: JsonField = JsonMissing.of() - private var event: JsonField = JsonMissing.of() + private var data: JsonField? = null + private var event: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -2742,8 +2742,8 @@ private constructor( fun build(): ThreadRunCancelled = ThreadRunCancelled( - data, - event, + checkNotNull(data) { "`data` is required but was not set" }, + checkNotNull(event) { "`event` is required but was not set" }, additionalProperties.toImmutable(), ) } @@ -2842,9 +2842,9 @@ private constructor( * Represents an execution run on a * [thread](https://platform.openai.com/docs/api-reference/threads). */ - @JsonProperty("data") @ExcludeMissing fun _data() = data + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data - @JsonProperty("event") @ExcludeMissing fun _event() = event + @JsonProperty("event") @ExcludeMissing fun _event(): JsonField = event @JsonAnyGetter @ExcludeMissing @@ -2869,8 +2869,8 @@ private constructor( class Builder { - private var data: JsonField = JsonMissing.of() - private var event: JsonField = JsonMissing.of() + private var data: JsonField? = null + private var event: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -2917,8 +2917,8 @@ private constructor( fun build(): ThreadRunExpired = ThreadRunExpired( - data, - event, + checkNotNull(data) { "`data` is required but was not set" }, + checkNotNull(event) { "`event` is required but was not set" }, additionalProperties.toImmutable(), ) } @@ -3016,9 +3016,9 @@ private constructor( fun event(): Event = event.getRequired("event") /** Represents a step in execution of a run. */ - @JsonProperty("data") @ExcludeMissing fun _data() = data + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data - @JsonProperty("event") @ExcludeMissing fun _event() = event + @JsonProperty("event") @ExcludeMissing fun _event(): JsonField = event @JsonAnyGetter @ExcludeMissing @@ -3043,8 +3043,8 @@ private constructor( class Builder { - private var data: JsonField = JsonMissing.of() - private var event: JsonField = JsonMissing.of() + private var data: JsonField? = null + private var event: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -3085,8 +3085,8 @@ private constructor( fun build(): ThreadRunStepCreated = ThreadRunStepCreated( - data, - event, + checkNotNull(data) { "`data` is required but was not set" }, + checkNotNull(event) { "`event` is required but was not set" }, additionalProperties.toImmutable(), ) } @@ -3185,9 +3185,9 @@ private constructor( fun event(): Event = event.getRequired("event") /** Represents a step in execution of a run. */ - @JsonProperty("data") @ExcludeMissing fun _data() = data + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data - @JsonProperty("event") @ExcludeMissing fun _event() = event + @JsonProperty("event") @ExcludeMissing fun _event(): JsonField = event @JsonAnyGetter @ExcludeMissing @@ -3212,8 +3212,8 @@ private constructor( class Builder { - private var data: JsonField = JsonMissing.of() - private var event: JsonField = JsonMissing.of() + private var data: JsonField? = null + private var event: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -3254,8 +3254,8 @@ private constructor( fun build(): ThreadRunStepInProgress = ThreadRunStepInProgress( - data, - event, + checkNotNull(data) { "`data` is required but was not set" }, + checkNotNull(event) { "`event` is required but was not set" }, additionalProperties.toImmutable(), ) } @@ -3354,9 +3354,9 @@ private constructor( fun event(): Event = event.getRequired("event") /** Represents a run step delta i.e. any changed fields on a run step during streaming. */ - @JsonProperty("data") @ExcludeMissing fun _data() = data + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data - @JsonProperty("event") @ExcludeMissing fun _event() = event + @JsonProperty("event") @ExcludeMissing fun _event(): JsonField = event @JsonAnyGetter @ExcludeMissing @@ -3381,8 +3381,8 @@ private constructor( class Builder { - private var data: JsonField = JsonMissing.of() - private var event: JsonField = JsonMissing.of() + private var data: JsonField? = null + private var event: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -3427,8 +3427,8 @@ private constructor( fun build(): ThreadRunStepDelta = ThreadRunStepDelta( - data, - event, + checkNotNull(data) { "`data` is required but was not set" }, + checkNotNull(event) { "`event` is required but was not set" }, additionalProperties.toImmutable(), ) } @@ -3527,9 +3527,9 @@ private constructor( fun event(): Event = event.getRequired("event") /** Represents a step in execution of a run. */ - @JsonProperty("data") @ExcludeMissing fun _data() = data + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data - @JsonProperty("event") @ExcludeMissing fun _event() = event + @JsonProperty("event") @ExcludeMissing fun _event(): JsonField = event @JsonAnyGetter @ExcludeMissing @@ -3554,8 +3554,8 @@ private constructor( class Builder { - private var data: JsonField = JsonMissing.of() - private var event: JsonField = JsonMissing.of() + private var data: JsonField? = null + private var event: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -3596,8 +3596,8 @@ private constructor( fun build(): ThreadRunStepCompleted = ThreadRunStepCompleted( - data, - event, + checkNotNull(data) { "`data` is required but was not set" }, + checkNotNull(event) { "`event` is required but was not set" }, additionalProperties.toImmutable(), ) } @@ -3695,9 +3695,9 @@ private constructor( fun event(): Event = event.getRequired("event") /** Represents a step in execution of a run. */ - @JsonProperty("data") @ExcludeMissing fun _data() = data + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data - @JsonProperty("event") @ExcludeMissing fun _event() = event + @JsonProperty("event") @ExcludeMissing fun _event(): JsonField = event @JsonAnyGetter @ExcludeMissing @@ -3722,8 +3722,8 @@ private constructor( class Builder { - private var data: JsonField = JsonMissing.of() - private var event: JsonField = JsonMissing.of() + private var data: JsonField? = null + private var event: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -3764,8 +3764,8 @@ private constructor( fun build(): ThreadRunStepFailed = ThreadRunStepFailed( - data, - event, + checkNotNull(data) { "`data` is required but was not set" }, + checkNotNull(event) { "`event` is required but was not set" }, additionalProperties.toImmutable(), ) } @@ -3864,9 +3864,9 @@ private constructor( fun event(): Event = event.getRequired("event") /** Represents a step in execution of a run. */ - @JsonProperty("data") @ExcludeMissing fun _data() = data + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data - @JsonProperty("event") @ExcludeMissing fun _event() = event + @JsonProperty("event") @ExcludeMissing fun _event(): JsonField = event @JsonAnyGetter @ExcludeMissing @@ -3891,8 +3891,8 @@ private constructor( class Builder { - private var data: JsonField = JsonMissing.of() - private var event: JsonField = JsonMissing.of() + private var data: JsonField? = null + private var event: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -3933,8 +3933,8 @@ private constructor( fun build(): ThreadRunStepCancelled = ThreadRunStepCancelled( - data, - event, + checkNotNull(data) { "`data` is required but was not set" }, + checkNotNull(event) { "`event` is required but was not set" }, additionalProperties.toImmutable(), ) } @@ -4032,9 +4032,9 @@ private constructor( fun event(): Event = event.getRequired("event") /** Represents a step in execution of a run. */ - @JsonProperty("data") @ExcludeMissing fun _data() = data + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data - @JsonProperty("event") @ExcludeMissing fun _event() = event + @JsonProperty("event") @ExcludeMissing fun _event(): JsonField = event @JsonAnyGetter @ExcludeMissing @@ -4059,8 +4059,8 @@ private constructor( class Builder { - private var data: JsonField = JsonMissing.of() - private var event: JsonField = JsonMissing.of() + private var data: JsonField? = null + private var event: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -4101,8 +4101,8 @@ private constructor( fun build(): ThreadRunStepExpired = ThreadRunStepExpired( - data, - event, + checkNotNull(data) { "`data` is required but was not set" }, + checkNotNull(event) { "`event` is required but was not set" }, additionalProperties.toImmutable(), ) } @@ -4206,9 +4206,9 @@ private constructor( * Represents a message within a * [thread](https://platform.openai.com/docs/api-reference/threads). */ - @JsonProperty("data") @ExcludeMissing fun _data() = data + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data - @JsonProperty("event") @ExcludeMissing fun _event() = event + @JsonProperty("event") @ExcludeMissing fun _event(): JsonField = event @JsonAnyGetter @ExcludeMissing @@ -4233,8 +4233,8 @@ private constructor( class Builder { - private var data: JsonField = JsonMissing.of() - private var event: JsonField = JsonMissing.of() + private var data: JsonField? = null + private var event: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -4281,8 +4281,8 @@ private constructor( fun build(): ThreadMessageCreated = ThreadMessageCreated( - data, - event, + checkNotNull(data) { "`data` is required but was not set" }, + checkNotNull(event) { "`event` is required but was not set" }, additionalProperties.toImmutable(), ) } @@ -4386,9 +4386,9 @@ private constructor( * Represents a message within a * [thread](https://platform.openai.com/docs/api-reference/threads). */ - @JsonProperty("data") @ExcludeMissing fun _data() = data + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data - @JsonProperty("event") @ExcludeMissing fun _event() = event + @JsonProperty("event") @ExcludeMissing fun _event(): JsonField = event @JsonAnyGetter @ExcludeMissing @@ -4413,8 +4413,8 @@ private constructor( class Builder { - private var data: JsonField = JsonMissing.of() - private var event: JsonField = JsonMissing.of() + private var data: JsonField? = null + private var event: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -4461,8 +4461,8 @@ private constructor( fun build(): ThreadMessageInProgress = ThreadMessageInProgress( - data, - event, + checkNotNull(data) { "`data` is required but was not set" }, + checkNotNull(event) { "`event` is required but was not set" }, additionalProperties.toImmutable(), ) } @@ -4560,9 +4560,9 @@ private constructor( fun event(): Event = event.getRequired("event") /** Represents a message delta i.e. any changed fields on a message during streaming. */ - @JsonProperty("data") @ExcludeMissing fun _data() = data + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data - @JsonProperty("event") @ExcludeMissing fun _event() = event + @JsonProperty("event") @ExcludeMissing fun _event(): JsonField = event @JsonAnyGetter @ExcludeMissing @@ -4587,8 +4587,8 @@ private constructor( class Builder { - private var data: JsonField = JsonMissing.of() - private var event: JsonField = JsonMissing.of() + private var data: JsonField? = null + private var event: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -4629,8 +4629,8 @@ private constructor( fun build(): ThreadMessageDelta = ThreadMessageDelta( - data, - event, + checkNotNull(data) { "`data` is required but was not set" }, + checkNotNull(event) { "`event` is required but was not set" }, additionalProperties.toImmutable(), ) } @@ -4734,9 +4734,9 @@ private constructor( * Represents a message within a * [thread](https://platform.openai.com/docs/api-reference/threads). */ - @JsonProperty("data") @ExcludeMissing fun _data() = data + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data - @JsonProperty("event") @ExcludeMissing fun _event() = event + @JsonProperty("event") @ExcludeMissing fun _event(): JsonField = event @JsonAnyGetter @ExcludeMissing @@ -4761,8 +4761,8 @@ private constructor( class Builder { - private var data: JsonField = JsonMissing.of() - private var event: JsonField = JsonMissing.of() + private var data: JsonField? = null + private var event: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -4809,8 +4809,8 @@ private constructor( fun build(): ThreadMessageCompleted = ThreadMessageCompleted( - data, - event, + checkNotNull(data) { "`data` is required but was not set" }, + checkNotNull(event) { "`event` is required but was not set" }, additionalProperties.toImmutable(), ) } @@ -4914,9 +4914,9 @@ private constructor( * Represents a message within a * [thread](https://platform.openai.com/docs/api-reference/threads). */ - @JsonProperty("data") @ExcludeMissing fun _data() = data + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data - @JsonProperty("event") @ExcludeMissing fun _event() = event + @JsonProperty("event") @ExcludeMissing fun _event(): JsonField = event @JsonAnyGetter @ExcludeMissing @@ -4941,8 +4941,8 @@ private constructor( class Builder { - private var data: JsonField = JsonMissing.of() - private var event: JsonField = JsonMissing.of() + private var data: JsonField? = null + private var event: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -4989,8 +4989,8 @@ private constructor( fun build(): ThreadMessageIncomplete = ThreadMessageIncomplete( - data, - event, + checkNotNull(data) { "`data` is required but was not set" }, + checkNotNull(event) { "`event` is required but was not set" }, additionalProperties.toImmutable(), ) } @@ -5086,9 +5086,9 @@ private constructor( fun event(): Event = event.getRequired("event") - @JsonProperty("data") @ExcludeMissing fun _data() = data + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField = data - @JsonProperty("event") @ExcludeMissing fun _event() = event + @JsonProperty("event") @ExcludeMissing fun _event(): JsonField = event @JsonAnyGetter @ExcludeMissing @@ -5113,8 +5113,8 @@ private constructor( class Builder { - private var data: JsonField = JsonMissing.of() - private var event: JsonField = JsonMissing.of() + private var data: JsonField? = null + private var event: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -5153,8 +5153,8 @@ private constructor( fun build(): ErrorEvent = ErrorEvent( - data, - event, + checkNotNull(data) { "`data` is required but was not set" }, + checkNotNull(event) { "`event` is required but was not set" }, additionalProperties.toImmutable(), ) } diff --git a/openai-java-core/src/main/kotlin/com/openai/models/AssistantToolChoice.kt b/openai-java-core/src/main/kotlin/com/openai/models/AssistantToolChoice.kt index 0e4457fe6..096187412 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/AssistantToolChoice.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/AssistantToolChoice.kt @@ -37,9 +37,11 @@ private constructor( Optional.ofNullable(function.getNullable("function")) /** The type of the tool. If type is `function`, the function name must be set */ - @JsonProperty("type") @ExcludeMissing fun _type() = type + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type - @JsonProperty("function") @ExcludeMissing fun _function() = function + @JsonProperty("function") + @ExcludeMissing + fun _function(): JsonField = function @JsonAnyGetter @ExcludeMissing @@ -64,7 +66,7 @@ private constructor( class Builder { - private var type: JsonField = JsonMissing.of() + private var type: JsonField? = null private var function: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @@ -108,7 +110,7 @@ private constructor( fun build(): AssistantToolChoice = AssistantToolChoice( - type, + checkNotNull(type) { "`type` is required but was not set" }, function, additionalProperties.toImmutable(), ) diff --git a/openai-java-core/src/main/kotlin/com/openai/models/AssistantToolChoiceFunction.kt b/openai-java-core/src/main/kotlin/com/openai/models/AssistantToolChoiceFunction.kt index d756cd676..ff83b3642 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/AssistantToolChoiceFunction.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/AssistantToolChoiceFunction.kt @@ -27,7 +27,7 @@ private constructor( fun name(): String = name.getRequired("name") /** The name of the function to call. */ - @JsonProperty("name") @ExcludeMissing fun _name() = name + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name @JsonAnyGetter @ExcludeMissing @@ -51,7 +51,7 @@ private constructor( class Builder { - private var name: JsonField = JsonMissing.of() + private var name: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -86,7 +86,10 @@ private constructor( } fun build(): AssistantToolChoiceFunction = - AssistantToolChoiceFunction(name, additionalProperties.toImmutable()) + AssistantToolChoiceFunction( + checkNotNull(name) { "`name` is required but was not set" }, + additionalProperties.toImmutable() + ) } override fun equals(other: Any?): Boolean { diff --git a/openai-java-core/src/main/kotlin/com/openai/models/AutoFileChunkingStrategyParam.kt b/openai-java-core/src/main/kotlin/com/openai/models/AutoFileChunkingStrategyParam.kt index 19138937d..9f60fff1e 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/AutoFileChunkingStrategyParam.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/AutoFileChunkingStrategyParam.kt @@ -33,7 +33,7 @@ private constructor( fun type(): Type = type.getRequired("type") /** Always `auto`. */ - @JsonProperty("type") @ExcludeMissing fun _type() = type + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type @JsonAnyGetter @ExcludeMissing @@ -57,7 +57,7 @@ private constructor( class Builder { - private var type: JsonField = JsonMissing.of() + private var type: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -92,7 +92,10 @@ private constructor( } fun build(): AutoFileChunkingStrategyParam = - AutoFileChunkingStrategyParam(type, additionalProperties.toImmutable()) + AutoFileChunkingStrategyParam( + checkNotNull(type) { "`type` is required but was not set" }, + additionalProperties.toImmutable() + ) } class Type diff --git a/openai-java-core/src/main/kotlin/com/openai/models/Batch.kt b/openai-java-core/src/main/kotlin/com/openai/models/Batch.kt index 2d7b2eeb8..e8b71b2d0 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/Batch.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/Batch.kt @@ -134,6 +134,13 @@ private constructor( fun inProgressAt(): Optional = Optional.ofNullable(inProgressAt.getNullable("in_progress_at")) + /** + * 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 maximum of 512 characters long. + */ + @JsonProperty("metadata") @ExcludeMissing fun _metadata(): JsonValue = metadata + /** The ID of the file containing the outputs of successfully executed requests. */ fun outputFileId(): Optional = Optional.ofNullable(outputFileId.getNullable("output_file_id")) @@ -142,67 +149,76 @@ private constructor( fun requestCounts(): Optional = Optional.ofNullable(requestCounts.getNullable("request_counts")) - @JsonProperty("id") @ExcludeMissing fun _id() = id + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id /** The time frame within which the batch should be processed. */ - @JsonProperty("completion_window") @ExcludeMissing fun _completionWindow() = completionWindow + @JsonProperty("completion_window") + @ExcludeMissing + fun _completionWindow(): JsonField = completionWindow /** The Unix timestamp (in seconds) for when the batch was created. */ - @JsonProperty("created_at") @ExcludeMissing fun _createdAt() = createdAt + @JsonProperty("created_at") @ExcludeMissing fun _createdAt(): JsonField = createdAt /** The OpenAI API endpoint used by the batch. */ - @JsonProperty("endpoint") @ExcludeMissing fun _endpoint() = endpoint + @JsonProperty("endpoint") @ExcludeMissing fun _endpoint(): JsonField = endpoint /** The ID of the input file for the batch. */ - @JsonProperty("input_file_id") @ExcludeMissing fun _inputFileId() = inputFileId + @JsonProperty("input_file_id") + @ExcludeMissing + fun _inputFileId(): JsonField = inputFileId /** The object type, which is always `batch`. */ - @JsonProperty("object") @ExcludeMissing fun _object_() = object_ + @JsonProperty("object") @ExcludeMissing fun _object_(): JsonField = object_ /** The current status of the batch. */ - @JsonProperty("status") @ExcludeMissing fun _status() = status + @JsonProperty("status") @ExcludeMissing fun _status(): JsonField = status /** The Unix timestamp (in seconds) for when the batch was cancelled. */ - @JsonProperty("cancelled_at") @ExcludeMissing fun _cancelledAt() = cancelledAt + @JsonProperty("cancelled_at") @ExcludeMissing fun _cancelledAt(): JsonField = cancelledAt /** The Unix timestamp (in seconds) for when the batch started cancelling. */ - @JsonProperty("cancelling_at") @ExcludeMissing fun _cancellingAt() = cancellingAt + @JsonProperty("cancelling_at") + @ExcludeMissing + fun _cancellingAt(): JsonField = cancellingAt /** The Unix timestamp (in seconds) for when the batch was completed. */ - @JsonProperty("completed_at") @ExcludeMissing fun _completedAt() = completedAt + @JsonProperty("completed_at") @ExcludeMissing fun _completedAt(): JsonField = completedAt /** The ID of the file containing the outputs of requests with errors. */ - @JsonProperty("error_file_id") @ExcludeMissing fun _errorFileId() = errorFileId + @JsonProperty("error_file_id") + @ExcludeMissing + fun _errorFileId(): JsonField = errorFileId - @JsonProperty("errors") @ExcludeMissing fun _errors() = errors + @JsonProperty("errors") @ExcludeMissing fun _errors(): JsonField = errors /** The Unix timestamp (in seconds) for when the batch expired. */ - @JsonProperty("expired_at") @ExcludeMissing fun _expiredAt() = expiredAt + @JsonProperty("expired_at") @ExcludeMissing fun _expiredAt(): JsonField = expiredAt /** The Unix timestamp (in seconds) for when the batch will expire. */ - @JsonProperty("expires_at") @ExcludeMissing fun _expiresAt() = expiresAt + @JsonProperty("expires_at") @ExcludeMissing fun _expiresAt(): JsonField = expiresAt /** The Unix timestamp (in seconds) for when the batch failed. */ - @JsonProperty("failed_at") @ExcludeMissing fun _failedAt() = failedAt + @JsonProperty("failed_at") @ExcludeMissing fun _failedAt(): JsonField = failedAt /** The Unix timestamp (in seconds) for when the batch started finalizing. */ - @JsonProperty("finalizing_at") @ExcludeMissing fun _finalizingAt() = finalizingAt + @JsonProperty("finalizing_at") + @ExcludeMissing + fun _finalizingAt(): JsonField = finalizingAt /** The Unix timestamp (in seconds) for when the batch started processing. */ - @JsonProperty("in_progress_at") @ExcludeMissing fun _inProgressAt() = inProgressAt - - /** - * 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 maximum of 512 characters long. - */ - @JsonProperty("metadata") @ExcludeMissing fun _metadata() = metadata + @JsonProperty("in_progress_at") + @ExcludeMissing + fun _inProgressAt(): JsonField = inProgressAt /** The ID of the file containing the outputs of successfully executed requests. */ - @JsonProperty("output_file_id") @ExcludeMissing fun _outputFileId() = outputFileId + @JsonProperty("output_file_id") + @ExcludeMissing + fun _outputFileId(): JsonField = outputFileId /** The request counts for different statuses within the batch. */ - @JsonProperty("request_counts") @ExcludeMissing fun _requestCounts() = requestCounts + @JsonProperty("request_counts") + @ExcludeMissing + fun _requestCounts(): JsonField = requestCounts @JsonAnyGetter @ExcludeMissing @@ -244,13 +260,13 @@ private constructor( class Builder { - private var id: JsonField = JsonMissing.of() - private var completionWindow: JsonField = JsonMissing.of() - private var createdAt: JsonField = JsonMissing.of() - private var endpoint: JsonField = JsonMissing.of() - private var inputFileId: JsonField = JsonMissing.of() - private var object_: JsonField = JsonMissing.of() - private var status: JsonField = JsonMissing.of() + private var id: JsonField? = null + private var completionWindow: JsonField? = null + private var createdAt: JsonField? = null + private var endpoint: JsonField? = null + private var inputFileId: JsonField? = null + private var object_: JsonField? = null + private var status: JsonField? = null private var cancelledAt: JsonField = JsonMissing.of() private var cancellingAt: JsonField = JsonMissing.of() private var completedAt: JsonField = JsonMissing.of() @@ -437,13 +453,13 @@ private constructor( fun build(): Batch = Batch( - id, - completionWindow, - createdAt, - endpoint, - inputFileId, - object_, - status, + checkNotNull(id) { "`id` is required but was not set" }, + checkNotNull(completionWindow) { "`completionWindow` is required but was not set" }, + checkNotNull(createdAt) { "`createdAt` is required but was not set" }, + checkNotNull(endpoint) { "`endpoint` is required but was not set" }, + checkNotNull(inputFileId) { "`inputFileId` is required but was not set" }, + checkNotNull(object_) { "`object_` is required but was not set" }, + checkNotNull(status) { "`status` is required but was not set" }, cancelledAt, cancellingAt, completedAt, @@ -624,10 +640,10 @@ private constructor( /** The object type, which is always `list`. */ fun object_(): Optional = Optional.ofNullable(object_.getNullable("object")) - @JsonProperty("data") @ExcludeMissing fun _data() = data + @JsonProperty("data") @ExcludeMissing fun _data(): JsonField> = data /** The object type, which is always `list`. */ - @JsonProperty("object") @ExcludeMissing fun _object_() = object_ + @JsonProperty("object") @ExcludeMissing fun _object_(): JsonField = object_ @JsonAnyGetter @ExcludeMissing @@ -652,20 +668,35 @@ private constructor( class Builder { - private var data: JsonField> = JsonMissing.of() + private var data: JsonField>? = null private var object_: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(errors: Errors) = apply { - data = errors.data + data = errors.data.map { it.toMutableList() } object_ = errors.object_ additionalProperties = errors.additionalProperties.toMutableMap() } fun data(data: List) = data(JsonField.of(data)) - fun data(data: JsonField>) = apply { this.data = data } + fun data(data: JsonField>) = apply { + this.data = data.map { it.toMutableList() } + } + + fun addData(data: BatchError) = apply { + this.data = + (this.data ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(data) + } + } /** The object type, which is always `list`. */ fun object_(object_: String) = object_(JsonField.of(object_)) @@ -694,7 +725,7 @@ private constructor( fun build(): Errors = Errors( - data.map { it.toImmutable() }, + (data ?: JsonMissing.of()).map { it.toImmutable() }, object_, additionalProperties.toImmutable(), ) diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BatchCancelParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BatchCancelParams.kt index 7b50d4dc4..1dd6bd6c3 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BatchCancelParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BatchCancelParams.kt @@ -10,6 +10,11 @@ import com.openai.core.toImmutable import java.util.Objects import java.util.Optional +/** + * Cancels an in-progress batch. The batch will be in status `cancelling` for up to 10 minutes, + * before changing to `cancelled`, where it will have partial results (if any) available in the + * output file. + */ class BatchCancelParams constructor( private val batchId: String, diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BatchCreateParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BatchCreateParams.kt index 8c62580c5..f17a69be9 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BatchCreateParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BatchCreateParams.kt @@ -9,6 +9,7 @@ import com.fasterxml.jackson.annotation.JsonProperty import com.openai.core.Enum import com.openai.core.ExcludeMissing import com.openai.core.JsonField +import com.openai.core.JsonMissing import com.openai.core.JsonValue import com.openai.core.NoAutoDetect import com.openai.core.http.Headers @@ -19,6 +20,7 @@ import com.openai.errors.OpenAIInvalidDataException import java.util.Objects import java.util.Optional +/** Creates and executes a batch from an uploaded file of requests */ class BatchCreateParams constructor( private val body: BatchCreateBody, @@ -54,12 +56,40 @@ constructor( /** Optional custom metadata for the batch. */ fun metadata(): Optional = body.metadata() - fun _additionalHeaders(): Headers = additionalHeaders + /** + * The time frame within which the batch should be processed. Currently only `24h` is supported. + */ + fun _completionWindow(): JsonField = body._completionWindow() - fun _additionalQueryParams(): QueryParams = additionalQueryParams + /** + * The endpoint to be used for all requests in the batch. Currently `/v1/chat/completions`, + * `/v1/embeddings`, and `/v1/completions` are supported. Note that `/v1/embeddings` batches are + * also restricted to a maximum of 50,000 embedding inputs across all requests in the batch. + */ + fun _endpoint(): JsonField = body._endpoint() + + /** + * The ID of an uploaded file that contains requests for the new batch. + * + * See [upload file](https://platform.openai.com/docs/api-reference/files/create) for how to + * upload a file. + * + * Your input file must be formatted as a + * [JSONL file](https://platform.openai.com/docs/api-reference/batch/request-input), and must be + * uploaded with the purpose `batch`. The file can contain up to 50,000 requests, and can be up + * to 200 MB in size. + */ + fun _inputFileId(): JsonField = body._inputFileId() + + /** Optional custom metadata for the batch. */ + fun _metadata(): JsonField = body._metadata() fun _additionalBodyProperties(): Map = body._additionalProperties() + fun _additionalHeaders(): Headers = additionalHeaders + + fun _additionalQueryParams(): QueryParams = additionalQueryParams + @JvmSynthetic internal fun getBody(): BatchCreateBody = body @JvmSynthetic internal fun getHeaders(): Headers = additionalHeaders @@ -70,20 +100,59 @@ constructor( class BatchCreateBody @JsonCreator internal constructor( - @JsonProperty("completion_window") private val completionWindow: CompletionWindow, - @JsonProperty("endpoint") private val endpoint: Endpoint, - @JsonProperty("input_file_id") private val inputFileId: String, - @JsonProperty("metadata") private val metadata: Metadata?, + @JsonProperty("completion_window") + @ExcludeMissing + private val completionWindow: JsonField = JsonMissing.of(), + @JsonProperty("endpoint") + @ExcludeMissing + private val endpoint: JsonField = JsonMissing.of(), + @JsonProperty("input_file_id") + @ExcludeMissing + private val inputFileId: JsonField = JsonMissing.of(), + @JsonProperty("metadata") + @ExcludeMissing + private val metadata: JsonField = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { + /** + * The time frame within which the batch should be processed. Currently only `24h` is + * supported. + */ + fun completionWindow(): CompletionWindow = completionWindow.getRequired("completion_window") + + /** + * The endpoint to be used for all requests in the batch. Currently `/v1/chat/completions`, + * `/v1/embeddings`, and `/v1/completions` are supported. Note that `/v1/embeddings` batches + * are also restricted to a maximum of 50,000 embedding inputs across all requests in the + * batch. + */ + fun endpoint(): Endpoint = endpoint.getRequired("endpoint") + + /** + * The ID of an uploaded file that contains requests for the new batch. + * + * See [upload file](https://platform.openai.com/docs/api-reference/files/create) for how to + * upload a file. + * + * Your input file must be formatted as a + * [JSONL file](https://platform.openai.com/docs/api-reference/batch/request-input), and + * must be uploaded with the purpose `batch`. The file can contain up to 50,000 requests, + * and can be up to 200 MB in size. + */ + fun inputFileId(): String = inputFileId.getRequired("input_file_id") + + /** Optional custom metadata for the batch. */ + fun metadata(): Optional = Optional.ofNullable(metadata.getNullable("metadata")) + /** * The time frame within which the batch should be processed. Currently only `24h` is * supported. */ @JsonProperty("completion_window") - fun completionWindow(): CompletionWindow = completionWindow + @ExcludeMissing + fun _completionWindow(): JsonField = completionWindow /** * The endpoint to be used for all requests in the batch. Currently `/v1/chat/completions`, @@ -91,7 +160,7 @@ constructor( * are also restricted to a maximum of 50,000 embedding inputs across all requests in the * batch. */ - @JsonProperty("endpoint") fun endpoint(): Endpoint = endpoint + @JsonProperty("endpoint") @ExcludeMissing fun _endpoint(): JsonField = endpoint /** * The ID of an uploaded file that contains requests for the new batch. @@ -104,15 +173,29 @@ constructor( * must be uploaded with the purpose `batch`. The file can contain up to 50,000 requests, * and can be up to 200 MB in size. */ - @JsonProperty("input_file_id") fun inputFileId(): String = inputFileId + @JsonProperty("input_file_id") + @ExcludeMissing + fun _inputFileId(): JsonField = inputFileId /** Optional custom metadata for the batch. */ - @JsonProperty("metadata") fun metadata(): Optional = Optional.ofNullable(metadata) + @JsonProperty("metadata") @ExcludeMissing fun _metadata(): JsonField = metadata @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): BatchCreateBody = apply { + if (!validated) { + completionWindow() + endpoint() + inputFileId() + metadata().map { it.validate() } + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -122,10 +205,10 @@ constructor( class Builder { - private var completionWindow: CompletionWindow? = null - private var endpoint: Endpoint? = null - private var inputFileId: String? = null - private var metadata: Metadata? = null + private var completionWindow: JsonField? = null + private var endpoint: JsonField? = null + private var inputFileId: JsonField? = null + private var metadata: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -141,7 +224,14 @@ constructor( * The time frame within which the batch should be processed. Currently only `24h` is * supported. */ - fun completionWindow(completionWindow: CompletionWindow) = apply { + fun completionWindow(completionWindow: CompletionWindow) = + completionWindow(JsonField.of(completionWindow)) + + /** + * The time frame within which the batch should be processed. Currently only `24h` is + * supported. + */ + fun completionWindow(completionWindow: JsonField) = apply { this.completionWindow = completionWindow } @@ -151,7 +241,28 @@ constructor( * that `/v1/embeddings` batches are also restricted to a maximum of 50,000 embedding * inputs across all requests in the batch. */ - fun endpoint(endpoint: Endpoint) = apply { this.endpoint = endpoint } + fun endpoint(endpoint: Endpoint) = endpoint(JsonField.of(endpoint)) + + /** + * The endpoint to be used for all requests in the batch. Currently + * `/v1/chat/completions`, `/v1/embeddings`, and `/v1/completions` are supported. Note + * that `/v1/embeddings` batches are also restricted to a maximum of 50,000 embedding + * inputs across all requests in the batch. + */ + fun endpoint(endpoint: JsonField) = apply { this.endpoint = endpoint } + + /** + * The ID of an uploaded file that contains requests for the new batch. + * + * See [upload file](https://platform.openai.com/docs/api-reference/files/create) for + * how to upload a file. + * + * Your input file must be formatted as a + * [JSONL file](https://platform.openai.com/docs/api-reference/batch/request-input), and + * must be uploaded with the purpose `batch`. The file can contain up to 50,000 + * requests, and can be up to 200 MB in size. + */ + fun inputFileId(inputFileId: String) = inputFileId(JsonField.of(inputFileId)) /** * The ID of an uploaded file that contains requests for the new batch. @@ -164,10 +275,18 @@ constructor( * must be uploaded with the purpose `batch`. The file can contain up to 50,000 * requests, and can be up to 200 MB in size. */ - fun inputFileId(inputFileId: String) = apply { this.inputFileId = inputFileId } + fun inputFileId(inputFileId: JsonField) = apply { + this.inputFileId = inputFileId + } + + /** Optional custom metadata for the batch. */ + fun metadata(metadata: Metadata?) = metadata(JsonField.ofNullable(metadata)) + + /** Optional custom metadata for the batch. */ + fun metadata(metadata: Optional) = metadata(metadata.orElse(null)) /** Optional custom metadata for the batch. */ - fun metadata(metadata: Metadata) = apply { this.metadata = metadata } + fun metadata(metadata: JsonField) = apply { this.metadata = metadata } fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() @@ -247,6 +366,14 @@ constructor( body.completionWindow(completionWindow) } + /** + * The time frame within which the batch should be processed. Currently only `24h` is + * supported. + */ + fun completionWindow(completionWindow: JsonField) = apply { + body.completionWindow(completionWindow) + } + /** * The endpoint to be used for all requests in the batch. Currently `/v1/chat/completions`, * `/v1/embeddings`, and `/v1/completions` are supported. Note that `/v1/embeddings` batches @@ -255,6 +382,14 @@ constructor( */ fun endpoint(endpoint: Endpoint) = apply { body.endpoint(endpoint) } + /** + * The endpoint to be used for all requests in the batch. Currently `/v1/chat/completions`, + * `/v1/embeddings`, and `/v1/completions` are supported. Note that `/v1/embeddings` batches + * are also restricted to a maximum of 50,000 embedding inputs across all requests in the + * batch. + */ + fun endpoint(endpoint: JsonField) = apply { body.endpoint(endpoint) } + /** * The ID of an uploaded file that contains requests for the new batch. * @@ -268,8 +403,46 @@ constructor( */ fun inputFileId(inputFileId: String) = apply { body.inputFileId(inputFileId) } + /** + * The ID of an uploaded file that contains requests for the new batch. + * + * See [upload file](https://platform.openai.com/docs/api-reference/files/create) for how to + * upload a file. + * + * Your input file must be formatted as a + * [JSONL file](https://platform.openai.com/docs/api-reference/batch/request-input), and + * must be uploaded with the purpose `batch`. The file can contain up to 50,000 requests, + * and can be up to 200 MB in size. + */ + fun inputFileId(inputFileId: JsonField) = apply { body.inputFileId(inputFileId) } + /** Optional custom metadata for the batch. */ - fun metadata(metadata: Metadata) = apply { body.metadata(metadata) } + fun metadata(metadata: Metadata?) = apply { body.metadata(metadata) } + + /** Optional custom metadata for the batch. */ + fun metadata(metadata: Optional) = metadata(metadata.orElse(null)) + + /** Optional custom metadata for the batch. */ + fun metadata(metadata: JsonField) = apply { body.metadata(metadata) } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() @@ -369,25 +542,6 @@ constructor( additionalQueryParams.removeAll(keys) } - fun additionalBodyProperties(additionalBodyProperties: Map) = apply { - body.additionalProperties(additionalBodyProperties) - } - - fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { - body.putAdditionalProperty(key, value) - } - - fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = - apply { - body.putAllAdditionalProperties(additionalBodyProperties) - } - - fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } - - fun removeAllAdditionalBodyProperties(keys: Set) = apply { - body.removeAllAdditionalProperties(keys) - } - fun build(): BatchCreateParams = BatchCreateParams( body.build(), @@ -523,6 +677,14 @@ constructor( @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): Metadata = apply { + if (!validated) { + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BatchError.kt b/openai-java-core/src/main/kotlin/com/openai/models/BatchError.kt index 8064eb29b..cbd0b4bd3 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BatchError.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BatchError.kt @@ -42,16 +42,16 @@ private constructor( fun param(): Optional = Optional.ofNullable(param.getNullable("param")) /** An error code identifying the error type. */ - @JsonProperty("code") @ExcludeMissing fun _code() = code + @JsonProperty("code") @ExcludeMissing fun _code(): JsonField = code /** The line number of the input file where the error occurred, if applicable. */ - @JsonProperty("line") @ExcludeMissing fun _line() = line + @JsonProperty("line") @ExcludeMissing fun _line(): JsonField = line /** A human-readable message providing more details about the error. */ - @JsonProperty("message") @ExcludeMissing fun _message() = message + @JsonProperty("message") @ExcludeMissing fun _message(): JsonField = message /** The name of the parameter that caused the error, if applicable. */ - @JsonProperty("param") @ExcludeMissing fun _param() = param + @JsonProperty("param") @ExcludeMissing fun _param(): JsonField = param @JsonAnyGetter @ExcludeMissing @@ -100,7 +100,14 @@ private constructor( fun code(code: JsonField) = apply { this.code = code } /** The line number of the input file where the error occurred, if applicable. */ - fun line(line: Long) = line(JsonField.of(line)) + fun line(line: Long?) = line(JsonField.ofNullable(line)) + + /** The line number of the input file where the error occurred, if applicable. */ + fun line(line: Long) = line(line as Long?) + + /** The line number of the input file where the error occurred, if applicable. */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun line(line: Optional) = line(line.orElse(null) as Long?) /** The line number of the input file where the error occurred, if applicable. */ fun line(line: JsonField) = apply { this.line = line } @@ -112,7 +119,10 @@ private constructor( fun message(message: JsonField) = apply { this.message = message } /** The name of the parameter that caused the error, if applicable. */ - fun param(param: String) = param(JsonField.of(param)) + fun param(param: String?) = param(JsonField.ofNullable(param)) + + /** The name of the parameter that caused the error, if applicable. */ + fun param(param: Optional) = param(param.orElse(null)) /** The name of the parameter that caused the error, if applicable. */ fun param(param: JsonField) = apply { this.param = param } diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BatchListParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BatchListParams.kt index 8e9d7d33b..85c1230b1 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BatchListParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BatchListParams.kt @@ -8,6 +8,7 @@ import com.openai.core.http.QueryParams import java.util.Objects import java.util.Optional +/** List your organization's batches. */ class BatchListParams constructor( private val after: String?, @@ -73,13 +74,34 @@ constructor( * obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page * of the list. */ - fun after(after: String) = apply { this.after = after } + fun after(after: String?) = apply { this.after = after } + + /** + * 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. + */ + fun after(after: Optional) = after(after.orElse(null)) + + /** + * A limit on the number of objects to be returned. Limit can range between 1 and 100, and + * the default is 20. + */ + fun limit(limit: Long?) = apply { this.limit = limit } + + /** + * A limit on the number of objects to be returned. Limit can range between 1 and 100, and + * the default is 20. + */ + fun limit(limit: Long) = limit(limit as Long?) /** * A limit on the number of objects to be returned. Limit can range between 1 and 100, and * the default is 20. */ - fun limit(limit: Long) = apply { this.limit = limit } + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun limit(limit: Optional) = limit(limit.orElse(null) as Long?) fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BatchRequestCounts.kt b/openai-java-core/src/main/kotlin/com/openai/models/BatchRequestCounts.kt index fc789d4a7..b6e6ea47e 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BatchRequestCounts.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BatchRequestCounts.kt @@ -38,13 +38,13 @@ private constructor( fun total(): Long = total.getRequired("total") /** Number of requests that have been completed successfully. */ - @JsonProperty("completed") @ExcludeMissing fun _completed() = completed + @JsonProperty("completed") @ExcludeMissing fun _completed(): JsonField = completed /** Number of requests that have failed. */ - @JsonProperty("failed") @ExcludeMissing fun _failed() = failed + @JsonProperty("failed") @ExcludeMissing fun _failed(): JsonField = failed /** Total number of requests in the batch. */ - @JsonProperty("total") @ExcludeMissing fun _total() = total + @JsonProperty("total") @ExcludeMissing fun _total(): JsonField = total @JsonAnyGetter @ExcludeMissing @@ -70,9 +70,9 @@ private constructor( class Builder { - private var completed: JsonField = JsonMissing.of() - private var failed: JsonField = JsonMissing.of() - private var total: JsonField = JsonMissing.of() + private var completed: JsonField? = null + private var failed: JsonField? = null + private var total: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -122,9 +122,9 @@ private constructor( fun build(): BatchRequestCounts = BatchRequestCounts( - completed, - failed, - total, + checkNotNull(completed) { "`completed` is required but was not set" }, + checkNotNull(failed) { "`failed` is required but was not set" }, + checkNotNull(total) { "`total` is required but was not set" }, additionalProperties.toImmutable(), ) } diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BatchRetrieveParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BatchRetrieveParams.kt index d945a6730..cc65fe36e 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BatchRetrieveParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BatchRetrieveParams.kt @@ -7,6 +7,7 @@ import com.openai.core.http.Headers import com.openai.core.http.QueryParams import java.util.Objects +/** Retrieves a batch. */ class BatchRetrieveParams constructor( private val batchId: String, diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaAssistantCreateParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaAssistantCreateParams.kt index 77aa53a11..f6148ef4c 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaAssistantCreateParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaAssistantCreateParams.kt @@ -7,6 +7,8 @@ import com.fasterxml.jackson.annotation.JsonAnySetter import com.fasterxml.jackson.annotation.JsonCreator import com.fasterxml.jackson.annotation.JsonProperty import com.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing import com.openai.core.JsonValue import com.openai.core.NoAutoDetect import com.openai.core.http.Headers @@ -16,6 +18,7 @@ import com.openai.core.toImmutable import java.util.Objects import java.util.Optional +/** Create an assistant with a model and instructions. */ class BetaAssistantCreateParams constructor( private val body: BetaAssistantCreateBody, @@ -44,7 +47,7 @@ constructor( * additional information about the object in a structured format. Keys can be a maximum of 64 * characters long and values can be a maximum of 512 characters long. */ - fun metadata(): Optional = body.metadata() + fun _metadata(): JsonValue = body._metadata() /** The name of the assistant. The maximum length is 256 characters. */ fun name(): Optional = body.name() @@ -99,12 +102,81 @@ constructor( */ fun topP(): Optional = body.topP() - fun _additionalHeaders(): Headers = additionalHeaders + /** + * ID of the model to use. You can use the + * [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all of + * your available models, or see our [Model overview](https://platform.openai.com/docs/models) + * for descriptions of them. + */ + fun _model(): JsonField = body._model() - fun _additionalQueryParams(): QueryParams = additionalQueryParams + /** The description of the assistant. The maximum length is 512 characters. */ + fun _description(): JsonField = body._description() + + /** + * The system instructions that the assistant uses. The maximum length is 256,000 characters. + */ + fun _instructions(): JsonField = body._instructions() + + /** The name of the assistant. The maximum length is 256 characters. */ + fun _name(): JsonField = body._name() + + /** + * Specifies the format that the model must output. Compatible with + * [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 + * Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo + * models since `gpt-3.5-turbo-1106`. + * + * Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which + * ensures the model will match your supplied JSON schema. Learn more in the + * [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). + * + * Setting to `{ "type": "json_object" }` enables JSON mode, which ensures 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. + */ + fun _responseFormat(): JsonField = body._responseFormat() + + /** + * 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. + */ + fun _temperature(): JsonField = body._temperature() + + /** + * A set of resources that are used by the assistant's tools. The resources are specific to the + * type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the + * `file_search` tool requires a list of vector store IDs. + */ + fun _toolResources(): JsonField = body._toolResources() + + /** + * 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`, `file_search`, or `function`. + */ + fun _tools(): JsonField> = body._tools() + + /** + * 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. + */ + fun _topP(): JsonField = body._topP() fun _additionalBodyProperties(): Map = body._additionalProperties() + fun _additionalHeaders(): Headers = additionalHeaders + + fun _additionalQueryParams(): QueryParams = additionalQueryParams + @JvmSynthetic internal fun getBody(): BetaAssistantCreateBody = body @JvmSynthetic internal fun getHeaders(): Headers = additionalHeaders @@ -115,16 +187,36 @@ constructor( class BetaAssistantCreateBody @JsonCreator internal constructor( - @JsonProperty("model") private val model: ChatModel, - @JsonProperty("description") private val description: String?, - @JsonProperty("instructions") private val instructions: String?, - @JsonProperty("metadata") private val metadata: JsonValue?, - @JsonProperty("name") private val name: String?, - @JsonProperty("response_format") private val responseFormat: AssistantResponseFormatOption?, - @JsonProperty("temperature") private val temperature: Double?, - @JsonProperty("tool_resources") private val toolResources: ToolResources?, - @JsonProperty("tools") private val tools: List?, - @JsonProperty("top_p") private val topP: Double?, + @JsonProperty("model") + @ExcludeMissing + private val model: JsonField = JsonMissing.of(), + @JsonProperty("description") + @ExcludeMissing + private val description: JsonField = JsonMissing.of(), + @JsonProperty("instructions") + @ExcludeMissing + private val instructions: JsonField = JsonMissing.of(), + @JsonProperty("metadata") + @ExcludeMissing + private val metadata: JsonValue = JsonMissing.of(), + @JsonProperty("name") + @ExcludeMissing + private val name: JsonField = JsonMissing.of(), + @JsonProperty("response_format") + @ExcludeMissing + private val responseFormat: JsonField = JsonMissing.of(), + @JsonProperty("temperature") + @ExcludeMissing + private val temperature: JsonField = JsonMissing.of(), + @JsonProperty("tool_resources") + @ExcludeMissing + private val toolResources: JsonField = JsonMissing.of(), + @JsonProperty("tools") + @ExcludeMissing + private val tools: JsonField> = JsonMissing.of(), + @JsonProperty("top_p") + @ExcludeMissing + private val topP: JsonField = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { @@ -135,29 +227,28 @@ constructor( * of your available models, or see our * [Model overview](https://platform.openai.com/docs/models) for descriptions of them. */ - @JsonProperty("model") fun model(): ChatModel = model + fun model(): ChatModel = model.getRequired("model") /** The description of the assistant. The maximum length is 512 characters. */ - @JsonProperty("description") - fun description(): Optional = Optional.ofNullable(description) + fun description(): Optional = + Optional.ofNullable(description.getNullable("description")) /** * The system instructions that the assistant uses. The maximum length is 256,000 * characters. */ - @JsonProperty("instructions") - fun instructions(): Optional = Optional.ofNullable(instructions) + fun instructions(): Optional = + Optional.ofNullable(instructions.getNullable("instructions")) /** * 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 maximum of 512 characters long. */ - @JsonProperty("metadata") - fun metadata(): Optional = Optional.ofNullable(metadata) + @JsonProperty("metadata") @ExcludeMissing fun _metadata(): JsonValue = metadata /** The name of the assistant. The maximum length is 256 characters. */ - @JsonProperty("name") fun name(): Optional = Optional.ofNullable(name) + fun name(): Optional = Optional.ofNullable(name.getNullable("name")) /** * Specifies the format that the model must output. Compatible with @@ -179,9 +270,87 @@ constructor( * partially cut off if `finish_reason="length"`, which indicates the generation exceeded * `max_tokens` or the conversation exceeded the max context length. */ - @JsonProperty("response_format") fun responseFormat(): Optional = - Optional.ofNullable(responseFormat) + Optional.ofNullable(responseFormat.getNullable("response_format")) + + /** + * 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. + */ + fun temperature(): Optional = + Optional.ofNullable(temperature.getNullable("temperature")) + + /** + * A set of resources that are used by the assistant's tools. The resources are specific to + * the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, + * while the `file_search` tool requires a list of vector store IDs. + */ + fun toolResources(): Optional = + Optional.ofNullable(toolResources.getNullable("tool_resources")) + + /** + * 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`, `file_search`, or `function`. + */ + fun tools(): Optional> = Optional.ofNullable(tools.getNullable("tools")) + + /** + * 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. + */ + fun topP(): Optional = Optional.ofNullable(topP.getNullable("top_p")) + + /** + * ID of the model to use. You can use the + * [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all + * of your available models, or see our + * [Model overview](https://platform.openai.com/docs/models) for descriptions of them. + */ + @JsonProperty("model") @ExcludeMissing fun _model(): JsonField = model + + /** The description of the assistant. The maximum length is 512 characters. */ + @JsonProperty("description") + @ExcludeMissing + fun _description(): JsonField = description + + /** + * The system instructions that the assistant uses. The maximum length is 256,000 + * characters. + */ + @JsonProperty("instructions") + @ExcludeMissing + fun _instructions(): JsonField = instructions + + /** The name of the assistant. The maximum length is 256 characters. */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Specifies the format that the model must output. Compatible with + * [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 + * Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 + * Turbo models since `gpt-3.5-turbo-1106`. + * + * Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs + * which ensures the model will match your supplied JSON schema. Learn more in the + * [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). + * + * Setting to `{ "type": "json_object" }` enables JSON mode, which ensures 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. + */ + @JsonProperty("response_format") + @ExcludeMissing + fun _responseFormat(): JsonField = responseFormat /** * What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the @@ -189,7 +358,8 @@ constructor( * deterministic. */ @JsonProperty("temperature") - fun temperature(): Optional = Optional.ofNullable(temperature) + @ExcludeMissing + fun _temperature(): JsonField = temperature /** * A set of resources that are used by the assistant's tools. The resources are specific to @@ -197,14 +367,14 @@ constructor( * while the `file_search` tool requires a list of vector store IDs. */ @JsonProperty("tool_resources") - fun toolResources(): Optional = Optional.ofNullable(toolResources) + @ExcludeMissing + fun _toolResources(): JsonField = toolResources /** * 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`, `file_search`, or `function`. */ - @JsonProperty("tools") - fun tools(): Optional> = Optional.ofNullable(tools) + @JsonProperty("tools") @ExcludeMissing fun _tools(): JsonField> = tools /** * An alternative to sampling with temperature, called nucleus sampling, where the model @@ -213,12 +383,29 @@ constructor( * * We generally recommend altering this or temperature but not both. */ - @JsonProperty("top_p") fun topP(): Optional = Optional.ofNullable(topP) + @JsonProperty("top_p") @ExcludeMissing fun _topP(): JsonField = topP @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): BetaAssistantCreateBody = apply { + if (!validated) { + model() + description() + instructions() + name() + responseFormat() + temperature() + toolResources().map { it.validate() } + tools() + topP() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -228,16 +415,16 @@ constructor( class Builder { - private var model: ChatModel? = null - private var description: String? = null - private var instructions: String? = null - private var metadata: JsonValue? = null - private var name: String? = null - private var responseFormat: AssistantResponseFormatOption? = null - private var temperature: Double? = null - private var toolResources: ToolResources? = null - private var tools: MutableList? = null - private var topP: Double? = null + private var model: JsonField? = null + private var description: JsonField = JsonMissing.of() + private var instructions: JsonField = JsonMissing.of() + private var metadata: JsonValue = JsonMissing.of() + private var name: JsonField = JsonMissing.of() + private var responseFormat: JsonField = JsonMissing.of() + private var temperature: JsonField = JsonMissing.of() + private var toolResources: JsonField = JsonMissing.of() + private var tools: JsonField>? = null + private var topP: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -250,7 +437,7 @@ constructor( responseFormat = betaAssistantCreateBody.responseFormat temperature = betaAssistantCreateBody.temperature toolResources = betaAssistantCreateBody.toolResources - tools = betaAssistantCreateBody.tools?.toMutableList() + tools = betaAssistantCreateBody.tools.map { it.toMutableList() } topP = betaAssistantCreateBody.topP additionalProperties = betaAssistantCreateBody.additionalProperties.toMutableMap() } @@ -261,7 +448,7 @@ constructor( * all of your available models, or see our * [Model overview](https://platform.openai.com/docs/models) for descriptions of them. */ - fun model(model: ChatModel) = apply { this.model = model } + fun model(model: ChatModel) = model(JsonField.of(model)) /** * ID of the model to use. You can use the @@ -269,16 +456,48 @@ constructor( * all of your available models, or see our * [Model overview](https://platform.openai.com/docs/models) for descriptions of them. */ - fun model(value: String) = apply { model = ChatModel.of(value) } + fun model(model: JsonField) = apply { this.model = model } + + /** + * ID of the model to use. You can use the + * [List models](https://platform.openai.com/docs/api-reference/models/list) API to see + * all of your available models, or see our + * [Model overview](https://platform.openai.com/docs/models) for descriptions of them. + */ + fun model(value: String) = apply { model(ChatModel.of(value)) } + + /** The description of the assistant. The maximum length is 512 characters. */ + fun description(description: String?) = description(JsonField.ofNullable(description)) + + /** The description of the assistant. The maximum length is 512 characters. */ + fun description(description: Optional) = description(description.orElse(null)) /** The description of the assistant. The maximum length is 512 characters. */ - fun description(description: String) = apply { this.description = description } + fun description(description: JsonField) = apply { + this.description = description + } + + /** + * The system instructions that the assistant uses. The maximum length is 256,000 + * characters. + */ + fun instructions(instructions: String?) = + instructions(JsonField.ofNullable(instructions)) /** * The system instructions that the assistant uses. The maximum length is 256,000 * characters. */ - fun instructions(instructions: String) = apply { this.instructions = instructions } + fun instructions(instructions: Optional) = + instructions(instructions.orElse(null)) + + /** + * The system instructions that the assistant uses. The maximum length is 256,000 + * characters. + */ + fun instructions(instructions: JsonField) = apply { + this.instructions = instructions + } /** * Set of 16 key-value pairs that can be attached to an object. This can be useful for @@ -288,7 +507,61 @@ constructor( fun metadata(metadata: JsonValue) = apply { this.metadata = metadata } /** The name of the assistant. The maximum length is 256 characters. */ - fun name(name: String) = apply { this.name = name } + fun name(name: String?) = name(JsonField.ofNullable(name)) + + /** The name of the assistant. The maximum length is 256 characters. */ + fun name(name: Optional) = name(name.orElse(null)) + + /** The name of the assistant. The maximum length is 256 characters. */ + fun name(name: JsonField) = apply { this.name = name } + + /** + * Specifies the format that the model must output. Compatible with + * [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 + * Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all + * GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. + * + * Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured + * Outputs which ensures the model will match your supplied JSON schema. Learn more in + * the + * [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). + * + * Setting to `{ "type": "json_object" }` enables JSON mode, which ensures 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. + */ + fun responseFormat(responseFormat: AssistantResponseFormatOption?) = + responseFormat(JsonField.ofNullable(responseFormat)) + + /** + * Specifies the format that the model must output. Compatible with + * [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 + * Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all + * GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. + * + * Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured + * Outputs which ensures the model will match your supplied JSON schema. Learn more in + * the + * [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). + * + * Setting to `{ "type": "json_object" }` enables JSON mode, which ensures 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. + */ + fun responseFormat(responseFormat: Optional) = + responseFormat(responseFormat.orElse(null)) /** * Specifies the format that the model must output. Compatible with @@ -311,47 +584,87 @@ constructor( * may be partially cut off if `finish_reason="length"`, which indicates the generation * exceeded `max_tokens` or the conversation exceeded the max context length. */ - fun responseFormat(responseFormat: AssistantResponseFormatOption) = apply { + fun responseFormat(responseFormat: JsonField) = apply { this.responseFormat = responseFormat } /** `auto` is the default value */ - fun responseFormat(behavior: AssistantResponseFormatOption.Behavior) = apply { - this.responseFormat = AssistantResponseFormatOption.ofBehavior(behavior) - } + fun responseFormat(behavior: AssistantResponseFormatOption.Behavior) = + responseFormat(AssistantResponseFormatOption.ofBehavior(behavior)) - fun responseFormat(responseFormatText: ResponseFormatText) = apply { - this.responseFormat = + fun responseFormat(responseFormatText: ResponseFormatText) = + responseFormat( AssistantResponseFormatOption.ofResponseFormatText(responseFormatText) - } + ) - fun responseFormat(responseFormatJsonObject: ResponseFormatJsonObject) = apply { - this.responseFormat = + fun responseFormat(responseFormatJsonObject: ResponseFormatJsonObject) = + responseFormat( AssistantResponseFormatOption.ofResponseFormatJsonObject( responseFormatJsonObject ) - } + ) - fun responseFormat(responseFormatJsonSchema: ResponseFormatJsonSchema) = apply { - this.responseFormat = + fun responseFormat(responseFormatJsonSchema: ResponseFormatJsonSchema) = + responseFormat( AssistantResponseFormatOption.ofResponseFormatJsonSchema( responseFormatJsonSchema ) - } + ) /** * 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. */ - fun temperature(temperature: Double) = apply { this.temperature = temperature } + fun temperature(temperature: Double?) = temperature(JsonField.ofNullable(temperature)) + + /** + * 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. + */ + fun temperature(temperature: Double) = temperature(temperature as Double?) + + /** + * 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. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun temperature(temperature: Optional) = + temperature(temperature.orElse(null) as Double?) + + /** + * 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. + */ + fun temperature(temperature: JsonField) = apply { + this.temperature = temperature + } + + /** + * A set of resources that are used by the assistant's tools. The resources are specific + * to the type of tool. For example, the `code_interpreter` tool requires a list of file + * IDs, while the `file_search` tool requires a list of vector store IDs. + */ + fun toolResources(toolResources: ToolResources?) = + toolResources(JsonField.ofNullable(toolResources)) /** * A set of resources that are used by the assistant's tools. The resources are specific * to the type of tool. For example, the `code_interpreter` tool requires a list of file * IDs, while the `file_search` tool requires a list of vector store IDs. */ - fun toolResources(toolResources: ToolResources) = apply { + fun toolResources(toolResources: Optional) = + toolResources(toolResources.orElse(null)) + + /** + * A set of resources that are used by the assistant's tools. The resources are specific + * to the type of tool. For example, the `code_interpreter` tool requires a list of file + * IDs, while the `file_search` tool requires a list of vector store IDs. + */ + fun toolResources(toolResources: JsonField) = apply { this.toolResources = toolResources } @@ -359,14 +672,31 @@ constructor( * 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`, `file_search`, or `function`. */ - fun tools(tools: List) = apply { this.tools = tools.toMutableList() } + fun tools(tools: List) = tools(JsonField.of(tools)) + + /** + * 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`, `file_search`, or `function`. + */ + fun tools(tools: JsonField>) = apply { + this.tools = tools.map { it.toMutableList() } + } /** * 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`, `file_search`, or `function`. */ fun addTool(tool: AssistantTool) = apply { - tools = (tools ?: mutableListOf()).apply { add(tool) } + tools = + (tools ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(tool) + } } /** @@ -376,7 +706,35 @@ constructor( * * We generally recommend altering this or temperature but not both. */ - fun topP(topP: Double) = apply { this.topP = topP } + fun topP(topP: Double?) = topP(JsonField.ofNullable(topP)) + + /** + * 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. + */ + fun topP(topP: Double) = topP(topP as Double?) + + /** + * 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. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun topP(topP: Optional) = topP(topP.orElse(null) as Double?) + + /** + * 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. + */ + fun topP(topP: JsonField) = apply { this.topP = topP } fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() @@ -407,7 +765,7 @@ constructor( responseFormat, temperature, toolResources, - tools?.toImmutable(), + (tools ?: JsonMissing.of()).map { it.toImmutable() }, topP, additionalProperties.toImmutable(), ) @@ -460,6 +818,14 @@ constructor( */ fun model(model: ChatModel) = apply { body.model(model) } + /** + * ID of the model to use. You can use the + * [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all + * of your available models, or see our + * [Model overview](https://platform.openai.com/docs/models) for descriptions of them. + */ + fun model(model: JsonField) = apply { body.model(model) } + /** * ID of the model to use. You can use the * [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all @@ -469,23 +835,96 @@ constructor( fun model(value: String) = apply { body.model(value) } /** The description of the assistant. The maximum length is 512 characters. */ - fun description(description: String) = apply { body.description(description) } + fun description(description: String?) = apply { body.description(description) } + + /** The description of the assistant. The maximum length is 512 characters. */ + fun description(description: Optional) = description(description.orElse(null)) + + /** The description of the assistant. The maximum length is 512 characters. */ + fun description(description: JsonField) = apply { body.description(description) } + + /** + * The system instructions that the assistant uses. The maximum length is 256,000 + * characters. + */ + fun instructions(instructions: String?) = apply { body.instructions(instructions) } /** * The system instructions that the assistant uses. The maximum length is 256,000 * characters. */ - fun instructions(instructions: String) = apply { body.instructions(instructions) } + fun instructions(instructions: Optional) = instructions(instructions.orElse(null)) + + /** + * The system instructions that the assistant uses. The maximum length is 256,000 + * characters. + */ + fun instructions(instructions: JsonField) = apply { + body.instructions(instructions) + } + + /** + * 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 maximum of 512 characters long. + */ + fun metadata(metadata: JsonValue) = apply { body.metadata(metadata) } + + /** The name of the assistant. The maximum length is 256 characters. */ + fun name(name: String?) = apply { body.name(name) } + + /** The name of the assistant. The maximum length is 256 characters. */ + fun name(name: Optional) = name(name.orElse(null)) + + /** The name of the assistant. The maximum length is 256 characters. */ + fun name(name: JsonField) = apply { body.name(name) } + + /** + * Specifies the format that the model must output. Compatible with + * [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 + * Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 + * Turbo models since `gpt-3.5-turbo-1106`. + * + * Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs + * which ensures the model will match your supplied JSON schema. Learn more in the + * [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). + * + * Setting to `{ "type": "json_object" }` enables JSON mode, which ensures 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. + */ + fun responseFormat(responseFormat: AssistantResponseFormatOption?) = apply { + body.responseFormat(responseFormat) + } /** - * 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 maximum of 512 characters long. + * Specifies the format that the model must output. Compatible with + * [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 + * Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 + * Turbo models since `gpt-3.5-turbo-1106`. + * + * Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs + * which ensures the model will match your supplied JSON schema. Learn more in the + * [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). + * + * Setting to `{ "type": "json_object" }` enables JSON mode, which ensures 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. */ - fun metadata(metadata: JsonValue) = apply { body.metadata(metadata) } - - /** The name of the assistant. The maximum length is 256 characters. */ - fun name(name: String) = apply { body.name(name) } + fun responseFormat(responseFormat: Optional) = + responseFormat(responseFormat.orElse(null)) /** * Specifies the format that the model must output. Compatible with @@ -507,7 +946,7 @@ constructor( * partially cut off if `finish_reason="length"`, which indicates the generation exceeded * `max_tokens` or the conversation exceeded the max context length. */ - fun responseFormat(responseFormat: AssistantResponseFormatOption) = apply { + fun responseFormat(responseFormat: JsonField) = apply { body.responseFormat(responseFormat) } @@ -533,14 +972,54 @@ constructor( * output more random, while lower values like 0.2 will make it more focused and * deterministic. */ - fun temperature(temperature: Double) = apply { body.temperature(temperature) } + fun temperature(temperature: Double?) = apply { body.temperature(temperature) } + + /** + * 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. + */ + fun temperature(temperature: Double) = temperature(temperature as Double?) + + /** + * 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. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun temperature(temperature: Optional) = + temperature(temperature.orElse(null) as Double?) + + /** + * 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. + */ + fun temperature(temperature: JsonField) = apply { body.temperature(temperature) } + + /** + * A set of resources that are used by the assistant's tools. The resources are specific to + * the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, + * while the `file_search` tool requires a list of vector store IDs. + */ + fun toolResources(toolResources: ToolResources?) = apply { + body.toolResources(toolResources) + } + + /** + * A set of resources that are used by the assistant's tools. The resources are specific to + * the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, + * while the `file_search` tool requires a list of vector store IDs. + */ + fun toolResources(toolResources: Optional) = + toolResources(toolResources.orElse(null)) /** * A set of resources that are used by the assistant's tools. The resources are specific to * the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, * while the `file_search` tool requires a list of vector store IDs. */ - fun toolResources(toolResources: ToolResources) = apply { + fun toolResources(toolResources: JsonField) = apply { body.toolResources(toolResources) } @@ -550,6 +1029,12 @@ constructor( */ fun tools(tools: List) = apply { body.tools(tools) } + /** + * 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`, `file_search`, or `function`. + */ + fun tools(tools: JsonField>) = apply { body.tools(tools) } + /** * 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`, `file_search`, or `function`. @@ -563,7 +1048,54 @@ constructor( * * We generally recommend altering this or temperature but not both. */ - fun topP(topP: Double) = apply { body.topP(topP) } + fun topP(topP: Double?) = apply { body.topP(topP) } + + /** + * 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. + */ + fun topP(topP: Double) = topP(topP as Double?) + + /** + * 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. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun topP(topP: Optional) = topP(topP.orElse(null) as Double?) + + /** + * 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. + */ + fun topP(topP: JsonField) = apply { body.topP(topP) } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() @@ -663,25 +1195,6 @@ constructor( additionalQueryParams.removeAll(keys) } - fun additionalBodyProperties(additionalBodyProperties: Map) = apply { - body.additionalProperties(additionalBodyProperties) - } - - fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { - body.putAdditionalProperty(key, value) - } - - fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = - apply { - body.putAllAdditionalProperties(additionalBodyProperties) - } - - fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } - - fun removeAllAdditionalBodyProperties(keys: Set) = apply { - body.removeAllAdditionalProperties(keys) - } - fun build(): BetaAssistantCreateParams = BetaAssistantCreateParams( body.build(), @@ -699,22 +1212,44 @@ constructor( class ToolResources @JsonCreator private constructor( - @JsonProperty("code_interpreter") private val codeInterpreter: CodeInterpreter?, - @JsonProperty("file_search") private val fileSearch: FileSearch?, + @JsonProperty("code_interpreter") + @ExcludeMissing + private val codeInterpreter: JsonField = JsonMissing.of(), + @JsonProperty("file_search") + @ExcludeMissing + private val fileSearch: JsonField = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { + fun codeInterpreter(): Optional = + Optional.ofNullable(codeInterpreter.getNullable("code_interpreter")) + + fun fileSearch(): Optional = + Optional.ofNullable(fileSearch.getNullable("file_search")) + @JsonProperty("code_interpreter") - fun codeInterpreter(): Optional = Optional.ofNullable(codeInterpreter) + @ExcludeMissing + fun _codeInterpreter(): JsonField = codeInterpreter @JsonProperty("file_search") - fun fileSearch(): Optional = Optional.ofNullable(fileSearch) + @ExcludeMissing + fun _fileSearch(): JsonField = fileSearch @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): ToolResources = apply { + if (!validated) { + codeInterpreter().map { it.validate() } + fileSearch().map { it.validate() } + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -724,8 +1259,8 @@ constructor( class Builder { - private var codeInterpreter: CodeInterpreter? = null - private var fileSearch: FileSearch? = null + private var codeInterpreter: JsonField = JsonMissing.of() + private var fileSearch: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -735,11 +1270,18 @@ constructor( additionalProperties = toolResources.additionalProperties.toMutableMap() } - fun codeInterpreter(codeInterpreter: CodeInterpreter) = apply { + fun codeInterpreter(codeInterpreter: CodeInterpreter) = + codeInterpreter(JsonField.of(codeInterpreter)) + + fun codeInterpreter(codeInterpreter: JsonField) = apply { this.codeInterpreter = codeInterpreter } - fun fileSearch(fileSearch: FileSearch) = apply { this.fileSearch = fileSearch } + fun fileSearch(fileSearch: FileSearch) = fileSearch(JsonField.of(fileSearch)) + + fun fileSearch(fileSearch: JsonField) = apply { + this.fileSearch = fileSearch + } fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() @@ -772,23 +1314,43 @@ constructor( class CodeInterpreter @JsonCreator private constructor( - @JsonProperty("file_ids") private val fileIds: List?, + @JsonProperty("file_ids") + @ExcludeMissing + private val fileIds: JsonField> = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { + /** + * A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made + * available to the `code_interpreter` tool. There can be a maximum of 20 files + * associated with the tool. + */ + fun fileIds(): Optional> = + Optional.ofNullable(fileIds.getNullable("file_ids")) + /** * A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made * available to the `code_interpreter` tool. There can be a maximum of 20 files * associated with the tool. */ @JsonProperty("file_ids") - fun fileIds(): Optional> = Optional.ofNullable(fileIds) + @ExcludeMissing + fun _fileIds(): JsonField> = fileIds @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): CodeInterpreter = apply { + if (!validated) { + fileIds() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -798,12 +1360,12 @@ constructor( class Builder { - private var fileIds: MutableList? = null + private var fileIds: JsonField>? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(codeInterpreter: CodeInterpreter) = apply { - fileIds = codeInterpreter.fileIds?.toMutableList() + fileIds = codeInterpreter.fileIds.map { it.toMutableList() } additionalProperties = codeInterpreter.additionalProperties.toMutableMap() } @@ -812,8 +1374,15 @@ constructor( * available to the `code_interpreter` tool. There can be a maximum of 20 files * associated with the tool. */ - fun fileIds(fileIds: List) = apply { - this.fileIds = fileIds.toMutableList() + fun fileIds(fileIds: List) = fileIds(JsonField.of(fileIds)) + + /** + * A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made + * available to the `code_interpreter` tool. There can be a maximum of 20 files + * associated with the tool. + */ + fun fileIds(fileIds: JsonField>) = apply { + this.fileIds = fileIds.map { it.toMutableList() } } /** @@ -822,7 +1391,16 @@ constructor( * associated with the tool. */ fun addFileId(fileId: String) = apply { - fileIds = (fileIds ?: mutableListOf()).apply { add(fileId) } + fileIds = + (fileIds ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(fileId) + } } fun additionalProperties(additionalProperties: Map) = apply { @@ -848,7 +1426,10 @@ constructor( } fun build(): CodeInterpreter = - CodeInterpreter(fileIds?.toImmutable(), additionalProperties.toImmutable()) + CodeInterpreter( + (fileIds ?: JsonMissing.of()).map { it.toImmutable() }, + additionalProperties.toImmutable() + ) } override fun equals(other: Any?): Boolean { @@ -873,12 +1454,34 @@ constructor( class FileSearch @JsonCreator private constructor( - @JsonProperty("vector_store_ids") private val vectorStoreIds: List?, - @JsonProperty("vector_stores") private val vectorStores: List?, + @JsonProperty("vector_store_ids") + @ExcludeMissing + private val vectorStoreIds: JsonField> = JsonMissing.of(), + @JsonProperty("vector_stores") + @ExcludeMissing + private val vectorStores: JsonField> = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { + /** + * The + * [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) + * attached to this assistant. There can be a maximum of 1 vector store attached to the + * assistant. + */ + fun vectorStoreIds(): Optional> = + Optional.ofNullable(vectorStoreIds.getNullable("vector_store_ids")) + + /** + * A helper to create a + * [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) + * with file_ids and attach it to this assistant. There can be a maximum of 1 vector + * store attached to the assistant. + */ + fun vectorStores(): Optional> = + Optional.ofNullable(vectorStores.getNullable("vector_stores")) + /** * The * [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) @@ -886,7 +1489,8 @@ constructor( * assistant. */ @JsonProperty("vector_store_ids") - fun vectorStoreIds(): Optional> = Optional.ofNullable(vectorStoreIds) + @ExcludeMissing + fun _vectorStoreIds(): JsonField> = vectorStoreIds /** * A helper to create a @@ -895,12 +1499,23 @@ constructor( * store attached to the assistant. */ @JsonProperty("vector_stores") - fun vectorStores(): Optional> = Optional.ofNullable(vectorStores) + @ExcludeMissing + fun _vectorStores(): JsonField> = vectorStores @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): FileSearch = apply { + if (!validated) { + vectorStoreIds() + vectorStores().map { it.forEach { it.validate() } } + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -910,14 +1525,14 @@ constructor( class Builder { - private var vectorStoreIds: MutableList? = null - private var vectorStores: MutableList? = null + private var vectorStoreIds: JsonField>? = null + private var vectorStores: JsonField>? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(fileSearch: FileSearch) = apply { - vectorStoreIds = fileSearch.vectorStoreIds?.toMutableList() - vectorStores = fileSearch.vectorStores?.toMutableList() + vectorStoreIds = fileSearch.vectorStoreIds.map { it.toMutableList() } + vectorStores = fileSearch.vectorStores.map { it.toMutableList() } additionalProperties = fileSearch.additionalProperties.toMutableMap() } @@ -927,8 +1542,17 @@ constructor( * attached to this assistant. There can be a maximum of 1 vector store attached to * the assistant. */ - fun vectorStoreIds(vectorStoreIds: List) = apply { - this.vectorStoreIds = vectorStoreIds.toMutableList() + fun vectorStoreIds(vectorStoreIds: List) = + vectorStoreIds(JsonField.of(vectorStoreIds)) + + /** + * The + * [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) + * attached to this assistant. There can be a maximum of 1 vector store attached to + * the assistant. + */ + fun vectorStoreIds(vectorStoreIds: JsonField>) = apply { + this.vectorStoreIds = vectorStoreIds.map { it.toMutableList() } } /** @@ -939,7 +1563,15 @@ constructor( */ fun addVectorStoreId(vectorStoreId: String) = apply { vectorStoreIds = - (vectorStoreIds ?: mutableListOf()).apply { add(vectorStoreId) } + (vectorStoreIds ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(vectorStoreId) + } } /** @@ -948,8 +1580,17 @@ constructor( * with file_ids and attach it to this assistant. There can be a maximum of 1 vector * store attached to the assistant. */ - fun vectorStores(vectorStores: List) = apply { - this.vectorStores = vectorStores.toMutableList() + fun vectorStores(vectorStores: List) = + vectorStores(JsonField.of(vectorStores)) + + /** + * A helper to create a + * [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) + * with file_ids and attach it to this assistant. There can be a maximum of 1 vector + * store attached to the assistant. + */ + fun vectorStores(vectorStores: JsonField>) = apply { + this.vectorStores = vectorStores.map { it.toMutableList() } } /** @@ -959,7 +1600,16 @@ constructor( * store attached to the assistant. */ fun addVectorStore(vectorStore: VectorStore) = apply { - vectorStores = (vectorStores ?: mutableListOf()).apply { add(vectorStore) } + vectorStores = + (vectorStores ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(vectorStore) + } } fun additionalProperties(additionalProperties: Map) = apply { @@ -986,8 +1636,8 @@ constructor( fun build(): FileSearch = FileSearch( - vectorStoreIds?.toImmutable(), - vectorStores?.toImmutable(), + (vectorStoreIds ?: JsonMissing.of()).map { it.toImmutable() }, + (vectorStores ?: JsonMissing.of()).map { it.toImmutable() }, additionalProperties.toImmutable(), ) } @@ -997,9 +1647,15 @@ constructor( @JsonCreator private constructor( @JsonProperty("chunking_strategy") - private val chunkingStrategy: FileChunkingStrategyParam?, - @JsonProperty("file_ids") private val fileIds: List?, - @JsonProperty("metadata") private val metadata: JsonValue?, + @ExcludeMissing + private val chunkingStrategy: JsonField = + JsonMissing.of(), + @JsonProperty("file_ids") + @ExcludeMissing + private val fileIds: JsonField> = JsonMissing.of(), + @JsonProperty("metadata") + @ExcludeMissing + private val metadata: JsonValue = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { @@ -1008,16 +1664,15 @@ constructor( * The chunking strategy used to chunk the file(s). If not set, will use the `auto` * strategy. Only applicable if `file_ids` is non-empty. */ - @JsonProperty("chunking_strategy") fun chunkingStrategy(): Optional = - Optional.ofNullable(chunkingStrategy) + Optional.ofNullable(chunkingStrategy.getNullable("chunking_strategy")) /** * A list of [file](https://platform.openai.com/docs/api-reference/files) IDs to add * to the vector store. There can be a maximum of 10000 files in a vector store. */ - @JsonProperty("file_ids") - fun fileIds(): Optional> = Optional.ofNullable(fileIds) + fun fileIds(): Optional> = + Optional.ofNullable(fileIds.getNullable("file_ids")) /** * Set of 16 key-value pairs that can be attached to a vector store. This can be @@ -1025,13 +1680,38 @@ constructor( * format. Keys can be a maximum of 64 characters long and values can be a maximum * of 512 characters long. */ - @JsonProperty("metadata") - fun metadata(): Optional = Optional.ofNullable(metadata) + @JsonProperty("metadata") @ExcludeMissing fun _metadata(): JsonValue = metadata + + /** + * The chunking strategy used to chunk the file(s). If not set, will use the `auto` + * strategy. Only applicable if `file_ids` is non-empty. + */ + @JsonProperty("chunking_strategy") + @ExcludeMissing + fun _chunkingStrategy(): JsonField = chunkingStrategy + + /** + * A list of [file](https://platform.openai.com/docs/api-reference/files) IDs to add + * to the vector store. There can be a maximum of 10000 files in a vector store. + */ + @JsonProperty("file_ids") + @ExcludeMissing + fun _fileIds(): JsonField> = fileIds @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): VectorStore = apply { + if (!validated) { + chunkingStrategy() + fileIds() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -1041,15 +1721,16 @@ constructor( class Builder { - private var chunkingStrategy: FileChunkingStrategyParam? = null - private var fileIds: MutableList? = null - private var metadata: JsonValue? = null + private var chunkingStrategy: JsonField = + JsonMissing.of() + private var fileIds: JsonField>? = null + private var metadata: JsonValue = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(vectorStore: VectorStore) = apply { chunkingStrategy = vectorStore.chunkingStrategy - fileIds = vectorStore.fileIds?.toMutableList() + fileIds = vectorStore.fileIds.map { it.toMutableList() } metadata = vectorStore.metadata additionalProperties = vectorStore.additionalProperties.toMutableMap() } @@ -1058,9 +1739,17 @@ constructor( * The chunking strategy used to chunk the file(s). If not set, will use the * `auto` strategy. Only applicable if `file_ids` is non-empty. */ - fun chunkingStrategy(chunkingStrategy: FileChunkingStrategyParam) = apply { - this.chunkingStrategy = chunkingStrategy - } + fun chunkingStrategy(chunkingStrategy: FileChunkingStrategyParam) = + chunkingStrategy(JsonField.of(chunkingStrategy)) + + /** + * The chunking strategy used to chunk the file(s). If not set, will use the + * `auto` strategy. Only applicable if `file_ids` is non-empty. + */ + fun chunkingStrategy(chunkingStrategy: JsonField) = + apply { + this.chunkingStrategy = chunkingStrategy + } /** * The default strategy. This strategy currently uses a `max_chunk_size_tokens` @@ -1068,29 +1757,36 @@ constructor( */ fun chunkingStrategy( autoFileChunkingStrategyParam: AutoFileChunkingStrategyParam - ) = apply { - this.chunkingStrategy = + ) = + chunkingStrategy( FileChunkingStrategyParam.ofAutoFileChunkingStrategyParam( autoFileChunkingStrategyParam ) - } + ) fun chunkingStrategy( staticFileChunkingStrategyParam: StaticFileChunkingStrategyParam - ) = apply { - this.chunkingStrategy = + ) = + chunkingStrategy( FileChunkingStrategyParam.ofStaticFileChunkingStrategyParam( staticFileChunkingStrategyParam ) - } + ) + + /** + * A list of [file](https://platform.openai.com/docs/api-reference/files) IDs to + * add to the vector store. There can be a maximum of 10000 files in a vector + * store. + */ + fun fileIds(fileIds: List) = fileIds(JsonField.of(fileIds)) /** * A list of [file](https://platform.openai.com/docs/api-reference/files) IDs to * add to the vector store. There can be a maximum of 10000 files in a vector * store. */ - fun fileIds(fileIds: List) = apply { - this.fileIds = fileIds.toMutableList() + fun fileIds(fileIds: JsonField>) = apply { + this.fileIds = fileIds.map { it.toMutableList() } } /** @@ -1099,7 +1795,16 @@ constructor( * store. */ fun addFileId(fileId: String) = apply { - fileIds = (fileIds ?: mutableListOf()).apply { add(fileId) } + fileIds = + (fileIds ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(fileId) + } } /** @@ -1135,7 +1840,7 @@ constructor( fun build(): VectorStore = VectorStore( chunkingStrategy, - fileIds?.toImmutable(), + (fileIds ?: JsonMissing.of()).map { it.toImmutable() }, metadata, additionalProperties.toImmutable(), ) diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaAssistantDeleteParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaAssistantDeleteParams.kt index 76e0c8e9a..dbfe9b9aa 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaAssistantDeleteParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaAssistantDeleteParams.kt @@ -10,6 +10,7 @@ import com.openai.core.toImmutable import java.util.Objects import java.util.Optional +/** Delete an assistant. */ class BetaAssistantDeleteParams constructor( private val assistantId: String, diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaAssistantListParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaAssistantListParams.kt index 21912e347..02d156050 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaAssistantListParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaAssistantListParams.kt @@ -12,6 +12,7 @@ import com.openai.errors.OpenAIInvalidDataException import java.util.Objects import java.util.Optional +/** Returns a list of assistants. */ class BetaAssistantListParams constructor( private val after: String?, @@ -98,7 +99,15 @@ constructor( * obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page * of the list. */ - fun after(after: String) = apply { this.after = after } + fun after(after: String?) = apply { this.after = after } + + /** + * 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. + */ + fun after(after: Optional) = after(after.orElse(null)) /** * A cursor for use in pagination. `before` is an object ID that defines your place in the @@ -106,19 +115,46 @@ constructor( * obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous * page of the list. */ - fun before(before: String) = apply { this.before = before } + fun before(before: String?) = apply { this.before = before } + + /** + * 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, starting with + * obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous + * page of the list. + */ + fun before(before: Optional) = before(before.orElse(null)) /** * A limit on the number of objects to be returned. Limit can range between 1 and 100, and * the default is 20. */ - fun limit(limit: Long) = apply { this.limit = limit } + fun limit(limit: Long?) = apply { this.limit = limit } + + /** + * A limit on the number of objects to be returned. Limit can range between 1 and 100, and + * the default is 20. + */ + fun limit(limit: Long) = limit(limit as Long?) + + /** + * A limit on the number of objects to be returned. Limit can range between 1 and 100, and + * the default is 20. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun limit(limit: Optional) = limit(limit.orElse(null) as Long?) + + /** + * Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and + * `desc` for descending order. + */ + fun order(order: Order?) = apply { this.order = order } /** * Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and * `desc` for descending order. */ - fun order(order: Order) = apply { this.order = order } + fun order(order: Optional) = order(order.orElse(null)) fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaAssistantRetrieveParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaAssistantRetrieveParams.kt index 3607834eb..11fa751bf 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaAssistantRetrieveParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaAssistantRetrieveParams.kt @@ -7,6 +7,7 @@ import com.openai.core.http.Headers import com.openai.core.http.QueryParams import java.util.Objects +/** Retrieves an assistant. */ class BetaAssistantRetrieveParams constructor( private val assistantId: String, diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaAssistantUpdateParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaAssistantUpdateParams.kt index 9c782ac99..4a0f70d6b 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaAssistantUpdateParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaAssistantUpdateParams.kt @@ -7,6 +7,8 @@ import com.fasterxml.jackson.annotation.JsonAnySetter import com.fasterxml.jackson.annotation.JsonCreator import com.fasterxml.jackson.annotation.JsonProperty import com.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing import com.openai.core.JsonValue import com.openai.core.NoAutoDetect import com.openai.core.http.Headers @@ -16,6 +18,7 @@ import com.openai.core.toImmutable import java.util.Objects import java.util.Optional +/** Modifies an assistant. */ class BetaAssistantUpdateParams constructor( private val assistantId: String, @@ -39,7 +42,7 @@ constructor( * additional information about the object in a structured format. Keys can be a maximum of 64 * characters long and values can be a maximum of 512 characters long. */ - fun metadata(): Optional = body.metadata() + fun _metadata(): JsonValue = body._metadata() /** * ID of the model to use. You can use the @@ -102,12 +105,81 @@ constructor( */ fun topP(): Optional = body.topP() - fun _additionalHeaders(): Headers = additionalHeaders + /** The description of the assistant. The maximum length is 512 characters. */ + fun _description(): JsonField = body._description() - fun _additionalQueryParams(): QueryParams = additionalQueryParams + /** + * The system instructions that the assistant uses. The maximum length is 256,000 characters. + */ + fun _instructions(): JsonField = body._instructions() + + /** + * ID of the model to use. You can use the + * [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all of + * your available models, or see our [Model overview](https://platform.openai.com/docs/models) + * for descriptions of them. + */ + fun _model(): JsonField = body._model() + + /** The name of the assistant. The maximum length is 256 characters. */ + fun _name(): JsonField = body._name() + + /** + * Specifies the format that the model must output. Compatible with + * [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 + * Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo + * models since `gpt-3.5-turbo-1106`. + * + * Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which + * ensures the model will match your supplied JSON schema. Learn more in the + * [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). + * + * Setting to `{ "type": "json_object" }` enables JSON mode, which ensures 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. + */ + fun _responseFormat(): JsonField = body._responseFormat() + + /** + * 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. + */ + fun _temperature(): JsonField = body._temperature() + + /** + * A set of resources that are used by the assistant's tools. The resources are specific to the + * type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the + * `file_search` tool requires a list of vector store IDs. + */ + fun _toolResources(): JsonField = body._toolResources() + + /** + * 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`, `file_search`, or `function`. + */ + fun _tools(): JsonField> = body._tools() + + /** + * 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. + */ + fun _topP(): JsonField = body._topP() fun _additionalBodyProperties(): Map = body._additionalProperties() + fun _additionalHeaders(): Headers = additionalHeaders + + fun _additionalQueryParams(): QueryParams = additionalQueryParams + @JvmSynthetic internal fun getBody(): BetaAssistantUpdateBody = body @JvmSynthetic internal fun getHeaders(): Headers = additionalHeaders @@ -125,38 +197,57 @@ constructor( class BetaAssistantUpdateBody @JsonCreator internal constructor( - @JsonProperty("description") private val description: String?, - @JsonProperty("instructions") private val instructions: String?, - @JsonProperty("metadata") private val metadata: JsonValue?, - @JsonProperty("model") private val model: String?, - @JsonProperty("name") private val name: String?, - @JsonProperty("response_format") private val responseFormat: AssistantResponseFormatOption?, - @JsonProperty("temperature") private val temperature: Double?, - @JsonProperty("tool_resources") private val toolResources: ToolResources?, - @JsonProperty("tools") private val tools: List?, - @JsonProperty("top_p") private val topP: Double?, + @JsonProperty("description") + @ExcludeMissing + private val description: JsonField = JsonMissing.of(), + @JsonProperty("instructions") + @ExcludeMissing + private val instructions: JsonField = JsonMissing.of(), + @JsonProperty("metadata") + @ExcludeMissing + private val metadata: JsonValue = JsonMissing.of(), + @JsonProperty("model") + @ExcludeMissing + private val model: JsonField = JsonMissing.of(), + @JsonProperty("name") + @ExcludeMissing + private val name: JsonField = JsonMissing.of(), + @JsonProperty("response_format") + @ExcludeMissing + private val responseFormat: JsonField = JsonMissing.of(), + @JsonProperty("temperature") + @ExcludeMissing + private val temperature: JsonField = JsonMissing.of(), + @JsonProperty("tool_resources") + @ExcludeMissing + private val toolResources: JsonField = JsonMissing.of(), + @JsonProperty("tools") + @ExcludeMissing + private val tools: JsonField> = JsonMissing.of(), + @JsonProperty("top_p") + @ExcludeMissing + private val topP: JsonField = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { /** The description of the assistant. The maximum length is 512 characters. */ - @JsonProperty("description") - fun description(): Optional = Optional.ofNullable(description) + fun description(): Optional = + Optional.ofNullable(description.getNullable("description")) /** * The system instructions that the assistant uses. The maximum length is 256,000 * characters. */ - @JsonProperty("instructions") - fun instructions(): Optional = Optional.ofNullable(instructions) + fun instructions(): Optional = + Optional.ofNullable(instructions.getNullable("instructions")) /** * 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 maximum of 512 characters long. */ - @JsonProperty("metadata") - fun metadata(): Optional = Optional.ofNullable(metadata) + @JsonProperty("metadata") @ExcludeMissing fun _metadata(): JsonValue = metadata /** * ID of the model to use. You can use the @@ -164,10 +255,10 @@ constructor( * of your available models, or see our * [Model overview](https://platform.openai.com/docs/models) for descriptions of them. */ - @JsonProperty("model") fun model(): Optional = Optional.ofNullable(model) + fun model(): Optional = Optional.ofNullable(model.getNullable("model")) /** The name of the assistant. The maximum length is 256 characters. */ - @JsonProperty("name") fun name(): Optional = Optional.ofNullable(name) + fun name(): Optional = Optional.ofNullable(name.getNullable("name")) /** * Specifies the format that the model must output. Compatible with @@ -189,9 +280,87 @@ constructor( * partially cut off if `finish_reason="length"`, which indicates the generation exceeded * `max_tokens` or the conversation exceeded the max context length. */ - @JsonProperty("response_format") fun responseFormat(): Optional = - Optional.ofNullable(responseFormat) + Optional.ofNullable(responseFormat.getNullable("response_format")) + + /** + * 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. + */ + fun temperature(): Optional = + Optional.ofNullable(temperature.getNullable("temperature")) + + /** + * A set of resources that are used by the assistant's tools. The resources are specific to + * the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, + * while the `file_search` tool requires a list of vector store IDs. + */ + fun toolResources(): Optional = + Optional.ofNullable(toolResources.getNullable("tool_resources")) + + /** + * 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`, `file_search`, or `function`. + */ + fun tools(): Optional> = Optional.ofNullable(tools.getNullable("tools")) + + /** + * 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. + */ + fun topP(): Optional = Optional.ofNullable(topP.getNullable("top_p")) + + /** The description of the assistant. The maximum length is 512 characters. */ + @JsonProperty("description") + @ExcludeMissing + fun _description(): JsonField = description + + /** + * The system instructions that the assistant uses. The maximum length is 256,000 + * characters. + */ + @JsonProperty("instructions") + @ExcludeMissing + fun _instructions(): JsonField = instructions + + /** + * ID of the model to use. You can use the + * [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all + * of your available models, or see our + * [Model overview](https://platform.openai.com/docs/models) for descriptions of them. + */ + @JsonProperty("model") @ExcludeMissing fun _model(): JsonField = model + + /** The name of the assistant. The maximum length is 256 characters. */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name + + /** + * Specifies the format that the model must output. Compatible with + * [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 + * Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 + * Turbo models since `gpt-3.5-turbo-1106`. + * + * Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs + * which ensures the model will match your supplied JSON schema. Learn more in the + * [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). + * + * Setting to `{ "type": "json_object" }` enables JSON mode, which ensures 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. + */ + @JsonProperty("response_format") + @ExcludeMissing + fun _responseFormat(): JsonField = responseFormat /** * What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the @@ -199,7 +368,8 @@ constructor( * deterministic. */ @JsonProperty("temperature") - fun temperature(): Optional = Optional.ofNullable(temperature) + @ExcludeMissing + fun _temperature(): JsonField = temperature /** * A set of resources that are used by the assistant's tools. The resources are specific to @@ -207,14 +377,14 @@ constructor( * while the `file_search` tool requires a list of vector store IDs. */ @JsonProperty("tool_resources") - fun toolResources(): Optional = Optional.ofNullable(toolResources) + @ExcludeMissing + fun _toolResources(): JsonField = toolResources /** * 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`, `file_search`, or `function`. */ - @JsonProperty("tools") - fun tools(): Optional> = Optional.ofNullable(tools) + @JsonProperty("tools") @ExcludeMissing fun _tools(): JsonField> = tools /** * An alternative to sampling with temperature, called nucleus sampling, where the model @@ -223,12 +393,29 @@ constructor( * * We generally recommend altering this or temperature but not both. */ - @JsonProperty("top_p") fun topP(): Optional = Optional.ofNullable(topP) + @JsonProperty("top_p") @ExcludeMissing fun _topP(): JsonField = topP @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): BetaAssistantUpdateBody = apply { + if (!validated) { + description() + instructions() + model() + name() + responseFormat() + temperature() + toolResources().map { it.validate() } + tools() + topP() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -238,16 +425,16 @@ constructor( class Builder { - private var description: String? = null - private var instructions: String? = null - private var metadata: JsonValue? = null - private var model: String? = null - private var name: String? = null - private var responseFormat: AssistantResponseFormatOption? = null - private var temperature: Double? = null - private var toolResources: ToolResources? = null - private var tools: MutableList? = null - private var topP: Double? = null + private var description: JsonField = JsonMissing.of() + private var instructions: JsonField = JsonMissing.of() + private var metadata: JsonValue = JsonMissing.of() + private var model: JsonField = JsonMissing.of() + private var name: JsonField = JsonMissing.of() + private var responseFormat: JsonField = JsonMissing.of() + private var temperature: JsonField = JsonMissing.of() + private var toolResources: JsonField = JsonMissing.of() + private var tools: JsonField>? = null + private var topP: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -260,19 +447,43 @@ constructor( responseFormat = betaAssistantUpdateBody.responseFormat temperature = betaAssistantUpdateBody.temperature toolResources = betaAssistantUpdateBody.toolResources - tools = betaAssistantUpdateBody.tools?.toMutableList() + tools = betaAssistantUpdateBody.tools.map { it.toMutableList() } topP = betaAssistantUpdateBody.topP additionalProperties = betaAssistantUpdateBody.additionalProperties.toMutableMap() } /** The description of the assistant. The maximum length is 512 characters. */ - fun description(description: String) = apply { this.description = description } + fun description(description: String?) = description(JsonField.ofNullable(description)) + + /** The description of the assistant. The maximum length is 512 characters. */ + fun description(description: Optional) = description(description.orElse(null)) + + /** The description of the assistant. The maximum length is 512 characters. */ + fun description(description: JsonField) = apply { + this.description = description + } /** * The system instructions that the assistant uses. The maximum length is 256,000 * characters. */ - fun instructions(instructions: String) = apply { this.instructions = instructions } + fun instructions(instructions: String?) = + instructions(JsonField.ofNullable(instructions)) + + /** + * The system instructions that the assistant uses. The maximum length is 256,000 + * characters. + */ + fun instructions(instructions: Optional) = + instructions(instructions.orElse(null)) + + /** + * The system instructions that the assistant uses. The maximum length is 256,000 + * characters. + */ + fun instructions(instructions: JsonField) = apply { + this.instructions = instructions + } /** * Set of 16 key-value pairs that can be attached to an object. This can be useful for @@ -287,10 +498,24 @@ constructor( * all of your available models, or see our * [Model overview](https://platform.openai.com/docs/models) for descriptions of them. */ - fun model(model: String) = apply { this.model = model } + fun model(model: String) = model(JsonField.of(model)) + + /** + * ID of the model to use. You can use the + * [List models](https://platform.openai.com/docs/api-reference/models/list) API to see + * all of your available models, or see our + * [Model overview](https://platform.openai.com/docs/models) for descriptions of them. + */ + fun model(model: JsonField) = apply { this.model = model } + + /** The name of the assistant. The maximum length is 256 characters. */ + fun name(name: String?) = name(JsonField.ofNullable(name)) + + /** The name of the assistant. The maximum length is 256 characters. */ + fun name(name: Optional) = name(name.orElse(null)) /** The name of the assistant. The maximum length is 256 characters. */ - fun name(name: String) = apply { this.name = name } + fun name(name: JsonField) = apply { this.name = name } /** * Specifies the format that the model must output. Compatible with @@ -313,62 +538,167 @@ constructor( * may be partially cut off if `finish_reason="length"`, which indicates the generation * exceeded `max_tokens` or the conversation exceeded the max context length. */ - fun responseFormat(responseFormat: AssistantResponseFormatOption) = apply { + fun responseFormat(responseFormat: AssistantResponseFormatOption?) = + responseFormat(JsonField.ofNullable(responseFormat)) + + /** + * Specifies the format that the model must output. Compatible with + * [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 + * Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all + * GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. + * + * Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured + * Outputs which ensures the model will match your supplied JSON schema. Learn more in + * the + * [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). + * + * Setting to `{ "type": "json_object" }` enables JSON mode, which ensures 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. + */ + fun responseFormat(responseFormat: Optional) = + responseFormat(responseFormat.orElse(null)) + + /** + * Specifies the format that the model must output. Compatible with + * [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 + * Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all + * GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. + * + * Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured + * Outputs which ensures the model will match your supplied JSON schema. Learn more in + * the + * [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). + * + * Setting to `{ "type": "json_object" }` enables JSON mode, which ensures 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. + */ + fun responseFormat(responseFormat: JsonField) = apply { this.responseFormat = responseFormat } /** `auto` is the default value */ - fun responseFormat(behavior: AssistantResponseFormatOption.Behavior) = apply { - this.responseFormat = AssistantResponseFormatOption.ofBehavior(behavior) - } + fun responseFormat(behavior: AssistantResponseFormatOption.Behavior) = + responseFormat(AssistantResponseFormatOption.ofBehavior(behavior)) - fun responseFormat(responseFormatText: ResponseFormatText) = apply { - this.responseFormat = + fun responseFormat(responseFormatText: ResponseFormatText) = + responseFormat( AssistantResponseFormatOption.ofResponseFormatText(responseFormatText) - } + ) - fun responseFormat(responseFormatJsonObject: ResponseFormatJsonObject) = apply { - this.responseFormat = + fun responseFormat(responseFormatJsonObject: ResponseFormatJsonObject) = + responseFormat( AssistantResponseFormatOption.ofResponseFormatJsonObject( responseFormatJsonObject ) - } + ) - fun responseFormat(responseFormatJsonSchema: ResponseFormatJsonSchema) = apply { - this.responseFormat = + fun responseFormat(responseFormatJsonSchema: ResponseFormatJsonSchema) = + responseFormat( AssistantResponseFormatOption.ofResponseFormatJsonSchema( responseFormatJsonSchema ) - } + ) + + /** + * 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. + */ + fun temperature(temperature: Double?) = temperature(JsonField.ofNullable(temperature)) + + /** + * 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. + */ + fun temperature(temperature: Double) = temperature(temperature as Double?) /** * 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. */ - fun temperature(temperature: Double) = apply { this.temperature = temperature } + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun temperature(temperature: Optional) = + temperature(temperature.orElse(null) as Double?) + + /** + * 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. + */ + fun temperature(temperature: JsonField) = apply { + this.temperature = temperature + } + + /** + * A set of resources that are used by the assistant's tools. The resources are specific + * to the type of tool. For example, the `code_interpreter` tool requires a list of file + * IDs, while the `file_search` tool requires a list of vector store IDs. + */ + fun toolResources(toolResources: ToolResources?) = + toolResources(JsonField.ofNullable(toolResources)) /** * A set of resources that are used by the assistant's tools. The resources are specific * to the type of tool. For example, the `code_interpreter` tool requires a list of file * IDs, while the `file_search` tool requires a list of vector store IDs. */ - fun toolResources(toolResources: ToolResources) = apply { - this.toolResources = toolResources - } + fun toolResources(toolResources: Optional) = + toolResources(toolResources.orElse(null)) + + /** + * A set of resources that are used by the assistant's tools. The resources are specific + * to the type of tool. For example, the `code_interpreter` tool requires a list of file + * IDs, while the `file_search` tool requires a list of vector store IDs. + */ + fun toolResources(toolResources: JsonField) = apply { + this.toolResources = toolResources + } + + /** + * 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`, `file_search`, or `function`. + */ + fun tools(tools: List) = tools(JsonField.of(tools)) /** * 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`, `file_search`, or `function`. */ - fun tools(tools: List) = apply { this.tools = tools.toMutableList() } + fun tools(tools: JsonField>) = apply { + this.tools = tools.map { it.toMutableList() } + } /** * 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`, `file_search`, or `function`. */ fun addTool(tool: AssistantTool) = apply { - tools = (tools ?: mutableListOf()).apply { add(tool) } + tools = + (tools ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(tool) + } } /** @@ -378,7 +708,35 @@ constructor( * * We generally recommend altering this or temperature but not both. */ - fun topP(topP: Double) = apply { this.topP = topP } + fun topP(topP: Double?) = topP(JsonField.ofNullable(topP)) + + /** + * 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. + */ + fun topP(topP: Double) = topP(topP as Double?) + + /** + * 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. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun topP(topP: Optional) = topP(topP.orElse(null) as Double?) + + /** + * 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. + */ + fun topP(topP: JsonField) = apply { this.topP = topP } fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() @@ -409,7 +767,7 @@ constructor( responseFormat, temperature, toolResources, - tools?.toImmutable(), + (tools ?: JsonMissing.of()).map { it.toImmutable() }, topP, additionalProperties.toImmutable(), ) @@ -459,13 +817,33 @@ constructor( fun assistantId(assistantId: String) = apply { this.assistantId = assistantId } /** The description of the assistant. The maximum length is 512 characters. */ - fun description(description: String) = apply { body.description(description) } + fun description(description: String?) = apply { body.description(description) } + + /** The description of the assistant. The maximum length is 512 characters. */ + fun description(description: Optional) = description(description.orElse(null)) + + /** The description of the assistant. The maximum length is 512 characters. */ + fun description(description: JsonField) = apply { body.description(description) } + + /** + * The system instructions that the assistant uses. The maximum length is 256,000 + * characters. + */ + fun instructions(instructions: String?) = apply { body.instructions(instructions) } + + /** + * The system instructions that the assistant uses. The maximum length is 256,000 + * characters. + */ + fun instructions(instructions: Optional) = instructions(instructions.orElse(null)) /** * The system instructions that the assistant uses. The maximum length is 256,000 * characters. */ - fun instructions(instructions: String) = apply { body.instructions(instructions) } + fun instructions(instructions: JsonField) = apply { + body.instructions(instructions) + } /** * Set of 16 key-value pairs that can be attached to an object. This can be useful for @@ -482,8 +860,69 @@ constructor( */ fun model(model: String) = apply { body.model(model) } + /** + * ID of the model to use. You can use the + * [List models](https://platform.openai.com/docs/api-reference/models/list) API to see all + * of your available models, or see our + * [Model overview](https://platform.openai.com/docs/models) for descriptions of them. + */ + fun model(model: JsonField) = apply { body.model(model) } + + /** The name of the assistant. The maximum length is 256 characters. */ + fun name(name: String?) = apply { body.name(name) } + + /** The name of the assistant. The maximum length is 256 characters. */ + fun name(name: Optional) = name(name.orElse(null)) + /** The name of the assistant. The maximum length is 256 characters. */ - fun name(name: String) = apply { body.name(name) } + fun name(name: JsonField) = apply { body.name(name) } + + /** + * Specifies the format that the model must output. Compatible with + * [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 + * Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 + * Turbo models since `gpt-3.5-turbo-1106`. + * + * Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs + * which ensures the model will match your supplied JSON schema. Learn more in the + * [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). + * + * Setting to `{ "type": "json_object" }` enables JSON mode, which ensures 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. + */ + fun responseFormat(responseFormat: AssistantResponseFormatOption?) = apply { + body.responseFormat(responseFormat) + } + + /** + * Specifies the format that the model must output. Compatible with + * [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 + * Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 + * Turbo models since `gpt-3.5-turbo-1106`. + * + * Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs + * which ensures the model will match your supplied JSON schema. Learn more in the + * [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). + * + * Setting to `{ "type": "json_object" }` enables JSON mode, which ensures 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. + */ + fun responseFormat(responseFormat: Optional) = + responseFormat(responseFormat.orElse(null)) /** * Specifies the format that the model must output. Compatible with @@ -505,7 +944,7 @@ constructor( * partially cut off if `finish_reason="length"`, which indicates the generation exceeded * `max_tokens` or the conversation exceeded the max context length. */ - fun responseFormat(responseFormat: AssistantResponseFormatOption) = apply { + fun responseFormat(responseFormat: JsonField) = apply { body.responseFormat(responseFormat) } @@ -531,14 +970,54 @@ constructor( * output more random, while lower values like 0.2 will make it more focused and * deterministic. */ - fun temperature(temperature: Double) = apply { body.temperature(temperature) } + fun temperature(temperature: Double?) = apply { body.temperature(temperature) } + + /** + * 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. + */ + fun temperature(temperature: Double) = temperature(temperature as Double?) + + /** + * 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. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun temperature(temperature: Optional) = + temperature(temperature.orElse(null) as Double?) + + /** + * 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. + */ + fun temperature(temperature: JsonField) = apply { body.temperature(temperature) } + + /** + * A set of resources that are used by the assistant's tools. The resources are specific to + * the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, + * while the `file_search` tool requires a list of vector store IDs. + */ + fun toolResources(toolResources: ToolResources?) = apply { + body.toolResources(toolResources) + } + + /** + * A set of resources that are used by the assistant's tools. The resources are specific to + * the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, + * while the `file_search` tool requires a list of vector store IDs. + */ + fun toolResources(toolResources: Optional) = + toolResources(toolResources.orElse(null)) /** * A set of resources that are used by the assistant's tools. The resources are specific to * the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, * while the `file_search` tool requires a list of vector store IDs. */ - fun toolResources(toolResources: ToolResources) = apply { + fun toolResources(toolResources: JsonField) = apply { body.toolResources(toolResources) } @@ -548,6 +1027,12 @@ constructor( */ fun tools(tools: List) = apply { body.tools(tools) } + /** + * 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`, `file_search`, or `function`. + */ + fun tools(tools: JsonField>) = apply { body.tools(tools) } + /** * 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`, `file_search`, or `function`. @@ -561,7 +1046,54 @@ constructor( * * We generally recommend altering this or temperature but not both. */ - fun topP(topP: Double) = apply { body.topP(topP) } + fun topP(topP: Double?) = apply { body.topP(topP) } + + /** + * 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. + */ + fun topP(topP: Double) = topP(topP as Double?) + + /** + * 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. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun topP(topP: Optional) = topP(topP.orElse(null) as Double?) + + /** + * 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. + */ + fun topP(topP: JsonField) = apply { body.topP(topP) } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() @@ -661,25 +1193,6 @@ constructor( additionalQueryParams.removeAll(keys) } - fun additionalBodyProperties(additionalBodyProperties: Map) = apply { - body.additionalProperties(additionalBodyProperties) - } - - fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { - body.putAdditionalProperty(key, value) - } - - fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = - apply { - body.putAllAdditionalProperties(additionalBodyProperties) - } - - fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } - - fun removeAllAdditionalBodyProperties(keys: Set) = apply { - body.removeAllAdditionalProperties(keys) - } - fun build(): BetaAssistantUpdateParams = BetaAssistantUpdateParams( checkNotNull(assistantId) { "`assistantId` is required but was not set" }, @@ -698,22 +1211,44 @@ constructor( class ToolResources @JsonCreator private constructor( - @JsonProperty("code_interpreter") private val codeInterpreter: CodeInterpreter?, - @JsonProperty("file_search") private val fileSearch: FileSearch?, + @JsonProperty("code_interpreter") + @ExcludeMissing + private val codeInterpreter: JsonField = JsonMissing.of(), + @JsonProperty("file_search") + @ExcludeMissing + private val fileSearch: JsonField = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { + fun codeInterpreter(): Optional = + Optional.ofNullable(codeInterpreter.getNullable("code_interpreter")) + + fun fileSearch(): Optional = + Optional.ofNullable(fileSearch.getNullable("file_search")) + @JsonProperty("code_interpreter") - fun codeInterpreter(): Optional = Optional.ofNullable(codeInterpreter) + @ExcludeMissing + fun _codeInterpreter(): JsonField = codeInterpreter @JsonProperty("file_search") - fun fileSearch(): Optional = Optional.ofNullable(fileSearch) + @ExcludeMissing + fun _fileSearch(): JsonField = fileSearch @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): ToolResources = apply { + if (!validated) { + codeInterpreter().map { it.validate() } + fileSearch().map { it.validate() } + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -723,8 +1258,8 @@ constructor( class Builder { - private var codeInterpreter: CodeInterpreter? = null - private var fileSearch: FileSearch? = null + private var codeInterpreter: JsonField = JsonMissing.of() + private var fileSearch: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -734,11 +1269,18 @@ constructor( additionalProperties = toolResources.additionalProperties.toMutableMap() } - fun codeInterpreter(codeInterpreter: CodeInterpreter) = apply { + fun codeInterpreter(codeInterpreter: CodeInterpreter) = + codeInterpreter(JsonField.of(codeInterpreter)) + + fun codeInterpreter(codeInterpreter: JsonField) = apply { this.codeInterpreter = codeInterpreter } - fun fileSearch(fileSearch: FileSearch) = apply { this.fileSearch = fileSearch } + fun fileSearch(fileSearch: FileSearch) = fileSearch(JsonField.of(fileSearch)) + + fun fileSearch(fileSearch: JsonField) = apply { + this.fileSearch = fileSearch + } fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() @@ -771,23 +1313,43 @@ constructor( class CodeInterpreter @JsonCreator private constructor( - @JsonProperty("file_ids") private val fileIds: List?, + @JsonProperty("file_ids") + @ExcludeMissing + private val fileIds: JsonField> = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { + /** + * Overrides the list of [file](https://platform.openai.com/docs/api-reference/files) + * IDs made available to the `code_interpreter` tool. There can be a maximum of 20 files + * associated with the tool. + */ + fun fileIds(): Optional> = + Optional.ofNullable(fileIds.getNullable("file_ids")) + /** * Overrides the list of [file](https://platform.openai.com/docs/api-reference/files) * IDs made available to the `code_interpreter` tool. There can be a maximum of 20 files * associated with the tool. */ @JsonProperty("file_ids") - fun fileIds(): Optional> = Optional.ofNullable(fileIds) + @ExcludeMissing + fun _fileIds(): JsonField> = fileIds @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): CodeInterpreter = apply { + if (!validated) { + fileIds() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -797,12 +1359,12 @@ constructor( class Builder { - private var fileIds: MutableList? = null + private var fileIds: JsonField>? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(codeInterpreter: CodeInterpreter) = apply { - fileIds = codeInterpreter.fileIds?.toMutableList() + fileIds = codeInterpreter.fileIds.map { it.toMutableList() } additionalProperties = codeInterpreter.additionalProperties.toMutableMap() } @@ -812,8 +1374,16 @@ constructor( * to the `code_interpreter` tool. There can be a maximum of 20 files associated * with the tool. */ - fun fileIds(fileIds: List) = apply { - this.fileIds = fileIds.toMutableList() + fun fileIds(fileIds: List) = fileIds(JsonField.of(fileIds)) + + /** + * Overrides the list of + * [file](https://platform.openai.com/docs/api-reference/files) IDs made available + * to the `code_interpreter` tool. There can be a maximum of 20 files associated + * with the tool. + */ + fun fileIds(fileIds: JsonField>) = apply { + this.fileIds = fileIds.map { it.toMutableList() } } /** @@ -823,7 +1393,16 @@ constructor( * with the tool. */ fun addFileId(fileId: String) = apply { - fileIds = (fileIds ?: mutableListOf()).apply { add(fileId) } + fileIds = + (fileIds ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(fileId) + } } fun additionalProperties(additionalProperties: Map) = apply { @@ -849,7 +1428,10 @@ constructor( } fun build(): CodeInterpreter = - CodeInterpreter(fileIds?.toImmutable(), additionalProperties.toImmutable()) + CodeInterpreter( + (fileIds ?: JsonMissing.of()).map { it.toImmutable() }, + additionalProperties.toImmutable() + ) } override fun equals(other: Any?): Boolean { @@ -874,11 +1456,22 @@ constructor( class FileSearch @JsonCreator private constructor( - @JsonProperty("vector_store_ids") private val vectorStoreIds: List?, + @JsonProperty("vector_store_ids") + @ExcludeMissing + private val vectorStoreIds: JsonField> = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { + /** + * Overrides the + * [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) + * attached to this assistant. There can be a maximum of 1 vector store attached to the + * assistant. + */ + fun vectorStoreIds(): Optional> = + Optional.ofNullable(vectorStoreIds.getNullable("vector_store_ids")) + /** * Overrides the * [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) @@ -886,12 +1479,22 @@ constructor( * assistant. */ @JsonProperty("vector_store_ids") - fun vectorStoreIds(): Optional> = Optional.ofNullable(vectorStoreIds) + @ExcludeMissing + fun _vectorStoreIds(): JsonField> = vectorStoreIds @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): FileSearch = apply { + if (!validated) { + vectorStoreIds() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -901,12 +1504,12 @@ constructor( class Builder { - private var vectorStoreIds: MutableList? = null + private var vectorStoreIds: JsonField>? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(fileSearch: FileSearch) = apply { - vectorStoreIds = fileSearch.vectorStoreIds?.toMutableList() + vectorStoreIds = fileSearch.vectorStoreIds.map { it.toMutableList() } additionalProperties = fileSearch.additionalProperties.toMutableMap() } @@ -916,8 +1519,17 @@ constructor( * attached to this assistant. There can be a maximum of 1 vector store attached to * the assistant. */ - fun vectorStoreIds(vectorStoreIds: List) = apply { - this.vectorStoreIds = vectorStoreIds.toMutableList() + fun vectorStoreIds(vectorStoreIds: List) = + vectorStoreIds(JsonField.of(vectorStoreIds)) + + /** + * Overrides the + * [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) + * attached to this assistant. There can be a maximum of 1 vector store attached to + * the assistant. + */ + fun vectorStoreIds(vectorStoreIds: JsonField>) = apply { + this.vectorStoreIds = vectorStoreIds.map { it.toMutableList() } } /** @@ -928,7 +1540,15 @@ constructor( */ fun addVectorStoreId(vectorStoreId: String) = apply { vectorStoreIds = - (vectorStoreIds ?: mutableListOf()).apply { add(vectorStoreId) } + (vectorStoreIds ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(vectorStoreId) + } } fun additionalProperties(additionalProperties: Map) = apply { @@ -954,7 +1574,10 @@ constructor( } fun build(): FileSearch = - FileSearch(vectorStoreIds?.toImmutable(), additionalProperties.toImmutable()) + FileSearch( + (vectorStoreIds ?: JsonMissing.of()).map { it.toImmutable() }, + additionalProperties.toImmutable() + ) } override fun equals(other: Any?): Boolean { diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadCreateAndRunParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadCreateAndRunParams.kt index 1d1a3afc5..4360aef30 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadCreateAndRunParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadCreateAndRunParams.kt @@ -18,6 +18,7 @@ import com.openai.core.BaseSerializer import com.openai.core.Enum import com.openai.core.ExcludeMissing import com.openai.core.JsonField +import com.openai.core.JsonMissing import com.openai.core.JsonValue import com.openai.core.NoAutoDetect import com.openai.core.getOrThrow @@ -30,6 +31,7 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull +/** Create a thread and run it in one request. */ class BetaThreadCreateAndRunParams constructor( private val body: BetaThreadCreateAndRunBody, @@ -70,7 +72,7 @@ constructor( * additional information about the object in a structured format. Keys can be a maximum of 64 * characters long and values can be a maximum of 512 characters long. */ - fun metadata(): Optional = body.metadata() + fun _metadata(): JsonValue = body._metadata() /** * The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to be used to @@ -155,12 +157,123 @@ constructor( */ fun truncationStrategy(): Optional = body.truncationStrategy() - fun _additionalHeaders(): Headers = additionalHeaders + /** + * The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) to use + * to execute this run. + */ + fun _assistantId(): JsonField = body._assistantId() - fun _additionalQueryParams(): QueryParams = additionalQueryParams + /** + * Override the default system message of the assistant. This is useful for modifying the + * behavior on a per-run basis. + */ + fun _instructions(): JsonField = body._instructions() + + /** + * The maximum number of completion tokens that may be used over the course of the run. The run + * will make a best effort to use only the number of completion tokens specified, across + * multiple turns of the run. If the run exceeds the number of completion tokens specified, the + * run will end with status `incomplete`. See `incomplete_details` for more info. + */ + fun _maxCompletionTokens(): JsonField = body._maxCompletionTokens() + + /** + * The maximum number of prompt tokens that may be used over the course of the run. The run will + * make a best effort to use only the number of prompt tokens specified, across multiple turns + * of the run. If the run exceeds the number of prompt tokens specified, the run will end with + * status `incomplete`. See `incomplete_details` for more info. + */ + fun _maxPromptTokens(): JsonField = body._maxPromptTokens() + + /** + * The ID of the [Model](https://platform.openai.com/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. + */ + fun _model(): JsonField = body._model() + + /** + * Whether to enable + * [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) + * during tool use. + */ + fun _parallelToolCalls(): JsonField = body._parallelToolCalls() + + /** + * Specifies the format that the model must output. Compatible with + * [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 + * Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo + * models since `gpt-3.5-turbo-1106`. + * + * Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which + * ensures the model will match your supplied JSON schema. Learn more in the + * [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). + * + * Setting to `{ "type": "json_object" }` enables JSON mode, which ensures 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. + */ + fun _responseFormat(): JsonField = body._responseFormat() + + /** + * 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. + */ + fun _temperature(): JsonField = body._temperature() + + /** If no thread is provided, an empty thread will be created. */ + fun _thread(): JsonField = body._thread() + + /** + * Controls which (if any) tool is called by the model. `none` means the model will not call any + * tools and instead generates a message. `auto` is the default value and means the model can + * pick between generating a message or calling one or more tools. `required` means the model + * must call one or more tools before responding to the user. Specifying a particular tool like + * `{"type": "file_search"}` or `{"type": "function", "function": {"name": "my_function"}}` + * forces the model to call that tool. + */ + fun _toolChoice(): JsonField = body._toolChoice() + + /** + * A set of resources that are used by the assistant's tools. The resources are specific to the + * type of tool. For example, the `code_interpreter` tool requires a list of file IDs, while the + * `file_search` tool requires a list of vector store IDs. + */ + fun _toolResources(): JsonField = body._toolResources() + + /** + * Override the tools the assistant can use for this run. This is useful for modifying the + * behavior on a per-run basis. + */ + fun _tools(): JsonField> = body._tools() + + /** + * 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. + */ + fun _topP(): JsonField = body._topP() + + /** + * Controls for how a thread will be truncated prior to the run. Use this to control the intial + * context window of the run. + */ + fun _truncationStrategy(): JsonField = body._truncationStrategy() fun _additionalBodyProperties(): Map = body._additionalProperties() + fun _additionalHeaders(): Headers = additionalHeaders + + fun _additionalQueryParams(): QueryParams = additionalQueryParams + @JvmSynthetic internal fun getBody(): BetaThreadCreateAndRunBody = body @JvmSynthetic internal fun getHeaders(): Headers = additionalHeaders @@ -171,21 +284,51 @@ constructor( class BetaThreadCreateAndRunBody @JsonCreator internal constructor( - @JsonProperty("assistant_id") private val assistantId: String, - @JsonProperty("instructions") private val instructions: String?, - @JsonProperty("max_completion_tokens") private val maxCompletionTokens: Long?, - @JsonProperty("max_prompt_tokens") private val maxPromptTokens: Long?, - @JsonProperty("metadata") private val metadata: JsonValue?, - @JsonProperty("model") private val model: ChatModel?, - @JsonProperty("parallel_tool_calls") private val parallelToolCalls: Boolean?, - @JsonProperty("response_format") private val responseFormat: AssistantResponseFormatOption?, - @JsonProperty("temperature") private val temperature: Double?, - @JsonProperty("thread") private val thread: Thread?, - @JsonProperty("tool_choice") private val toolChoice: AssistantToolChoiceOption?, - @JsonProperty("tool_resources") private val toolResources: ToolResources?, - @JsonProperty("tools") private val tools: List?, - @JsonProperty("top_p") private val topP: Double?, - @JsonProperty("truncation_strategy") private val truncationStrategy: TruncationStrategy?, + @JsonProperty("assistant_id") + @ExcludeMissing + private val assistantId: JsonField = JsonMissing.of(), + @JsonProperty("instructions") + @ExcludeMissing + private val instructions: JsonField = JsonMissing.of(), + @JsonProperty("max_completion_tokens") + @ExcludeMissing + private val maxCompletionTokens: JsonField = JsonMissing.of(), + @JsonProperty("max_prompt_tokens") + @ExcludeMissing + private val maxPromptTokens: JsonField = JsonMissing.of(), + @JsonProperty("metadata") + @ExcludeMissing + private val metadata: JsonValue = JsonMissing.of(), + @JsonProperty("model") + @ExcludeMissing + private val model: JsonField = JsonMissing.of(), + @JsonProperty("parallel_tool_calls") + @ExcludeMissing + private val parallelToolCalls: JsonField = JsonMissing.of(), + @JsonProperty("response_format") + @ExcludeMissing + private val responseFormat: JsonField = JsonMissing.of(), + @JsonProperty("temperature") + @ExcludeMissing + private val temperature: JsonField = JsonMissing.of(), + @JsonProperty("thread") + @ExcludeMissing + private val thread: JsonField = JsonMissing.of(), + @JsonProperty("tool_choice") + @ExcludeMissing + private val toolChoice: JsonField = JsonMissing.of(), + @JsonProperty("tool_resources") + @ExcludeMissing + private val toolResources: JsonField = JsonMissing.of(), + @JsonProperty("tools") + @ExcludeMissing + private val tools: JsonField> = JsonMissing.of(), + @JsonProperty("top_p") + @ExcludeMissing + private val topP: JsonField = JsonMissing.of(), + @JsonProperty("truncation_strategy") + @ExcludeMissing + private val truncationStrategy: JsonField = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { @@ -194,14 +337,14 @@ constructor( * The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) to * use to execute this run. */ - @JsonProperty("assistant_id") fun assistantId(): String = assistantId + fun assistantId(): String = assistantId.getRequired("assistant_id") /** * Override the default system message of the assistant. This is useful for modifying the * behavior on a per-run basis. */ - @JsonProperty("instructions") - fun instructions(): Optional = Optional.ofNullable(instructions) + fun instructions(): Optional = + Optional.ofNullable(instructions.getNullable("instructions")) /** * The maximum number of completion tokens that may be used over the course of the run. The @@ -209,8 +352,8 @@ constructor( * multiple turns of the run. If the run exceeds the number of completion tokens specified, * the run will end with status `incomplete`. See `incomplete_details` for more info. */ - @JsonProperty("max_completion_tokens") - fun maxCompletionTokens(): Optional = Optional.ofNullable(maxCompletionTokens) + fun maxCompletionTokens(): Optional = + Optional.ofNullable(maxCompletionTokens.getNullable("max_completion_tokens")) /** * The maximum number of prompt tokens that may be used over the course of the run. The run @@ -218,23 +361,148 @@ constructor( * multiple turns of the run. If the run exceeds the number of prompt tokens specified, the * run will end with status `incomplete`. See `incomplete_details` for more info. */ - @JsonProperty("max_prompt_tokens") - fun maxPromptTokens(): Optional = Optional.ofNullable(maxPromptTokens) + fun maxPromptTokens(): Optional = + Optional.ofNullable(maxPromptTokens.getNullable("max_prompt_tokens")) /** * 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 maximum of 512 characters long. */ - @JsonProperty("metadata") - fun metadata(): Optional = Optional.ofNullable(metadata) + @JsonProperty("metadata") @ExcludeMissing fun _metadata(): JsonValue = metadata + + /** + * The ID of the [Model](https://platform.openai.com/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. + */ + fun model(): Optional = Optional.ofNullable(model.getNullable("model")) + + /** + * Whether to enable + * [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) + * during tool use. + */ + fun parallelToolCalls(): Optional = + Optional.ofNullable(parallelToolCalls.getNullable("parallel_tool_calls")) + + /** + * Specifies the format that the model must output. Compatible with + * [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 + * Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 + * Turbo models since `gpt-3.5-turbo-1106`. + * + * Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs + * which ensures the model will match your supplied JSON schema. Learn more in the + * [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). + * + * Setting to `{ "type": "json_object" }` enables JSON mode, which ensures 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. + */ + fun responseFormat(): Optional = + Optional.ofNullable(responseFormat.getNullable("response_format")) + + /** + * 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. + */ + fun temperature(): Optional = + Optional.ofNullable(temperature.getNullable("temperature")) + + /** If no thread is provided, an empty thread will be created. */ + fun thread(): Optional = Optional.ofNullable(thread.getNullable("thread")) + + /** + * Controls which (if any) tool is called by the model. `none` means the model will not call + * any tools and instead generates a message. `auto` is the default value and means the + * model can pick between generating a message or calling one or more tools. `required` + * means the model must call one or more tools before responding to the user. Specifying a + * particular tool like `{"type": "file_search"}` or `{"type": "function", "function": + * {"name": "my_function"}}` forces the model to call that tool. + */ + fun toolChoice(): Optional = + Optional.ofNullable(toolChoice.getNullable("tool_choice")) + + /** + * A set of resources that are used by the assistant's tools. The resources are specific to + * the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, + * while the `file_search` tool requires a list of vector store IDs. + */ + fun toolResources(): Optional = + Optional.ofNullable(toolResources.getNullable("tool_resources")) + + /** + * Override the tools the assistant can use for this run. This is useful for modifying the + * behavior on a per-run basis. + */ + fun tools(): Optional> = Optional.ofNullable(tools.getNullable("tools")) + + /** + * 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. + */ + fun topP(): Optional = Optional.ofNullable(topP.getNullable("top_p")) + + /** + * Controls for how a thread will be truncated prior to the run. Use this to control the + * intial context window of the run. + */ + fun truncationStrategy(): Optional = + Optional.ofNullable(truncationStrategy.getNullable("truncation_strategy")) + + /** + * The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) to + * use to execute this run. + */ + @JsonProperty("assistant_id") + @ExcludeMissing + fun _assistantId(): JsonField = assistantId + + /** + * Override the default system message of the assistant. This is useful for modifying the + * behavior on a per-run basis. + */ + @JsonProperty("instructions") + @ExcludeMissing + fun _instructions(): JsonField = instructions + + /** + * The maximum number of completion tokens that may be used over the course of the run. The + * run will make a best effort to use only the number of completion tokens specified, across + * multiple turns of the run. If the run exceeds the number of completion tokens specified, + * the run will end with status `incomplete`. See `incomplete_details` for more info. + */ + @JsonProperty("max_completion_tokens") + @ExcludeMissing + fun _maxCompletionTokens(): JsonField = maxCompletionTokens + + /** + * The maximum number of prompt tokens that may be used over the course of the run. The run + * will make a best effort to use only the number of prompt tokens specified, across + * multiple turns of the run. If the run exceeds the number of prompt tokens specified, the + * run will end with status `incomplete`. See `incomplete_details` for more info. + */ + @JsonProperty("max_prompt_tokens") + @ExcludeMissing + fun _maxPromptTokens(): JsonField = maxPromptTokens /** * The ID of the [Model](https://platform.openai.com/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. */ - @JsonProperty("model") fun model(): Optional = Optional.ofNullable(model) + @JsonProperty("model") @ExcludeMissing fun _model(): JsonField = model /** * Whether to enable @@ -242,7 +510,8 @@ constructor( * during tool use. */ @JsonProperty("parallel_tool_calls") - fun parallelToolCalls(): Optional = Optional.ofNullable(parallelToolCalls) + @ExcludeMissing + fun _parallelToolCalls(): JsonField = parallelToolCalls /** * Specifies the format that the model must output. Compatible with @@ -265,8 +534,8 @@ constructor( * `max_tokens` or the conversation exceeded the max context length. */ @JsonProperty("response_format") - fun responseFormat(): Optional = - Optional.ofNullable(responseFormat) + @ExcludeMissing + fun _responseFormat(): JsonField = responseFormat /** * What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the @@ -274,10 +543,11 @@ constructor( * deterministic. */ @JsonProperty("temperature") - fun temperature(): Optional = Optional.ofNullable(temperature) + @ExcludeMissing + fun _temperature(): JsonField = temperature /** If no thread is provided, an empty thread will be created. */ - @JsonProperty("thread") fun thread(): Optional = Optional.ofNullable(thread) + @JsonProperty("thread") @ExcludeMissing fun _thread(): JsonField = thread /** * Controls which (if any) tool is called by the model. `none` means the model will not call @@ -288,7 +558,8 @@ constructor( * {"name": "my_function"}}` forces the model to call that tool. */ @JsonProperty("tool_choice") - fun toolChoice(): Optional = Optional.ofNullable(toolChoice) + @ExcludeMissing + fun _toolChoice(): JsonField = toolChoice /** * A set of resources that are used by the assistant's tools. The resources are specific to @@ -296,13 +567,14 @@ constructor( * while the `file_search` tool requires a list of vector store IDs. */ @JsonProperty("tool_resources") - fun toolResources(): Optional = Optional.ofNullable(toolResources) + @ExcludeMissing + fun _toolResources(): JsonField = toolResources /** * Override the tools the assistant can use for this run. This is useful for modifying the * behavior on a per-run basis. */ - @JsonProperty("tools") fun tools(): Optional> = Optional.ofNullable(tools) + @JsonProperty("tools") @ExcludeMissing fun _tools(): JsonField> = tools /** * An alternative to sampling with temperature, called nucleus sampling, where the model @@ -311,20 +583,42 @@ constructor( * * We generally recommend altering this or temperature but not both. */ - @JsonProperty("top_p") fun topP(): Optional = Optional.ofNullable(topP) + @JsonProperty("top_p") @ExcludeMissing fun _topP(): JsonField = topP /** * Controls for how a thread will be truncated prior to the run. Use this to control the * intial context window of the run. */ @JsonProperty("truncation_strategy") - fun truncationStrategy(): Optional = - Optional.ofNullable(truncationStrategy) + @ExcludeMissing + fun _truncationStrategy(): JsonField = truncationStrategy @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): BetaThreadCreateAndRunBody = apply { + if (!validated) { + assistantId() + instructions() + maxCompletionTokens() + maxPromptTokens() + model() + parallelToolCalls() + responseFormat() + temperature() + thread().map { it.validate() } + toolChoice() + toolResources().map { it.validate() } + tools() + topP() + truncationStrategy().map { it.validate() } + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -334,21 +628,21 @@ constructor( class Builder { - private var assistantId: String? = null - private var instructions: String? = null - private var maxCompletionTokens: Long? = null - private var maxPromptTokens: Long? = null - private var metadata: JsonValue? = null - private var model: ChatModel? = null - private var parallelToolCalls: Boolean? = null - private var responseFormat: AssistantResponseFormatOption? = null - private var temperature: Double? = null - private var thread: Thread? = null - private var toolChoice: AssistantToolChoiceOption? = null - private var toolResources: ToolResources? = null - private var tools: MutableList? = null - private var topP: Double? = null - private var truncationStrategy: TruncationStrategy? = null + private var assistantId: JsonField? = null + private var instructions: JsonField = JsonMissing.of() + private var maxCompletionTokens: JsonField = JsonMissing.of() + private var maxPromptTokens: JsonField = JsonMissing.of() + private var metadata: JsonValue = JsonMissing.of() + private var model: JsonField = JsonMissing.of() + private var parallelToolCalls: JsonField = JsonMissing.of() + private var responseFormat: JsonField = JsonMissing.of() + private var temperature: JsonField = JsonMissing.of() + private var thread: JsonField = JsonMissing.of() + private var toolChoice: JsonField = JsonMissing.of() + private var toolResources: JsonField = JsonMissing.of() + private var tools: JsonField>? = null + private var topP: JsonField = JsonMissing.of() + private var truncationStrategy: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -365,7 +659,7 @@ constructor( thread = betaThreadCreateAndRunBody.thread toolChoice = betaThreadCreateAndRunBody.toolChoice toolResources = betaThreadCreateAndRunBody.toolResources - tools = betaThreadCreateAndRunBody.tools?.toMutableList() + tools = betaThreadCreateAndRunBody.tools.map { it.toMutableList() } topP = betaThreadCreateAndRunBody.topP truncationStrategy = betaThreadCreateAndRunBody.truncationStrategy additionalProperties = @@ -376,13 +670,57 @@ constructor( * The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) * to use to execute this run. */ - fun assistantId(assistantId: String) = apply { this.assistantId = assistantId } + fun assistantId(assistantId: String) = assistantId(JsonField.of(assistantId)) + + /** + * The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) + * to use to execute this run. + */ + fun assistantId(assistantId: JsonField) = apply { + this.assistantId = assistantId + } + + /** + * Override the default system message of the assistant. This is useful for modifying + * the behavior on a per-run basis. + */ + fun instructions(instructions: String?) = + instructions(JsonField.ofNullable(instructions)) /** * Override the default system message of the assistant. This is useful for modifying * the behavior on a per-run basis. */ - fun instructions(instructions: String) = apply { this.instructions = instructions } + fun instructions(instructions: Optional) = + instructions(instructions.orElse(null)) + + /** + * Override the default system message of the assistant. This is useful for modifying + * the behavior on a per-run basis. + */ + fun instructions(instructions: JsonField) = apply { + this.instructions = instructions + } + + /** + * The maximum number of completion tokens that may be used over the course of the run. + * The run will make a best effort to use only the number of completion tokens + * specified, across multiple turns of the run. If the run exceeds the number of + * completion tokens specified, the run will end with status `incomplete`. See + * `incomplete_details` for more info. + */ + fun maxCompletionTokens(maxCompletionTokens: Long?) = + maxCompletionTokens(JsonField.ofNullable(maxCompletionTokens)) + + /** + * The maximum number of completion tokens that may be used over the course of the run. + * The run will make a best effort to use only the number of completion tokens + * specified, across multiple turns of the run. If the run exceeds the number of + * completion tokens specified, the run will end with status `incomplete`. See + * `incomplete_details` for more info. + */ + fun maxCompletionTokens(maxCompletionTokens: Long) = + maxCompletionTokens(maxCompletionTokens as Long?) /** * The maximum number of completion tokens that may be used over the course of the run. @@ -391,7 +729,18 @@ constructor( * completion tokens specified, the run will end with status `incomplete`. See * `incomplete_details` for more info. */ - fun maxCompletionTokens(maxCompletionTokens: Long) = apply { + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun maxCompletionTokens(maxCompletionTokens: Optional) = + maxCompletionTokens(maxCompletionTokens.orElse(null) as Long?) + + /** + * The maximum number of completion tokens that may be used over the course of the run. + * The run will make a best effort to use only the number of completion tokens + * specified, across multiple turns of the run. If the run exceeds the number of + * completion tokens specified, the run will end with status `incomplete`. See + * `incomplete_details` for more info. + */ + fun maxCompletionTokens(maxCompletionTokens: JsonField) = apply { this.maxCompletionTokens = maxCompletionTokens } @@ -401,7 +750,34 @@ constructor( * multiple turns of the run. If the run exceeds the number of prompt tokens specified, * the run will end with status `incomplete`. See `incomplete_details` for more info. */ - fun maxPromptTokens(maxPromptTokens: Long) = apply { + fun maxPromptTokens(maxPromptTokens: Long?) = + maxPromptTokens(JsonField.ofNullable(maxPromptTokens)) + + /** + * The maximum number of prompt tokens that may be used over the course of the run. The + * run will make a best effort to use only the number of prompt tokens specified, across + * multiple turns of the run. If the run exceeds the number of prompt tokens specified, + * the run will end with status `incomplete`. See `incomplete_details` for more info. + */ + fun maxPromptTokens(maxPromptTokens: Long) = maxPromptTokens(maxPromptTokens as Long?) + + /** + * The maximum number of prompt tokens that may be used over the course of the run. The + * run will make a best effort to use only the number of prompt tokens specified, across + * multiple turns of the run. If the run exceeds the number of prompt tokens specified, + * the run will end with status `incomplete`. See `incomplete_details` for more info. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun maxPromptTokens(maxPromptTokens: Optional) = + maxPromptTokens(maxPromptTokens.orElse(null) as Long?) + + /** + * The maximum number of prompt tokens that may be used over the course of the run. The + * run will make a best effort to use only the number of prompt tokens specified, across + * multiple turns of the run. If the run exceeds the number of prompt tokens specified, + * the run will end with status `incomplete`. See `incomplete_details` for more info. + */ + fun maxPromptTokens(maxPromptTokens: JsonField) = apply { this.maxPromptTokens = maxPromptTokens } @@ -418,7 +794,23 @@ constructor( * associated with the assistant. If not, the model associated with the assistant will * be used. */ - fun model(model: ChatModel) = apply { this.model = model } + fun model(model: ChatModel?) = model(JsonField.ofNullable(model)) + + /** + * The ID of the [Model](https://platform.openai.com/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. + */ + fun model(model: Optional) = model(model.orElse(null)) + + /** + * The ID of the [Model](https://platform.openai.com/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. + */ + fun model(model: JsonField) = apply { this.model = model } /** * The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to be @@ -426,16 +818,72 @@ constructor( * associated with the assistant. If not, the model associated with the assistant will * be used. */ - fun model(value: String) = apply { model = ChatModel.of(value) } + fun model(value: String) = apply { model(ChatModel.of(value)) } + + /** + * Whether to enable + * [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) + * during tool use. + */ + fun parallelToolCalls(parallelToolCalls: Boolean) = + parallelToolCalls(JsonField.of(parallelToolCalls)) /** * Whether to enable * [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) * during tool use. */ - fun parallelToolCalls(parallelToolCalls: Boolean) = apply { - this.parallelToolCalls = parallelToolCalls - } + fun parallelToolCalls(parallelToolCalls: JsonField) = apply { + this.parallelToolCalls = parallelToolCalls + } + + /** + * Specifies the format that the model must output. Compatible with + * [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 + * Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all + * GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. + * + * Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured + * Outputs which ensures the model will match your supplied JSON schema. Learn more in + * the + * [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). + * + * Setting to `{ "type": "json_object" }` enables JSON mode, which ensures 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. + */ + fun responseFormat(responseFormat: AssistantResponseFormatOption?) = + responseFormat(JsonField.ofNullable(responseFormat)) + + /** + * Specifies the format that the model must output. Compatible with + * [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 + * Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all + * GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. + * + * Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured + * Outputs which ensures the model will match your supplied JSON schema. Learn more in + * the + * [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). + * + * Setting to `{ "type": "json_object" }` enables JSON mode, which ensures 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. + */ + fun responseFormat(responseFormat: Optional) = + responseFormat(responseFormat.orElse(null)) /** * Specifies the format that the model must output. Compatible with @@ -458,43 +906,92 @@ constructor( * may be partially cut off if `finish_reason="length"`, which indicates the generation * exceeded `max_tokens` or the conversation exceeded the max context length. */ - fun responseFormat(responseFormat: AssistantResponseFormatOption) = apply { + fun responseFormat(responseFormat: JsonField) = apply { this.responseFormat = responseFormat } /** `auto` is the default value */ - fun responseFormat(behavior: AssistantResponseFormatOption.Behavior) = apply { - this.responseFormat = AssistantResponseFormatOption.ofBehavior(behavior) - } + fun responseFormat(behavior: AssistantResponseFormatOption.Behavior) = + responseFormat(AssistantResponseFormatOption.ofBehavior(behavior)) - fun responseFormat(responseFormatText: ResponseFormatText) = apply { - this.responseFormat = + fun responseFormat(responseFormatText: ResponseFormatText) = + responseFormat( AssistantResponseFormatOption.ofResponseFormatText(responseFormatText) - } + ) - fun responseFormat(responseFormatJsonObject: ResponseFormatJsonObject) = apply { - this.responseFormat = + fun responseFormat(responseFormatJsonObject: ResponseFormatJsonObject) = + responseFormat( AssistantResponseFormatOption.ofResponseFormatJsonObject( responseFormatJsonObject ) - } + ) - fun responseFormat(responseFormatJsonSchema: ResponseFormatJsonSchema) = apply { - this.responseFormat = + fun responseFormat(responseFormatJsonSchema: ResponseFormatJsonSchema) = + responseFormat( AssistantResponseFormatOption.ofResponseFormatJsonSchema( responseFormatJsonSchema ) - } + ) + + /** + * 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. + */ + fun temperature(temperature: Double?) = temperature(JsonField.ofNullable(temperature)) + + /** + * 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. + */ + fun temperature(temperature: Double) = temperature(temperature as Double?) + + /** + * 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. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun temperature(temperature: Optional) = + temperature(temperature.orElse(null) as Double?) /** * 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. */ - fun temperature(temperature: Double) = apply { this.temperature = temperature } + fun temperature(temperature: JsonField) = apply { + this.temperature = temperature + } /** If no thread is provided, an empty thread will be created. */ - fun thread(thread: Thread) = apply { this.thread = thread } + fun thread(thread: Thread) = thread(JsonField.of(thread)) + + /** If no thread is provided, an empty thread will be created. */ + fun thread(thread: JsonField) = apply { this.thread = thread } + + /** + * Controls which (if any) tool is called by the model. `none` means the model will not + * call any tools and instead generates a message. `auto` is the default value and means + * the model can pick between generating a message or calling one or more tools. + * `required` means the model must call one or more tools before responding to the user. + * Specifying a particular tool like `{"type": "file_search"}` or `{"type": "function", + * "function": {"name": "my_function"}}` forces the model to call that tool. + */ + fun toolChoice(toolChoice: AssistantToolChoiceOption?) = + toolChoice(JsonField.ofNullable(toolChoice)) + + /** + * Controls which (if any) tool is called by the model. `none` means the model will not + * call any tools and instead generates a message. `auto` is the default value and means + * the model can pick between generating a message or calling one or more tools. + * `required` means the model must call one or more tools before responding to the user. + * Specifying a particular tool like `{"type": "file_search"}` or `{"type": "function", + * "function": {"name": "my_function"}}` forces the model to call that tool. + */ + fun toolChoice(toolChoice: Optional) = + toolChoice(toolChoice.orElse(null)) /** * Controls which (if any) tool is called by the model. `none` means the model will not @@ -504,7 +1001,7 @@ constructor( * Specifying a particular tool like `{"type": "file_search"}` or `{"type": "function", * "function": {"name": "my_function"}}` forces the model to call that tool. */ - fun toolChoice(toolChoice: AssistantToolChoiceOption) = apply { + fun toolChoice(toolChoice: JsonField) = apply { this.toolChoice = toolChoice } @@ -514,25 +1011,38 @@ constructor( * tools. `required` means the model must call one or more tools before responding to * the user. */ - fun toolChoice(behavior: AssistantToolChoiceOption.Behavior) = apply { - this.toolChoice = AssistantToolChoiceOption.ofBehavior(behavior) - } + fun toolChoice(behavior: AssistantToolChoiceOption.Behavior) = + toolChoice(AssistantToolChoiceOption.ofBehavior(behavior)) /** * Specifies a tool the model should use. Use to force the model to call a specific * tool. */ - fun toolChoice(assistantToolChoice: AssistantToolChoice) = apply { - this.toolChoice = - AssistantToolChoiceOption.ofAssistantToolChoice(assistantToolChoice) - } + fun toolChoice(assistantToolChoice: AssistantToolChoice) = + toolChoice(AssistantToolChoiceOption.ofAssistantToolChoice(assistantToolChoice)) + + /** + * A set of resources that are used by the assistant's tools. The resources are specific + * to the type of tool. For example, the `code_interpreter` tool requires a list of file + * IDs, while the `file_search` tool requires a list of vector store IDs. + */ + fun toolResources(toolResources: ToolResources?) = + toolResources(JsonField.ofNullable(toolResources)) /** * A set of resources that are used by the assistant's tools. The resources are specific * to the type of tool. For example, the `code_interpreter` tool requires a list of file * IDs, while the `file_search` tool requires a list of vector store IDs. */ - fun toolResources(toolResources: ToolResources) = apply { + fun toolResources(toolResources: Optional) = + toolResources(toolResources.orElse(null)) + + /** + * A set of resources that are used by the assistant's tools. The resources are specific + * to the type of tool. For example, the `code_interpreter` tool requires a list of file + * IDs, while the `file_search` tool requires a list of vector store IDs. + */ + fun toolResources(toolResources: JsonField) = apply { this.toolResources = toolResources } @@ -540,14 +1050,37 @@ constructor( * Override the tools the assistant can use for this run. This is useful for modifying * the behavior on a per-run basis. */ - fun tools(tools: List) = apply { this.tools = tools.toMutableList() } + fun tools(tools: List?) = tools(JsonField.ofNullable(tools)) + + /** + * Override the tools the assistant can use for this run. This is useful for modifying + * the behavior on a per-run basis. + */ + fun tools(tools: Optional>) = tools(tools.orElse(null)) + + /** + * Override the tools the assistant can use for this run. This is useful for modifying + * the behavior on a per-run basis. + */ + fun tools(tools: JsonField>) = apply { + this.tools = tools.map { it.toMutableList() } + } /** * Override the tools the assistant can use for this run. This is useful for modifying * the behavior on a per-run basis. */ fun addTool(tool: Tool) = apply { - tools = (tools ?: mutableListOf()).apply { add(tool) } + tools = + (tools ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(tool) + } } /** @@ -557,13 +1090,55 @@ constructor( * * We generally recommend altering this or temperature but not both. */ - fun topP(topP: Double) = apply { this.topP = topP } + fun topP(topP: Double?) = topP(JsonField.ofNullable(topP)) + + /** + * 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. + */ + fun topP(topP: Double) = topP(topP as Double?) + + /** + * 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. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun topP(topP: Optional) = topP(topP.orElse(null) as Double?) + + /** + * 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. + */ + fun topP(topP: JsonField) = apply { this.topP = topP } + + /** + * Controls for how a thread will be truncated prior to the run. Use this to control the + * intial context window of the run. + */ + fun truncationStrategy(truncationStrategy: TruncationStrategy?) = + truncationStrategy(JsonField.ofNullable(truncationStrategy)) + + /** + * Controls for how a thread will be truncated prior to the run. Use this to control the + * intial context window of the run. + */ + fun truncationStrategy(truncationStrategy: Optional) = + truncationStrategy(truncationStrategy.orElse(null)) /** * Controls for how a thread will be truncated prior to the run. Use this to control the * intial context window of the run. */ - fun truncationStrategy(truncationStrategy: TruncationStrategy) = apply { + fun truncationStrategy(truncationStrategy: JsonField) = apply { this.truncationStrategy = truncationStrategy } @@ -600,7 +1175,7 @@ constructor( thread, toolChoice, toolResources, - tools?.toImmutable(), + (tools ?: JsonMissing.of()).map { it.toImmutable() }, topP, truncationStrategy, additionalProperties.toImmutable(), @@ -652,11 +1227,60 @@ constructor( */ fun assistantId(assistantId: String) = apply { body.assistantId(assistantId) } + /** + * The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) to + * use to execute this run. + */ + fun assistantId(assistantId: JsonField) = apply { body.assistantId(assistantId) } + + /** + * Override the default system message of the assistant. This is useful for modifying the + * behavior on a per-run basis. + */ + fun instructions(instructions: String?) = apply { body.instructions(instructions) } + /** * Override the default system message of the assistant. This is useful for modifying the * behavior on a per-run basis. */ - fun instructions(instructions: String) = apply { body.instructions(instructions) } + fun instructions(instructions: Optional) = instructions(instructions.orElse(null)) + + /** + * Override the default system message of the assistant. This is useful for modifying the + * behavior on a per-run basis. + */ + fun instructions(instructions: JsonField) = apply { + body.instructions(instructions) + } + + /** + * The maximum number of completion tokens that may be used over the course of the run. The + * run will make a best effort to use only the number of completion tokens specified, across + * multiple turns of the run. If the run exceeds the number of completion tokens specified, + * the run will end with status `incomplete`. See `incomplete_details` for more info. + */ + fun maxCompletionTokens(maxCompletionTokens: Long?) = apply { + body.maxCompletionTokens(maxCompletionTokens) + } + + /** + * The maximum number of completion tokens that may be used over the course of the run. The + * run will make a best effort to use only the number of completion tokens specified, across + * multiple turns of the run. If the run exceeds the number of completion tokens specified, + * the run will end with status `incomplete`. See `incomplete_details` for more info. + */ + fun maxCompletionTokens(maxCompletionTokens: Long) = + maxCompletionTokens(maxCompletionTokens as Long?) + + /** + * The maximum number of completion tokens that may be used over the course of the run. The + * run will make a best effort to use only the number of completion tokens specified, across + * multiple turns of the run. If the run exceeds the number of completion tokens specified, + * the run will end with status `incomplete`. See `incomplete_details` for more info. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun maxCompletionTokens(maxCompletionTokens: Optional) = + maxCompletionTokens(maxCompletionTokens.orElse(null) as Long?) /** * The maximum number of completion tokens that may be used over the course of the run. The @@ -664,7 +1288,7 @@ constructor( * multiple turns of the run. If the run exceeds the number of completion tokens specified, * the run will end with status `incomplete`. See `incomplete_details` for more info. */ - fun maxCompletionTokens(maxCompletionTokens: Long) = apply { + fun maxCompletionTokens(maxCompletionTokens: JsonField) = apply { body.maxCompletionTokens(maxCompletionTokens) } @@ -674,7 +1298,37 @@ constructor( * multiple turns of the run. If the run exceeds the number of prompt tokens specified, the * run will end with status `incomplete`. See `incomplete_details` for more info. */ - fun maxPromptTokens(maxPromptTokens: Long) = apply { body.maxPromptTokens(maxPromptTokens) } + fun maxPromptTokens(maxPromptTokens: Long?) = apply { + body.maxPromptTokens(maxPromptTokens) + } + + /** + * The maximum number of prompt tokens that may be used over the course of the run. The run + * will make a best effort to use only the number of prompt tokens specified, across + * multiple turns of the run. If the run exceeds the number of prompt tokens specified, the + * run will end with status `incomplete`. See `incomplete_details` for more info. + */ + fun maxPromptTokens(maxPromptTokens: Long) = maxPromptTokens(maxPromptTokens as Long?) + + /** + * The maximum number of prompt tokens that may be used over the course of the run. The run + * will make a best effort to use only the number of prompt tokens specified, across + * multiple turns of the run. If the run exceeds the number of prompt tokens specified, the + * run will end with status `incomplete`. See `incomplete_details` for more info. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun maxPromptTokens(maxPromptTokens: Optional) = + maxPromptTokens(maxPromptTokens.orElse(null) as Long?) + + /** + * The maximum number of prompt tokens that may be used over the course of the run. The run + * will make a best effort to use only the number of prompt tokens specified, across + * multiple turns of the run. If the run exceeds the number of prompt tokens specified, the + * run will end with status `incomplete`. See `incomplete_details` for more info. + */ + fun maxPromptTokens(maxPromptTokens: JsonField) = apply { + body.maxPromptTokens(maxPromptTokens) + } /** * Set of 16 key-value pairs that can be attached to an object. This can be useful for @@ -688,7 +1342,21 @@ constructor( * 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. */ - fun model(model: ChatModel) = apply { body.model(model) } + fun model(model: ChatModel?) = apply { body.model(model) } + + /** + * The ID of the [Model](https://platform.openai.com/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. + */ + fun model(model: Optional) = model(model.orElse(null)) + + /** + * The ID of the [Model](https://platform.openai.com/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. + */ + fun model(model: JsonField) = apply { body.model(model) } /** * The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to be used @@ -706,6 +1374,62 @@ constructor( body.parallelToolCalls(parallelToolCalls) } + /** + * Whether to enable + * [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) + * during tool use. + */ + fun parallelToolCalls(parallelToolCalls: JsonField) = apply { + body.parallelToolCalls(parallelToolCalls) + } + + /** + * Specifies the format that the model must output. Compatible with + * [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 + * Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 + * Turbo models since `gpt-3.5-turbo-1106`. + * + * Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs + * which ensures the model will match your supplied JSON schema. Learn more in the + * [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). + * + * Setting to `{ "type": "json_object" }` enables JSON mode, which ensures 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. + */ + fun responseFormat(responseFormat: AssistantResponseFormatOption?) = apply { + body.responseFormat(responseFormat) + } + + /** + * Specifies the format that the model must output. Compatible with + * [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 + * Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 + * Turbo models since `gpt-3.5-turbo-1106`. + * + * Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs + * which ensures the model will match your supplied JSON schema. Learn more in the + * [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). + * + * Setting to `{ "type": "json_object" }` enables JSON mode, which ensures 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. + */ + fun responseFormat(responseFormat: Optional) = + responseFormat(responseFormat.orElse(null)) + /** * Specifies the format that the model must output. Compatible with * [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 @@ -726,7 +1450,7 @@ constructor( * partially cut off if `finish_reason="length"`, which indicates the generation exceeded * `max_tokens` or the conversation exceeded the max context length. */ - fun responseFormat(responseFormat: AssistantResponseFormatOption) = apply { + fun responseFormat(responseFormat: JsonField) = apply { body.responseFormat(responseFormat) } @@ -743,20 +1467,69 @@ constructor( body.responseFormat(responseFormatJsonObject) } - fun responseFormat(responseFormatJsonSchema: ResponseFormatJsonSchema) = apply { - body.responseFormat(responseFormatJsonSchema) - } + fun responseFormat(responseFormatJsonSchema: ResponseFormatJsonSchema) = apply { + body.responseFormat(responseFormatJsonSchema) + } + + /** + * 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. + */ + fun temperature(temperature: Double?) = apply { body.temperature(temperature) } + + /** + * 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. + */ + fun temperature(temperature: Double) = temperature(temperature as Double?) + + /** + * 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. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun temperature(temperature: Optional) = + temperature(temperature.orElse(null) as Double?) /** * 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. */ - fun temperature(temperature: Double) = apply { body.temperature(temperature) } + fun temperature(temperature: JsonField) = apply { body.temperature(temperature) } /** If no thread is provided, an empty thread will be created. */ fun thread(thread: Thread) = apply { body.thread(thread) } + /** If no thread is provided, an empty thread will be created. */ + fun thread(thread: JsonField) = apply { body.thread(thread) } + + /** + * Controls which (if any) tool is called by the model. `none` means the model will not call + * any tools and instead generates a message. `auto` is the default value and means the + * model can pick between generating a message or calling one or more tools. `required` + * means the model must call one or more tools before responding to the user. Specifying a + * particular tool like `{"type": "file_search"}` or `{"type": "function", "function": + * {"name": "my_function"}}` forces the model to call that tool. + */ + fun toolChoice(toolChoice: AssistantToolChoiceOption?) = apply { + body.toolChoice(toolChoice) + } + + /** + * Controls which (if any) tool is called by the model. `none` means the model will not call + * any tools and instead generates a message. `auto` is the default value and means the + * model can pick between generating a message or calling one or more tools. `required` + * means the model must call one or more tools before responding to the user. Specifying a + * particular tool like `{"type": "file_search"}` or `{"type": "function", "function": + * {"name": "my_function"}}` forces the model to call that tool. + */ + fun toolChoice(toolChoice: Optional) = + toolChoice(toolChoice.orElse(null)) + /** * Controls which (if any) tool is called by the model. `none` means the model will not call * any tools and instead generates a message. `auto` is the default value and means the @@ -765,7 +1538,7 @@ constructor( * particular tool like `{"type": "file_search"}` or `{"type": "function", "function": * {"name": "my_function"}}` forces the model to call that tool. */ - fun toolChoice(toolChoice: AssistantToolChoiceOption) = apply { + fun toolChoice(toolChoice: JsonField) = apply { body.toolChoice(toolChoice) } @@ -790,7 +1563,24 @@ constructor( * the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, * while the `file_search` tool requires a list of vector store IDs. */ - fun toolResources(toolResources: ToolResources) = apply { + fun toolResources(toolResources: ToolResources?) = apply { + body.toolResources(toolResources) + } + + /** + * A set of resources that are used by the assistant's tools. The resources are specific to + * the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, + * while the `file_search` tool requires a list of vector store IDs. + */ + fun toolResources(toolResources: Optional) = + toolResources(toolResources.orElse(null)) + + /** + * A set of resources that are used by the assistant's tools. The resources are specific to + * the type of tool. For example, the `code_interpreter` tool requires a list of file IDs, + * while the `file_search` tool requires a list of vector store IDs. + */ + fun toolResources(toolResources: JsonField) = apply { body.toolResources(toolResources) } @@ -798,7 +1588,19 @@ constructor( * Override the tools the assistant can use for this run. This is useful for modifying the * behavior on a per-run basis. */ - fun tools(tools: List) = apply { body.tools(tools) } + fun tools(tools: List?) = apply { body.tools(tools) } + + /** + * Override the tools the assistant can use for this run. This is useful for modifying the + * behavior on a per-run basis. + */ + fun tools(tools: Optional>) = tools(tools.orElse(null)) + + /** + * Override the tools the assistant can use for this run. This is useful for modifying the + * behavior on a per-run basis. + */ + fun tools(tools: JsonField>) = apply { body.tools(tools) } /** * Override the tools the assistant can use for this run. This is useful for modifying the @@ -813,16 +1615,78 @@ constructor( * * We generally recommend altering this or temperature but not both. */ - fun topP(topP: Double) = apply { body.topP(topP) } + fun topP(topP: Double?) = apply { body.topP(topP) } + + /** + * 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. + */ + fun topP(topP: Double) = topP(topP as Double?) + + /** + * 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. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun topP(topP: Optional) = topP(topP.orElse(null) as Double?) + + /** + * 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. + */ + fun topP(topP: JsonField) = apply { body.topP(topP) } + + /** + * Controls for how a thread will be truncated prior to the run. Use this to control the + * intial context window of the run. + */ + fun truncationStrategy(truncationStrategy: TruncationStrategy?) = apply { + body.truncationStrategy(truncationStrategy) + } + + /** + * Controls for how a thread will be truncated prior to the run. Use this to control the + * intial context window of the run. + */ + fun truncationStrategy(truncationStrategy: Optional) = + truncationStrategy(truncationStrategy.orElse(null)) /** * Controls for how a thread will be truncated prior to the run. Use this to control the * intial context window of the run. */ - fun truncationStrategy(truncationStrategy: TruncationStrategy) = apply { + fun truncationStrategy(truncationStrategy: JsonField) = apply { body.truncationStrategy(truncationStrategy) } + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } + fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() putAllAdditionalHeaders(additionalHeaders) @@ -921,25 +1785,6 @@ constructor( additionalQueryParams.removeAll(keys) } - fun additionalBodyProperties(additionalBodyProperties: Map) = apply { - body.additionalProperties(additionalBodyProperties) - } - - fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { - body.putAdditionalProperty(key, value) - } - - fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = - apply { - body.putAllAdditionalProperties(additionalBodyProperties) - } - - fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } - - fun removeAllAdditionalBodyProperties(keys: Set) = apply { - body.removeAllAdditionalProperties(keys) - } - fun build(): BetaThreadCreateAndRunParams = BetaThreadCreateAndRunParams( body.build(), @@ -953,9 +1798,15 @@ constructor( class Thread @JsonCreator private constructor( - @JsonProperty("messages") private val messages: List?, - @JsonProperty("metadata") private val metadata: JsonValue?, - @JsonProperty("tool_resources") private val toolResources: ToolResources?, + @JsonProperty("messages") + @ExcludeMissing + private val messages: JsonField> = JsonMissing.of(), + @JsonProperty("metadata") + @ExcludeMissing + private val metadata: JsonValue = JsonMissing.of(), + @JsonProperty("tool_resources") + @ExcludeMissing + private val toolResources: JsonField = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { @@ -964,16 +1815,32 @@ constructor( * A list of [messages](https://platform.openai.com/docs/api-reference/messages) to start * the thread with. */ - @JsonProperty("messages") - fun messages(): Optional> = Optional.ofNullable(messages) + fun messages(): Optional> = + Optional.ofNullable(messages.getNullable("messages")) /** * 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 maximum of 512 characters long. */ - @JsonProperty("metadata") - fun metadata(): Optional = Optional.ofNullable(metadata) + @JsonProperty("metadata") @ExcludeMissing fun _metadata(): JsonValue = metadata + + /** + * A set of resources that are made available to the assistant's tools in this thread. The + * resources are specific to the type of tool. For example, the `code_interpreter` tool + * requires a list of file IDs, while the `file_search` tool requires a list of vector store + * IDs. + */ + fun toolResources(): Optional = + Optional.ofNullable(toolResources.getNullable("tool_resources")) + + /** + * A list of [messages](https://platform.openai.com/docs/api-reference/messages) to start + * the thread with. + */ + @JsonProperty("messages") + @ExcludeMissing + fun _messages(): JsonField> = messages /** * A set of resources that are made available to the assistant's tools in this thread. The @@ -982,12 +1849,23 @@ constructor( * IDs. */ @JsonProperty("tool_resources") - fun toolResources(): Optional = Optional.ofNullable(toolResources) + @ExcludeMissing + fun _toolResources(): JsonField = toolResources @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): Thread = apply { + if (!validated) { + messages().map { it.forEach { it.validate() } } + toolResources().map { it.validate() } + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -997,14 +1875,14 @@ constructor( class Builder { - private var messages: MutableList? = null - private var metadata: JsonValue? = null - private var toolResources: ToolResources? = null + private var messages: JsonField>? = null + private var metadata: JsonValue = JsonMissing.of() + private var toolResources: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(thread: Thread) = apply { - messages = thread.messages?.toMutableList() + messages = thread.messages.map { it.toMutableList() } metadata = thread.metadata toolResources = thread.toolResources additionalProperties = thread.additionalProperties.toMutableMap() @@ -1014,8 +1892,14 @@ constructor( * A list of [messages](https://platform.openai.com/docs/api-reference/messages) to * start the thread with. */ - fun messages(messages: List) = apply { - this.messages = messages.toMutableList() + fun messages(messages: List) = messages(JsonField.of(messages)) + + /** + * A list of [messages](https://platform.openai.com/docs/api-reference/messages) to + * start the thread with. + */ + fun messages(messages: JsonField>) = apply { + this.messages = messages.map { it.toMutableList() } } /** @@ -1023,7 +1907,16 @@ constructor( * start the thread with. */ fun addMessage(message: Message) = apply { - messages = (messages ?: mutableListOf()).apply { add(message) } + messages = + (messages ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(message) + } } /** @@ -1039,7 +1932,25 @@ constructor( * tool requires a list of file IDs, while the `file_search` tool requires a list of * vector store IDs. */ - fun toolResources(toolResources: ToolResources) = apply { + fun toolResources(toolResources: ToolResources?) = + toolResources(JsonField.ofNullable(toolResources)) + + /** + * A set of resources that are made available to the assistant's tools in this thread. + * The resources are specific to the type of tool. For example, the `code_interpreter` + * tool requires a list of file IDs, while the `file_search` tool requires a list of + * vector store IDs. + */ + fun toolResources(toolResources: Optional) = + toolResources(toolResources.orElse(null)) + + /** + * A set of resources that are made available to the assistant's tools in this thread. + * The resources are specific to the type of tool. For example, the `code_interpreter` + * tool requires a list of file IDs, while the `file_search` tool requires a list of + * vector store IDs. + */ + fun toolResources(toolResources: JsonField) = apply { this.toolResources = toolResources } @@ -1064,7 +1975,7 @@ constructor( fun build(): Thread = Thread( - messages?.toImmutable(), + (messages ?: JsonMissing.of()).map { it.toImmutable() }, metadata, toolResources, additionalProperties.toImmutable(), @@ -1075,16 +1986,24 @@ constructor( class Message @JsonCreator private constructor( - @JsonProperty("content") private val content: Content, - @JsonProperty("role") private val role: Role, - @JsonProperty("attachments") private val attachments: List?, - @JsonProperty("metadata") private val metadata: JsonValue?, + @JsonProperty("content") + @ExcludeMissing + private val content: JsonField = JsonMissing.of(), + @JsonProperty("role") + @ExcludeMissing + private val role: JsonField = JsonMissing.of(), + @JsonProperty("attachments") + @ExcludeMissing + private val attachments: JsonField> = JsonMissing.of(), + @JsonProperty("metadata") + @ExcludeMissing + private val metadata: JsonValue = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { /** The text contents of the message. */ - @JsonProperty("content") fun content(): Content = content + fun content(): Content = content.getRequired("content") /** * The role of the entity that is creating the message. Allowed values include: @@ -1093,24 +2012,51 @@ constructor( * - `assistant`: Indicates the message is generated by the assistant. Use this value to * insert messages from the assistant into the conversation. */ - @JsonProperty("role") fun role(): Role = role + fun role(): Role = role.getRequired("role") /** A list of files attached to the message, and the tools they should be added to. */ - @JsonProperty("attachments") - fun attachments(): Optional> = Optional.ofNullable(attachments) + fun attachments(): Optional> = + Optional.ofNullable(attachments.getNullable("attachments")) /** * 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 maximum of 512 characters long. */ - @JsonProperty("metadata") - fun metadata(): Optional = Optional.ofNullable(metadata) + @JsonProperty("metadata") @ExcludeMissing fun _metadata(): JsonValue = metadata + + /** The text contents of the message. */ + @JsonProperty("content") @ExcludeMissing fun _content(): JsonField = content + + /** + * The role of the entity that is creating the message. Allowed values include: + * - `user`: Indicates the message is sent by an actual user and should be used in most + * cases to represent user-generated messages. + * - `assistant`: Indicates the message is generated by the assistant. Use this value to + * insert messages from the assistant into the conversation. + */ + @JsonProperty("role") @ExcludeMissing fun _role(): JsonField = role + + /** A list of files attached to the message, and the tools they should be added to. */ + @JsonProperty("attachments") + @ExcludeMissing + fun _attachments(): JsonField> = attachments @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): Message = apply { + if (!validated) { + content() + role() + attachments().map { it.forEach { it.validate() } } + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -1120,28 +2066,29 @@ constructor( class Builder { - private var content: Content? = null - private var role: Role? = null - private var attachments: MutableList? = null - private var metadata: JsonValue? = null + private var content: JsonField? = null + private var role: JsonField? = null + private var attachments: JsonField>? = null + private var metadata: JsonValue = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(message: Message) = apply { content = message.content role = message.role - attachments = message.attachments?.toMutableList() + attachments = message.attachments.map { it.toMutableList() } metadata = message.metadata additionalProperties = message.additionalProperties.toMutableMap() } /** The text contents of the message. */ - fun content(content: Content) = apply { this.content = content } + fun content(content: Content) = content(JsonField.of(content)) /** The text contents of the message. */ - fun content(textContent: String) = apply { - this.content = Content.ofTextContent(textContent) - } + fun content(content: JsonField) = apply { this.content = content } + + /** The text contents of the message. */ + fun content(textContent: String) = content(Content.ofTextContent(textContent)) /** * An array of content parts with a defined type, each can be of type `text` or @@ -1150,7 +2097,16 @@ constructor( */ fun contentOfArrayOfContentParts( arrayOfContentParts: List - ) = apply { this.content = Content.ofArrayOfContentParts(arrayOfContentParts) } + ) = content(Content.ofArrayOfContentParts(arrayOfContentParts)) + + /** + * The role of the entity that is creating the message. Allowed values include: + * - `user`: Indicates the message is sent by an actual user and should be used in + * most cases to represent user-generated messages. + * - `assistant`: Indicates the message is generated by the assistant. Use this + * value to insert messages from the assistant into the conversation. + */ + fun role(role: Role) = role(JsonField.of(role)) /** * The role of the entity that is creating the message. Allowed values include: @@ -1159,20 +2115,41 @@ constructor( * - `assistant`: Indicates the message is generated by the assistant. Use this * value to insert messages from the assistant into the conversation. */ - fun role(role: Role) = apply { this.role = role } + fun role(role: JsonField) = apply { this.role = role } + + /** + * A list of files attached to the message, and the tools they should be added to. + */ + fun attachments(attachments: List?) = + attachments(JsonField.ofNullable(attachments)) + + /** + * A list of files attached to the message, and the tools they should be added to. + */ + fun attachments(attachments: Optional>) = + attachments(attachments.orElse(null)) /** * A list of files attached to the message, and the tools they should be added to. */ - fun attachments(attachments: List) = apply { - this.attachments = attachments.toMutableList() + fun attachments(attachments: JsonField>) = apply { + this.attachments = attachments.map { it.toMutableList() } } /** * A list of files attached to the message, and the tools they should be added to. */ fun addAttachment(attachment: Attachment) = apply { - attachments = (attachments ?: mutableListOf()).apply { add(attachment) } + attachments = + (attachments ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(attachment) + } } /** @@ -1209,7 +2186,7 @@ constructor( Message( checkNotNull(content) { "`content` is required but was not set" }, checkNotNull(role) { "`role` is required but was not set" }, - attachments?.toImmutable(), + (attachments ?: JsonMissing.of()).map { it.toImmutable() }, metadata, additionalProperties.toImmutable(), ) @@ -1225,6 +2202,8 @@ constructor( private val _json: JsonValue? = null, ) { + private var validated: Boolean = false + /** The text contents of the message. */ fun textContent(): Optional = Optional.ofNullable(textContent) /** @@ -1260,6 +2239,15 @@ constructor( } } + fun validate(): Content = apply { + if (!validated) { + if (textContent == null && arrayOfContentParts == null) { + throw OpenAIInvalidDataException("Unknown Content: $_json") + } + validated = true + } + } + override fun equals(other: Any?): Boolean { if (this === other) { return true @@ -1404,24 +2392,42 @@ constructor( class Attachment @JsonCreator private constructor( - @JsonProperty("file_id") private val fileId: String?, - @JsonProperty("tools") private val tools: List?, + @JsonProperty("file_id") + @ExcludeMissing + private val fileId: JsonField = JsonMissing.of(), + @JsonProperty("tools") + @ExcludeMissing + private val tools: JsonField> = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { /** The ID of the file to attach to the message. */ - @JsonProperty("file_id") - fun fileId(): Optional = Optional.ofNullable(fileId) + fun fileId(): Optional = Optional.ofNullable(fileId.getNullable("file_id")) /** The tools to add this file to. */ - @JsonProperty("tools") - fun tools(): Optional> = Optional.ofNullable(tools) + fun tools(): Optional> = Optional.ofNullable(tools.getNullable("tools")) + + /** The ID of the file to attach to the message. */ + @JsonProperty("file_id") @ExcludeMissing fun _fileId(): JsonField = fileId + + /** The tools to add this file to. */ + @JsonProperty("tools") @ExcludeMissing fun _tools(): JsonField> = tools @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): Attachment = apply { + if (!validated) { + fileId() + tools() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -1431,26 +2437,43 @@ constructor( class Builder { - private var fileId: String? = null - private var tools: MutableList? = null + private var fileId: JsonField = JsonMissing.of() + private var tools: JsonField>? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(attachment: Attachment) = apply { fileId = attachment.fileId - tools = attachment.tools?.toMutableList() + tools = attachment.tools.map { it.toMutableList() } additionalProperties = attachment.additionalProperties.toMutableMap() } /** The ID of the file to attach to the message. */ - fun fileId(fileId: String) = apply { this.fileId = fileId } + fun fileId(fileId: String) = fileId(JsonField.of(fileId)) + + /** The ID of the file to attach to the message. */ + fun fileId(fileId: JsonField) = apply { this.fileId = fileId } + + /** The tools to add this file to. */ + fun tools(tools: List) = tools(JsonField.of(tools)) /** The tools to add this file to. */ - fun tools(tools: List) = apply { this.tools = tools.toMutableList() } + fun tools(tools: JsonField>) = apply { + this.tools = tools.map { it.toMutableList() } + } /** The tools to add this file to. */ fun addTool(tool: Tool) = apply { - tools = (tools ?: mutableListOf()).apply { add(tool) } + tools = + (tools ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(tool) + } } fun additionalProperties(additionalProperties: Map) = apply { @@ -1478,7 +2501,7 @@ constructor( fun build(): Attachment = Attachment( fileId, - tools?.toImmutable(), + (tools ?: JsonMissing.of()).map { it.toImmutable() }, additionalProperties.toImmutable(), ) } @@ -1492,6 +2515,8 @@ constructor( private val _json: JsonValue? = null, ) { + private var validated: Boolean = false + fun codeInterpreterTool(): Optional = Optional.ofNullable(codeInterpreterTool) @@ -1517,6 +2542,17 @@ constructor( } } + fun validate(): Tool = apply { + if (!validated) { + if (codeInterpreterTool == null && fileSearch == null) { + throw OpenAIInvalidDataException("Unknown Tool: $_json") + } + codeInterpreterTool?.validate() + fileSearch?.validate() + validated = true + } + } + override fun equals(other: Any?): Boolean { if (this === other) { return true @@ -1566,15 +2602,20 @@ constructor( when (type) { "code_interpreter" -> { - tryDeserialize(node, jacksonTypeRef()) + tryDeserialize(node, jacksonTypeRef()) { + it.validate() + } ?.let { return Tool(codeInterpreterTool = it, _json = json) } } "file_search" -> { - tryDeserialize(node, jacksonTypeRef())?.let { - return Tool(fileSearch = it, _json = json) - } + tryDeserialize(node, jacksonTypeRef()) { + it.validate() + } + ?.let { + return Tool(fileSearch = it, _json = json) + } } } @@ -1603,19 +2644,33 @@ constructor( class FileSearch @JsonCreator private constructor( - @JsonProperty("type") private val type: Type, + @JsonProperty("type") + @ExcludeMissing + private val type: JsonField = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { /** The type of tool being defined: `file_search` */ - @JsonProperty("type") fun type(): Type = type + fun type(): Type = type.getRequired("type") + + /** The type of tool being defined: `file_search` */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): FileSearch = apply { + if (!validated) { + type() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -1625,7 +2680,7 @@ constructor( class Builder { - private var type: Type? = null + private var type: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @@ -1637,7 +2692,10 @@ constructor( } /** The type of tool being defined: `file_search` */ - fun type(type: Type) = apply { this.type = type } + fun type(type: Type) = type(JsonField.of(type)) + + /** The type of tool being defined: `file_search` */ + fun type(type: JsonField) = apply { this.type = type } fun additionalProperties(additionalProperties: Map) = apply { @@ -1785,22 +2843,44 @@ constructor( class ToolResources @JsonCreator private constructor( - @JsonProperty("code_interpreter") private val codeInterpreter: CodeInterpreter?, - @JsonProperty("file_search") private val fileSearch: FileSearch?, + @JsonProperty("code_interpreter") + @ExcludeMissing + private val codeInterpreter: JsonField = JsonMissing.of(), + @JsonProperty("file_search") + @ExcludeMissing + private val fileSearch: JsonField = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { + fun codeInterpreter(): Optional = + Optional.ofNullable(codeInterpreter.getNullable("code_interpreter")) + + fun fileSearch(): Optional = + Optional.ofNullable(fileSearch.getNullable("file_search")) + @JsonProperty("code_interpreter") - fun codeInterpreter(): Optional = Optional.ofNullable(codeInterpreter) + @ExcludeMissing + fun _codeInterpreter(): JsonField = codeInterpreter @JsonProperty("file_search") - fun fileSearch(): Optional = Optional.ofNullable(fileSearch) + @ExcludeMissing + fun _fileSearch(): JsonField = fileSearch @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): ToolResources = apply { + if (!validated) { + codeInterpreter().map { it.validate() } + fileSearch().map { it.validate() } + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -1810,8 +2890,8 @@ constructor( class Builder { - private var codeInterpreter: CodeInterpreter? = null - private var fileSearch: FileSearch? = null + private var codeInterpreter: JsonField = JsonMissing.of() + private var fileSearch: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -1821,11 +2901,18 @@ constructor( additionalProperties = toolResources.additionalProperties.toMutableMap() } - fun codeInterpreter(codeInterpreter: CodeInterpreter) = apply { + fun codeInterpreter(codeInterpreter: CodeInterpreter) = + codeInterpreter(JsonField.of(codeInterpreter)) + + fun codeInterpreter(codeInterpreter: JsonField) = apply { this.codeInterpreter = codeInterpreter } - fun fileSearch(fileSearch: FileSearch) = apply { this.fileSearch = fileSearch } + fun fileSearch(fileSearch: FileSearch) = fileSearch(JsonField.of(fileSearch)) + + fun fileSearch(fileSearch: JsonField) = apply { + this.fileSearch = fileSearch + } fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() @@ -1861,23 +2948,43 @@ constructor( class CodeInterpreter @JsonCreator private constructor( - @JsonProperty("file_ids") private val fileIds: List?, + @JsonProperty("file_ids") + @ExcludeMissing + private val fileIds: JsonField> = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { + /** + * A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made + * available to the `code_interpreter` tool. There can be a maximum of 20 files + * associated with the tool. + */ + fun fileIds(): Optional> = + Optional.ofNullable(fileIds.getNullable("file_ids")) + /** * A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made * available to the `code_interpreter` tool. There can be a maximum of 20 files * associated with the tool. */ @JsonProperty("file_ids") - fun fileIds(): Optional> = Optional.ofNullable(fileIds) + @ExcludeMissing + fun _fileIds(): JsonField> = fileIds @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): CodeInterpreter = apply { + if (!validated) { + fileIds() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -1887,12 +2994,12 @@ constructor( class Builder { - private var fileIds: MutableList? = null + private var fileIds: JsonField>? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(codeInterpreter: CodeInterpreter) = apply { - fileIds = codeInterpreter.fileIds?.toMutableList() + fileIds = codeInterpreter.fileIds.map { it.toMutableList() } additionalProperties = codeInterpreter.additionalProperties.toMutableMap() } @@ -1901,8 +3008,15 @@ constructor( * made available to the `code_interpreter` tool. There can be a maximum of 20 * files associated with the tool. */ - fun fileIds(fileIds: List) = apply { - this.fileIds = fileIds.toMutableList() + fun fileIds(fileIds: List) = fileIds(JsonField.of(fileIds)) + + /** + * A list of [file](https://platform.openai.com/docs/api-reference/files) IDs + * made available to the `code_interpreter` tool. There can be a maximum of 20 + * files associated with the tool. + */ + fun fileIds(fileIds: JsonField>) = apply { + this.fileIds = fileIds.map { it.toMutableList() } } /** @@ -1911,7 +3025,16 @@ constructor( * files associated with the tool. */ fun addFileId(fileId: String) = apply { - fileIds = (fileIds ?: mutableListOf()).apply { add(fileId) } + fileIds = + (fileIds ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(fileId) + } } fun additionalProperties(additionalProperties: Map) = apply { @@ -1937,7 +3060,10 @@ constructor( } fun build(): CodeInterpreter = - CodeInterpreter(fileIds?.toImmutable(), additionalProperties.toImmutable()) + CodeInterpreter( + (fileIds ?: JsonMissing.of()).map { it.toImmutable() }, + additionalProperties.toImmutable() + ) } override fun equals(other: Any?): Boolean { @@ -1962,12 +3088,34 @@ constructor( class FileSearch @JsonCreator private constructor( - @JsonProperty("vector_store_ids") private val vectorStoreIds: List?, - @JsonProperty("vector_stores") private val vectorStores: List?, + @JsonProperty("vector_store_ids") + @ExcludeMissing + private val vectorStoreIds: JsonField> = JsonMissing.of(), + @JsonProperty("vector_stores") + @ExcludeMissing + private val vectorStores: JsonField> = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { + /** + * The + * [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) + * attached to this thread. There can be a maximum of 1 vector store attached to the + * thread. + */ + fun vectorStoreIds(): Optional> = + Optional.ofNullable(vectorStoreIds.getNullable("vector_store_ids")) + + /** + * A helper to create a + * [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) + * with file_ids and attach it to this thread. There can be a maximum of 1 vector + * store attached to the thread. + */ + fun vectorStores(): Optional> = + Optional.ofNullable(vectorStores.getNullable("vector_stores")) + /** * The * [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) @@ -1975,7 +3123,8 @@ constructor( * thread. */ @JsonProperty("vector_store_ids") - fun vectorStoreIds(): Optional> = Optional.ofNullable(vectorStoreIds) + @ExcludeMissing + fun _vectorStoreIds(): JsonField> = vectorStoreIds /** * A helper to create a @@ -1984,12 +3133,23 @@ constructor( * store attached to the thread. */ @JsonProperty("vector_stores") - fun vectorStores(): Optional> = Optional.ofNullable(vectorStores) + @ExcludeMissing + fun _vectorStores(): JsonField> = vectorStores @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): FileSearch = apply { + if (!validated) { + vectorStoreIds() + vectorStores().map { it.forEach { it.validate() } } + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -1999,14 +3159,14 @@ constructor( class Builder { - private var vectorStoreIds: MutableList? = null - private var vectorStores: MutableList? = null + private var vectorStoreIds: JsonField>? = null + private var vectorStores: JsonField>? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(fileSearch: FileSearch) = apply { - vectorStoreIds = fileSearch.vectorStoreIds?.toMutableList() - vectorStores = fileSearch.vectorStores?.toMutableList() + vectorStoreIds = fileSearch.vectorStoreIds.map { it.toMutableList() } + vectorStores = fileSearch.vectorStores.map { it.toMutableList() } additionalProperties = fileSearch.additionalProperties.toMutableMap() } @@ -2016,8 +3176,17 @@ constructor( * attached to this thread. There can be a maximum of 1 vector store attached to * the thread. */ - fun vectorStoreIds(vectorStoreIds: List) = apply { - this.vectorStoreIds = vectorStoreIds.toMutableList() + fun vectorStoreIds(vectorStoreIds: List) = + vectorStoreIds(JsonField.of(vectorStoreIds)) + + /** + * The + * [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) + * attached to this thread. There can be a maximum of 1 vector store attached to + * the thread. + */ + fun vectorStoreIds(vectorStoreIds: JsonField>) = apply { + this.vectorStoreIds = vectorStoreIds.map { it.toMutableList() } } /** @@ -2028,7 +3197,15 @@ constructor( */ fun addVectorStoreId(vectorStoreId: String) = apply { vectorStoreIds = - (vectorStoreIds ?: mutableListOf()).apply { add(vectorStoreId) } + (vectorStoreIds ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(vectorStoreId) + } } /** @@ -2037,8 +3214,17 @@ constructor( * with file_ids and attach it to this thread. There can be a maximum of 1 * vector store attached to the thread. */ - fun vectorStores(vectorStores: List) = apply { - this.vectorStores = vectorStores.toMutableList() + fun vectorStores(vectorStores: List) = + vectorStores(JsonField.of(vectorStores)) + + /** + * A helper to create a + * [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) + * with file_ids and attach it to this thread. There can be a maximum of 1 + * vector store attached to the thread. + */ + fun vectorStores(vectorStores: JsonField>) = apply { + this.vectorStores = vectorStores.map { it.toMutableList() } } /** @@ -2048,7 +3234,16 @@ constructor( * vector store attached to the thread. */ fun addVectorStore(vectorStore: VectorStore) = apply { - vectorStores = (vectorStores ?: mutableListOf()).apply { add(vectorStore) } + vectorStores = + (vectorStores ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(vectorStore) + } } fun additionalProperties(additionalProperties: Map) = apply { @@ -2075,8 +3270,8 @@ constructor( fun build(): FileSearch = FileSearch( - vectorStoreIds?.toImmutable(), - vectorStores?.toImmutable(), + (vectorStoreIds ?: JsonMissing.of()).map { it.toImmutable() }, + (vectorStores ?: JsonMissing.of()).map { it.toImmutable() }, additionalProperties.toImmutable(), ) } @@ -2086,9 +3281,15 @@ constructor( @JsonCreator private constructor( @JsonProperty("chunking_strategy") - private val chunkingStrategy: FileChunkingStrategyParam?, - @JsonProperty("file_ids") private val fileIds: List?, - @JsonProperty("metadata") private val metadata: JsonValue?, + @ExcludeMissing + private val chunkingStrategy: JsonField = + JsonMissing.of(), + @JsonProperty("file_ids") + @ExcludeMissing + private val fileIds: JsonField> = JsonMissing.of(), + @JsonProperty("metadata") + @ExcludeMissing + private val metadata: JsonValue = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { @@ -2097,17 +3298,16 @@ constructor( * The chunking strategy used to chunk the file(s). If not set, will use the * `auto` strategy. Only applicable if `file_ids` is non-empty. */ - @JsonProperty("chunking_strategy") fun chunkingStrategy(): Optional = - Optional.ofNullable(chunkingStrategy) + Optional.ofNullable(chunkingStrategy.getNullable("chunking_strategy")) /** * A list of [file](https://platform.openai.com/docs/api-reference/files) IDs to * add to the vector store. There can be a maximum of 10000 files in a vector * store. */ - @JsonProperty("file_ids") - fun fileIds(): Optional> = Optional.ofNullable(fileIds) + fun fileIds(): Optional> = + Optional.ofNullable(fileIds.getNullable("file_ids")) /** * Set of 16 key-value pairs that can be attached to a vector store. This can be @@ -2115,13 +3315,39 @@ constructor( * structured format. Keys can be a maximum of 64 characters long and values can * be a maximum of 512 characters long. */ - @JsonProperty("metadata") - fun metadata(): Optional = Optional.ofNullable(metadata) + @JsonProperty("metadata") @ExcludeMissing fun _metadata(): JsonValue = metadata + + /** + * The chunking strategy used to chunk the file(s). If not set, will use the + * `auto` strategy. Only applicable if `file_ids` is non-empty. + */ + @JsonProperty("chunking_strategy") + @ExcludeMissing + fun _chunkingStrategy(): JsonField = chunkingStrategy + + /** + * A list of [file](https://platform.openai.com/docs/api-reference/files) IDs to + * add to the vector store. There can be a maximum of 10000 files in a vector + * store. + */ + @JsonProperty("file_ids") + @ExcludeMissing + fun _fileIds(): JsonField> = fileIds @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): VectorStore = apply { + if (!validated) { + chunkingStrategy() + fileIds() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -2131,16 +3357,17 @@ constructor( class Builder { - private var chunkingStrategy: FileChunkingStrategyParam? = null - private var fileIds: MutableList? = null - private var metadata: JsonValue? = null + private var chunkingStrategy: JsonField = + JsonMissing.of() + private var fileIds: JsonField>? = null + private var metadata: JsonValue = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(vectorStore: VectorStore) = apply { chunkingStrategy = vectorStore.chunkingStrategy - fileIds = vectorStore.fileIds?.toMutableList() + fileIds = vectorStore.fileIds.map { it.toMutableList() } metadata = vectorStore.metadata additionalProperties = vectorStore.additionalProperties.toMutableMap() } @@ -2149,9 +3376,16 @@ constructor( * The chunking strategy used to chunk the file(s). If not set, will use the * `auto` strategy. Only applicable if `file_ids` is non-empty. */ - fun chunkingStrategy(chunkingStrategy: FileChunkingStrategyParam) = apply { - this.chunkingStrategy = chunkingStrategy - } + fun chunkingStrategy(chunkingStrategy: FileChunkingStrategyParam) = + chunkingStrategy(JsonField.of(chunkingStrategy)) + + /** + * The chunking strategy used to chunk the file(s). If not set, will use the + * `auto` strategy. Only applicable if `file_ids` is non-empty. + */ + fun chunkingStrategy( + chunkingStrategy: JsonField + ) = apply { this.chunkingStrategy = chunkingStrategy } /** * The default strategy. This strategy currently uses a @@ -2159,29 +3393,36 @@ constructor( */ fun chunkingStrategy( autoFileChunkingStrategyParam: AutoFileChunkingStrategyParam - ) = apply { - this.chunkingStrategy = + ) = + chunkingStrategy( FileChunkingStrategyParam.ofAutoFileChunkingStrategyParam( autoFileChunkingStrategyParam ) - } + ) fun chunkingStrategy( staticFileChunkingStrategyParam: StaticFileChunkingStrategyParam - ) = apply { - this.chunkingStrategy = + ) = + chunkingStrategy( FileChunkingStrategyParam.ofStaticFileChunkingStrategyParam( staticFileChunkingStrategyParam ) - } + ) + + /** + * A list of [file](https://platform.openai.com/docs/api-reference/files) + * IDs to add to the vector store. There can be a maximum of 10000 files in + * a vector store. + */ + fun fileIds(fileIds: List) = fileIds(JsonField.of(fileIds)) /** * A list of [file](https://platform.openai.com/docs/api-reference/files) * IDs to add to the vector store. There can be a maximum of 10000 files in * a vector store. */ - fun fileIds(fileIds: List) = apply { - this.fileIds = fileIds.toMutableList() + fun fileIds(fileIds: JsonField>) = apply { + this.fileIds = fileIds.map { it.toMutableList() } } /** @@ -2190,7 +3431,16 @@ constructor( * a vector store. */ fun addFileId(fileId: String) = apply { - fileIds = (fileIds ?: mutableListOf()).apply { add(fileId) } + fileIds = + (fileIds ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(fileId) + } } /** @@ -2226,7 +3476,7 @@ constructor( fun build(): VectorStore = VectorStore( chunkingStrategy, - fileIds?.toImmutable(), + (fileIds ?: JsonMissing.of()).map { it.toImmutable() }, metadata, additionalProperties.toImmutable(), ) @@ -2313,22 +3563,44 @@ constructor( class ToolResources @JsonCreator private constructor( - @JsonProperty("code_interpreter") private val codeInterpreter: CodeInterpreter?, - @JsonProperty("file_search") private val fileSearch: FileSearch?, + @JsonProperty("code_interpreter") + @ExcludeMissing + private val codeInterpreter: JsonField = JsonMissing.of(), + @JsonProperty("file_search") + @ExcludeMissing + private val fileSearch: JsonField = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { + fun codeInterpreter(): Optional = + Optional.ofNullable(codeInterpreter.getNullable("code_interpreter")) + + fun fileSearch(): Optional = + Optional.ofNullable(fileSearch.getNullable("file_search")) + @JsonProperty("code_interpreter") - fun codeInterpreter(): Optional = Optional.ofNullable(codeInterpreter) + @ExcludeMissing + fun _codeInterpreter(): JsonField = codeInterpreter @JsonProperty("file_search") - fun fileSearch(): Optional = Optional.ofNullable(fileSearch) + @ExcludeMissing + fun _fileSearch(): JsonField = fileSearch @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): ToolResources = apply { + if (!validated) { + codeInterpreter().map { it.validate() } + fileSearch().map { it.validate() } + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -2338,8 +3610,8 @@ constructor( class Builder { - private var codeInterpreter: CodeInterpreter? = null - private var fileSearch: FileSearch? = null + private var codeInterpreter: JsonField = JsonMissing.of() + private var fileSearch: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -2349,11 +3621,18 @@ constructor( additionalProperties = toolResources.additionalProperties.toMutableMap() } - fun codeInterpreter(codeInterpreter: CodeInterpreter) = apply { + fun codeInterpreter(codeInterpreter: CodeInterpreter) = + codeInterpreter(JsonField.of(codeInterpreter)) + + fun codeInterpreter(codeInterpreter: JsonField) = apply { this.codeInterpreter = codeInterpreter } - fun fileSearch(fileSearch: FileSearch) = apply { this.fileSearch = fileSearch } + fun fileSearch(fileSearch: FileSearch) = fileSearch(JsonField.of(fileSearch)) + + fun fileSearch(fileSearch: JsonField) = apply { + this.fileSearch = fileSearch + } fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() @@ -2386,23 +3665,43 @@ constructor( class CodeInterpreter @JsonCreator private constructor( - @JsonProperty("file_ids") private val fileIds: List?, + @JsonProperty("file_ids") + @ExcludeMissing + private val fileIds: JsonField> = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { + /** + * A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made + * available to the `code_interpreter` tool. There can be a maximum of 20 files + * associated with the tool. + */ + fun fileIds(): Optional> = + Optional.ofNullable(fileIds.getNullable("file_ids")) + /** * A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made * available to the `code_interpreter` tool. There can be a maximum of 20 files * associated with the tool. */ @JsonProperty("file_ids") - fun fileIds(): Optional> = Optional.ofNullable(fileIds) + @ExcludeMissing + fun _fileIds(): JsonField> = fileIds @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): CodeInterpreter = apply { + if (!validated) { + fileIds() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -2412,12 +3711,12 @@ constructor( class Builder { - private var fileIds: MutableList? = null + private var fileIds: JsonField>? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(codeInterpreter: CodeInterpreter) = apply { - fileIds = codeInterpreter.fileIds?.toMutableList() + fileIds = codeInterpreter.fileIds.map { it.toMutableList() } additionalProperties = codeInterpreter.additionalProperties.toMutableMap() } @@ -2426,8 +3725,15 @@ constructor( * available to the `code_interpreter` tool. There can be a maximum of 20 files * associated with the tool. */ - fun fileIds(fileIds: List) = apply { - this.fileIds = fileIds.toMutableList() + fun fileIds(fileIds: List) = fileIds(JsonField.of(fileIds)) + + /** + * A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made + * available to the `code_interpreter` tool. There can be a maximum of 20 files + * associated with the tool. + */ + fun fileIds(fileIds: JsonField>) = apply { + this.fileIds = fileIds.map { it.toMutableList() } } /** @@ -2436,7 +3742,16 @@ constructor( * associated with the tool. */ fun addFileId(fileId: String) = apply { - fileIds = (fileIds ?: mutableListOf()).apply { add(fileId) } + fileIds = + (fileIds ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(fileId) + } } fun additionalProperties(additionalProperties: Map) = apply { @@ -2462,7 +3777,10 @@ constructor( } fun build(): CodeInterpreter = - CodeInterpreter(fileIds?.toImmutable(), additionalProperties.toImmutable()) + CodeInterpreter( + (fileIds ?: JsonMissing.of()).map { it.toImmutable() }, + additionalProperties.toImmutable() + ) } override fun equals(other: Any?): Boolean { @@ -2487,11 +3805,22 @@ constructor( class FileSearch @JsonCreator private constructor( - @JsonProperty("vector_store_ids") private val vectorStoreIds: List?, + @JsonProperty("vector_store_ids") + @ExcludeMissing + private val vectorStoreIds: JsonField> = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { + /** + * The ID of the + * [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) + * attached to this assistant. There can be a maximum of 1 vector store attached to the + * assistant. + */ + fun vectorStoreIds(): Optional> = + Optional.ofNullable(vectorStoreIds.getNullable("vector_store_ids")) + /** * The ID of the * [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) @@ -2499,12 +3828,22 @@ constructor( * assistant. */ @JsonProperty("vector_store_ids") - fun vectorStoreIds(): Optional> = Optional.ofNullable(vectorStoreIds) + @ExcludeMissing + fun _vectorStoreIds(): JsonField> = vectorStoreIds @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): FileSearch = apply { + if (!validated) { + vectorStoreIds() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -2514,12 +3853,12 @@ constructor( class Builder { - private var vectorStoreIds: MutableList? = null + private var vectorStoreIds: JsonField>? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(fileSearch: FileSearch) = apply { - vectorStoreIds = fileSearch.vectorStoreIds?.toMutableList() + vectorStoreIds = fileSearch.vectorStoreIds.map { it.toMutableList() } additionalProperties = fileSearch.additionalProperties.toMutableMap() } @@ -2529,8 +3868,17 @@ constructor( * attached to this assistant. There can be a maximum of 1 vector store attached to * the assistant. */ - fun vectorStoreIds(vectorStoreIds: List) = apply { - this.vectorStoreIds = vectorStoreIds.toMutableList() + fun vectorStoreIds(vectorStoreIds: List) = + vectorStoreIds(JsonField.of(vectorStoreIds)) + + /** + * The ID of the + * [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) + * attached to this assistant. There can be a maximum of 1 vector store attached to + * the assistant. + */ + fun vectorStoreIds(vectorStoreIds: JsonField>) = apply { + this.vectorStoreIds = vectorStoreIds.map { it.toMutableList() } } /** @@ -2541,7 +3889,15 @@ constructor( */ fun addVectorStoreId(vectorStoreId: String) = apply { vectorStoreIds = - (vectorStoreIds ?: mutableListOf()).apply { add(vectorStoreId) } + (vectorStoreIds ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(vectorStoreId) + } } fun additionalProperties(additionalProperties: Map) = apply { @@ -2567,7 +3923,10 @@ constructor( } fun build(): FileSearch = - FileSearch(vectorStoreIds?.toImmutable(), additionalProperties.toImmutable()) + FileSearch( + (vectorStoreIds ?: JsonMissing.of()).map { it.toImmutable() }, + additionalProperties.toImmutable() + ) } override fun equals(other: Any?): Boolean { @@ -2616,6 +3975,8 @@ constructor( private val _json: JsonValue? = null, ) { + private var validated: Boolean = false + fun codeInterpreterTool(): Optional = Optional.ofNullable(codeInterpreterTool) @@ -2647,6 +4008,18 @@ constructor( } } + fun validate(): Tool = apply { + if (!validated) { + if (codeInterpreterTool == null && fileSearchTool == null && functionTool == null) { + throw OpenAIInvalidDataException("Unknown Tool: $_json") + } + codeInterpreterTool?.validate() + fileSearchTool?.validate() + functionTool?.validate() + validated = true + } + } + override fun equals(other: Any?): Boolean { if (this === other) { return true @@ -2698,15 +4071,18 @@ constructor( override fun ObjectCodec.deserialize(node: JsonNode): Tool { val json = JsonValue.fromJsonNode(node) - tryDeserialize(node, jacksonTypeRef())?.let { - return Tool(codeInterpreterTool = it, _json = json) - } - tryDeserialize(node, jacksonTypeRef())?.let { - return Tool(fileSearchTool = it, _json = json) - } - tryDeserialize(node, jacksonTypeRef())?.let { - return Tool(functionTool = it, _json = json) - } + tryDeserialize(node, jacksonTypeRef()) { it.validate() } + ?.let { + return Tool(codeInterpreterTool = it, _json = json) + } + tryDeserialize(node, jacksonTypeRef()) { it.validate() } + ?.let { + return Tool(fileSearchTool = it, _json = json) + } + tryDeserialize(node, jacksonTypeRef()) { it.validate() } + ?.let { + return Tool(functionTool = it, _json = json) + } return Tool(_json = json) } @@ -2739,8 +4115,10 @@ constructor( class TruncationStrategy @JsonCreator private constructor( - @JsonProperty("type") private val type: Type, - @JsonProperty("last_messages") private val lastMessages: Long?, + @JsonProperty("type") @ExcludeMissing private val type: JsonField = JsonMissing.of(), + @JsonProperty("last_messages") + @ExcludeMissing + private val lastMessages: JsonField = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { @@ -2751,19 +4129,45 @@ constructor( * thread. When set to `auto`, messages in the middle of the thread will be dropped to fit * the context length of the model, `max_prompt_tokens`. */ - @JsonProperty("type") fun type(): Type = type + fun type(): Type = type.getRequired("type") + + /** + * The number of most recent messages from the thread when constructing the context for the + * run. + */ + fun lastMessages(): Optional = + Optional.ofNullable(lastMessages.getNullable("last_messages")) + + /** + * The truncation strategy to use for the thread. The default is `auto`. If set to + * `last_messages`, the thread will be truncated to the n most recent messages in the + * thread. When set to `auto`, messages in the middle of the thread will be dropped to fit + * the context length of the model, `max_prompt_tokens`. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type /** * The number of most recent messages from the thread when constructing the context for the * run. */ @JsonProperty("last_messages") - fun lastMessages(): Optional = Optional.ofNullable(lastMessages) + @ExcludeMissing + fun _lastMessages(): JsonField = lastMessages @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): TruncationStrategy = apply { + if (!validated) { + type() + lastMessages() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -2773,8 +4177,8 @@ constructor( class Builder { - private var type: Type? = null - private var lastMessages: Long? = null + private var type: JsonField? = null + private var lastMessages: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -2790,13 +4194,43 @@ constructor( * thread. When set to `auto`, messages in the middle of the thread will be dropped to * fit the context length of the model, `max_prompt_tokens`. */ - fun type(type: Type) = apply { this.type = type } + fun type(type: Type) = type(JsonField.of(type)) + + /** + * The truncation strategy to use for the thread. The default is `auto`. If set to + * `last_messages`, the thread will be truncated to the n most recent messages in the + * thread. When set to `auto`, messages in the middle of the thread will be dropped to + * fit the context length of the model, `max_prompt_tokens`. + */ + fun type(type: JsonField) = apply { this.type = type } /** * The number of most recent messages from the thread when constructing the context for * the run. */ - fun lastMessages(lastMessages: Long) = apply { this.lastMessages = lastMessages } + fun lastMessages(lastMessages: Long?) = lastMessages(JsonField.ofNullable(lastMessages)) + + /** + * The number of most recent messages from the thread when constructing the context for + * the run. + */ + fun lastMessages(lastMessages: Long) = lastMessages(lastMessages as Long?) + + /** + * The number of most recent messages from the thread when constructing the context for + * the run. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun lastMessages(lastMessages: Optional) = + lastMessages(lastMessages.orElse(null) as Long?) + + /** + * The number of most recent messages from the thread when constructing the context for + * the run. + */ + fun lastMessages(lastMessages: JsonField) = apply { + this.lastMessages = lastMessages + } fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadCreateParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadCreateParams.kt index 4104f8c36..600b8b7a8 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadCreateParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadCreateParams.kt @@ -18,6 +18,7 @@ import com.openai.core.BaseSerializer import com.openai.core.Enum import com.openai.core.ExcludeMissing import com.openai.core.JsonField +import com.openai.core.JsonMissing import com.openai.core.JsonValue import com.openai.core.NoAutoDetect import com.openai.core.getOrThrow @@ -30,6 +31,7 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull +/** Create a thread. */ class BetaThreadCreateParams constructor( private val body: BetaThreadCreateBody, @@ -48,7 +50,7 @@ constructor( * additional information about the object in a structured format. Keys can be a maximum of 64 * characters long and values can be a maximum of 512 characters long. */ - fun metadata(): Optional = body.metadata() + fun _metadata(): JsonValue = body._metadata() /** * A set of resources that are made available to the assistant's tools in this thread. The @@ -57,12 +59,25 @@ constructor( */ fun toolResources(): Optional = body.toolResources() - fun _additionalHeaders(): Headers = additionalHeaders + /** + * A list of [messages](https://platform.openai.com/docs/api-reference/messages) to start the + * thread with. + */ + fun _messages(): JsonField> = body._messages() - fun _additionalQueryParams(): QueryParams = additionalQueryParams + /** + * A set of resources that are made available to the assistant's tools in this thread. The + * resources are specific to the type of tool. For example, the `code_interpreter` tool requires + * a list of file IDs, while the `file_search` tool requires a list of vector store IDs. + */ + fun _toolResources(): JsonField = body._toolResources() fun _additionalBodyProperties(): Map = body._additionalProperties() + fun _additionalHeaders(): Headers = additionalHeaders + + fun _additionalQueryParams(): QueryParams = additionalQueryParams + @JvmSynthetic internal fun getBody(): BetaThreadCreateBody = body @JvmSynthetic internal fun getHeaders(): Headers = additionalHeaders @@ -73,9 +88,15 @@ constructor( class BetaThreadCreateBody @JsonCreator internal constructor( - @JsonProperty("messages") private val messages: List?, - @JsonProperty("metadata") private val metadata: JsonValue?, - @JsonProperty("tool_resources") private val toolResources: ToolResources?, + @JsonProperty("messages") + @ExcludeMissing + private val messages: JsonField> = JsonMissing.of(), + @JsonProperty("metadata") + @ExcludeMissing + private val metadata: JsonValue = JsonMissing.of(), + @JsonProperty("tool_resources") + @ExcludeMissing + private val toolResources: JsonField = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { @@ -84,16 +105,32 @@ constructor( * A list of [messages](https://platform.openai.com/docs/api-reference/messages) to start * the thread with. */ - @JsonProperty("messages") - fun messages(): Optional> = Optional.ofNullable(messages) + fun messages(): Optional> = + Optional.ofNullable(messages.getNullable("messages")) /** * 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 maximum of 512 characters long. */ - @JsonProperty("metadata") - fun metadata(): Optional = Optional.ofNullable(metadata) + @JsonProperty("metadata") @ExcludeMissing fun _metadata(): JsonValue = metadata + + /** + * A set of resources that are made available to the assistant's tools in this thread. The + * resources are specific to the type of tool. For example, the `code_interpreter` tool + * requires a list of file IDs, while the `file_search` tool requires a list of vector store + * IDs. + */ + fun toolResources(): Optional = + Optional.ofNullable(toolResources.getNullable("tool_resources")) + + /** + * A list of [messages](https://platform.openai.com/docs/api-reference/messages) to start + * the thread with. + */ + @JsonProperty("messages") + @ExcludeMissing + fun _messages(): JsonField> = messages /** * A set of resources that are made available to the assistant's tools in this thread. The @@ -102,12 +139,23 @@ constructor( * IDs. */ @JsonProperty("tool_resources") - fun toolResources(): Optional = Optional.ofNullable(toolResources) + @ExcludeMissing + fun _toolResources(): JsonField = toolResources @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): BetaThreadCreateBody = apply { + if (!validated) { + messages().map { it.forEach { it.validate() } } + toolResources().map { it.validate() } + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -117,14 +165,14 @@ constructor( class Builder { - private var messages: MutableList? = null - private var metadata: JsonValue? = null - private var toolResources: ToolResources? = null + private var messages: JsonField>? = null + private var metadata: JsonValue = JsonMissing.of() + private var toolResources: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(betaThreadCreateBody: BetaThreadCreateBody) = apply { - messages = betaThreadCreateBody.messages?.toMutableList() + messages = betaThreadCreateBody.messages.map { it.toMutableList() } metadata = betaThreadCreateBody.metadata toolResources = betaThreadCreateBody.toolResources additionalProperties = betaThreadCreateBody.additionalProperties.toMutableMap() @@ -134,8 +182,14 @@ constructor( * A list of [messages](https://platform.openai.com/docs/api-reference/messages) to * start the thread with. */ - fun messages(messages: List) = apply { - this.messages = messages.toMutableList() + fun messages(messages: List) = messages(JsonField.of(messages)) + + /** + * A list of [messages](https://platform.openai.com/docs/api-reference/messages) to + * start the thread with. + */ + fun messages(messages: JsonField>) = apply { + this.messages = messages.map { it.toMutableList() } } /** @@ -143,7 +197,16 @@ constructor( * start the thread with. */ fun addMessage(message: Message) = apply { - messages = (messages ?: mutableListOf()).apply { add(message) } + messages = + (messages ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(message) + } } /** @@ -159,7 +222,25 @@ constructor( * tool requires a list of file IDs, while the `file_search` tool requires a list of * vector store IDs. */ - fun toolResources(toolResources: ToolResources) = apply { + fun toolResources(toolResources: ToolResources?) = + toolResources(JsonField.ofNullable(toolResources)) + + /** + * A set of resources that are made available to the assistant's tools in this thread. + * The resources are specific to the type of tool. For example, the `code_interpreter` + * tool requires a list of file IDs, while the `file_search` tool requires a list of + * vector store IDs. + */ + fun toolResources(toolResources: Optional) = + toolResources(toolResources.orElse(null)) + + /** + * A set of resources that are made available to the assistant's tools in this thread. + * The resources are specific to the type of tool. For example, the `code_interpreter` + * tool requires a list of file IDs, while the `file_search` tool requires a list of + * vector store IDs. + */ + fun toolResources(toolResources: JsonField) = apply { this.toolResources = toolResources } @@ -184,7 +265,7 @@ constructor( fun build(): BetaThreadCreateBody = BetaThreadCreateBody( - messages?.toImmutable(), + (messages ?: JsonMissing.of()).map { it.toImmutable() }, metadata, toolResources, additionalProperties.toImmutable(), @@ -236,6 +317,12 @@ constructor( */ fun messages(messages: List) = apply { body.messages(messages) } + /** + * A list of [messages](https://platform.openai.com/docs/api-reference/messages) to start + * the thread with. + */ + fun messages(messages: JsonField>) = apply { body.messages(messages) } + /** * A list of [messages](https://platform.openai.com/docs/api-reference/messages) to start * the thread with. @@ -255,10 +342,48 @@ constructor( * requires a list of file IDs, while the `file_search` tool requires a list of vector store * IDs. */ - fun toolResources(toolResources: ToolResources) = apply { + fun toolResources(toolResources: ToolResources?) = apply { + body.toolResources(toolResources) + } + + /** + * A set of resources that are made available to the assistant's tools in this thread. The + * resources are specific to the type of tool. For example, the `code_interpreter` tool + * requires a list of file IDs, while the `file_search` tool requires a list of vector store + * IDs. + */ + fun toolResources(toolResources: Optional) = + toolResources(toolResources.orElse(null)) + + /** + * A set of resources that are made available to the assistant's tools in this thread. The + * resources are specific to the type of tool. For example, the `code_interpreter` tool + * requires a list of file IDs, while the `file_search` tool requires a list of vector store + * IDs. + */ + fun toolResources(toolResources: JsonField) = apply { body.toolResources(toolResources) } + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } + fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() putAllAdditionalHeaders(additionalHeaders) @@ -357,25 +482,6 @@ constructor( additionalQueryParams.removeAll(keys) } - fun additionalBodyProperties(additionalBodyProperties: Map) = apply { - body.additionalProperties(additionalBodyProperties) - } - - fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { - body.putAdditionalProperty(key, value) - } - - fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = - apply { - body.putAllAdditionalProperties(additionalBodyProperties) - } - - fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } - - fun removeAllAdditionalBodyProperties(keys: Set) = apply { - body.removeAllAdditionalProperties(keys) - } - fun build(): BetaThreadCreateParams = BetaThreadCreateParams( body.build(), @@ -388,16 +494,22 @@ constructor( class Message @JsonCreator private constructor( - @JsonProperty("content") private val content: Content, - @JsonProperty("role") private val role: Role, - @JsonProperty("attachments") private val attachments: List?, - @JsonProperty("metadata") private val metadata: JsonValue?, + @JsonProperty("content") + @ExcludeMissing + private val content: JsonField = JsonMissing.of(), + @JsonProperty("role") @ExcludeMissing private val role: JsonField = JsonMissing.of(), + @JsonProperty("attachments") + @ExcludeMissing + private val attachments: JsonField> = JsonMissing.of(), + @JsonProperty("metadata") + @ExcludeMissing + private val metadata: JsonValue = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { /** The text contents of the message. */ - @JsonProperty("content") fun content(): Content = content + fun content(): Content = content.getRequired("content") /** * The role of the entity that is creating the message. Allowed values include: @@ -406,24 +518,51 @@ constructor( * - `assistant`: Indicates the message is generated by the assistant. Use this value to * insert messages from the assistant into the conversation. */ - @JsonProperty("role") fun role(): Role = role + fun role(): Role = role.getRequired("role") /** A list of files attached to the message, and the tools they should be added to. */ - @JsonProperty("attachments") - fun attachments(): Optional> = Optional.ofNullable(attachments) + fun attachments(): Optional> = + Optional.ofNullable(attachments.getNullable("attachments")) /** * 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 maximum of 512 characters long. */ - @JsonProperty("metadata") - fun metadata(): Optional = Optional.ofNullable(metadata) + @JsonProperty("metadata") @ExcludeMissing fun _metadata(): JsonValue = metadata + + /** The text contents of the message. */ + @JsonProperty("content") @ExcludeMissing fun _content(): JsonField = content + + /** + * The role of the entity that is creating the message. Allowed values include: + * - `user`: Indicates the message is sent by an actual user and should be used in most + * cases to represent user-generated messages. + * - `assistant`: Indicates the message is generated by the assistant. Use this value to + * insert messages from the assistant into the conversation. + */ + @JsonProperty("role") @ExcludeMissing fun _role(): JsonField = role + + /** A list of files attached to the message, and the tools they should be added to. */ + @JsonProperty("attachments") + @ExcludeMissing + fun _attachments(): JsonField> = attachments @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): Message = apply { + if (!validated) { + content() + role() + attachments().map { it.forEach { it.validate() } } + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -433,28 +572,29 @@ constructor( class Builder { - private var content: Content? = null - private var role: Role? = null - private var attachments: MutableList? = null - private var metadata: JsonValue? = null + private var content: JsonField? = null + private var role: JsonField? = null + private var attachments: JsonField>? = null + private var metadata: JsonValue = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(message: Message) = apply { content = message.content role = message.role - attachments = message.attachments?.toMutableList() + attachments = message.attachments.map { it.toMutableList() } metadata = message.metadata additionalProperties = message.additionalProperties.toMutableMap() } /** The text contents of the message. */ - fun content(content: Content) = apply { this.content = content } + fun content(content: Content) = content(JsonField.of(content)) /** The text contents of the message. */ - fun content(textContent: String) = apply { - this.content = Content.ofTextContent(textContent) - } + fun content(content: JsonField) = apply { this.content = content } + + /** The text contents of the message. */ + fun content(textContent: String) = content(Content.ofTextContent(textContent)) /** * An array of content parts with a defined type, each can be of type `text` or images @@ -462,9 +602,16 @@ constructor( * [Vision-compatible models](https://platform.openai.com/docs/models). */ fun contentOfArrayOfContentParts(arrayOfContentParts: List) = - apply { - this.content = Content.ofArrayOfContentParts(arrayOfContentParts) - } + content(Content.ofArrayOfContentParts(arrayOfContentParts)) + + /** + * The role of the entity that is creating the message. Allowed values include: + * - `user`: Indicates the message is sent by an actual user and should be used in most + * cases to represent user-generated messages. + * - `assistant`: Indicates the message is generated by the assistant. Use this value to + * insert messages from the assistant into the conversation. + */ + fun role(role: Role) = role(JsonField.of(role)) /** * The role of the entity that is creating the message. Allowed values include: @@ -473,16 +620,33 @@ constructor( * - `assistant`: Indicates the message is generated by the assistant. Use this value to * insert messages from the assistant into the conversation. */ - fun role(role: Role) = apply { this.role = role } + fun role(role: JsonField) = apply { this.role = role } /** A list of files attached to the message, and the tools they should be added to. */ - fun attachments(attachments: List) = apply { - this.attachments = attachments.toMutableList() + fun attachments(attachments: List?) = + attachments(JsonField.ofNullable(attachments)) + + /** A list of files attached to the message, and the tools they should be added to. */ + fun attachments(attachments: Optional>) = + attachments(attachments.orElse(null)) + + /** A list of files attached to the message, and the tools they should be added to. */ + fun attachments(attachments: JsonField>) = apply { + this.attachments = attachments.map { it.toMutableList() } } /** A list of files attached to the message, and the tools they should be added to. */ fun addAttachment(attachment: Attachment) = apply { - attachments = (attachments ?: mutableListOf()).apply { add(attachment) } + attachments = + (attachments ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(attachment) + } } /** @@ -515,7 +679,7 @@ constructor( Message( checkNotNull(content) { "`content` is required but was not set" }, checkNotNull(role) { "`role` is required but was not set" }, - attachments?.toImmutable(), + (attachments ?: JsonMissing.of()).map { it.toImmutable() }, metadata, additionalProperties.toImmutable(), ) @@ -531,6 +695,8 @@ constructor( private val _json: JsonValue? = null, ) { + private var validated: Boolean = false + /** The text contents of the message. */ fun textContent(): Optional = Optional.ofNullable(textContent) /** @@ -566,6 +732,15 @@ constructor( } } + fun validate(): Content = apply { + if (!validated) { + if (textContent == null && arrayOfContentParts == null) { + throw OpenAIInvalidDataException("Unknown Content: $_json") + } + validated = true + } + } + override fun equals(other: Any?): Boolean { if (this === other) { return true @@ -707,22 +882,42 @@ constructor( class Attachment @JsonCreator private constructor( - @JsonProperty("file_id") private val fileId: String?, - @JsonProperty("tools") private val tools: List?, + @JsonProperty("file_id") + @ExcludeMissing + private val fileId: JsonField = JsonMissing.of(), + @JsonProperty("tools") + @ExcludeMissing + private val tools: JsonField> = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { /** The ID of the file to attach to the message. */ - @JsonProperty("file_id") fun fileId(): Optional = Optional.ofNullable(fileId) + fun fileId(): Optional = Optional.ofNullable(fileId.getNullable("file_id")) /** The tools to add this file to. */ - @JsonProperty("tools") fun tools(): Optional> = Optional.ofNullable(tools) + fun tools(): Optional> = Optional.ofNullable(tools.getNullable("tools")) + + /** The ID of the file to attach to the message. */ + @JsonProperty("file_id") @ExcludeMissing fun _fileId(): JsonField = fileId + + /** The tools to add this file to. */ + @JsonProperty("tools") @ExcludeMissing fun _tools(): JsonField> = tools @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): Attachment = apply { + if (!validated) { + fileId() + tools() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -732,26 +927,43 @@ constructor( class Builder { - private var fileId: String? = null - private var tools: MutableList? = null + private var fileId: JsonField = JsonMissing.of() + private var tools: JsonField>? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(attachment: Attachment) = apply { fileId = attachment.fileId - tools = attachment.tools?.toMutableList() + tools = attachment.tools.map { it.toMutableList() } additionalProperties = attachment.additionalProperties.toMutableMap() } /** The ID of the file to attach to the message. */ - fun fileId(fileId: String) = apply { this.fileId = fileId } + fun fileId(fileId: String) = fileId(JsonField.of(fileId)) + + /** The ID of the file to attach to the message. */ + fun fileId(fileId: JsonField) = apply { this.fileId = fileId } /** The tools to add this file to. */ - fun tools(tools: List) = apply { this.tools = tools.toMutableList() } + fun tools(tools: List) = tools(JsonField.of(tools)) + + /** The tools to add this file to. */ + fun tools(tools: JsonField>) = apply { + this.tools = tools.map { it.toMutableList() } + } /** The tools to add this file to. */ fun addTool(tool: Tool) = apply { - tools = (tools ?: mutableListOf()).apply { add(tool) } + tools = + (tools ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(tool) + } } fun additionalProperties(additionalProperties: Map) = apply { @@ -779,7 +991,7 @@ constructor( fun build(): Attachment = Attachment( fileId, - tools?.toImmutable(), + (tools ?: JsonMissing.of()).map { it.toImmutable() }, additionalProperties.toImmutable(), ) } @@ -793,6 +1005,8 @@ constructor( private val _json: JsonValue? = null, ) { + private var validated: Boolean = false + fun codeInterpreterTool(): Optional = Optional.ofNullable(codeInterpreterTool) @@ -818,6 +1032,17 @@ constructor( } } + fun validate(): Tool = apply { + if (!validated) { + if (codeInterpreterTool == null && fileSearch == null) { + throw OpenAIInvalidDataException("Unknown Tool: $_json") + } + codeInterpreterTool?.validate() + fileSearch?.validate() + validated = true + } + } + override fun equals(other: Any?): Boolean { if (this === other) { return true @@ -866,14 +1091,18 @@ constructor( when (type) { "code_interpreter" -> { - tryDeserialize(node, jacksonTypeRef())?.let { - return Tool(codeInterpreterTool = it, _json = json) - } + tryDeserialize(node, jacksonTypeRef()) { + it.validate() + } + ?.let { + return Tool(codeInterpreterTool = it, _json = json) + } } "file_search" -> { - tryDeserialize(node, jacksonTypeRef())?.let { - return Tool(fileSearch = it, _json = json) - } + tryDeserialize(node, jacksonTypeRef()) { it.validate() } + ?.let { + return Tool(fileSearch = it, _json = json) + } } } @@ -902,18 +1131,32 @@ constructor( class FileSearch @JsonCreator private constructor( - @JsonProperty("type") private val type: Type, + @JsonProperty("type") + @ExcludeMissing + private val type: JsonField = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { /** The type of tool being defined: `file_search` */ - @JsonProperty("type") fun type(): Type = type + fun type(): Type = type.getRequired("type") + + /** The type of tool being defined: `file_search` */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): FileSearch = apply { + if (!validated) { + type() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -923,7 +1166,7 @@ constructor( class Builder { - private var type: Type? = null + private var type: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @@ -934,7 +1177,10 @@ constructor( } /** The type of tool being defined: `file_search` */ - fun type(type: Type) = apply { this.type = type } + fun type(type: Type) = type(JsonField.of(type)) + + /** The type of tool being defined: `file_search` */ + fun type(type: JsonField) = apply { this.type = type } fun additionalProperties(additionalProperties: Map) = apply { @@ -1081,22 +1327,44 @@ constructor( class ToolResources @JsonCreator private constructor( - @JsonProperty("code_interpreter") private val codeInterpreter: CodeInterpreter?, - @JsonProperty("file_search") private val fileSearch: FileSearch?, + @JsonProperty("code_interpreter") + @ExcludeMissing + private val codeInterpreter: JsonField = JsonMissing.of(), + @JsonProperty("file_search") + @ExcludeMissing + private val fileSearch: JsonField = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { + fun codeInterpreter(): Optional = + Optional.ofNullable(codeInterpreter.getNullable("code_interpreter")) + + fun fileSearch(): Optional = + Optional.ofNullable(fileSearch.getNullable("file_search")) + @JsonProperty("code_interpreter") - fun codeInterpreter(): Optional = Optional.ofNullable(codeInterpreter) + @ExcludeMissing + fun _codeInterpreter(): JsonField = codeInterpreter @JsonProperty("file_search") - fun fileSearch(): Optional = Optional.ofNullable(fileSearch) + @ExcludeMissing + fun _fileSearch(): JsonField = fileSearch @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): ToolResources = apply { + if (!validated) { + codeInterpreter().map { it.validate() } + fileSearch().map { it.validate() } + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -1106,8 +1374,8 @@ constructor( class Builder { - private var codeInterpreter: CodeInterpreter? = null - private var fileSearch: FileSearch? = null + private var codeInterpreter: JsonField = JsonMissing.of() + private var fileSearch: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -1117,11 +1385,18 @@ constructor( additionalProperties = toolResources.additionalProperties.toMutableMap() } - fun codeInterpreter(codeInterpreter: CodeInterpreter) = apply { + fun codeInterpreter(codeInterpreter: CodeInterpreter) = + codeInterpreter(JsonField.of(codeInterpreter)) + + fun codeInterpreter(codeInterpreter: JsonField) = apply { this.codeInterpreter = codeInterpreter } - fun fileSearch(fileSearch: FileSearch) = apply { this.fileSearch = fileSearch } + fun fileSearch(fileSearch: FileSearch) = fileSearch(JsonField.of(fileSearch)) + + fun fileSearch(fileSearch: JsonField) = apply { + this.fileSearch = fileSearch + } fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() @@ -1154,23 +1429,43 @@ constructor( class CodeInterpreter @JsonCreator private constructor( - @JsonProperty("file_ids") private val fileIds: List?, + @JsonProperty("file_ids") + @ExcludeMissing + private val fileIds: JsonField> = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { + /** + * A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made + * available to the `code_interpreter` tool. There can be a maximum of 20 files + * associated with the tool. + */ + fun fileIds(): Optional> = + Optional.ofNullable(fileIds.getNullable("file_ids")) + /** * A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made * available to the `code_interpreter` tool. There can be a maximum of 20 files * associated with the tool. */ @JsonProperty("file_ids") - fun fileIds(): Optional> = Optional.ofNullable(fileIds) + @ExcludeMissing + fun _fileIds(): JsonField> = fileIds @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): CodeInterpreter = apply { + if (!validated) { + fileIds() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -1180,12 +1475,12 @@ constructor( class Builder { - private var fileIds: MutableList? = null + private var fileIds: JsonField>? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(codeInterpreter: CodeInterpreter) = apply { - fileIds = codeInterpreter.fileIds?.toMutableList() + fileIds = codeInterpreter.fileIds.map { it.toMutableList() } additionalProperties = codeInterpreter.additionalProperties.toMutableMap() } @@ -1194,8 +1489,15 @@ constructor( * available to the `code_interpreter` tool. There can be a maximum of 20 files * associated with the tool. */ - fun fileIds(fileIds: List) = apply { - this.fileIds = fileIds.toMutableList() + fun fileIds(fileIds: List) = fileIds(JsonField.of(fileIds)) + + /** + * A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made + * available to the `code_interpreter` tool. There can be a maximum of 20 files + * associated with the tool. + */ + fun fileIds(fileIds: JsonField>) = apply { + this.fileIds = fileIds.map { it.toMutableList() } } /** @@ -1204,7 +1506,16 @@ constructor( * associated with the tool. */ fun addFileId(fileId: String) = apply { - fileIds = (fileIds ?: mutableListOf()).apply { add(fileId) } + fileIds = + (fileIds ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(fileId) + } } fun additionalProperties(additionalProperties: Map) = apply { @@ -1230,7 +1541,10 @@ constructor( } fun build(): CodeInterpreter = - CodeInterpreter(fileIds?.toImmutable(), additionalProperties.toImmutable()) + CodeInterpreter( + (fileIds ?: JsonMissing.of()).map { it.toImmutable() }, + additionalProperties.toImmutable() + ) } override fun equals(other: Any?): Boolean { @@ -1255,12 +1569,34 @@ constructor( class FileSearch @JsonCreator private constructor( - @JsonProperty("vector_store_ids") private val vectorStoreIds: List?, - @JsonProperty("vector_stores") private val vectorStores: List?, + @JsonProperty("vector_store_ids") + @ExcludeMissing + private val vectorStoreIds: JsonField> = JsonMissing.of(), + @JsonProperty("vector_stores") + @ExcludeMissing + private val vectorStores: JsonField> = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { + /** + * The + * [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) + * attached to this thread. There can be a maximum of 1 vector store attached to the + * thread. + */ + fun vectorStoreIds(): Optional> = + Optional.ofNullable(vectorStoreIds.getNullable("vector_store_ids")) + + /** + * A helper to create a + * [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) + * with file_ids and attach it to this thread. There can be a maximum of 1 vector store + * attached to the thread. + */ + fun vectorStores(): Optional> = + Optional.ofNullable(vectorStores.getNullable("vector_stores")) + /** * The * [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) @@ -1268,7 +1604,8 @@ constructor( * thread. */ @JsonProperty("vector_store_ids") - fun vectorStoreIds(): Optional> = Optional.ofNullable(vectorStoreIds) + @ExcludeMissing + fun _vectorStoreIds(): JsonField> = vectorStoreIds /** * A helper to create a @@ -1277,12 +1614,23 @@ constructor( * attached to the thread. */ @JsonProperty("vector_stores") - fun vectorStores(): Optional> = Optional.ofNullable(vectorStores) + @ExcludeMissing + fun _vectorStores(): JsonField> = vectorStores @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): FileSearch = apply { + if (!validated) { + vectorStoreIds() + vectorStores().map { it.forEach { it.validate() } } + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -1292,14 +1640,14 @@ constructor( class Builder { - private var vectorStoreIds: MutableList? = null - private var vectorStores: MutableList? = null + private var vectorStoreIds: JsonField>? = null + private var vectorStores: JsonField>? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(fileSearch: FileSearch) = apply { - vectorStoreIds = fileSearch.vectorStoreIds?.toMutableList() - vectorStores = fileSearch.vectorStores?.toMutableList() + vectorStoreIds = fileSearch.vectorStoreIds.map { it.toMutableList() } + vectorStores = fileSearch.vectorStores.map { it.toMutableList() } additionalProperties = fileSearch.additionalProperties.toMutableMap() } @@ -1309,8 +1657,17 @@ constructor( * attached to this thread. There can be a maximum of 1 vector store attached to the * thread. */ - fun vectorStoreIds(vectorStoreIds: List) = apply { - this.vectorStoreIds = vectorStoreIds.toMutableList() + fun vectorStoreIds(vectorStoreIds: List) = + vectorStoreIds(JsonField.of(vectorStoreIds)) + + /** + * The + * [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) + * attached to this thread. There can be a maximum of 1 vector store attached to the + * thread. + */ + fun vectorStoreIds(vectorStoreIds: JsonField>) = apply { + this.vectorStoreIds = vectorStoreIds.map { it.toMutableList() } } /** @@ -1321,7 +1678,15 @@ constructor( */ fun addVectorStoreId(vectorStoreId: String) = apply { vectorStoreIds = - (vectorStoreIds ?: mutableListOf()).apply { add(vectorStoreId) } + (vectorStoreIds ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(vectorStoreId) + } } /** @@ -1330,8 +1695,17 @@ constructor( * with file_ids and attach it to this thread. There can be a maximum of 1 vector * store attached to the thread. */ - fun vectorStores(vectorStores: List) = apply { - this.vectorStores = vectorStores.toMutableList() + fun vectorStores(vectorStores: List) = + vectorStores(JsonField.of(vectorStores)) + + /** + * A helper to create a + * [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) + * with file_ids and attach it to this thread. There can be a maximum of 1 vector + * store attached to the thread. + */ + fun vectorStores(vectorStores: JsonField>) = apply { + this.vectorStores = vectorStores.map { it.toMutableList() } } /** @@ -1341,7 +1715,16 @@ constructor( * store attached to the thread. */ fun addVectorStore(vectorStore: VectorStore) = apply { - vectorStores = (vectorStores ?: mutableListOf()).apply { add(vectorStore) } + vectorStores = + (vectorStores ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(vectorStore) + } } fun additionalProperties(additionalProperties: Map) = apply { @@ -1368,8 +1751,8 @@ constructor( fun build(): FileSearch = FileSearch( - vectorStoreIds?.toImmutable(), - vectorStores?.toImmutable(), + (vectorStoreIds ?: JsonMissing.of()).map { it.toImmutable() }, + (vectorStores ?: JsonMissing.of()).map { it.toImmutable() }, additionalProperties.toImmutable(), ) } @@ -1379,9 +1762,15 @@ constructor( @JsonCreator private constructor( @JsonProperty("chunking_strategy") - private val chunkingStrategy: FileChunkingStrategyParam?, - @JsonProperty("file_ids") private val fileIds: List?, - @JsonProperty("metadata") private val metadata: JsonValue?, + @ExcludeMissing + private val chunkingStrategy: JsonField = + JsonMissing.of(), + @JsonProperty("file_ids") + @ExcludeMissing + private val fileIds: JsonField> = JsonMissing.of(), + @JsonProperty("metadata") + @ExcludeMissing + private val metadata: JsonValue = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { @@ -1390,16 +1779,15 @@ constructor( * The chunking strategy used to chunk the file(s). If not set, will use the `auto` * strategy. Only applicable if `file_ids` is non-empty. */ - @JsonProperty("chunking_strategy") fun chunkingStrategy(): Optional = - Optional.ofNullable(chunkingStrategy) + Optional.ofNullable(chunkingStrategy.getNullable("chunking_strategy")) /** * A list of [file](https://platform.openai.com/docs/api-reference/files) IDs to add * to the vector store. There can be a maximum of 10000 files in a vector store. */ - @JsonProperty("file_ids") - fun fileIds(): Optional> = Optional.ofNullable(fileIds) + fun fileIds(): Optional> = + Optional.ofNullable(fileIds.getNullable("file_ids")) /** * Set of 16 key-value pairs that can be attached to a vector store. This can be @@ -1407,13 +1795,38 @@ constructor( * format. Keys can be a maximum of 64 characters long and values can be a maximum * of 512 characters long. */ - @JsonProperty("metadata") - fun metadata(): Optional = Optional.ofNullable(metadata) + @JsonProperty("metadata") @ExcludeMissing fun _metadata(): JsonValue = metadata + + /** + * The chunking strategy used to chunk the file(s). If not set, will use the `auto` + * strategy. Only applicable if `file_ids` is non-empty. + */ + @JsonProperty("chunking_strategy") + @ExcludeMissing + fun _chunkingStrategy(): JsonField = chunkingStrategy + + /** + * A list of [file](https://platform.openai.com/docs/api-reference/files) IDs to add + * to the vector store. There can be a maximum of 10000 files in a vector store. + */ + @JsonProperty("file_ids") + @ExcludeMissing + fun _fileIds(): JsonField> = fileIds @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): VectorStore = apply { + if (!validated) { + chunkingStrategy() + fileIds() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -1423,15 +1836,16 @@ constructor( class Builder { - private var chunkingStrategy: FileChunkingStrategyParam? = null - private var fileIds: MutableList? = null - private var metadata: JsonValue? = null + private var chunkingStrategy: JsonField = + JsonMissing.of() + private var fileIds: JsonField>? = null + private var metadata: JsonValue = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(vectorStore: VectorStore) = apply { chunkingStrategy = vectorStore.chunkingStrategy - fileIds = vectorStore.fileIds?.toMutableList() + fileIds = vectorStore.fileIds.map { it.toMutableList() } metadata = vectorStore.metadata additionalProperties = vectorStore.additionalProperties.toMutableMap() } @@ -1440,9 +1854,17 @@ constructor( * The chunking strategy used to chunk the file(s). If not set, will use the * `auto` strategy. Only applicable if `file_ids` is non-empty. */ - fun chunkingStrategy(chunkingStrategy: FileChunkingStrategyParam) = apply { - this.chunkingStrategy = chunkingStrategy - } + fun chunkingStrategy(chunkingStrategy: FileChunkingStrategyParam) = + chunkingStrategy(JsonField.of(chunkingStrategy)) + + /** + * The chunking strategy used to chunk the file(s). If not set, will use the + * `auto` strategy. Only applicable if `file_ids` is non-empty. + */ + fun chunkingStrategy(chunkingStrategy: JsonField) = + apply { + this.chunkingStrategy = chunkingStrategy + } /** * The default strategy. This strategy currently uses a `max_chunk_size_tokens` @@ -1450,29 +1872,36 @@ constructor( */ fun chunkingStrategy( autoFileChunkingStrategyParam: AutoFileChunkingStrategyParam - ) = apply { - this.chunkingStrategy = + ) = + chunkingStrategy( FileChunkingStrategyParam.ofAutoFileChunkingStrategyParam( autoFileChunkingStrategyParam ) - } + ) fun chunkingStrategy( staticFileChunkingStrategyParam: StaticFileChunkingStrategyParam - ) = apply { - this.chunkingStrategy = + ) = + chunkingStrategy( FileChunkingStrategyParam.ofStaticFileChunkingStrategyParam( staticFileChunkingStrategyParam ) - } + ) + + /** + * A list of [file](https://platform.openai.com/docs/api-reference/files) IDs to + * add to the vector store. There can be a maximum of 10000 files in a vector + * store. + */ + fun fileIds(fileIds: List) = fileIds(JsonField.of(fileIds)) /** * A list of [file](https://platform.openai.com/docs/api-reference/files) IDs to * add to the vector store. There can be a maximum of 10000 files in a vector * store. */ - fun fileIds(fileIds: List) = apply { - this.fileIds = fileIds.toMutableList() + fun fileIds(fileIds: JsonField>) = apply { + this.fileIds = fileIds.map { it.toMutableList() } } /** @@ -1481,7 +1910,16 @@ constructor( * store. */ fun addFileId(fileId: String) = apply { - fileIds = (fileIds ?: mutableListOf()).apply { add(fileId) } + fileIds = + (fileIds ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(fileId) + } } /** @@ -1517,7 +1955,7 @@ constructor( fun build(): VectorStore = VectorStore( chunkingStrategy, - fileIds?.toImmutable(), + (fileIds ?: JsonMissing.of()).map { it.toImmutable() }, metadata, additionalProperties.toImmutable(), ) diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadDeleteParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadDeleteParams.kt index fc34f6f5f..31d441d65 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadDeleteParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadDeleteParams.kt @@ -10,6 +10,7 @@ import com.openai.core.toImmutable import java.util.Objects import java.util.Optional +/** Delete a thread. */ class BetaThreadDeleteParams constructor( private val threadId: String, diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadMessageCreateParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadMessageCreateParams.kt index 358eeb2a8..c8cf7f412 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadMessageCreateParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadMessageCreateParams.kt @@ -18,6 +18,7 @@ import com.openai.core.BaseSerializer import com.openai.core.Enum import com.openai.core.ExcludeMissing import com.openai.core.JsonField +import com.openai.core.JsonMissing import com.openai.core.JsonValue import com.openai.core.NoAutoDetect import com.openai.core.getOrThrow @@ -30,6 +31,7 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull +/** Create a message. */ class BetaThreadMessageCreateParams constructor( private val threadId: String, @@ -60,14 +62,29 @@ constructor( * additional information about the object in a structured format. Keys can be a maximum of 64 * characters long and values can be a maximum of 512 characters long. */ - fun metadata(): Optional = body.metadata() + fun _metadata(): JsonValue = body._metadata() - fun _additionalHeaders(): Headers = additionalHeaders + /** The text contents of the message. */ + fun _content(): JsonField = body._content() - fun _additionalQueryParams(): QueryParams = additionalQueryParams + /** + * The role of the entity that is creating the message. Allowed values include: + * - `user`: Indicates the message is sent by an actual user and should be used in most cases to + * represent user-generated messages. + * - `assistant`: Indicates the message is generated by the assistant. Use this value to insert + * messages from the assistant into the conversation. + */ + fun _role(): JsonField = body._role() + + /** A list of files attached to the message, and the tools they should be added to. */ + fun _attachments(): JsonField> = body._attachments() fun _additionalBodyProperties(): Map = body._additionalProperties() + fun _additionalHeaders(): Headers = additionalHeaders + + fun _additionalQueryParams(): QueryParams = additionalQueryParams + @JvmSynthetic internal fun getBody(): BetaThreadMessageCreateBody = body @JvmSynthetic internal fun getHeaders(): Headers = additionalHeaders @@ -85,16 +102,22 @@ constructor( class BetaThreadMessageCreateBody @JsonCreator internal constructor( - @JsonProperty("content") private val content: Content, - @JsonProperty("role") private val role: Role, - @JsonProperty("attachments") private val attachments: List?, - @JsonProperty("metadata") private val metadata: JsonValue?, + @JsonProperty("content") + @ExcludeMissing + private val content: JsonField = JsonMissing.of(), + @JsonProperty("role") @ExcludeMissing private val role: JsonField = JsonMissing.of(), + @JsonProperty("attachments") + @ExcludeMissing + private val attachments: JsonField> = JsonMissing.of(), + @JsonProperty("metadata") + @ExcludeMissing + private val metadata: JsonValue = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { /** The text contents of the message. */ - @JsonProperty("content") fun content(): Content = content + fun content(): Content = content.getRequired("content") /** * The role of the entity that is creating the message. Allowed values include: @@ -103,24 +126,51 @@ constructor( * - `assistant`: Indicates the message is generated by the assistant. Use this value to * insert messages from the assistant into the conversation. */ - @JsonProperty("role") fun role(): Role = role + fun role(): Role = role.getRequired("role") /** A list of files attached to the message, and the tools they should be added to. */ - @JsonProperty("attachments") - fun attachments(): Optional> = Optional.ofNullable(attachments) + fun attachments(): Optional> = + Optional.ofNullable(attachments.getNullable("attachments")) /** * 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 maximum of 512 characters long. */ - @JsonProperty("metadata") - fun metadata(): Optional = Optional.ofNullable(metadata) + @JsonProperty("metadata") @ExcludeMissing fun _metadata(): JsonValue = metadata + + /** The text contents of the message. */ + @JsonProperty("content") @ExcludeMissing fun _content(): JsonField = content + + /** + * The role of the entity that is creating the message. Allowed values include: + * - `user`: Indicates the message is sent by an actual user and should be used in most + * cases to represent user-generated messages. + * - `assistant`: Indicates the message is generated by the assistant. Use this value to + * insert messages from the assistant into the conversation. + */ + @JsonProperty("role") @ExcludeMissing fun _role(): JsonField = role + + /** A list of files attached to the message, and the tools they should be added to. */ + @JsonProperty("attachments") + @ExcludeMissing + fun _attachments(): JsonField> = attachments @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): BetaThreadMessageCreateBody = apply { + if (!validated) { + content() + role() + attachments().map { it.forEach { it.validate() } } + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -130,29 +180,30 @@ constructor( class Builder { - private var content: Content? = null - private var role: Role? = null - private var attachments: MutableList? = null - private var metadata: JsonValue? = null + private var content: JsonField? = null + private var role: JsonField? = null + private var attachments: JsonField>? = null + private var metadata: JsonValue = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(betaThreadMessageCreateBody: BetaThreadMessageCreateBody) = apply { content = betaThreadMessageCreateBody.content role = betaThreadMessageCreateBody.role - attachments = betaThreadMessageCreateBody.attachments?.toMutableList() + attachments = betaThreadMessageCreateBody.attachments.map { it.toMutableList() } metadata = betaThreadMessageCreateBody.metadata additionalProperties = betaThreadMessageCreateBody.additionalProperties.toMutableMap() } /** The text contents of the message. */ - fun content(content: Content) = apply { this.content = content } + fun content(content: Content) = content(JsonField.of(content)) /** The text contents of the message. */ - fun content(textContent: String) = apply { - this.content = Content.ofTextContent(textContent) - } + fun content(content: JsonField) = apply { this.content = content } + + /** The text contents of the message. */ + fun content(textContent: String) = content(Content.ofTextContent(textContent)) /** * An array of content parts with a defined type, each can be of type `text` or images @@ -160,9 +211,7 @@ constructor( * [Vision-compatible models](https://platform.openai.com/docs/models). */ fun contentOfArrayOfContentParts(arrayOfContentParts: List) = - apply { - this.content = Content.ofArrayOfContentParts(arrayOfContentParts) - } + content(Content.ofArrayOfContentParts(arrayOfContentParts)) /** * The role of the entity that is creating the message. Allowed values include: @@ -171,16 +220,42 @@ constructor( * - `assistant`: Indicates the message is generated by the assistant. Use this value to * insert messages from the assistant into the conversation. */ - fun role(role: Role) = apply { this.role = role } + fun role(role: Role) = role(JsonField.of(role)) + + /** + * The role of the entity that is creating the message. Allowed values include: + * - `user`: Indicates the message is sent by an actual user and should be used in most + * cases to represent user-generated messages. + * - `assistant`: Indicates the message is generated by the assistant. Use this value to + * insert messages from the assistant into the conversation. + */ + fun role(role: JsonField) = apply { this.role = role } + + /** A list of files attached to the message, and the tools they should be added to. */ + fun attachments(attachments: List?) = + attachments(JsonField.ofNullable(attachments)) + + /** A list of files attached to the message, and the tools they should be added to. */ + fun attachments(attachments: Optional>) = + attachments(attachments.orElse(null)) /** A list of files attached to the message, and the tools they should be added to. */ - fun attachments(attachments: List) = apply { - this.attachments = attachments.toMutableList() + fun attachments(attachments: JsonField>) = apply { + this.attachments = attachments.map { it.toMutableList() } } /** A list of files attached to the message, and the tools they should be added to. */ fun addAttachment(attachment: Attachment) = apply { - attachments = (attachments ?: mutableListOf()).apply { add(attachment) } + attachments = + (attachments ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(attachment) + } } /** @@ -213,7 +288,7 @@ constructor( BetaThreadMessageCreateBody( checkNotNull(content) { "`content` is required but was not set" }, checkNotNull(role) { "`role` is required but was not set" }, - attachments?.toImmutable(), + (attachments ?: JsonMissing.of()).map { it.toImmutable() }, metadata, additionalProperties.toImmutable(), ) @@ -266,6 +341,9 @@ constructor( /** The text contents of the message. */ fun content(content: Content) = apply { body.content(content) } + /** The text contents of the message. */ + fun content(content: JsonField) = apply { body.content(content) } + /** The text contents of the message. */ fun content(textContent: String) = apply { body.content(textContent) } @@ -288,8 +366,26 @@ constructor( */ fun role(role: Role) = apply { body.role(role) } + /** + * The role of the entity that is creating the message. Allowed values include: + * - `user`: Indicates the message is sent by an actual user and should be used in most + * cases to represent user-generated messages. + * - `assistant`: Indicates the message is generated by the assistant. Use this value to + * insert messages from the assistant into the conversation. + */ + fun role(role: JsonField) = apply { body.role(role) } + + /** A list of files attached to the message, and the tools they should be added to. */ + fun attachments(attachments: List?) = apply { body.attachments(attachments) } + /** A list of files attached to the message, and the tools they should be added to. */ - fun attachments(attachments: List) = apply { body.attachments(attachments) } + fun attachments(attachments: Optional>) = + attachments(attachments.orElse(null)) + + /** A list of files attached to the message, and the tools they should be added to. */ + fun attachments(attachments: JsonField>) = apply { + body.attachments(attachments) + } /** A list of files attached to the message, and the tools they should be added to. */ fun addAttachment(attachment: Attachment) = apply { body.addAttachment(attachment) } @@ -301,6 +397,25 @@ constructor( */ fun metadata(metadata: JsonValue) = apply { body.metadata(metadata) } + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } + fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() putAllAdditionalHeaders(additionalHeaders) @@ -399,25 +514,6 @@ constructor( additionalQueryParams.removeAll(keys) } - fun additionalBodyProperties(additionalBodyProperties: Map) = apply { - body.additionalProperties(additionalBodyProperties) - } - - fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { - body.putAdditionalProperty(key, value) - } - - fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = - apply { - body.putAllAdditionalProperties(additionalBodyProperties) - } - - fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } - - fun removeAllAdditionalBodyProperties(keys: Set) = apply { - body.removeAllAdditionalProperties(keys) - } - fun build(): BetaThreadMessageCreateParams = BetaThreadMessageCreateParams( checkNotNull(threadId) { "`threadId` is required but was not set" }, @@ -437,6 +533,8 @@ constructor( private val _json: JsonValue? = null, ) { + private var validated: Boolean = false + /** The text contents of the message. */ fun textContent(): Optional = Optional.ofNullable(textContent) /** @@ -471,6 +569,15 @@ constructor( } } + fun validate(): Content = apply { + if (!validated) { + if (textContent == null && arrayOfContentParts == null) { + throw OpenAIInvalidDataException("Unknown Content: $_json") + } + validated = true + } + } + override fun equals(other: Any?): Boolean { if (this === other) { return true @@ -610,22 +717,42 @@ constructor( class Attachment @JsonCreator private constructor( - @JsonProperty("file_id") private val fileId: String?, - @JsonProperty("tools") private val tools: List?, + @JsonProperty("file_id") + @ExcludeMissing + private val fileId: JsonField = JsonMissing.of(), + @JsonProperty("tools") + @ExcludeMissing + private val tools: JsonField> = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { /** The ID of the file to attach to the message. */ - @JsonProperty("file_id") fun fileId(): Optional = Optional.ofNullable(fileId) + fun fileId(): Optional = Optional.ofNullable(fileId.getNullable("file_id")) + + /** The tools to add this file to. */ + fun tools(): Optional> = Optional.ofNullable(tools.getNullable("tools")) + + /** The ID of the file to attach to the message. */ + @JsonProperty("file_id") @ExcludeMissing fun _fileId(): JsonField = fileId /** The tools to add this file to. */ - @JsonProperty("tools") fun tools(): Optional> = Optional.ofNullable(tools) + @JsonProperty("tools") @ExcludeMissing fun _tools(): JsonField> = tools @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): Attachment = apply { + if (!validated) { + fileId() + tools() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -635,26 +762,43 @@ constructor( class Builder { - private var fileId: String? = null - private var tools: MutableList? = null + private var fileId: JsonField = JsonMissing.of() + private var tools: JsonField>? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(attachment: Attachment) = apply { fileId = attachment.fileId - tools = attachment.tools?.toMutableList() + tools = attachment.tools.map { it.toMutableList() } additionalProperties = attachment.additionalProperties.toMutableMap() } /** The ID of the file to attach to the message. */ - fun fileId(fileId: String) = apply { this.fileId = fileId } + fun fileId(fileId: String) = fileId(JsonField.of(fileId)) + + /** The ID of the file to attach to the message. */ + fun fileId(fileId: JsonField) = apply { this.fileId = fileId } + + /** The tools to add this file to. */ + fun tools(tools: List) = tools(JsonField.of(tools)) /** The tools to add this file to. */ - fun tools(tools: List) = apply { this.tools = tools.toMutableList() } + fun tools(tools: JsonField>) = apply { + this.tools = tools.map { it.toMutableList() } + } /** The tools to add this file to. */ fun addTool(tool: Tool) = apply { - tools = (tools ?: mutableListOf()).apply { add(tool) } + tools = + (tools ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(tool) + } } fun additionalProperties(additionalProperties: Map) = apply { @@ -679,7 +823,7 @@ constructor( fun build(): Attachment = Attachment( fileId, - tools?.toImmutable(), + (tools ?: JsonMissing.of()).map { it.toImmutable() }, additionalProperties.toImmutable(), ) } @@ -693,6 +837,8 @@ constructor( private val _json: JsonValue? = null, ) { + private var validated: Boolean = false + fun codeInterpreterTool(): Optional = Optional.ofNullable(codeInterpreterTool) @@ -718,6 +864,17 @@ constructor( } } + fun validate(): Tool = apply { + if (!validated) { + if (codeInterpreterTool == null && fileSearch == null) { + throw OpenAIInvalidDataException("Unknown Tool: $_json") + } + codeInterpreterTool?.validate() + fileSearch?.validate() + validated = true + } + } + override fun equals(other: Any?): Boolean { if (this === other) { return true @@ -764,14 +921,18 @@ constructor( when (type) { "code_interpreter" -> { - tryDeserialize(node, jacksonTypeRef())?.let { - return Tool(codeInterpreterTool = it, _json = json) - } + tryDeserialize(node, jacksonTypeRef()) { + it.validate() + } + ?.let { + return Tool(codeInterpreterTool = it, _json = json) + } } "file_search" -> { - tryDeserialize(node, jacksonTypeRef())?.let { - return Tool(fileSearch = it, _json = json) - } + tryDeserialize(node, jacksonTypeRef()) { it.validate() } + ?.let { + return Tool(fileSearch = it, _json = json) + } } } @@ -800,18 +961,32 @@ constructor( class FileSearch @JsonCreator private constructor( - @JsonProperty("type") private val type: Type, + @JsonProperty("type") + @ExcludeMissing + private val type: JsonField = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { /** The type of tool being defined: `file_search` */ - @JsonProperty("type") fun type(): Type = type + fun type(): Type = type.getRequired("type") + + /** The type of tool being defined: `file_search` */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): FileSearch = apply { + if (!validated) { + type() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -821,7 +996,7 @@ constructor( class Builder { - private var type: Type? = null + private var type: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -831,7 +1006,10 @@ constructor( } /** The type of tool being defined: `file_search` */ - fun type(type: Type) = apply { this.type = type } + fun type(type: Type) = type(JsonField.of(type)) + + /** The type of tool being defined: `file_search` */ + fun type(type: JsonField) = apply { this.type = type } fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadMessageDeleteParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadMessageDeleteParams.kt index 080ab40c0..b8aea35d6 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadMessageDeleteParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadMessageDeleteParams.kt @@ -10,6 +10,7 @@ import com.openai.core.toImmutable import java.util.Objects import java.util.Optional +/** Deletes a message. */ class BetaThreadMessageDeleteParams constructor( private val threadId: String, diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadMessageListParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadMessageListParams.kt index 941b88e4a..4609331f2 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadMessageListParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadMessageListParams.kt @@ -12,6 +12,7 @@ import com.openai.errors.OpenAIInvalidDataException import java.util.Objects import java.util.Optional +/** Returns a list of messages for a given thread. */ class BetaThreadMessageListParams constructor( private val threadId: String, @@ -119,7 +120,23 @@ constructor( * obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page * of the list. */ - fun after(after: String) = apply { this.after = after } + fun after(after: String?) = apply { this.after = after } + + /** + * 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. + */ + fun after(after: Optional) = after(after.orElse(null)) + + /** + * 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, starting with + * obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous + * page of the list. + */ + fun before(before: String?) = apply { this.before = before } /** * A cursor for use in pagination. `before` is an object ID that defines your place in the @@ -127,22 +144,44 @@ constructor( * obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous * page of the list. */ - fun before(before: String) = apply { this.before = before } + fun before(before: Optional) = before(before.orElse(null)) /** * A limit on the number of objects to be returned. Limit can range between 1 and 100, and * the default is 20. */ - fun limit(limit: Long) = apply { this.limit = limit } + fun limit(limit: Long?) = apply { this.limit = limit } + + /** + * A limit on the number of objects to be returned. Limit can range between 1 and 100, and + * the default is 20. + */ + fun limit(limit: Long) = limit(limit as Long?) + + /** + * A limit on the number of objects to be returned. Limit can range between 1 and 100, and + * the default is 20. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun limit(limit: Optional) = limit(limit.orElse(null) as Long?) /** * Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and * `desc` for descending order. */ - fun order(order: Order) = apply { this.order = order } + fun order(order: Order?) = apply { this.order = order } + + /** + * Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and + * `desc` for descending order. + */ + fun order(order: Optional) = order(order.orElse(null)) + + /** Filter messages by the run ID that generated them. */ + fun runId(runId: String?) = apply { this.runId = runId } /** Filter messages by the run ID that generated them. */ - fun runId(runId: String) = apply { this.runId = runId } + fun runId(runId: Optional) = runId(runId.orElse(null)) fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadMessageRetrieveParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadMessageRetrieveParams.kt index 5d07ebaa5..d880d8ba0 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadMessageRetrieveParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadMessageRetrieveParams.kt @@ -7,6 +7,7 @@ import com.openai.core.http.Headers import com.openai.core.http.QueryParams import java.util.Objects +/** Retrieve a message. */ class BetaThreadMessageRetrieveParams constructor( private val threadId: String, diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadMessageUpdateParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadMessageUpdateParams.kt index d14346d17..7f3994c84 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadMessageUpdateParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadMessageUpdateParams.kt @@ -7,6 +7,7 @@ import com.fasterxml.jackson.annotation.JsonAnySetter import com.fasterxml.jackson.annotation.JsonCreator import com.fasterxml.jackson.annotation.JsonProperty import com.openai.core.ExcludeMissing +import com.openai.core.JsonMissing import com.openai.core.JsonValue import com.openai.core.NoAutoDetect import com.openai.core.http.Headers @@ -14,8 +15,8 @@ import com.openai.core.http.QueryParams import com.openai.core.immutableEmptyMap import com.openai.core.toImmutable import java.util.Objects -import java.util.Optional +/** Modifies a message. */ class BetaThreadMessageUpdateParams constructor( private val threadId: String, @@ -34,14 +35,14 @@ constructor( * additional information about the object in a structured format. Keys can be a maximum of 64 * characters long and values can be a maximum of 512 characters long. */ - fun metadata(): Optional = body.metadata() + fun _metadata(): JsonValue = body._metadata() + + fun _additionalBodyProperties(): Map = body._additionalProperties() fun _additionalHeaders(): Headers = additionalHeaders fun _additionalQueryParams(): QueryParams = additionalQueryParams - fun _additionalBodyProperties(): Map = body._additionalProperties() - @JvmSynthetic internal fun getBody(): BetaThreadMessageUpdateBody = body @JvmSynthetic internal fun getHeaders(): Headers = additionalHeaders @@ -60,7 +61,9 @@ constructor( class BetaThreadMessageUpdateBody @JsonCreator internal constructor( - @JsonProperty("metadata") private val metadata: JsonValue?, + @JsonProperty("metadata") + @ExcludeMissing + private val metadata: JsonValue = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { @@ -70,13 +73,20 @@ constructor( * storing additional information about the object in a structured format. Keys can be a * maximum of 64 characters long and values can be a maximum of 512 characters long. */ - @JsonProperty("metadata") - fun metadata(): Optional = Optional.ofNullable(metadata) + @JsonProperty("metadata") @ExcludeMissing fun _metadata(): JsonValue = metadata @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): BetaThreadMessageUpdateBody = apply { + if (!validated) { + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -86,7 +96,7 @@ constructor( class Builder { - private var metadata: JsonValue? = null + private var metadata: JsonValue = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -181,6 +191,25 @@ constructor( */ fun metadata(metadata: JsonValue) = apply { body.metadata(metadata) } + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } + fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() putAllAdditionalHeaders(additionalHeaders) @@ -279,25 +308,6 @@ constructor( additionalQueryParams.removeAll(keys) } - fun additionalBodyProperties(additionalBodyProperties: Map) = apply { - body.additionalProperties(additionalBodyProperties) - } - - fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { - body.putAdditionalProperty(key, value) - } - - fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = - apply { - body.putAllAdditionalProperties(additionalBodyProperties) - } - - fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } - - fun removeAllAdditionalBodyProperties(keys: Set) = apply { - body.removeAllAdditionalProperties(keys) - } - fun build(): BetaThreadMessageUpdateParams = BetaThreadMessageUpdateParams( checkNotNull(threadId) { "`threadId` is required but was not set" }, diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRetrieveParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRetrieveParams.kt index f923526c7..2f2c981bf 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRetrieveParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRetrieveParams.kt @@ -7,6 +7,7 @@ import com.openai.core.http.Headers import com.openai.core.http.QueryParams import java.util.Objects +/** Retrieves a thread. */ class BetaThreadRetrieveParams constructor( private val threadId: String, diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunCancelParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunCancelParams.kt index f5f11d3ca..ac3309db5 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunCancelParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunCancelParams.kt @@ -10,6 +10,7 @@ import com.openai.core.toImmutable import java.util.Objects import java.util.Optional +/** Cancels a run that is `in_progress`. */ class BetaThreadRunCancelParams constructor( private val threadId: String, diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunCreateParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunCreateParams.kt index 90742d1dc..709594b80 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunCreateParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunCreateParams.kt @@ -18,6 +18,7 @@ import com.openai.core.BaseSerializer import com.openai.core.Enum import com.openai.core.ExcludeMissing import com.openai.core.JsonField +import com.openai.core.JsonMissing import com.openai.core.JsonValue import com.openai.core.NoAutoDetect import com.openai.core.getOrThrow @@ -30,6 +31,7 @@ import java.util.Objects import java.util.Optional import kotlin.jvm.optionals.getOrNull +/** Create a run. */ class BetaThreadRunCreateParams constructor( private val threadId: String, @@ -95,7 +97,7 @@ constructor( * additional information about the object in a structured format. Keys can be a maximum of 64 * characters long and values can be a maximum of 512 characters long. */ - fun metadata(): Optional = body.metadata() + fun _metadata(): JsonValue = body._metadata() /** * The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to be used to @@ -170,12 +172,123 @@ constructor( */ fun truncationStrategy(): Optional = body.truncationStrategy() - fun _additionalHeaders(): Headers = additionalHeaders + /** + * The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) to use + * to execute this run. + */ + fun _assistantId(): JsonField = body._assistantId() - fun _additionalQueryParams(): QueryParams = additionalQueryParams + /** + * 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. + */ + fun _additionalInstructions(): JsonField = body._additionalInstructions() + + /** Adds additional messages to the thread before creating the run. */ + fun _additionalMessages(): JsonField> = body._additionalMessages() + + /** + * Overrides the + * [instructions](https://platform.openai.com/docs/api-reference/assistants/createAssistant) of + * the assistant. This is useful for modifying the behavior on a per-run basis. + */ + fun _instructions(): JsonField = body._instructions() + + /** + * The maximum number of completion tokens that may be used over the course of the run. The run + * will make a best effort to use only the number of completion tokens specified, across + * multiple turns of the run. If the run exceeds the number of completion tokens specified, the + * run will end with status `incomplete`. See `incomplete_details` for more info. + */ + fun _maxCompletionTokens(): JsonField = body._maxCompletionTokens() + + /** + * The maximum number of prompt tokens that may be used over the course of the run. The run will + * make a best effort to use only the number of prompt tokens specified, across multiple turns + * of the run. If the run exceeds the number of prompt tokens specified, the run will end with + * status `incomplete`. See `incomplete_details` for more info. + */ + fun _maxPromptTokens(): JsonField = body._maxPromptTokens() + + /** + * The ID of the [Model](https://platform.openai.com/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. + */ + fun _model(): JsonField = body._model() + + /** + * Whether to enable + * [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) + * during tool use. + */ + fun _parallelToolCalls(): JsonField = body._parallelToolCalls() + + /** + * Specifies the format that the model must output. Compatible with + * [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 + * Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 Turbo + * models since `gpt-3.5-turbo-1106`. + * + * Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs which + * ensures the model will match your supplied JSON schema. Learn more in the + * [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). + * + * Setting to `{ "type": "json_object" }` enables JSON mode, which ensures 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. + */ + fun _responseFormat(): JsonField = body._responseFormat() + + /** + * 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. + */ + fun _temperature(): JsonField = body._temperature() + + /** + * Controls which (if any) tool is called by the model. `none` means the model will not call any + * tools and instead generates a message. `auto` is the default value and means the model can + * pick between generating a message or calling one or more tools. `required` means the model + * must call one or more tools before responding to the user. Specifying a particular tool like + * `{"type": "file_search"}` or `{"type": "function", "function": {"name": "my_function"}}` + * forces the model to call that tool. + */ + fun _toolChoice(): JsonField = body._toolChoice() + + /** + * Override the tools the assistant can use for this run. This is useful for modifying the + * behavior on a per-run basis. + */ + fun _tools(): JsonField> = body._tools() + + /** + * 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. + */ + fun _topP(): JsonField = body._topP() + + /** + * Controls for how a thread will be truncated prior to the run. Use this to control the intial + * context window of the run. + */ + fun _truncationStrategy(): JsonField = body._truncationStrategy() fun _additionalBodyProperties(): Map = body._additionalProperties() + fun _additionalHeaders(): Headers = additionalHeaders + + fun _additionalQueryParams(): QueryParams = additionalQueryParams + @JvmSynthetic internal fun getBody(): BetaThreadRunCreateBody = body @JvmSynthetic internal fun getHeaders(): Headers = additionalHeaders @@ -199,22 +312,51 @@ constructor( class BetaThreadRunCreateBody @JsonCreator internal constructor( - @JsonProperty("assistant_id") private val assistantId: String, - @JsonProperty("additional_instructions") private val additionalInstructions: String?, + @JsonProperty("assistant_id") + @ExcludeMissing + private val assistantId: JsonField = JsonMissing.of(), + @JsonProperty("additional_instructions") + @ExcludeMissing + private val additionalInstructions: JsonField = JsonMissing.of(), @JsonProperty("additional_messages") - private val additionalMessages: List?, - @JsonProperty("instructions") private val instructions: String?, - @JsonProperty("max_completion_tokens") private val maxCompletionTokens: Long?, - @JsonProperty("max_prompt_tokens") private val maxPromptTokens: Long?, - @JsonProperty("metadata") private val metadata: JsonValue?, - @JsonProperty("model") private val model: ChatModel?, - @JsonProperty("parallel_tool_calls") private val parallelToolCalls: Boolean?, - @JsonProperty("response_format") private val responseFormat: AssistantResponseFormatOption?, - @JsonProperty("temperature") private val temperature: Double?, - @JsonProperty("tool_choice") private val toolChoice: AssistantToolChoiceOption?, - @JsonProperty("tools") private val tools: List?, - @JsonProperty("top_p") private val topP: Double?, - @JsonProperty("truncation_strategy") private val truncationStrategy: TruncationStrategy?, + @ExcludeMissing + private val additionalMessages: JsonField> = JsonMissing.of(), + @JsonProperty("instructions") + @ExcludeMissing + private val instructions: JsonField = JsonMissing.of(), + @JsonProperty("max_completion_tokens") + @ExcludeMissing + private val maxCompletionTokens: JsonField = JsonMissing.of(), + @JsonProperty("max_prompt_tokens") + @ExcludeMissing + private val maxPromptTokens: JsonField = JsonMissing.of(), + @JsonProperty("metadata") + @ExcludeMissing + private val metadata: JsonValue = JsonMissing.of(), + @JsonProperty("model") + @ExcludeMissing + private val model: JsonField = JsonMissing.of(), + @JsonProperty("parallel_tool_calls") + @ExcludeMissing + private val parallelToolCalls: JsonField = JsonMissing.of(), + @JsonProperty("response_format") + @ExcludeMissing + private val responseFormat: JsonField = JsonMissing.of(), + @JsonProperty("temperature") + @ExcludeMissing + private val temperature: JsonField = JsonMissing.of(), + @JsonProperty("tool_choice") + @ExcludeMissing + private val toolChoice: JsonField = JsonMissing.of(), + @JsonProperty("tools") + @ExcludeMissing + private val tools: JsonField> = JsonMissing.of(), + @JsonProperty("top_p") + @ExcludeMissing + private val topP: JsonField = JsonMissing.of(), + @JsonProperty("truncation_strategy") + @ExcludeMissing + private val truncationStrategy: JsonField = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { @@ -223,28 +365,27 @@ constructor( * The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) to * use to execute this run. */ - @JsonProperty("assistant_id") fun assistantId(): String = assistantId + fun assistantId(): String = assistantId.getRequired("assistant_id") /** * 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. */ - @JsonProperty("additional_instructions") - fun additionalInstructions(): Optional = Optional.ofNullable(additionalInstructions) + fun additionalInstructions(): Optional = + Optional.ofNullable(additionalInstructions.getNullable("additional_instructions")) /** Adds additional messages to the thread before creating the run. */ - @JsonProperty("additional_messages") fun additionalMessages(): Optional> = - Optional.ofNullable(additionalMessages) + Optional.ofNullable(additionalMessages.getNullable("additional_messages")) /** * Overrides the * [instructions](https://platform.openai.com/docs/api-reference/assistants/createAssistant) * of the assistant. This is useful for modifying the behavior on a per-run basis. */ - @JsonProperty("instructions") - fun instructions(): Optional = Optional.ofNullable(instructions) + fun instructions(): Optional = + Optional.ofNullable(instructions.getNullable("instructions")) /** * The maximum number of completion tokens that may be used over the course of the run. The @@ -252,8 +393,8 @@ constructor( * multiple turns of the run. If the run exceeds the number of completion tokens specified, * the run will end with status `incomplete`. See `incomplete_details` for more info. */ - @JsonProperty("max_completion_tokens") - fun maxCompletionTokens(): Optional = Optional.ofNullable(maxCompletionTokens) + fun maxCompletionTokens(): Optional = + Optional.ofNullable(maxCompletionTokens.getNullable("max_completion_tokens")) /** * The maximum number of prompt tokens that may be used over the course of the run. The run @@ -261,23 +402,152 @@ constructor( * multiple turns of the run. If the run exceeds the number of prompt tokens specified, the * run will end with status `incomplete`. See `incomplete_details` for more info. */ - @JsonProperty("max_prompt_tokens") - fun maxPromptTokens(): Optional = Optional.ofNullable(maxPromptTokens) + fun maxPromptTokens(): Optional = + Optional.ofNullable(maxPromptTokens.getNullable("max_prompt_tokens")) /** * 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 maximum of 512 characters long. */ - @JsonProperty("metadata") - fun metadata(): Optional = Optional.ofNullable(metadata) + @JsonProperty("metadata") @ExcludeMissing fun _metadata(): JsonValue = metadata /** * The ID of the [Model](https://platform.openai.com/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. */ - @JsonProperty("model") fun model(): Optional = Optional.ofNullable(model) + fun model(): Optional = Optional.ofNullable(model.getNullable("model")) + + /** + * Whether to enable + * [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) + * during tool use. + */ + fun parallelToolCalls(): Optional = + Optional.ofNullable(parallelToolCalls.getNullable("parallel_tool_calls")) + + /** + * Specifies the format that the model must output. Compatible with + * [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 + * Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 + * Turbo models since `gpt-3.5-turbo-1106`. + * + * Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs + * which ensures the model will match your supplied JSON schema. Learn more in the + * [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). + * + * Setting to `{ "type": "json_object" }` enables JSON mode, which ensures 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. + */ + fun responseFormat(): Optional = + Optional.ofNullable(responseFormat.getNullable("response_format")) + + /** + * 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. + */ + fun temperature(): Optional = + Optional.ofNullable(temperature.getNullable("temperature")) + + /** + * Controls which (if any) tool is called by the model. `none` means the model will not call + * any tools and instead generates a message. `auto` is the default value and means the + * model can pick between generating a message or calling one or more tools. `required` + * means the model must call one or more tools before responding to the user. Specifying a + * particular tool like `{"type": "file_search"}` or `{"type": "function", "function": + * {"name": "my_function"}}` forces the model to call that tool. + */ + fun toolChoice(): Optional = + Optional.ofNullable(toolChoice.getNullable("tool_choice")) + + /** + * Override the tools the assistant can use for this run. This is useful for modifying the + * behavior on a per-run basis. + */ + fun tools(): Optional> = Optional.ofNullable(tools.getNullable("tools")) + + /** + * 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. + */ + fun topP(): Optional = Optional.ofNullable(topP.getNullable("top_p")) + + /** + * Controls for how a thread will be truncated prior to the run. Use this to control the + * intial context window of the run. + */ + fun truncationStrategy(): Optional = + Optional.ofNullable(truncationStrategy.getNullable("truncation_strategy")) + + /** + * The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) to + * use to execute this run. + */ + @JsonProperty("assistant_id") + @ExcludeMissing + fun _assistantId(): JsonField = assistantId + + /** + * 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. + */ + @JsonProperty("additional_instructions") + @ExcludeMissing + fun _additionalInstructions(): JsonField = additionalInstructions + + /** Adds additional messages to the thread before creating the run. */ + @JsonProperty("additional_messages") + @ExcludeMissing + fun _additionalMessages(): JsonField> = additionalMessages + + /** + * Overrides the + * [instructions](https://platform.openai.com/docs/api-reference/assistants/createAssistant) + * of the assistant. This is useful for modifying the behavior on a per-run basis. + */ + @JsonProperty("instructions") + @ExcludeMissing + fun _instructions(): JsonField = instructions + + /** + * The maximum number of completion tokens that may be used over the course of the run. The + * run will make a best effort to use only the number of completion tokens specified, across + * multiple turns of the run. If the run exceeds the number of completion tokens specified, + * the run will end with status `incomplete`. See `incomplete_details` for more info. + */ + @JsonProperty("max_completion_tokens") + @ExcludeMissing + fun _maxCompletionTokens(): JsonField = maxCompletionTokens + + /** + * The maximum number of prompt tokens that may be used over the course of the run. The run + * will make a best effort to use only the number of prompt tokens specified, across + * multiple turns of the run. If the run exceeds the number of prompt tokens specified, the + * run will end with status `incomplete`. See `incomplete_details` for more info. + */ + @JsonProperty("max_prompt_tokens") + @ExcludeMissing + fun _maxPromptTokens(): JsonField = maxPromptTokens + + /** + * The ID of the [Model](https://platform.openai.com/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. + */ + @JsonProperty("model") @ExcludeMissing fun _model(): JsonField = model /** * Whether to enable @@ -285,7 +555,8 @@ constructor( * during tool use. */ @JsonProperty("parallel_tool_calls") - fun parallelToolCalls(): Optional = Optional.ofNullable(parallelToolCalls) + @ExcludeMissing + fun _parallelToolCalls(): JsonField = parallelToolCalls /** * Specifies the format that the model must output. Compatible with @@ -308,8 +579,8 @@ constructor( * `max_tokens` or the conversation exceeded the max context length. */ @JsonProperty("response_format") - fun responseFormat(): Optional = - Optional.ofNullable(responseFormat) + @ExcludeMissing + fun _responseFormat(): JsonField = responseFormat /** * What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the @@ -317,7 +588,8 @@ constructor( * deterministic. */ @JsonProperty("temperature") - fun temperature(): Optional = Optional.ofNullable(temperature) + @ExcludeMissing + fun _temperature(): JsonField = temperature /** * Controls which (if any) tool is called by the model. `none` means the model will not call @@ -328,14 +600,14 @@ constructor( * {"name": "my_function"}}` forces the model to call that tool. */ @JsonProperty("tool_choice") - fun toolChoice(): Optional = Optional.ofNullable(toolChoice) + @ExcludeMissing + fun _toolChoice(): JsonField = toolChoice /** * Override the tools the assistant can use for this run. This is useful for modifying the * behavior on a per-run basis. */ - @JsonProperty("tools") - fun tools(): Optional> = Optional.ofNullable(tools) + @JsonProperty("tools") @ExcludeMissing fun _tools(): JsonField> = tools /** * An alternative to sampling with temperature, called nucleus sampling, where the model @@ -344,20 +616,42 @@ constructor( * * We generally recommend altering this or temperature but not both. */ - @JsonProperty("top_p") fun topP(): Optional = Optional.ofNullable(topP) + @JsonProperty("top_p") @ExcludeMissing fun _topP(): JsonField = topP /** * Controls for how a thread will be truncated prior to the run. Use this to control the * intial context window of the run. */ @JsonProperty("truncation_strategy") - fun truncationStrategy(): Optional = - Optional.ofNullable(truncationStrategy) + @ExcludeMissing + fun _truncationStrategy(): JsonField = truncationStrategy @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): BetaThreadRunCreateBody = apply { + if (!validated) { + assistantId() + additionalInstructions() + additionalMessages().map { it.forEach { it.validate() } } + instructions() + maxCompletionTokens() + maxPromptTokens() + model() + parallelToolCalls() + responseFormat() + temperature() + toolChoice() + tools() + topP() + truncationStrategy().map { it.validate() } + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -367,28 +661,29 @@ constructor( class Builder { - private var assistantId: String? = null - private var additionalInstructions: String? = null - private var additionalMessages: MutableList? = null - private var instructions: String? = null - private var maxCompletionTokens: Long? = null - private var maxPromptTokens: Long? = null - private var metadata: JsonValue? = null - private var model: ChatModel? = null - private var parallelToolCalls: Boolean? = null - private var responseFormat: AssistantResponseFormatOption? = null - private var temperature: Double? = null - private var toolChoice: AssistantToolChoiceOption? = null - private var tools: MutableList? = null - private var topP: Double? = null - private var truncationStrategy: TruncationStrategy? = null + private var assistantId: JsonField? = null + private var additionalInstructions: JsonField = JsonMissing.of() + private var additionalMessages: JsonField>? = null + private var instructions: JsonField = JsonMissing.of() + private var maxCompletionTokens: JsonField = JsonMissing.of() + private var maxPromptTokens: JsonField = JsonMissing.of() + private var metadata: JsonValue = JsonMissing.of() + private var model: JsonField = JsonMissing.of() + private var parallelToolCalls: JsonField = JsonMissing.of() + private var responseFormat: JsonField = JsonMissing.of() + private var temperature: JsonField = JsonMissing.of() + private var toolChoice: JsonField = JsonMissing.of() + private var tools: JsonField>? = null + private var topP: JsonField = JsonMissing.of() + private var truncationStrategy: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(betaThreadRunCreateBody: BetaThreadRunCreateBody) = apply { assistantId = betaThreadRunCreateBody.assistantId additionalInstructions = betaThreadRunCreateBody.additionalInstructions - additionalMessages = betaThreadRunCreateBody.additionalMessages?.toMutableList() + additionalMessages = + betaThreadRunCreateBody.additionalMessages.map { it.toMutableList() } instructions = betaThreadRunCreateBody.instructions maxCompletionTokens = betaThreadRunCreateBody.maxCompletionTokens maxPromptTokens = betaThreadRunCreateBody.maxPromptTokens @@ -398,7 +693,7 @@ constructor( responseFormat = betaThreadRunCreateBody.responseFormat temperature = betaThreadRunCreateBody.temperature toolChoice = betaThreadRunCreateBody.toolChoice - tools = betaThreadRunCreateBody.tools?.toMutableList() + tools = betaThreadRunCreateBody.tools.map { it.toMutableList() } topP = betaThreadRunCreateBody.topP truncationStrategy = betaThreadRunCreateBody.truncationStrategy additionalProperties = betaThreadRunCreateBody.additionalProperties.toMutableMap() @@ -408,26 +703,66 @@ constructor( * The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) * to use to execute this run. */ - fun assistantId(assistantId: String) = apply { this.assistantId = assistantId } + fun assistantId(assistantId: String) = assistantId(JsonField.of(assistantId)) + + /** + * The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) + * to use to execute this run. + */ + fun assistantId(assistantId: JsonField) = apply { + this.assistantId = assistantId + } + + /** + * 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. + */ + fun additionalInstructions(additionalInstructions: String?) = + additionalInstructions(JsonField.ofNullable(additionalInstructions)) /** * 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. */ - fun additionalInstructions(additionalInstructions: String) = apply { + fun additionalInstructions(additionalInstructions: Optional) = + additionalInstructions(additionalInstructions.orElse(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. + */ + fun additionalInstructions(additionalInstructions: JsonField) = apply { this.additionalInstructions = additionalInstructions } /** Adds additional messages to the thread before creating the run. */ - fun additionalMessages(additionalMessages: List) = apply { - this.additionalMessages = additionalMessages.toMutableList() + fun additionalMessages(additionalMessages: List?) = + additionalMessages(JsonField.ofNullable(additionalMessages)) + + /** Adds additional messages to the thread before creating the run. */ + fun additionalMessages(additionalMessages: Optional>) = + additionalMessages(additionalMessages.orElse(null)) + + /** Adds additional messages to the thread before creating the run. */ + fun additionalMessages(additionalMessages: JsonField>) = apply { + this.additionalMessages = additionalMessages.map { it.toMutableList() } } /** Adds additional messages to the thread before creating the run. */ fun addAdditionalMessage(additionalMessage: AdditionalMessage) = apply { additionalMessages = - (additionalMessages ?: mutableListOf()).apply { add(additionalMessage) } + (additionalMessages ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(additionalMessage) + } } /** @@ -435,7 +770,35 @@ constructor( * [instructions](https://platform.openai.com/docs/api-reference/assistants/createAssistant) * of the assistant. This is useful for modifying the behavior on a per-run basis. */ - fun instructions(instructions: String) = apply { this.instructions = instructions } + fun instructions(instructions: String?) = + instructions(JsonField.ofNullable(instructions)) + + /** + * Overrides the + * [instructions](https://platform.openai.com/docs/api-reference/assistants/createAssistant) + * of the assistant. This is useful for modifying the behavior on a per-run basis. + */ + fun instructions(instructions: Optional) = + instructions(instructions.orElse(null)) + + /** + * Overrides the + * [instructions](https://platform.openai.com/docs/api-reference/assistants/createAssistant) + * of the assistant. This is useful for modifying the behavior on a per-run basis. + */ + fun instructions(instructions: JsonField) = apply { + this.instructions = instructions + } + + /** + * The maximum number of completion tokens that may be used over the course of the run. + * The run will make a best effort to use only the number of completion tokens + * specified, across multiple turns of the run. If the run exceeds the number of + * completion tokens specified, the run will end with status `incomplete`. See + * `incomplete_details` for more info. + */ + fun maxCompletionTokens(maxCompletionTokens: Long?) = + maxCompletionTokens(JsonField.ofNullable(maxCompletionTokens)) /** * The maximum number of completion tokens that may be used over the course of the run. @@ -444,7 +807,28 @@ constructor( * completion tokens specified, the run will end with status `incomplete`. See * `incomplete_details` for more info. */ - fun maxCompletionTokens(maxCompletionTokens: Long) = apply { + fun maxCompletionTokens(maxCompletionTokens: Long) = + maxCompletionTokens(maxCompletionTokens as Long?) + + /** + * The maximum number of completion tokens that may be used over the course of the run. + * The run will make a best effort to use only the number of completion tokens + * specified, across multiple turns of the run. If the run exceeds the number of + * completion tokens specified, the run will end with status `incomplete`. See + * `incomplete_details` for more info. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun maxCompletionTokens(maxCompletionTokens: Optional) = + maxCompletionTokens(maxCompletionTokens.orElse(null) as Long?) + + /** + * The maximum number of completion tokens that may be used over the course of the run. + * The run will make a best effort to use only the number of completion tokens + * specified, across multiple turns of the run. If the run exceeds the number of + * completion tokens specified, the run will end with status `incomplete`. See + * `incomplete_details` for more info. + */ + fun maxCompletionTokens(maxCompletionTokens: JsonField) = apply { this.maxCompletionTokens = maxCompletionTokens } @@ -454,7 +838,34 @@ constructor( * multiple turns of the run. If the run exceeds the number of prompt tokens specified, * the run will end with status `incomplete`. See `incomplete_details` for more info. */ - fun maxPromptTokens(maxPromptTokens: Long) = apply { + fun maxPromptTokens(maxPromptTokens: Long?) = + maxPromptTokens(JsonField.ofNullable(maxPromptTokens)) + + /** + * The maximum number of prompt tokens that may be used over the course of the run. The + * run will make a best effort to use only the number of prompt tokens specified, across + * multiple turns of the run. If the run exceeds the number of prompt tokens specified, + * the run will end with status `incomplete`. See `incomplete_details` for more info. + */ + fun maxPromptTokens(maxPromptTokens: Long) = maxPromptTokens(maxPromptTokens as Long?) + + /** + * The maximum number of prompt tokens that may be used over the course of the run. The + * run will make a best effort to use only the number of prompt tokens specified, across + * multiple turns of the run. If the run exceeds the number of prompt tokens specified, + * the run will end with status `incomplete`. See `incomplete_details` for more info. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun maxPromptTokens(maxPromptTokens: Optional) = + maxPromptTokens(maxPromptTokens.orElse(null) as Long?) + + /** + * The maximum number of prompt tokens that may be used over the course of the run. The + * run will make a best effort to use only the number of prompt tokens specified, across + * multiple turns of the run. If the run exceeds the number of prompt tokens specified, + * the run will end with status `incomplete`. See `incomplete_details` for more info. + */ + fun maxPromptTokens(maxPromptTokens: JsonField) = apply { this.maxPromptTokens = maxPromptTokens } @@ -471,7 +882,15 @@ constructor( * associated with the assistant. If not, the model associated with the assistant will * be used. */ - fun model(model: ChatModel) = apply { this.model = model } + fun model(model: ChatModel?) = model(JsonField.ofNullable(model)) + + /** + * The ID of the [Model](https://platform.openai.com/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. + */ + fun model(model: Optional) = model(model.orElse(null)) /** * The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to be @@ -479,16 +898,80 @@ constructor( * associated with the assistant. If not, the model associated with the assistant will * be used. */ - fun model(value: String) = apply { model = ChatModel.of(value) } + fun model(model: JsonField) = apply { this.model = model } + + /** + * The ID of the [Model](https://platform.openai.com/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. + */ + fun model(value: String) = apply { model(ChatModel.of(value)) } /** * Whether to enable * [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) * during tool use. */ - fun parallelToolCalls(parallelToolCalls: Boolean) = apply { - this.parallelToolCalls = parallelToolCalls - } + fun parallelToolCalls(parallelToolCalls: Boolean) = + parallelToolCalls(JsonField.of(parallelToolCalls)) + + /** + * Whether to enable + * [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) + * during tool use. + */ + fun parallelToolCalls(parallelToolCalls: JsonField) = apply { + this.parallelToolCalls = parallelToolCalls + } + + /** + * Specifies the format that the model must output. Compatible with + * [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 + * Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all + * GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. + * + * Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured + * Outputs which ensures the model will match your supplied JSON schema. Learn more in + * the + * [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). + * + * Setting to `{ "type": "json_object" }` enables JSON mode, which ensures 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. + */ + fun responseFormat(responseFormat: AssistantResponseFormatOption?) = + responseFormat(JsonField.ofNullable(responseFormat)) + + /** + * Specifies the format that the model must output. Compatible with + * [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 + * Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all + * GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. + * + * Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured + * Outputs which ensures the model will match your supplied JSON schema. Learn more in + * the + * [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). + * + * Setting to `{ "type": "json_object" }` enables JSON mode, which ensures 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. + */ + fun responseFormat(responseFormat: Optional) = + responseFormat(responseFormat.orElse(null)) /** * Specifies the format that the model must output. Compatible with @@ -511,40 +994,86 @@ constructor( * may be partially cut off if `finish_reason="length"`, which indicates the generation * exceeded `max_tokens` or the conversation exceeded the max context length. */ - fun responseFormat(responseFormat: AssistantResponseFormatOption) = apply { + fun responseFormat(responseFormat: JsonField) = apply { this.responseFormat = responseFormat } /** `auto` is the default value */ - fun responseFormat(behavior: AssistantResponseFormatOption.Behavior) = apply { - this.responseFormat = AssistantResponseFormatOption.ofBehavior(behavior) - } + fun responseFormat(behavior: AssistantResponseFormatOption.Behavior) = + responseFormat(AssistantResponseFormatOption.ofBehavior(behavior)) - fun responseFormat(responseFormatText: ResponseFormatText) = apply { - this.responseFormat = + fun responseFormat(responseFormatText: ResponseFormatText) = + responseFormat( AssistantResponseFormatOption.ofResponseFormatText(responseFormatText) - } + ) - fun responseFormat(responseFormatJsonObject: ResponseFormatJsonObject) = apply { - this.responseFormat = + fun responseFormat(responseFormatJsonObject: ResponseFormatJsonObject) = + responseFormat( AssistantResponseFormatOption.ofResponseFormatJsonObject( responseFormatJsonObject ) - } + ) - fun responseFormat(responseFormatJsonSchema: ResponseFormatJsonSchema) = apply { - this.responseFormat = + fun responseFormat(responseFormatJsonSchema: ResponseFormatJsonSchema) = + responseFormat( AssistantResponseFormatOption.ofResponseFormatJsonSchema( responseFormatJsonSchema ) - } + ) + + /** + * 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. + */ + fun temperature(temperature: Double?) = temperature(JsonField.ofNullable(temperature)) + + /** + * 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. + */ + fun temperature(temperature: Double) = temperature(temperature as Double?) + + /** + * 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. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun temperature(temperature: Optional) = + temperature(temperature.orElse(null) as Double?) /** * 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. */ - fun temperature(temperature: Double) = apply { this.temperature = temperature } + fun temperature(temperature: JsonField) = apply { + this.temperature = temperature + } + + /** + * Controls which (if any) tool is called by the model. `none` means the model will not + * call any tools and instead generates a message. `auto` is the default value and means + * the model can pick between generating a message or calling one or more tools. + * `required` means the model must call one or more tools before responding to the user. + * Specifying a particular tool like `{"type": "file_search"}` or `{"type": "function", + * "function": {"name": "my_function"}}` forces the model to call that tool. + */ + fun toolChoice(toolChoice: AssistantToolChoiceOption?) = + toolChoice(JsonField.ofNullable(toolChoice)) + + /** + * Controls which (if any) tool is called by the model. `none` means the model will not + * call any tools and instead generates a message. `auto` is the default value and means + * the model can pick between generating a message or calling one or more tools. + * `required` means the model must call one or more tools before responding to the user. + * Specifying a particular tool like `{"type": "file_search"}` or `{"type": "function", + * "function": {"name": "my_function"}}` forces the model to call that tool. + */ + fun toolChoice(toolChoice: Optional) = + toolChoice(toolChoice.orElse(null)) /** * Controls which (if any) tool is called by the model. `none` means the model will not @@ -554,7 +1083,7 @@ constructor( * Specifying a particular tool like `{"type": "file_search"}` or `{"type": "function", * "function": {"name": "my_function"}}` forces the model to call that tool. */ - fun toolChoice(toolChoice: AssistantToolChoiceOption) = apply { + fun toolChoice(toolChoice: JsonField) = apply { this.toolChoice = toolChoice } @@ -564,31 +1093,51 @@ constructor( * tools. `required` means the model must call one or more tools before responding to * the user. */ - fun toolChoice(behavior: AssistantToolChoiceOption.Behavior) = apply { - this.toolChoice = AssistantToolChoiceOption.ofBehavior(behavior) - } + fun toolChoice(behavior: AssistantToolChoiceOption.Behavior) = + toolChoice(AssistantToolChoiceOption.ofBehavior(behavior)) /** * Specifies a tool the model should use. Use to force the model to call a specific * tool. */ - fun toolChoice(assistantToolChoice: AssistantToolChoice) = apply { - this.toolChoice = - AssistantToolChoiceOption.ofAssistantToolChoice(assistantToolChoice) - } + fun toolChoice(assistantToolChoice: AssistantToolChoice) = + toolChoice(AssistantToolChoiceOption.ofAssistantToolChoice(assistantToolChoice)) + + /** + * Override the tools the assistant can use for this run. This is useful for modifying + * the behavior on a per-run basis. + */ + fun tools(tools: List?) = tools(JsonField.ofNullable(tools)) + + /** + * Override the tools the assistant can use for this run. This is useful for modifying + * the behavior on a per-run basis. + */ + fun tools(tools: Optional>) = tools(tools.orElse(null)) /** * Override the tools the assistant can use for this run. This is useful for modifying * the behavior on a per-run basis. */ - fun tools(tools: List) = apply { this.tools = tools.toMutableList() } + fun tools(tools: JsonField>) = apply { + this.tools = tools.map { it.toMutableList() } + } /** * Override the tools the assistant can use for this run. This is useful for modifying * the behavior on a per-run basis. */ fun addTool(tool: AssistantTool) = apply { - tools = (tools ?: mutableListOf()).apply { add(tool) } + tools = + (tools ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(tool) + } } /** @@ -598,13 +1147,55 @@ constructor( * * We generally recommend altering this or temperature but not both. */ - fun topP(topP: Double) = apply { this.topP = topP } + fun topP(topP: Double?) = topP(JsonField.ofNullable(topP)) + + /** + * 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. + */ + fun topP(topP: Double) = topP(topP as Double?) + + /** + * 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. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun topP(topP: Optional) = topP(topP.orElse(null) as Double?) + + /** + * 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. + */ + fun topP(topP: JsonField) = apply { this.topP = topP } + + /** + * Controls for how a thread will be truncated prior to the run. Use this to control the + * intial context window of the run. + */ + fun truncationStrategy(truncationStrategy: TruncationStrategy?) = + truncationStrategy(JsonField.ofNullable(truncationStrategy)) + + /** + * Controls for how a thread will be truncated prior to the run. Use this to control the + * intial context window of the run. + */ + fun truncationStrategy(truncationStrategy: Optional) = + truncationStrategy(truncationStrategy.orElse(null)) /** * Controls for how a thread will be truncated prior to the run. Use this to control the * intial context window of the run. */ - fun truncationStrategy(truncationStrategy: TruncationStrategy) = apply { + fun truncationStrategy(truncationStrategy: JsonField) = apply { this.truncationStrategy = truncationStrategy } @@ -631,7 +1222,7 @@ constructor( BetaThreadRunCreateBody( checkNotNull(assistantId) { "`assistantId` is required but was not set" }, additionalInstructions, - additionalMessages?.toImmutable(), + (additionalMessages ?: JsonMissing.of()).map { it.toImmutable() }, instructions, maxCompletionTokens, maxPromptTokens, @@ -641,7 +1232,7 @@ constructor( responseFormat, temperature, toolChoice, - tools?.toImmutable(), + (tools ?: JsonMissing.of()).map { it.toImmutable() }, topP, truncationStrategy, additionalProperties.toImmutable(), @@ -702,10 +1293,21 @@ constructor( * [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) * for more information. */ - fun include(include: List) = apply { - this.include = include.toMutableList() + fun include(include: List?) = apply { + this.include = include?.toMutableList() } + /** + * A list of additional fields to include in the response. Currently the only supported + * value is `step_details.tool_calls[*].file_search.results[*].content` to fetch the file + * search result content. + * + * See the + * [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) + * for more information. + */ + fun include(include: Optional>) = include(include.orElse(null)) + /** * A list of additional fields to include in the response. Currently the only supported * value is `step_details.tool_calls[*].file_search.results[*].content` to fetch the file @@ -725,17 +1327,49 @@ constructor( */ fun assistantId(assistantId: String) = apply { body.assistantId(assistantId) } + /** + * The ID of the [assistant](https://platform.openai.com/docs/api-reference/assistants) to + * use to execute this run. + */ + fun assistantId(assistantId: JsonField) = apply { body.assistantId(assistantId) } + + /** + * 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. + */ + fun additionalInstructions(additionalInstructions: String?) = apply { + body.additionalInstructions(additionalInstructions) + } + + /** + * 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. + */ + fun additionalInstructions(additionalInstructions: Optional) = + additionalInstructions(additionalInstructions.orElse(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. */ - fun additionalInstructions(additionalInstructions: String) = apply { + fun additionalInstructions(additionalInstructions: JsonField) = apply { body.additionalInstructions(additionalInstructions) } /** Adds additional messages to the thread before creating the run. */ - fun additionalMessages(additionalMessages: List) = apply { + fun additionalMessages(additionalMessages: List?) = apply { + body.additionalMessages(additionalMessages) + } + + /** Adds additional messages to the thread before creating the run. */ + fun additionalMessages(additionalMessages: Optional>) = + additionalMessages(additionalMessages.orElse(null)) + + /** Adds additional messages to the thread before creating the run. */ + fun additionalMessages(additionalMessages: JsonField>) = apply { body.additionalMessages(additionalMessages) } @@ -749,7 +1383,52 @@ constructor( * [instructions](https://platform.openai.com/docs/api-reference/assistants/createAssistant) * of the assistant. This is useful for modifying the behavior on a per-run basis. */ - fun instructions(instructions: String) = apply { body.instructions(instructions) } + fun instructions(instructions: String?) = apply { body.instructions(instructions) } + + /** + * Overrides the + * [instructions](https://platform.openai.com/docs/api-reference/assistants/createAssistant) + * of the assistant. This is useful for modifying the behavior on a per-run basis. + */ + fun instructions(instructions: Optional) = instructions(instructions.orElse(null)) + + /** + * Overrides the + * [instructions](https://platform.openai.com/docs/api-reference/assistants/createAssistant) + * of the assistant. This is useful for modifying the behavior on a per-run basis. + */ + fun instructions(instructions: JsonField) = apply { + body.instructions(instructions) + } + + /** + * The maximum number of completion tokens that may be used over the course of the run. The + * run will make a best effort to use only the number of completion tokens specified, across + * multiple turns of the run. If the run exceeds the number of completion tokens specified, + * the run will end with status `incomplete`. See `incomplete_details` for more info. + */ + fun maxCompletionTokens(maxCompletionTokens: Long?) = apply { + body.maxCompletionTokens(maxCompletionTokens) + } + + /** + * The maximum number of completion tokens that may be used over the course of the run. The + * run will make a best effort to use only the number of completion tokens specified, across + * multiple turns of the run. If the run exceeds the number of completion tokens specified, + * the run will end with status `incomplete`. See `incomplete_details` for more info. + */ + fun maxCompletionTokens(maxCompletionTokens: Long) = + maxCompletionTokens(maxCompletionTokens as Long?) + + /** + * The maximum number of completion tokens that may be used over the course of the run. The + * run will make a best effort to use only the number of completion tokens specified, across + * multiple turns of the run. If the run exceeds the number of completion tokens specified, + * the run will end with status `incomplete`. See `incomplete_details` for more info. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun maxCompletionTokens(maxCompletionTokens: Optional) = + maxCompletionTokens(maxCompletionTokens.orElse(null) as Long?) /** * The maximum number of completion tokens that may be used over the course of the run. The @@ -757,7 +1436,7 @@ constructor( * multiple turns of the run. If the run exceeds the number of completion tokens specified, * the run will end with status `incomplete`. See `incomplete_details` for more info. */ - fun maxCompletionTokens(maxCompletionTokens: Long) = apply { + fun maxCompletionTokens(maxCompletionTokens: JsonField) = apply { body.maxCompletionTokens(maxCompletionTokens) } @@ -767,7 +1446,37 @@ constructor( * multiple turns of the run. If the run exceeds the number of prompt tokens specified, the * run will end with status `incomplete`. See `incomplete_details` for more info. */ - fun maxPromptTokens(maxPromptTokens: Long) = apply { body.maxPromptTokens(maxPromptTokens) } + fun maxPromptTokens(maxPromptTokens: Long?) = apply { + body.maxPromptTokens(maxPromptTokens) + } + + /** + * The maximum number of prompt tokens that may be used over the course of the run. The run + * will make a best effort to use only the number of prompt tokens specified, across + * multiple turns of the run. If the run exceeds the number of prompt tokens specified, the + * run will end with status `incomplete`. See `incomplete_details` for more info. + */ + fun maxPromptTokens(maxPromptTokens: Long) = maxPromptTokens(maxPromptTokens as Long?) + + /** + * The maximum number of prompt tokens that may be used over the course of the run. The run + * will make a best effort to use only the number of prompt tokens specified, across + * multiple turns of the run. If the run exceeds the number of prompt tokens specified, the + * run will end with status `incomplete`. See `incomplete_details` for more info. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun maxPromptTokens(maxPromptTokens: Optional) = + maxPromptTokens(maxPromptTokens.orElse(null) as Long?) + + /** + * The maximum number of prompt tokens that may be used over the course of the run. The run + * will make a best effort to use only the number of prompt tokens specified, across + * multiple turns of the run. If the run exceeds the number of prompt tokens specified, the + * run will end with status `incomplete`. See `incomplete_details` for more info. + */ + fun maxPromptTokens(maxPromptTokens: JsonField) = apply { + body.maxPromptTokens(maxPromptTokens) + } /** * Set of 16 key-value pairs that can be attached to an object. This can be useful for @@ -781,7 +1490,21 @@ constructor( * 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. */ - fun model(model: ChatModel) = apply { body.model(model) } + fun model(model: ChatModel?) = apply { body.model(model) } + + /** + * The ID of the [Model](https://platform.openai.com/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. + */ + fun model(model: Optional) = model(model.orElse(null)) + + /** + * The ID of the [Model](https://platform.openai.com/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. + */ + fun model(model: JsonField) = apply { body.model(model) } /** * The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to be used @@ -795,9 +1518,65 @@ constructor( * [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) * during tool use. */ - fun parallelToolCalls(parallelToolCalls: Boolean) = apply { - body.parallelToolCalls(parallelToolCalls) - } + fun parallelToolCalls(parallelToolCalls: Boolean) = apply { + body.parallelToolCalls(parallelToolCalls) + } + + /** + * Whether to enable + * [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) + * during tool use. + */ + fun parallelToolCalls(parallelToolCalls: JsonField) = apply { + body.parallelToolCalls(parallelToolCalls) + } + + /** + * Specifies the format that the model must output. Compatible with + * [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 + * Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 + * Turbo models since `gpt-3.5-turbo-1106`. + * + * Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs + * which ensures the model will match your supplied JSON schema. Learn more in the + * [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). + * + * Setting to `{ "type": "json_object" }` enables JSON mode, which ensures 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. + */ + fun responseFormat(responseFormat: AssistantResponseFormatOption?) = apply { + body.responseFormat(responseFormat) + } + + /** + * Specifies the format that the model must output. Compatible with + * [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), [GPT-4 + * Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), and all GPT-3.5 + * Turbo models since `gpt-3.5-turbo-1106`. + * + * Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured Outputs + * which ensures the model will match your supplied JSON schema. Learn more in the + * [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). + * + * Setting to `{ "type": "json_object" }` enables JSON mode, which ensures 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. + */ + fun responseFormat(responseFormat: Optional) = + responseFormat(responseFormat.orElse(null)) /** * Specifies the format that the model must output. Compatible with @@ -819,7 +1598,7 @@ constructor( * partially cut off if `finish_reason="length"`, which indicates the generation exceeded * `max_tokens` or the conversation exceeded the max context length. */ - fun responseFormat(responseFormat: AssistantResponseFormatOption) = apply { + fun responseFormat(responseFormat: JsonField) = apply { body.responseFormat(responseFormat) } @@ -845,7 +1624,53 @@ constructor( * output more random, while lower values like 0.2 will make it more focused and * deterministic. */ - fun temperature(temperature: Double) = apply { body.temperature(temperature) } + fun temperature(temperature: Double?) = apply { body.temperature(temperature) } + + /** + * 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. + */ + fun temperature(temperature: Double) = temperature(temperature as Double?) + + /** + * 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. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun temperature(temperature: Optional) = + temperature(temperature.orElse(null) as Double?) + + /** + * 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. + */ + fun temperature(temperature: JsonField) = apply { body.temperature(temperature) } + + /** + * Controls which (if any) tool is called by the model. `none` means the model will not call + * any tools and instead generates a message. `auto` is the default value and means the + * model can pick between generating a message or calling one or more tools. `required` + * means the model must call one or more tools before responding to the user. Specifying a + * particular tool like `{"type": "file_search"}` or `{"type": "function", "function": + * {"name": "my_function"}}` forces the model to call that tool. + */ + fun toolChoice(toolChoice: AssistantToolChoiceOption?) = apply { + body.toolChoice(toolChoice) + } + + /** + * Controls which (if any) tool is called by the model. `none` means the model will not call + * any tools and instead generates a message. `auto` is the default value and means the + * model can pick between generating a message or calling one or more tools. `required` + * means the model must call one or more tools before responding to the user. Specifying a + * particular tool like `{"type": "file_search"}` or `{"type": "function", "function": + * {"name": "my_function"}}` forces the model to call that tool. + */ + fun toolChoice(toolChoice: Optional) = + toolChoice(toolChoice.orElse(null)) /** * Controls which (if any) tool is called by the model. `none` means the model will not call @@ -855,7 +1680,7 @@ constructor( * particular tool like `{"type": "file_search"}` or `{"type": "function", "function": * {"name": "my_function"}}` forces the model to call that tool. */ - fun toolChoice(toolChoice: AssistantToolChoiceOption) = apply { + fun toolChoice(toolChoice: JsonField) = apply { body.toolChoice(toolChoice) } @@ -879,7 +1704,19 @@ constructor( * Override the tools the assistant can use for this run. This is useful for modifying the * behavior on a per-run basis. */ - fun tools(tools: List) = apply { body.tools(tools) } + fun tools(tools: List?) = apply { body.tools(tools) } + + /** + * Override the tools the assistant can use for this run. This is useful for modifying the + * behavior on a per-run basis. + */ + fun tools(tools: Optional>) = tools(tools.orElse(null)) + + /** + * Override the tools the assistant can use for this run. This is useful for modifying the + * behavior on a per-run basis. + */ + fun tools(tools: JsonField>) = apply { body.tools(tools) } /** * Override the tools the assistant can use for this run. This is useful for modifying the @@ -894,16 +1731,78 @@ constructor( * * We generally recommend altering this or temperature but not both. */ - fun topP(topP: Double) = apply { body.topP(topP) } + fun topP(topP: Double?) = apply { body.topP(topP) } + + /** + * 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. + */ + fun topP(topP: Double) = topP(topP as Double?) + + /** + * 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. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun topP(topP: Optional) = topP(topP.orElse(null) as Double?) + + /** + * 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. + */ + fun topP(topP: JsonField) = apply { body.topP(topP) } + + /** + * Controls for how a thread will be truncated prior to the run. Use this to control the + * intial context window of the run. + */ + fun truncationStrategy(truncationStrategy: TruncationStrategy?) = apply { + body.truncationStrategy(truncationStrategy) + } + + /** + * Controls for how a thread will be truncated prior to the run. Use this to control the + * intial context window of the run. + */ + fun truncationStrategy(truncationStrategy: Optional) = + truncationStrategy(truncationStrategy.orElse(null)) /** * Controls for how a thread will be truncated prior to the run. Use this to control the * intial context window of the run. */ - fun truncationStrategy(truncationStrategy: TruncationStrategy) = apply { + fun truncationStrategy(truncationStrategy: JsonField) = apply { body.truncationStrategy(truncationStrategy) } + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } + fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() putAllAdditionalHeaders(additionalHeaders) @@ -1002,25 +1901,6 @@ constructor( additionalQueryParams.removeAll(keys) } - fun additionalBodyProperties(additionalBodyProperties: Map) = apply { - body.additionalProperties(additionalBodyProperties) - } - - fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { - body.putAdditionalProperty(key, value) - } - - fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = - apply { - body.putAllAdditionalProperties(additionalBodyProperties) - } - - fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } - - fun removeAllAdditionalBodyProperties(keys: Set) = apply { - body.removeAllAdditionalProperties(keys) - } - fun build(): BetaThreadRunCreateParams = BetaThreadRunCreateParams( checkNotNull(threadId) { "`threadId` is required but was not set" }, @@ -1035,16 +1915,22 @@ constructor( class AdditionalMessage @JsonCreator private constructor( - @JsonProperty("content") private val content: Content, - @JsonProperty("role") private val role: Role, - @JsonProperty("attachments") private val attachments: List?, - @JsonProperty("metadata") private val metadata: JsonValue?, + @JsonProperty("content") + @ExcludeMissing + private val content: JsonField = JsonMissing.of(), + @JsonProperty("role") @ExcludeMissing private val role: JsonField = JsonMissing.of(), + @JsonProperty("attachments") + @ExcludeMissing + private val attachments: JsonField> = JsonMissing.of(), + @JsonProperty("metadata") + @ExcludeMissing + private val metadata: JsonValue = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { /** The text contents of the message. */ - @JsonProperty("content") fun content(): Content = content + fun content(): Content = content.getRequired("content") /** * The role of the entity that is creating the message. Allowed values include: @@ -1053,24 +1939,51 @@ constructor( * - `assistant`: Indicates the message is generated by the assistant. Use this value to * insert messages from the assistant into the conversation. */ - @JsonProperty("role") fun role(): Role = role + fun role(): Role = role.getRequired("role") /** A list of files attached to the message, and the tools they should be added to. */ - @JsonProperty("attachments") - fun attachments(): Optional> = Optional.ofNullable(attachments) + fun attachments(): Optional> = + Optional.ofNullable(attachments.getNullable("attachments")) /** * 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 maximum of 512 characters long. */ - @JsonProperty("metadata") - fun metadata(): Optional = Optional.ofNullable(metadata) + @JsonProperty("metadata") @ExcludeMissing fun _metadata(): JsonValue = metadata + + /** The text contents of the message. */ + @JsonProperty("content") @ExcludeMissing fun _content(): JsonField = content + + /** + * The role of the entity that is creating the message. Allowed values include: + * - `user`: Indicates the message is sent by an actual user and should be used in most + * cases to represent user-generated messages. + * - `assistant`: Indicates the message is generated by the assistant. Use this value to + * insert messages from the assistant into the conversation. + */ + @JsonProperty("role") @ExcludeMissing fun _role(): JsonField = role + + /** A list of files attached to the message, and the tools they should be added to. */ + @JsonProperty("attachments") + @ExcludeMissing + fun _attachments(): JsonField> = attachments @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): AdditionalMessage = apply { + if (!validated) { + content() + role() + attachments().map { it.forEach { it.validate() } } + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -1080,28 +1993,29 @@ constructor( class Builder { - private var content: Content? = null - private var role: Role? = null - private var attachments: MutableList? = null - private var metadata: JsonValue? = null + private var content: JsonField? = null + private var role: JsonField? = null + private var attachments: JsonField>? = null + private var metadata: JsonValue = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(additionalMessage: AdditionalMessage) = apply { content = additionalMessage.content role = additionalMessage.role - attachments = additionalMessage.attachments?.toMutableList() + attachments = additionalMessage.attachments.map { it.toMutableList() } metadata = additionalMessage.metadata additionalProperties = additionalMessage.additionalProperties.toMutableMap() } /** The text contents of the message. */ - fun content(content: Content) = apply { this.content = content } + fun content(content: Content) = content(JsonField.of(content)) /** The text contents of the message. */ - fun content(textContent: String) = apply { - this.content = Content.ofTextContent(textContent) - } + fun content(content: JsonField) = apply { this.content = content } + + /** The text contents of the message. */ + fun content(textContent: String) = content(Content.ofTextContent(textContent)) /** * An array of content parts with a defined type, each can be of type `text` or images @@ -1109,9 +2023,16 @@ constructor( * [Vision-compatible models](https://platform.openai.com/docs/models). */ fun contentOfArrayOfContentParts(arrayOfContentParts: List) = - apply { - this.content = Content.ofArrayOfContentParts(arrayOfContentParts) - } + content(Content.ofArrayOfContentParts(arrayOfContentParts)) + + /** + * The role of the entity that is creating the message. Allowed values include: + * - `user`: Indicates the message is sent by an actual user and should be used in most + * cases to represent user-generated messages. + * - `assistant`: Indicates the message is generated by the assistant. Use this value to + * insert messages from the assistant into the conversation. + */ + fun role(role: Role) = role(JsonField.of(role)) /** * The role of the entity that is creating the message. Allowed values include: @@ -1120,16 +2041,33 @@ constructor( * - `assistant`: Indicates the message is generated by the assistant. Use this value to * insert messages from the assistant into the conversation. */ - fun role(role: Role) = apply { this.role = role } + fun role(role: JsonField) = apply { this.role = role } + + /** A list of files attached to the message, and the tools they should be added to. */ + fun attachments(attachments: List?) = + attachments(JsonField.ofNullable(attachments)) /** A list of files attached to the message, and the tools they should be added to. */ - fun attachments(attachments: List) = apply { - this.attachments = attachments.toMutableList() + fun attachments(attachments: Optional>) = + attachments(attachments.orElse(null)) + + /** A list of files attached to the message, and the tools they should be added to. */ + fun attachments(attachments: JsonField>) = apply { + this.attachments = attachments.map { it.toMutableList() } } /** A list of files attached to the message, and the tools they should be added to. */ fun addAttachment(attachment: Attachment) = apply { - attachments = (attachments ?: mutableListOf()).apply { add(attachment) } + attachments = + (attachments ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(attachment) + } } /** @@ -1162,7 +2100,7 @@ constructor( AdditionalMessage( checkNotNull(content) { "`content` is required but was not set" }, checkNotNull(role) { "`role` is required but was not set" }, - attachments?.toImmutable(), + (attachments ?: JsonMissing.of()).map { it.toImmutable() }, metadata, additionalProperties.toImmutable(), ) @@ -1178,6 +2116,8 @@ constructor( private val _json: JsonValue? = null, ) { + private var validated: Boolean = false + /** The text contents of the message. */ fun textContent(): Optional = Optional.ofNullable(textContent) /** @@ -1213,6 +2153,15 @@ constructor( } } + fun validate(): Content = apply { + if (!validated) { + if (textContent == null && arrayOfContentParts == null) { + throw OpenAIInvalidDataException("Unknown Content: $_json") + } + validated = true + } + } + override fun equals(other: Any?): Boolean { if (this === other) { return true @@ -1354,22 +2303,42 @@ constructor( class Attachment @JsonCreator private constructor( - @JsonProperty("file_id") private val fileId: String?, - @JsonProperty("tools") private val tools: List?, + @JsonProperty("file_id") + @ExcludeMissing + private val fileId: JsonField = JsonMissing.of(), + @JsonProperty("tools") + @ExcludeMissing + private val tools: JsonField> = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { /** The ID of the file to attach to the message. */ - @JsonProperty("file_id") fun fileId(): Optional = Optional.ofNullable(fileId) + fun fileId(): Optional = Optional.ofNullable(fileId.getNullable("file_id")) + + /** The tools to add this file to. */ + fun tools(): Optional> = Optional.ofNullable(tools.getNullable("tools")) + + /** The ID of the file to attach to the message. */ + @JsonProperty("file_id") @ExcludeMissing fun _fileId(): JsonField = fileId /** The tools to add this file to. */ - @JsonProperty("tools") fun tools(): Optional> = Optional.ofNullable(tools) + @JsonProperty("tools") @ExcludeMissing fun _tools(): JsonField> = tools @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): Attachment = apply { + if (!validated) { + fileId() + tools() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -1379,26 +2348,43 @@ constructor( class Builder { - private var fileId: String? = null - private var tools: MutableList? = null + private var fileId: JsonField = JsonMissing.of() + private var tools: JsonField>? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(attachment: Attachment) = apply { fileId = attachment.fileId - tools = attachment.tools?.toMutableList() + tools = attachment.tools.map { it.toMutableList() } additionalProperties = attachment.additionalProperties.toMutableMap() } /** The ID of the file to attach to the message. */ - fun fileId(fileId: String) = apply { this.fileId = fileId } + fun fileId(fileId: String) = fileId(JsonField.of(fileId)) + + /** The ID of the file to attach to the message. */ + fun fileId(fileId: JsonField) = apply { this.fileId = fileId } + + /** The tools to add this file to. */ + fun tools(tools: List) = tools(JsonField.of(tools)) /** The tools to add this file to. */ - fun tools(tools: List) = apply { this.tools = tools.toMutableList() } + fun tools(tools: JsonField>) = apply { + this.tools = tools.map { it.toMutableList() } + } /** The tools to add this file to. */ fun addTool(tool: Tool) = apply { - tools = (tools ?: mutableListOf()).apply { add(tool) } + tools = + (tools ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(tool) + } } fun additionalProperties(additionalProperties: Map) = apply { @@ -1426,7 +2412,7 @@ constructor( fun build(): Attachment = Attachment( fileId, - tools?.toImmutable(), + (tools ?: JsonMissing.of()).map { it.toImmutable() }, additionalProperties.toImmutable(), ) } @@ -1440,6 +2426,8 @@ constructor( private val _json: JsonValue? = null, ) { + private var validated: Boolean = false + fun codeInterpreterTool(): Optional = Optional.ofNullable(codeInterpreterTool) @@ -1465,6 +2453,17 @@ constructor( } } + fun validate(): Tool = apply { + if (!validated) { + if (codeInterpreterTool == null && fileSearch == null) { + throw OpenAIInvalidDataException("Unknown Tool: $_json") + } + codeInterpreterTool?.validate() + fileSearch?.validate() + validated = true + } + } + override fun equals(other: Any?): Boolean { if (this === other) { return true @@ -1513,14 +2512,18 @@ constructor( when (type) { "code_interpreter" -> { - tryDeserialize(node, jacksonTypeRef())?.let { - return Tool(codeInterpreterTool = it, _json = json) - } + tryDeserialize(node, jacksonTypeRef()) { + it.validate() + } + ?.let { + return Tool(codeInterpreterTool = it, _json = json) + } } "file_search" -> { - tryDeserialize(node, jacksonTypeRef())?.let { - return Tool(fileSearch = it, _json = json) - } + tryDeserialize(node, jacksonTypeRef()) { it.validate() } + ?.let { + return Tool(fileSearch = it, _json = json) + } } } @@ -1549,18 +2552,32 @@ constructor( class FileSearch @JsonCreator private constructor( - @JsonProperty("type") private val type: Type, + @JsonProperty("type") + @ExcludeMissing + private val type: JsonField = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { /** The type of tool being defined: `file_search` */ - @JsonProperty("type") fun type(): Type = type + fun type(): Type = type.getRequired("type") + + /** The type of tool being defined: `file_search` */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): FileSearch = apply { + if (!validated) { + type() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -1570,7 +2587,7 @@ constructor( class Builder { - private var type: Type? = null + private var type: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @@ -1581,7 +2598,10 @@ constructor( } /** The type of tool being defined: `file_search` */ - fun type(type: Type) = apply { this.type = type } + fun type(type: Type) = type(JsonField.of(type)) + + /** The type of tool being defined: `file_search` */ + fun type(type: JsonField) = apply { this.type = type } fun additionalProperties(additionalProperties: Map) = apply { @@ -1727,8 +2747,10 @@ constructor( class TruncationStrategy @JsonCreator private constructor( - @JsonProperty("type") private val type: Type, - @JsonProperty("last_messages") private val lastMessages: Long?, + @JsonProperty("type") @ExcludeMissing private val type: JsonField = JsonMissing.of(), + @JsonProperty("last_messages") + @ExcludeMissing + private val lastMessages: JsonField = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { @@ -1739,19 +2761,45 @@ constructor( * thread. When set to `auto`, messages in the middle of the thread will be dropped to fit * the context length of the model, `max_prompt_tokens`. */ - @JsonProperty("type") fun type(): Type = type + fun type(): Type = type.getRequired("type") + + /** + * The number of most recent messages from the thread when constructing the context for the + * run. + */ + fun lastMessages(): Optional = + Optional.ofNullable(lastMessages.getNullable("last_messages")) + + /** + * The truncation strategy to use for the thread. The default is `auto`. If set to + * `last_messages`, the thread will be truncated to the n most recent messages in the + * thread. When set to `auto`, messages in the middle of the thread will be dropped to fit + * the context length of the model, `max_prompt_tokens`. + */ + @JsonProperty("type") @ExcludeMissing fun _type(): JsonField = type /** * The number of most recent messages from the thread when constructing the context for the * run. */ @JsonProperty("last_messages") - fun lastMessages(): Optional = Optional.ofNullable(lastMessages) + @ExcludeMissing + fun _lastMessages(): JsonField = lastMessages @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): TruncationStrategy = apply { + if (!validated) { + type() + lastMessages() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -1761,8 +2809,8 @@ constructor( class Builder { - private var type: Type? = null - private var lastMessages: Long? = null + private var type: JsonField? = null + private var lastMessages: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -1778,13 +2826,43 @@ constructor( * thread. When set to `auto`, messages in the middle of the thread will be dropped to * fit the context length of the model, `max_prompt_tokens`. */ - fun type(type: Type) = apply { this.type = type } + fun type(type: Type) = type(JsonField.of(type)) + + /** + * The truncation strategy to use for the thread. The default is `auto`. If set to + * `last_messages`, the thread will be truncated to the n most recent messages in the + * thread. When set to `auto`, messages in the middle of the thread will be dropped to + * fit the context length of the model, `max_prompt_tokens`. + */ + fun type(type: JsonField) = apply { this.type = type } /** * The number of most recent messages from the thread when constructing the context for * the run. */ - fun lastMessages(lastMessages: Long) = apply { this.lastMessages = lastMessages } + fun lastMessages(lastMessages: Long?) = lastMessages(JsonField.ofNullable(lastMessages)) + + /** + * The number of most recent messages from the thread when constructing the context for + * the run. + */ + fun lastMessages(lastMessages: Long) = lastMessages(lastMessages as Long?) + + /** + * The number of most recent messages from the thread when constructing the context for + * the run. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun lastMessages(lastMessages: Optional) = + lastMessages(lastMessages.orElse(null) as Long?) + + /** + * The number of most recent messages from the thread when constructing the context for + * the run. + */ + fun lastMessages(lastMessages: JsonField) = apply { + this.lastMessages = lastMessages + } fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunListParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunListParams.kt index c63196696..f54f659de 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunListParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunListParams.kt @@ -12,6 +12,7 @@ import com.openai.errors.OpenAIInvalidDataException import java.util.Objects import java.util.Optional +/** Returns a list of runs belonging to a thread. */ class BetaThreadRunListParams constructor( private val threadId: String, @@ -112,7 +113,15 @@ constructor( * obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page * of the list. */ - fun after(after: String) = apply { this.after = after } + fun after(after: String?) = apply { this.after = after } + + /** + * 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. + */ + fun after(after: Optional) = after(after.orElse(null)) /** * A cursor for use in pagination. `before` is an object ID that defines your place in the @@ -120,19 +129,46 @@ constructor( * obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous * page of the list. */ - fun before(before: String) = apply { this.before = before } + fun before(before: String?) = apply { this.before = before } + + /** + * 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, starting with + * obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous + * page of the list. + */ + fun before(before: Optional) = before(before.orElse(null)) /** * A limit on the number of objects to be returned. Limit can range between 1 and 100, and * the default is 20. */ - fun limit(limit: Long) = apply { this.limit = limit } + fun limit(limit: Long?) = apply { this.limit = limit } + + /** + * A limit on the number of objects to be returned. Limit can range between 1 and 100, and + * the default is 20. + */ + fun limit(limit: Long) = limit(limit as Long?) + + /** + * A limit on the number of objects to be returned. Limit can range between 1 and 100, and + * the default is 20. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun limit(limit: Optional) = limit(limit.orElse(null) as Long?) + + /** + * Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and + * `desc` for descending order. + */ + fun order(order: Order?) = apply { this.order = order } /** * Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and * `desc` for descending order. */ - fun order(order: Order) = apply { this.order = order } + fun order(order: Optional) = order(order.orElse(null)) fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunRetrieveParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunRetrieveParams.kt index c42f9547f..1c2f84f4b 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunRetrieveParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunRetrieveParams.kt @@ -7,6 +7,7 @@ import com.openai.core.http.Headers import com.openai.core.http.QueryParams import java.util.Objects +/** Retrieves a run. */ class BetaThreadRunRetrieveParams constructor( private val threadId: String, diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunStepListParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunStepListParams.kt index 104b3682e..99dddc898 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunStepListParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunStepListParams.kt @@ -13,6 +13,7 @@ import com.openai.errors.OpenAIInvalidDataException import java.util.Objects import java.util.Optional +/** Returns a list of run steps belonging to a run. */ class BetaThreadRunStepListParams constructor( private val threadId: String, @@ -136,7 +137,23 @@ constructor( * obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page * of the list. */ - fun after(after: String) = apply { this.after = after } + fun after(after: String?) = apply { this.after = after } + + /** + * 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. + */ + fun after(after: Optional) = after(after.orElse(null)) + + /** + * 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, starting with + * obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous + * page of the list. + */ + fun before(before: String?) = apply { this.before = before } /** * A cursor for use in pagination. `before` is an object ID that defines your place in the @@ -144,7 +161,7 @@ constructor( * obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous * page of the list. */ - fun before(before: String) = apply { this.before = before } + fun before(before: Optional) = before(before.orElse(null)) /** * A list of additional fields to include in the response. Currently the only supported @@ -155,10 +172,21 @@ constructor( * [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) * for more information. */ - fun include(include: List) = apply { - this.include = include.toMutableList() + fun include(include: List?) = apply { + this.include = include?.toMutableList() } + /** + * A list of additional fields to include in the response. Currently the only supported + * value is `step_details.tool_calls[*].file_search.results[*].content` to fetch the file + * search result content. + * + * See the + * [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) + * for more information. + */ + fun include(include: Optional>) = include(include.orElse(null)) + /** * A list of additional fields to include in the response. Currently the only supported * value is `step_details.tool_calls[*].file_search.results[*].content` to fetch the file @@ -176,13 +204,32 @@ constructor( * A limit on the number of objects to be returned. Limit can range between 1 and 100, and * the default is 20. */ - fun limit(limit: Long) = apply { this.limit = limit } + fun limit(limit: Long?) = apply { this.limit = limit } + + /** + * A limit on the number of objects to be returned. Limit can range between 1 and 100, and + * the default is 20. + */ + fun limit(limit: Long) = limit(limit as Long?) + + /** + * A limit on the number of objects to be returned. Limit can range between 1 and 100, and + * the default is 20. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun limit(limit: Optional) = limit(limit.orElse(null) as Long?) + + /** + * Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and + * `desc` for descending order. + */ + fun order(order: Order?) = apply { this.order = order } /** * Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and * `desc` for descending order. */ - fun order(order: Order) = apply { this.order = order } + fun order(order: Optional) = order(order.orElse(null)) fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunStepRetrieveParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunStepRetrieveParams.kt index c9854adac..044524444 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunStepRetrieveParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunStepRetrieveParams.kt @@ -9,6 +9,7 @@ import com.openai.core.toImmutable import java.util.Objects import java.util.Optional +/** Retrieves a run step. */ class BetaThreadRunStepRetrieveParams constructor( private val threadId: String, @@ -103,10 +104,21 @@ constructor( * [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) * for more information. */ - fun include(include: List) = apply { - this.include = include.toMutableList() + fun include(include: List?) = apply { + this.include = include?.toMutableList() } + /** + * A list of additional fields to include in the response. Currently the only supported + * value is `step_details.tool_calls[*].file_search.results[*].content` to fetch the file + * search result content. + * + * See the + * [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) + * for more information. + */ + fun include(include: Optional>) = include(include.orElse(null)) + /** * A list of additional fields to include in the response. Currently the only supported * value is `step_details.tool_calls[*].file_search.results[*].content` to fetch the file diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunSubmitToolOutputsParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunSubmitToolOutputsParams.kt index 769bd42cd..283e22efb 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunSubmitToolOutputsParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunSubmitToolOutputsParams.kt @@ -7,6 +7,8 @@ import com.fasterxml.jackson.annotation.JsonAnySetter import com.fasterxml.jackson.annotation.JsonCreator import com.fasterxml.jackson.annotation.JsonProperty import com.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing import com.openai.core.JsonValue import com.openai.core.NoAutoDetect import com.openai.core.http.Headers @@ -16,6 +18,11 @@ import com.openai.core.toImmutable import java.util.Objects import java.util.Optional +/** + * 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. + */ class BetaThreadRunSubmitToolOutputsParams constructor( private val threadId: String, @@ -32,12 +39,15 @@ constructor( /** A list of tools for which the outputs are being submitted. */ fun toolOutputs(): List = body.toolOutputs() + /** A list of tools for which the outputs are being submitted. */ + fun _toolOutputs(): JsonField> = body._toolOutputs() + + fun _additionalBodyProperties(): Map = body._additionalProperties() + fun _additionalHeaders(): Headers = additionalHeaders fun _additionalQueryParams(): QueryParams = additionalQueryParams - fun _additionalBodyProperties(): Map = body._additionalProperties() - @JvmSynthetic internal fun getBody(): BetaThreadRunSubmitToolOutputsBody = body @JvmSynthetic internal fun getHeaders(): Headers = additionalHeaders @@ -56,18 +66,34 @@ constructor( class BetaThreadRunSubmitToolOutputsBody @JsonCreator internal constructor( - @JsonProperty("tool_outputs") private val toolOutputs: List, + @JsonProperty("tool_outputs") + @ExcludeMissing + private val toolOutputs: JsonField> = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { /** A list of tools for which the outputs are being submitted. */ - @JsonProperty("tool_outputs") fun toolOutputs(): List = toolOutputs + fun toolOutputs(): List = toolOutputs.getRequired("tool_outputs") + + /** A list of tools for which the outputs are being submitted. */ + @JsonProperty("tool_outputs") + @ExcludeMissing + fun _toolOutputs(): JsonField> = toolOutputs @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): BetaThreadRunSubmitToolOutputsBody = apply { + if (!validated) { + toolOutputs().forEach { it.validate() } + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -77,26 +103,39 @@ constructor( class Builder { - private var toolOutputs: MutableList? = null + private var toolOutputs: JsonField>? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from( betaThreadRunSubmitToolOutputsBody: BetaThreadRunSubmitToolOutputsBody ) = apply { - toolOutputs = betaThreadRunSubmitToolOutputsBody.toolOutputs.toMutableList() + toolOutputs = + betaThreadRunSubmitToolOutputsBody.toolOutputs.map { it.toMutableList() } additionalProperties = betaThreadRunSubmitToolOutputsBody.additionalProperties.toMutableMap() } /** A list of tools for which the outputs are being submitted. */ - fun toolOutputs(toolOutputs: List) = apply { - this.toolOutputs = toolOutputs.toMutableList() + fun toolOutputs(toolOutputs: List) = toolOutputs(JsonField.of(toolOutputs)) + + /** A list of tools for which the outputs are being submitted. */ + fun toolOutputs(toolOutputs: JsonField>) = apply { + this.toolOutputs = toolOutputs.map { it.toMutableList() } } /** A list of tools for which the outputs are being submitted. */ fun addToolOutput(toolOutput: ToolOutput) = apply { - toolOutputs = (toolOutputs ?: mutableListOf()).apply { add(toolOutput) } + toolOutputs = + (toolOutputs ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(toolOutput) + } } fun additionalProperties(additionalProperties: Map) = apply { @@ -121,7 +160,7 @@ constructor( fun build(): BetaThreadRunSubmitToolOutputsBody = BetaThreadRunSubmitToolOutputsBody( checkNotNull(toolOutputs) { "`toolOutputs` is required but was not set" } - .toImmutable(), + .map { it.toImmutable() }, additionalProperties.toImmutable() ) } @@ -180,9 +219,33 @@ constructor( /** A list of tools for which the outputs are being submitted. */ fun toolOutputs(toolOutputs: List) = apply { body.toolOutputs(toolOutputs) } + /** A list of tools for which the outputs are being submitted. */ + fun toolOutputs(toolOutputs: JsonField>) = apply { + body.toolOutputs(toolOutputs) + } + /** A list of tools for which the outputs are being submitted. */ fun addToolOutput(toolOutput: ToolOutput) = apply { body.addToolOutput(toolOutput) } + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } + fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() putAllAdditionalHeaders(additionalHeaders) @@ -281,25 +344,6 @@ constructor( additionalQueryParams.removeAll(keys) } - fun additionalBodyProperties(additionalBodyProperties: Map) = apply { - body.additionalProperties(additionalBodyProperties) - } - - fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { - body.putAdditionalProperty(key, value) - } - - fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = - apply { - body.putAllAdditionalProperties(additionalBodyProperties) - } - - fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } - - fun removeAllAdditionalBodyProperties(keys: Set) = apply { - body.removeAllAdditionalProperties(keys) - } - fun build(): BetaThreadRunSubmitToolOutputsParams = BetaThreadRunSubmitToolOutputsParams( checkNotNull(threadId) { "`threadId` is required but was not set" }, @@ -314,26 +358,51 @@ constructor( class ToolOutput @JsonCreator private constructor( - @JsonProperty("output") private val output: String?, - @JsonProperty("tool_call_id") private val toolCallId: String?, + @JsonProperty("output") + @ExcludeMissing + private val output: JsonField = JsonMissing.of(), + @JsonProperty("tool_call_id") + @ExcludeMissing + private val toolCallId: JsonField = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { /** The output of the tool call to be submitted to continue the run. */ - @JsonProperty("output") fun output(): Optional = Optional.ofNullable(output) + fun output(): Optional = Optional.ofNullable(output.getNullable("output")) + + /** + * The ID of the tool call in the `required_action` object within the run object the output + * is being submitted for. + */ + fun toolCallId(): Optional = + Optional.ofNullable(toolCallId.getNullable("tool_call_id")) + + /** The output of the tool call to be submitted to continue the run. */ + @JsonProperty("output") @ExcludeMissing fun _output(): JsonField = output /** * The ID of the tool call in the `required_action` object within the run object the output * is being submitted for. */ @JsonProperty("tool_call_id") - fun toolCallId(): Optional = Optional.ofNullable(toolCallId) + @ExcludeMissing + fun _toolCallId(): JsonField = toolCallId @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): ToolOutput = apply { + if (!validated) { + output() + toolCallId() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -343,8 +412,8 @@ constructor( class Builder { - private var output: String? = null - private var toolCallId: String? = null + private var output: JsonField = JsonMissing.of() + private var toolCallId: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -355,13 +424,22 @@ constructor( } /** The output of the tool call to be submitted to continue the run. */ - fun output(output: String) = apply { this.output = output } + fun output(output: String) = output(JsonField.of(output)) + + /** The output of the tool call to be submitted to continue the run. */ + fun output(output: JsonField) = apply { this.output = output } + + /** + * The ID of the tool call in the `required_action` object within the run object the + * output is being submitted for. + */ + fun toolCallId(toolCallId: String) = toolCallId(JsonField.of(toolCallId)) /** * The ID of the tool call in the `required_action` object within the run object the * output is being submitted for. */ - fun toolCallId(toolCallId: String) = apply { this.toolCallId = toolCallId } + fun toolCallId(toolCallId: JsonField) = apply { this.toolCallId = toolCallId } fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunUpdateParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunUpdateParams.kt index 24f5d23b2..00e97b589 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunUpdateParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadRunUpdateParams.kt @@ -7,6 +7,7 @@ import com.fasterxml.jackson.annotation.JsonAnySetter import com.fasterxml.jackson.annotation.JsonCreator import com.fasterxml.jackson.annotation.JsonProperty import com.openai.core.ExcludeMissing +import com.openai.core.JsonMissing import com.openai.core.JsonValue import com.openai.core.NoAutoDetect import com.openai.core.http.Headers @@ -14,8 +15,8 @@ import com.openai.core.http.QueryParams import com.openai.core.immutableEmptyMap import com.openai.core.toImmutable import java.util.Objects -import java.util.Optional +/** Modifies a run. */ class BetaThreadRunUpdateParams constructor( private val threadId: String, @@ -34,14 +35,14 @@ constructor( * additional information about the object in a structured format. Keys can be a maximum of 64 * characters long and values can be a maximum of 512 characters long. */ - fun metadata(): Optional = body.metadata() + fun _metadata(): JsonValue = body._metadata() + + fun _additionalBodyProperties(): Map = body._additionalProperties() fun _additionalHeaders(): Headers = additionalHeaders fun _additionalQueryParams(): QueryParams = additionalQueryParams - fun _additionalBodyProperties(): Map = body._additionalProperties() - @JvmSynthetic internal fun getBody(): BetaThreadRunUpdateBody = body @JvmSynthetic internal fun getHeaders(): Headers = additionalHeaders @@ -60,7 +61,9 @@ constructor( class BetaThreadRunUpdateBody @JsonCreator internal constructor( - @JsonProperty("metadata") private val metadata: JsonValue?, + @JsonProperty("metadata") + @ExcludeMissing + private val metadata: JsonValue = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { @@ -70,13 +73,20 @@ constructor( * storing additional information about the object in a structured format. Keys can be a * maximum of 64 characters long and values can be a maximum of 512 characters long. */ - @JsonProperty("metadata") - fun metadata(): Optional = Optional.ofNullable(metadata) + @JsonProperty("metadata") @ExcludeMissing fun _metadata(): JsonValue = metadata @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): BetaThreadRunUpdateBody = apply { + if (!validated) { + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -86,7 +96,7 @@ constructor( class Builder { - private var metadata: JsonValue? = null + private var metadata: JsonValue = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -179,6 +189,25 @@ constructor( */ fun metadata(metadata: JsonValue) = apply { body.metadata(metadata) } + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } + fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() putAllAdditionalHeaders(additionalHeaders) @@ -277,25 +306,6 @@ constructor( additionalQueryParams.removeAll(keys) } - fun additionalBodyProperties(additionalBodyProperties: Map) = apply { - body.additionalProperties(additionalBodyProperties) - } - - fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { - body.putAdditionalProperty(key, value) - } - - fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = - apply { - body.putAllAdditionalProperties(additionalBodyProperties) - } - - fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } - - fun removeAllAdditionalBodyProperties(keys: Set) = apply { - body.removeAllAdditionalProperties(keys) - } - fun build(): BetaThreadRunUpdateParams = BetaThreadRunUpdateParams( checkNotNull(threadId) { "`threadId` is required but was not set" }, diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadUpdateParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadUpdateParams.kt index aa030853c..9360c31a3 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadUpdateParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaThreadUpdateParams.kt @@ -7,6 +7,8 @@ import com.fasterxml.jackson.annotation.JsonAnySetter import com.fasterxml.jackson.annotation.JsonCreator import com.fasterxml.jackson.annotation.JsonProperty import com.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing import com.openai.core.JsonValue import com.openai.core.NoAutoDetect import com.openai.core.http.Headers @@ -16,6 +18,7 @@ import com.openai.core.toImmutable import java.util.Objects import java.util.Optional +/** Modifies a thread. */ class BetaThreadUpdateParams constructor( private val threadId: String, @@ -31,7 +34,7 @@ constructor( * additional information about the object in a structured format. Keys can be a maximum of 64 * characters long and values can be a maximum of 512 characters long. */ - fun metadata(): Optional = body.metadata() + fun _metadata(): JsonValue = body._metadata() /** * A set of resources that are made available to the assistant's tools in this thread. The @@ -40,12 +43,19 @@ constructor( */ fun toolResources(): Optional = body.toolResources() + /** + * A set of resources that are made available to the assistant's tools in this thread. The + * resources are specific to the type of tool. For example, the `code_interpreter` tool requires + * a list of file IDs, while the `file_search` tool requires a list of vector store IDs. + */ + fun _toolResources(): JsonField = body._toolResources() + + fun _additionalBodyProperties(): Map = body._additionalProperties() + fun _additionalHeaders(): Headers = additionalHeaders fun _additionalQueryParams(): QueryParams = additionalQueryParams - fun _additionalBodyProperties(): Map = body._additionalProperties() - @JvmSynthetic internal fun getBody(): BetaThreadUpdateBody = body @JvmSynthetic internal fun getHeaders(): Headers = additionalHeaders @@ -63,8 +73,12 @@ constructor( class BetaThreadUpdateBody @JsonCreator internal constructor( - @JsonProperty("metadata") private val metadata: JsonValue?, - @JsonProperty("tool_resources") private val toolResources: ToolResources?, + @JsonProperty("metadata") + @ExcludeMissing + private val metadata: JsonValue = JsonMissing.of(), + @JsonProperty("tool_resources") + @ExcludeMissing + private val toolResources: JsonField = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { @@ -74,8 +88,16 @@ constructor( * storing additional information about the object in a structured format. Keys can be a * maximum of 64 characters long and values can be a maximum of 512 characters long. */ - @JsonProperty("metadata") - fun metadata(): Optional = Optional.ofNullable(metadata) + @JsonProperty("metadata") @ExcludeMissing fun _metadata(): JsonValue = metadata + + /** + * A set of resources that are made available to the assistant's tools in this thread. The + * resources are specific to the type of tool. For example, the `code_interpreter` tool + * requires a list of file IDs, while the `file_search` tool requires a list of vector store + * IDs. + */ + fun toolResources(): Optional = + Optional.ofNullable(toolResources.getNullable("tool_resources")) /** * A set of resources that are made available to the assistant's tools in this thread. The @@ -84,12 +106,22 @@ constructor( * IDs. */ @JsonProperty("tool_resources") - fun toolResources(): Optional = Optional.ofNullable(toolResources) + @ExcludeMissing + fun _toolResources(): JsonField = toolResources @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): BetaThreadUpdateBody = apply { + if (!validated) { + toolResources().map { it.validate() } + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -99,8 +131,8 @@ constructor( class Builder { - private var metadata: JsonValue? = null - private var toolResources: ToolResources? = null + private var metadata: JsonValue = JsonMissing.of() + private var toolResources: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -123,7 +155,25 @@ constructor( * tool requires a list of file IDs, while the `file_search` tool requires a list of * vector store IDs. */ - fun toolResources(toolResources: ToolResources) = apply { + fun toolResources(toolResources: ToolResources?) = + toolResources(JsonField.ofNullable(toolResources)) + + /** + * A set of resources that are made available to the assistant's tools in this thread. + * The resources are specific to the type of tool. For example, the `code_interpreter` + * tool requires a list of file IDs, while the `file_search` tool requires a list of + * vector store IDs. + */ + fun toolResources(toolResources: Optional) = + toolResources(toolResources.orElse(null)) + + /** + * A set of resources that are made available to the assistant's tools in this thread. + * The resources are specific to the type of tool. For example, the `code_interpreter` + * tool requires a list of file IDs, while the `file_search` tool requires a list of + * vector store IDs. + */ + fun toolResources(toolResources: JsonField) = apply { this.toolResources = toolResources } @@ -210,10 +260,48 @@ constructor( * requires a list of file IDs, while the `file_search` tool requires a list of vector store * IDs. */ - fun toolResources(toolResources: ToolResources) = apply { + fun toolResources(toolResources: ToolResources?) = apply { + body.toolResources(toolResources) + } + + /** + * A set of resources that are made available to the assistant's tools in this thread. The + * resources are specific to the type of tool. For example, the `code_interpreter` tool + * requires a list of file IDs, while the `file_search` tool requires a list of vector store + * IDs. + */ + fun toolResources(toolResources: Optional) = + toolResources(toolResources.orElse(null)) + + /** + * A set of resources that are made available to the assistant's tools in this thread. The + * resources are specific to the type of tool. For example, the `code_interpreter` tool + * requires a list of file IDs, while the `file_search` tool requires a list of vector store + * IDs. + */ + fun toolResources(toolResources: JsonField) = apply { body.toolResources(toolResources) } + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } + fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() putAllAdditionalHeaders(additionalHeaders) @@ -312,25 +400,6 @@ constructor( additionalQueryParams.removeAll(keys) } - fun additionalBodyProperties(additionalBodyProperties: Map) = apply { - body.additionalProperties(additionalBodyProperties) - } - - fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { - body.putAdditionalProperty(key, value) - } - - fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = - apply { - body.putAllAdditionalProperties(additionalBodyProperties) - } - - fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } - - fun removeAllAdditionalBodyProperties(keys: Set) = apply { - body.removeAllAdditionalProperties(keys) - } - fun build(): BetaThreadUpdateParams = BetaThreadUpdateParams( checkNotNull(threadId) { "`threadId` is required but was not set" }, @@ -349,22 +418,44 @@ constructor( class ToolResources @JsonCreator private constructor( - @JsonProperty("code_interpreter") private val codeInterpreter: CodeInterpreter?, - @JsonProperty("file_search") private val fileSearch: FileSearch?, + @JsonProperty("code_interpreter") + @ExcludeMissing + private val codeInterpreter: JsonField = JsonMissing.of(), + @JsonProperty("file_search") + @ExcludeMissing + private val fileSearch: JsonField = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { + fun codeInterpreter(): Optional = + Optional.ofNullable(codeInterpreter.getNullable("code_interpreter")) + + fun fileSearch(): Optional = + Optional.ofNullable(fileSearch.getNullable("file_search")) + @JsonProperty("code_interpreter") - fun codeInterpreter(): Optional = Optional.ofNullable(codeInterpreter) + @ExcludeMissing + fun _codeInterpreter(): JsonField = codeInterpreter @JsonProperty("file_search") - fun fileSearch(): Optional = Optional.ofNullable(fileSearch) + @ExcludeMissing + fun _fileSearch(): JsonField = fileSearch @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): ToolResources = apply { + if (!validated) { + codeInterpreter().map { it.validate() } + fileSearch().map { it.validate() } + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -374,8 +465,8 @@ constructor( class Builder { - private var codeInterpreter: CodeInterpreter? = null - private var fileSearch: FileSearch? = null + private var codeInterpreter: JsonField = JsonMissing.of() + private var fileSearch: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -385,11 +476,18 @@ constructor( additionalProperties = toolResources.additionalProperties.toMutableMap() } - fun codeInterpreter(codeInterpreter: CodeInterpreter) = apply { + fun codeInterpreter(codeInterpreter: CodeInterpreter) = + codeInterpreter(JsonField.of(codeInterpreter)) + + fun codeInterpreter(codeInterpreter: JsonField) = apply { this.codeInterpreter = codeInterpreter } - fun fileSearch(fileSearch: FileSearch) = apply { this.fileSearch = fileSearch } + fun fileSearch(fileSearch: FileSearch) = fileSearch(JsonField.of(fileSearch)) + + fun fileSearch(fileSearch: JsonField) = apply { + this.fileSearch = fileSearch + } fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() @@ -422,23 +520,43 @@ constructor( class CodeInterpreter @JsonCreator private constructor( - @JsonProperty("file_ids") private val fileIds: List?, + @JsonProperty("file_ids") + @ExcludeMissing + private val fileIds: JsonField> = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { + /** + * A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made + * available to the `code_interpreter` tool. There can be a maximum of 20 files + * associated with the tool. + */ + fun fileIds(): Optional> = + Optional.ofNullable(fileIds.getNullable("file_ids")) + /** * A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made * available to the `code_interpreter` tool. There can be a maximum of 20 files * associated with the tool. */ @JsonProperty("file_ids") - fun fileIds(): Optional> = Optional.ofNullable(fileIds) + @ExcludeMissing + fun _fileIds(): JsonField> = fileIds @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): CodeInterpreter = apply { + if (!validated) { + fileIds() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -448,12 +566,12 @@ constructor( class Builder { - private var fileIds: MutableList? = null + private var fileIds: JsonField>? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(codeInterpreter: CodeInterpreter) = apply { - fileIds = codeInterpreter.fileIds?.toMutableList() + fileIds = codeInterpreter.fileIds.map { it.toMutableList() } additionalProperties = codeInterpreter.additionalProperties.toMutableMap() } @@ -462,8 +580,15 @@ constructor( * available to the `code_interpreter` tool. There can be a maximum of 20 files * associated with the tool. */ - fun fileIds(fileIds: List) = apply { - this.fileIds = fileIds.toMutableList() + fun fileIds(fileIds: List) = fileIds(JsonField.of(fileIds)) + + /** + * A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made + * available to the `code_interpreter` tool. There can be a maximum of 20 files + * associated with the tool. + */ + fun fileIds(fileIds: JsonField>) = apply { + this.fileIds = fileIds.map { it.toMutableList() } } /** @@ -472,7 +597,16 @@ constructor( * associated with the tool. */ fun addFileId(fileId: String) = apply { - fileIds = (fileIds ?: mutableListOf()).apply { add(fileId) } + fileIds = + (fileIds ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(fileId) + } } fun additionalProperties(additionalProperties: Map) = apply { @@ -498,7 +632,10 @@ constructor( } fun build(): CodeInterpreter = - CodeInterpreter(fileIds?.toImmutable(), additionalProperties.toImmutable()) + CodeInterpreter( + (fileIds ?: JsonMissing.of()).map { it.toImmutable() }, + additionalProperties.toImmutable() + ) } override fun equals(other: Any?): Boolean { @@ -523,11 +660,22 @@ constructor( class FileSearch @JsonCreator private constructor( - @JsonProperty("vector_store_ids") private val vectorStoreIds: List?, + @JsonProperty("vector_store_ids") + @ExcludeMissing + private val vectorStoreIds: JsonField> = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { + /** + * The + * [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) + * attached to this thread. There can be a maximum of 1 vector store attached to the + * thread. + */ + fun vectorStoreIds(): Optional> = + Optional.ofNullable(vectorStoreIds.getNullable("vector_store_ids")) + /** * The * [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) @@ -535,12 +683,22 @@ constructor( * thread. */ @JsonProperty("vector_store_ids") - fun vectorStoreIds(): Optional> = Optional.ofNullable(vectorStoreIds) + @ExcludeMissing + fun _vectorStoreIds(): JsonField> = vectorStoreIds @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): FileSearch = apply { + if (!validated) { + vectorStoreIds() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -550,12 +708,12 @@ constructor( class Builder { - private var vectorStoreIds: MutableList? = null + private var vectorStoreIds: JsonField>? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(fileSearch: FileSearch) = apply { - vectorStoreIds = fileSearch.vectorStoreIds?.toMutableList() + vectorStoreIds = fileSearch.vectorStoreIds.map { it.toMutableList() } additionalProperties = fileSearch.additionalProperties.toMutableMap() } @@ -565,8 +723,17 @@ constructor( * attached to this thread. There can be a maximum of 1 vector store attached to the * thread. */ - fun vectorStoreIds(vectorStoreIds: List) = apply { - this.vectorStoreIds = vectorStoreIds.toMutableList() + fun vectorStoreIds(vectorStoreIds: List) = + vectorStoreIds(JsonField.of(vectorStoreIds)) + + /** + * The + * [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) + * attached to this thread. There can be a maximum of 1 vector store attached to the + * thread. + */ + fun vectorStoreIds(vectorStoreIds: JsonField>) = apply { + this.vectorStoreIds = vectorStoreIds.map { it.toMutableList() } } /** @@ -577,7 +744,15 @@ constructor( */ fun addVectorStoreId(vectorStoreId: String) = apply { vectorStoreIds = - (vectorStoreIds ?: mutableListOf()).apply { add(vectorStoreId) } + (vectorStoreIds ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(vectorStoreId) + } } fun additionalProperties(additionalProperties: Map) = apply { @@ -603,7 +778,10 @@ constructor( } fun build(): FileSearch = - FileSearch(vectorStoreIds?.toImmutable(), additionalProperties.toImmutable()) + FileSearch( + (vectorStoreIds ?: JsonMissing.of()).map { it.toImmutable() }, + additionalProperties.toImmutable() + ) } override fun equals(other: Any?): Boolean { diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreCreateParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreCreateParams.kt index 4cebe5251..70bf2d606 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreCreateParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreCreateParams.kt @@ -9,6 +9,7 @@ import com.fasterxml.jackson.annotation.JsonProperty import com.openai.core.Enum import com.openai.core.ExcludeMissing import com.openai.core.JsonField +import com.openai.core.JsonMissing import com.openai.core.JsonValue import com.openai.core.NoAutoDetect import com.openai.core.http.Headers @@ -19,6 +20,7 @@ import com.openai.errors.OpenAIInvalidDataException import java.util.Objects import java.util.Optional +/** Create a vector store. */ class BetaVectorStoreCreateParams constructor( private val body: BetaVectorStoreCreateBody, @@ -46,17 +48,35 @@ constructor( * additional information about the object in a structured format. Keys can be a maximum of 64 * characters long and values can be a maximum of 512 characters long. */ - fun metadata(): Optional = body.metadata() + fun _metadata(): JsonValue = body._metadata() /** The name of the vector store. */ fun name(): Optional = body.name() - fun _additionalHeaders(): Headers = additionalHeaders + /** + * The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy. + * Only applicable if `file_ids` is non-empty. + */ + fun _chunkingStrategy(): JsonField = body._chunkingStrategy() - fun _additionalQueryParams(): QueryParams = additionalQueryParams + /** The expiration policy for a vector store. */ + fun _expiresAfter(): JsonField = body._expiresAfter() + + /** + * A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the vector + * store should use. Useful for tools like `file_search` that can access files. + */ + fun _fileIds(): JsonField> = body._fileIds() + + /** The name of the vector store. */ + fun _name(): JsonField = body._name() fun _additionalBodyProperties(): Map = body._additionalProperties() + fun _additionalHeaders(): Headers = additionalHeaders + + fun _additionalQueryParams(): QueryParams = additionalQueryParams + @JvmSynthetic internal fun getBody(): BetaVectorStoreCreateBody = body @JvmSynthetic internal fun getHeaders(): Headers = additionalHeaders @@ -67,11 +87,21 @@ constructor( class BetaVectorStoreCreateBody @JsonCreator internal constructor( - @JsonProperty("chunking_strategy") private val chunkingStrategy: FileChunkingStrategyParam?, - @JsonProperty("expires_after") private val expiresAfter: ExpiresAfter?, - @JsonProperty("file_ids") private val fileIds: List?, - @JsonProperty("metadata") private val metadata: JsonValue?, - @JsonProperty("name") private val name: String?, + @JsonProperty("chunking_strategy") + @ExcludeMissing + private val chunkingStrategy: JsonField = JsonMissing.of(), + @JsonProperty("expires_after") + @ExcludeMissing + private val expiresAfter: JsonField = JsonMissing.of(), + @JsonProperty("file_ids") + @ExcludeMissing + private val fileIds: JsonField> = JsonMissing.of(), + @JsonProperty("metadata") + @ExcludeMissing + private val metadata: JsonValue = JsonMissing.of(), + @JsonProperty("name") + @ExcludeMissing + private val name: JsonField = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { @@ -80,36 +110,67 @@ constructor( * The chunking strategy used to chunk the file(s). If not set, will use the `auto` * strategy. Only applicable if `file_ids` is non-empty. */ - @JsonProperty("chunking_strategy") fun chunkingStrategy(): Optional = - Optional.ofNullable(chunkingStrategy) + Optional.ofNullable(chunkingStrategy.getNullable("chunking_strategy")) /** The expiration policy for a vector store. */ - @JsonProperty("expires_after") - fun expiresAfter(): Optional = Optional.ofNullable(expiresAfter) + fun expiresAfter(): Optional = + Optional.ofNullable(expiresAfter.getNullable("expires_after")) /** * A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the * vector store should use. Useful for tools like `file_search` that can access files. */ - @JsonProperty("file_ids") - fun fileIds(): Optional> = Optional.ofNullable(fileIds) + fun fileIds(): Optional> = Optional.ofNullable(fileIds.getNullable("file_ids")) /** * 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 maximum of 512 characters long. */ - @JsonProperty("metadata") - fun metadata(): Optional = Optional.ofNullable(metadata) + @JsonProperty("metadata") @ExcludeMissing fun _metadata(): JsonValue = metadata /** The name of the vector store. */ - @JsonProperty("name") fun name(): Optional = Optional.ofNullable(name) + fun name(): Optional = Optional.ofNullable(name.getNullable("name")) + + /** + * The chunking strategy used to chunk the file(s). If not set, will use the `auto` + * strategy. Only applicable if `file_ids` is non-empty. + */ + @JsonProperty("chunking_strategy") + @ExcludeMissing + fun _chunkingStrategy(): JsonField = chunkingStrategy + + /** The expiration policy for a vector store. */ + @JsonProperty("expires_after") + @ExcludeMissing + fun _expiresAfter(): JsonField = expiresAfter + + /** + * A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the + * vector store should use. Useful for tools like `file_search` that can access files. + */ + @JsonProperty("file_ids") @ExcludeMissing fun _fileIds(): JsonField> = fileIds + + /** The name of the vector store. */ + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): BetaVectorStoreCreateBody = apply { + if (!validated) { + chunkingStrategy() + expiresAfter().map { it.validate() } + fileIds() + name() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -119,18 +180,18 @@ constructor( class Builder { - private var chunkingStrategy: FileChunkingStrategyParam? = null - private var expiresAfter: ExpiresAfter? = null - private var fileIds: MutableList? = null - private var metadata: JsonValue? = null - private var name: String? = null + private var chunkingStrategy: JsonField = JsonMissing.of() + private var expiresAfter: JsonField = JsonMissing.of() + private var fileIds: JsonField>? = null + private var metadata: JsonValue = JsonMissing.of() + private var name: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(betaVectorStoreCreateBody: BetaVectorStoreCreateBody) = apply { chunkingStrategy = betaVectorStoreCreateBody.chunkingStrategy expiresAfter = betaVectorStoreCreateBody.expiresAfter - fileIds = betaVectorStoreCreateBody.fileIds?.toMutableList() + fileIds = betaVectorStoreCreateBody.fileIds.map { it.toMutableList() } metadata = betaVectorStoreCreateBody.metadata name = betaVectorStoreCreateBody.name additionalProperties = betaVectorStoreCreateBody.additionalProperties.toMutableMap() @@ -140,7 +201,14 @@ constructor( * The chunking strategy used to chunk the file(s). If not set, will use the `auto` * strategy. Only applicable if `file_ids` is non-empty. */ - fun chunkingStrategy(chunkingStrategy: FileChunkingStrategyParam) = apply { + fun chunkingStrategy(chunkingStrategy: FileChunkingStrategyParam) = + chunkingStrategy(JsonField.of(chunkingStrategy)) + + /** + * The chunking strategy used to chunk the file(s). If not set, will use the `auto` + * strategy. Only applicable if `file_ids` is non-empty. + */ + fun chunkingStrategy(chunkingStrategy: JsonField) = apply { this.chunkingStrategy = chunkingStrategy } @@ -149,23 +217,24 @@ constructor( * and `chunk_overlap_tokens` of `400`. */ fun chunkingStrategy(autoFileChunkingStrategyParam: AutoFileChunkingStrategyParam) = - apply { - this.chunkingStrategy = - FileChunkingStrategyParam.ofAutoFileChunkingStrategyParam( - autoFileChunkingStrategyParam - ) - } + chunkingStrategy( + FileChunkingStrategyParam.ofAutoFileChunkingStrategyParam( + autoFileChunkingStrategyParam + ) + ) fun chunkingStrategy(staticFileChunkingStrategyParam: StaticFileChunkingStrategyParam) = - apply { - this.chunkingStrategy = - FileChunkingStrategyParam.ofStaticFileChunkingStrategyParam( - staticFileChunkingStrategyParam - ) - } + chunkingStrategy( + FileChunkingStrategyParam.ofStaticFileChunkingStrategyParam( + staticFileChunkingStrategyParam + ) + ) + + /** The expiration policy for a vector store. */ + fun expiresAfter(expiresAfter: ExpiresAfter) = expiresAfter(JsonField.of(expiresAfter)) /** The expiration policy for a vector store. */ - fun expiresAfter(expiresAfter: ExpiresAfter) = apply { + fun expiresAfter(expiresAfter: JsonField) = apply { this.expiresAfter = expiresAfter } @@ -173,14 +242,31 @@ constructor( * A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the * vector store should use. Useful for tools like `file_search` that can access files. */ - fun fileIds(fileIds: List) = apply { this.fileIds = fileIds.toMutableList() } + fun fileIds(fileIds: List) = fileIds(JsonField.of(fileIds)) + + /** + * A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the + * vector store should use. Useful for tools like `file_search` that can access files. + */ + fun fileIds(fileIds: JsonField>) = apply { + this.fileIds = fileIds.map { it.toMutableList() } + } /** * A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the * vector store should use. Useful for tools like `file_search` that can access files. */ fun addFileId(fileId: String) = apply { - fileIds = (fileIds ?: mutableListOf()).apply { add(fileId) } + fileIds = + (fileIds ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(fileId) + } } /** @@ -191,7 +277,10 @@ constructor( fun metadata(metadata: JsonValue) = apply { this.metadata = metadata } /** The name of the vector store. */ - fun name(name: String) = apply { this.name = name } + fun name(name: String) = name(JsonField.of(name)) + + /** The name of the vector store. */ + fun name(name: JsonField) = apply { this.name = name } fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() @@ -216,7 +305,7 @@ constructor( BetaVectorStoreCreateBody( chunkingStrategy, expiresAfter, - fileIds?.toImmutable(), + (fileIds ?: JsonMissing.of()).map { it.toImmutable() }, metadata, name, additionalProperties.toImmutable(), @@ -270,6 +359,14 @@ constructor( body.chunkingStrategy(chunkingStrategy) } + /** + * The chunking strategy used to chunk the file(s). If not set, will use the `auto` + * strategy. Only applicable if `file_ids` is non-empty. + */ + fun chunkingStrategy(chunkingStrategy: JsonField) = apply { + body.chunkingStrategy(chunkingStrategy) + } + /** * The default strategy. This strategy currently uses a `max_chunk_size_tokens` of `800` and * `chunk_overlap_tokens` of `400`. @@ -286,12 +383,23 @@ constructor( /** The expiration policy for a vector store. */ fun expiresAfter(expiresAfter: ExpiresAfter) = apply { body.expiresAfter(expiresAfter) } + /** The expiration policy for a vector store. */ + fun expiresAfter(expiresAfter: JsonField) = apply { + body.expiresAfter(expiresAfter) + } + /** * A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the * vector store should use. Useful for tools like `file_search` that can access files. */ fun fileIds(fileIds: List) = apply { body.fileIds(fileIds) } + /** + * A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the + * vector store should use. Useful for tools like `file_search` that can access files. + */ + fun fileIds(fileIds: JsonField>) = apply { body.fileIds(fileIds) } + /** * A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the * vector store should use. Useful for tools like `file_search` that can access files. @@ -308,6 +416,28 @@ constructor( /** The name of the vector store. */ fun name(name: String) = apply { body.name(name) } + /** The name of the vector store. */ + fun name(name: JsonField) = apply { body.name(name) } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } + fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() putAllAdditionalHeaders(additionalHeaders) @@ -406,25 +536,6 @@ constructor( additionalQueryParams.removeAll(keys) } - fun additionalBodyProperties(additionalBodyProperties: Map) = apply { - body.additionalProperties(additionalBodyProperties) - } - - fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { - body.putAdditionalProperty(key, value) - } - - fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = - apply { - body.putAllAdditionalProperties(additionalBodyProperties) - } - - fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } - - fun removeAllAdditionalBodyProperties(keys: Set) = apply { - body.removeAllAdditionalProperties(keys) - } - fun build(): BetaVectorStoreCreateParams = BetaVectorStoreCreateParams( body.build(), @@ -438,8 +549,10 @@ constructor( class ExpiresAfter @JsonCreator private constructor( - @JsonProperty("anchor") private val anchor: Anchor, - @JsonProperty("days") private val days: Long, + @JsonProperty("anchor") + @ExcludeMissing + private val anchor: JsonField = JsonMissing.of(), + @JsonProperty("days") @ExcludeMissing private val days: JsonField = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { @@ -448,15 +561,34 @@ constructor( * Anchor timestamp after which the expiration policy applies. Supported anchors: * `last_active_at`. */ - @JsonProperty("anchor") fun anchor(): Anchor = anchor + fun anchor(): Anchor = anchor.getRequired("anchor") /** The number of days after the anchor time that the vector store will expire. */ - @JsonProperty("days") fun days(): Long = days + fun days(): Long = days.getRequired("days") + + /** + * Anchor timestamp after which the expiration policy applies. Supported anchors: + * `last_active_at`. + */ + @JsonProperty("anchor") @ExcludeMissing fun _anchor(): JsonField = anchor + + /** The number of days after the anchor time that the vector store will expire. */ + @JsonProperty("days") @ExcludeMissing fun _days(): JsonField = days @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): ExpiresAfter = apply { + if (!validated) { + anchor() + days() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -466,8 +598,8 @@ constructor( class Builder { - private var anchor: Anchor? = null - private var days: Long? = null + private var anchor: JsonField? = null + private var days: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -481,10 +613,19 @@ constructor( * Anchor timestamp after which the expiration policy applies. Supported anchors: * `last_active_at`. */ - fun anchor(anchor: Anchor) = apply { this.anchor = anchor } + fun anchor(anchor: Anchor) = anchor(JsonField.of(anchor)) + + /** + * Anchor timestamp after which the expiration policy applies. Supported anchors: + * `last_active_at`. + */ + fun anchor(anchor: JsonField) = apply { this.anchor = anchor } + + /** The number of days after the anchor time that the vector store will expire. */ + fun days(days: Long) = days(JsonField.of(days)) /** The number of days after the anchor time that the vector store will expire. */ - fun days(days: Long) = apply { this.days = days } + fun days(days: JsonField) = apply { this.days = days } fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreDeleteParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreDeleteParams.kt index 763c5163f..6249c7b76 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreDeleteParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreDeleteParams.kt @@ -10,6 +10,7 @@ import com.openai.core.toImmutable import java.util.Objects import java.util.Optional +/** Delete a vector store. */ class BetaVectorStoreDeleteParams constructor( private val vectorStoreId: String, diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileBatchCancelParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileBatchCancelParams.kt index 446427379..860f978af 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileBatchCancelParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileBatchCancelParams.kt @@ -10,6 +10,10 @@ import com.openai.core.toImmutable import java.util.Objects import java.util.Optional +/** + * Cancel a vector store file batch. This attempts to cancel the processing of files in this batch + * as soon as possible. + */ class BetaVectorStoreFileBatchCancelParams constructor( private val vectorStoreId: String, diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileBatchCreateParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileBatchCreateParams.kt index 0134b5e9d..f657977ad 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileBatchCreateParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileBatchCreateParams.kt @@ -7,6 +7,8 @@ import com.fasterxml.jackson.annotation.JsonAnySetter import com.fasterxml.jackson.annotation.JsonCreator import com.fasterxml.jackson.annotation.JsonProperty import com.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing import com.openai.core.JsonValue import com.openai.core.NoAutoDetect import com.openai.core.http.Headers @@ -16,6 +18,7 @@ import com.openai.core.toImmutable import java.util.Objects import java.util.Optional +/** Create a vector store file batch. */ class BetaVectorStoreFileBatchCreateParams constructor( private val vectorStoreId: String, @@ -38,12 +41,24 @@ constructor( */ fun chunkingStrategy(): Optional = body.chunkingStrategy() - fun _additionalHeaders(): Headers = additionalHeaders + /** + * A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the vector + * store should use. Useful for tools like `file_search` that can access files. + */ + fun _fileIds(): JsonField> = body._fileIds() - fun _additionalQueryParams(): QueryParams = additionalQueryParams + /** + * The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy. + * Only applicable if `file_ids` is non-empty. + */ + fun _chunkingStrategy(): JsonField = body._chunkingStrategy() fun _additionalBodyProperties(): Map = body._additionalProperties() + fun _additionalHeaders(): Headers = additionalHeaders + + fun _additionalQueryParams(): QueryParams = additionalQueryParams + @JvmSynthetic internal fun getBody(): BetaVectorStoreFileBatchCreateBody = body @JvmSynthetic internal fun getHeaders(): Headers = additionalHeaders @@ -61,8 +76,12 @@ constructor( class BetaVectorStoreFileBatchCreateBody @JsonCreator internal constructor( - @JsonProperty("file_ids") private val fileIds: List, - @JsonProperty("chunking_strategy") private val chunkingStrategy: FileChunkingStrategyParam?, + @JsonProperty("file_ids") + @ExcludeMissing + private val fileIds: JsonField> = JsonMissing.of(), + @JsonProperty("chunking_strategy") + @ExcludeMissing + private val chunkingStrategy: JsonField = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { @@ -71,20 +90,43 @@ constructor( * A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the * vector store should use. Useful for tools like `file_search` that can access files. */ - @JsonProperty("file_ids") fun fileIds(): List = fileIds + fun fileIds(): List = fileIds.getRequired("file_ids") /** * The chunking strategy used to chunk the file(s). If not set, will use the `auto` * strategy. Only applicable if `file_ids` is non-empty. */ - @JsonProperty("chunking_strategy") fun chunkingStrategy(): Optional = - Optional.ofNullable(chunkingStrategy) + Optional.ofNullable(chunkingStrategy.getNullable("chunking_strategy")) + + /** + * A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the + * vector store should use. Useful for tools like `file_search` that can access files. + */ + @JsonProperty("file_ids") @ExcludeMissing fun _fileIds(): JsonField> = fileIds + + /** + * The chunking strategy used to chunk the file(s). If not set, will use the `auto` + * strategy. Only applicable if `file_ids` is non-empty. + */ + @JsonProperty("chunking_strategy") + @ExcludeMissing + fun _chunkingStrategy(): JsonField = chunkingStrategy @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): BetaVectorStoreFileBatchCreateBody = apply { + if (!validated) { + fileIds() + chunkingStrategy() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -94,15 +136,15 @@ constructor( class Builder { - private var fileIds: MutableList? = null - private var chunkingStrategy: FileChunkingStrategyParam? = null + private var fileIds: JsonField>? = null + private var chunkingStrategy: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from( betaVectorStoreFileBatchCreateBody: BetaVectorStoreFileBatchCreateBody ) = apply { - fileIds = betaVectorStoreFileBatchCreateBody.fileIds.toMutableList() + fileIds = betaVectorStoreFileBatchCreateBody.fileIds.map { it.toMutableList() } chunkingStrategy = betaVectorStoreFileBatchCreateBody.chunkingStrategy additionalProperties = betaVectorStoreFileBatchCreateBody.additionalProperties.toMutableMap() @@ -112,21 +154,45 @@ constructor( * A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the * vector store should use. Useful for tools like `file_search` that can access files. */ - fun fileIds(fileIds: List) = apply { this.fileIds = fileIds.toMutableList() } + fun fileIds(fileIds: List) = fileIds(JsonField.of(fileIds)) + + /** + * A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the + * vector store should use. Useful for tools like `file_search` that can access files. + */ + fun fileIds(fileIds: JsonField>) = apply { + this.fileIds = fileIds.map { it.toMutableList() } + } /** * A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the * vector store should use. Useful for tools like `file_search` that can access files. */ fun addFileId(fileId: String) = apply { - fileIds = (fileIds ?: mutableListOf()).apply { add(fileId) } + fileIds = + (fileIds ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(fileId) + } } /** * The chunking strategy used to chunk the file(s). If not set, will use the `auto` * strategy. Only applicable if `file_ids` is non-empty. */ - fun chunkingStrategy(chunkingStrategy: FileChunkingStrategyParam) = apply { + fun chunkingStrategy(chunkingStrategy: FileChunkingStrategyParam) = + chunkingStrategy(JsonField.of(chunkingStrategy)) + + /** + * The chunking strategy used to chunk the file(s). If not set, will use the `auto` + * strategy. Only applicable if `file_ids` is non-empty. + */ + fun chunkingStrategy(chunkingStrategy: JsonField) = apply { this.chunkingStrategy = chunkingStrategy } @@ -135,20 +201,18 @@ constructor( * and `chunk_overlap_tokens` of `400`. */ fun chunkingStrategy(autoFileChunkingStrategyParam: AutoFileChunkingStrategyParam) = - apply { - this.chunkingStrategy = - FileChunkingStrategyParam.ofAutoFileChunkingStrategyParam( - autoFileChunkingStrategyParam - ) - } + chunkingStrategy( + FileChunkingStrategyParam.ofAutoFileChunkingStrategyParam( + autoFileChunkingStrategyParam + ) + ) fun chunkingStrategy(staticFileChunkingStrategyParam: StaticFileChunkingStrategyParam) = - apply { - this.chunkingStrategy = - FileChunkingStrategyParam.ofStaticFileChunkingStrategyParam( - staticFileChunkingStrategyParam - ) - } + chunkingStrategy( + FileChunkingStrategyParam.ofStaticFileChunkingStrategyParam( + staticFileChunkingStrategyParam + ) + ) fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() @@ -171,7 +235,8 @@ constructor( fun build(): BetaVectorStoreFileBatchCreateBody = BetaVectorStoreFileBatchCreateBody( - checkNotNull(fileIds) { "`fileIds` is required but was not set" }.toImmutable(), + checkNotNull(fileIds) { "`fileIds` is required but was not set" } + .map { it.toImmutable() }, chunkingStrategy, additionalProperties.toImmutable(), ) @@ -230,6 +295,12 @@ constructor( */ fun fileIds(fileIds: List) = apply { body.fileIds(fileIds) } + /** + * A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the + * vector store should use. Useful for tools like `file_search` that can access files. + */ + fun fileIds(fileIds: JsonField>) = apply { body.fileIds(fileIds) } + /** * A list of [File](https://platform.openai.com/docs/api-reference/files) IDs that the * vector store should use. Useful for tools like `file_search` that can access files. @@ -244,6 +315,14 @@ constructor( body.chunkingStrategy(chunkingStrategy) } + /** + * The chunking strategy used to chunk the file(s). If not set, will use the `auto` + * strategy. Only applicable if `file_ids` is non-empty. + */ + fun chunkingStrategy(chunkingStrategy: JsonField) = apply { + body.chunkingStrategy(chunkingStrategy) + } + /** * The default strategy. This strategy currently uses a `max_chunk_size_tokens` of `800` and * `chunk_overlap_tokens` of `400`. @@ -257,6 +336,25 @@ constructor( body.chunkingStrategy(staticFileChunkingStrategyParam) } + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } + fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() putAllAdditionalHeaders(additionalHeaders) @@ -355,25 +453,6 @@ constructor( additionalQueryParams.removeAll(keys) } - fun additionalBodyProperties(additionalBodyProperties: Map) = apply { - body.additionalProperties(additionalBodyProperties) - } - - fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { - body.putAdditionalProperty(key, value) - } - - fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = - apply { - body.putAllAdditionalProperties(additionalBodyProperties) - } - - fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } - - fun removeAllAdditionalBodyProperties(keys: Set) = apply { - body.removeAllAdditionalProperties(keys) - } - fun build(): BetaVectorStoreFileBatchCreateParams = BetaVectorStoreFileBatchCreateParams( checkNotNull(vectorStoreId) { "`vectorStoreId` is required but was not set" }, diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileBatchListFilesParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileBatchListFilesParams.kt index f7c99e63d..31c095516 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileBatchListFilesParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileBatchListFilesParams.kt @@ -12,6 +12,7 @@ import com.openai.errors.OpenAIInvalidDataException import java.util.Objects import java.util.Optional +/** Returns a list of vector store files in a batch. */ class BetaVectorStoreFileBatchListFilesParams constructor( private val vectorStoreId: String, @@ -131,7 +132,23 @@ constructor( * obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page * of the list. */ - fun after(after: String) = apply { this.after = after } + fun after(after: String?) = apply { this.after = after } + + /** + * 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. + */ + fun after(after: Optional) = after(after.orElse(null)) + + /** + * 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, starting with + * obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous + * page of the list. + */ + fun before(before: String?) = apply { this.before = before } /** * A cursor for use in pagination. `before` is an object ID that defines your place in the @@ -139,22 +156,44 @@ constructor( * obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous * page of the list. */ - fun before(before: String) = apply { this.before = before } + fun before(before: Optional) = before(before.orElse(null)) + + /** Filter by file status. One of `in_progress`, `completed`, `failed`, `cancelled`. */ + fun filter(filter: Filter?) = apply { this.filter = filter } /** Filter by file status. One of `in_progress`, `completed`, `failed`, `cancelled`. */ - fun filter(filter: Filter) = apply { this.filter = filter } + fun filter(filter: Optional) = filter(filter.orElse(null)) /** * A limit on the number of objects to be returned. Limit can range between 1 and 100, and * the default is 20. */ - fun limit(limit: Long) = apply { this.limit = limit } + fun limit(limit: Long?) = apply { this.limit = limit } + + /** + * A limit on the number of objects to be returned. Limit can range between 1 and 100, and + * the default is 20. + */ + fun limit(limit: Long) = limit(limit as Long?) + + /** + * A limit on the number of objects to be returned. Limit can range between 1 and 100, and + * the default is 20. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun limit(limit: Optional) = limit(limit.orElse(null) as Long?) + + /** + * Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and + * `desc` for descending order. + */ + fun order(order: Order?) = apply { this.order = order } /** * Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and * `desc` for descending order. */ - fun order(order: Order) = apply { this.order = order } + fun order(order: Optional) = order(order.orElse(null)) fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileBatchRetrieveParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileBatchRetrieveParams.kt index 446e22bb8..805a7f394 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileBatchRetrieveParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileBatchRetrieveParams.kt @@ -7,6 +7,7 @@ import com.openai.core.http.Headers import com.openai.core.http.QueryParams import java.util.Objects +/** Retrieves a vector store file batch. */ class BetaVectorStoreFileBatchRetrieveParams constructor( private val vectorStoreId: String, diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileCreateParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileCreateParams.kt index 8fed88c16..6c7260625 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileCreateParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileCreateParams.kt @@ -7,6 +7,8 @@ import com.fasterxml.jackson.annotation.JsonAnySetter import com.fasterxml.jackson.annotation.JsonCreator import com.fasterxml.jackson.annotation.JsonProperty import com.openai.core.ExcludeMissing +import com.openai.core.JsonField +import com.openai.core.JsonMissing import com.openai.core.JsonValue import com.openai.core.NoAutoDetect import com.openai.core.http.Headers @@ -16,6 +18,11 @@ import com.openai.core.toImmutable import java.util.Objects import java.util.Optional +/** + * Create a vector store file by attaching a + * [File](https://platform.openai.com/docs/api-reference/files) to a + * [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object). + */ class BetaVectorStoreFileCreateParams constructor( private val vectorStoreId: String, @@ -38,12 +45,24 @@ constructor( */ fun chunkingStrategy(): Optional = body.chunkingStrategy() - fun _additionalHeaders(): Headers = additionalHeaders + /** + * A [File](https://platform.openai.com/docs/api-reference/files) ID that the vector store + * should use. Useful for tools like `file_search` that can access files. + */ + fun _fileId(): JsonField = body._fileId() - fun _additionalQueryParams(): QueryParams = additionalQueryParams + /** + * The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy. + * Only applicable if `file_ids` is non-empty. + */ + fun _chunkingStrategy(): JsonField = body._chunkingStrategy() fun _additionalBodyProperties(): Map = body._additionalProperties() + fun _additionalHeaders(): Headers = additionalHeaders + + fun _additionalQueryParams(): QueryParams = additionalQueryParams + @JvmSynthetic internal fun getBody(): BetaVectorStoreFileCreateBody = body @JvmSynthetic internal fun getHeaders(): Headers = additionalHeaders @@ -61,8 +80,12 @@ constructor( class BetaVectorStoreFileCreateBody @JsonCreator internal constructor( - @JsonProperty("file_id") private val fileId: String, - @JsonProperty("chunking_strategy") private val chunkingStrategy: FileChunkingStrategyParam?, + @JsonProperty("file_id") + @ExcludeMissing + private val fileId: JsonField = JsonMissing.of(), + @JsonProperty("chunking_strategy") + @ExcludeMissing + private val chunkingStrategy: JsonField = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { @@ -71,20 +94,43 @@ constructor( * A [File](https://platform.openai.com/docs/api-reference/files) ID that the vector store * should use. Useful for tools like `file_search` that can access files. */ - @JsonProperty("file_id") fun fileId(): String = fileId + fun fileId(): String = fileId.getRequired("file_id") /** * The chunking strategy used to chunk the file(s). If not set, will use the `auto` * strategy. Only applicable if `file_ids` is non-empty. */ - @JsonProperty("chunking_strategy") fun chunkingStrategy(): Optional = - Optional.ofNullable(chunkingStrategy) + Optional.ofNullable(chunkingStrategy.getNullable("chunking_strategy")) + + /** + * A [File](https://platform.openai.com/docs/api-reference/files) ID that the vector store + * should use. Useful for tools like `file_search` that can access files. + */ + @JsonProperty("file_id") @ExcludeMissing fun _fileId(): JsonField = fileId + + /** + * The chunking strategy used to chunk the file(s). If not set, will use the `auto` + * strategy. Only applicable if `file_ids` is non-empty. + */ + @JsonProperty("chunking_strategy") + @ExcludeMissing + fun _chunkingStrategy(): JsonField = chunkingStrategy @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): BetaVectorStoreFileCreateBody = apply { + if (!validated) { + fileId() + chunkingStrategy() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -94,8 +140,8 @@ constructor( class Builder { - private var fileId: String? = null - private var chunkingStrategy: FileChunkingStrategyParam? = null + private var fileId: JsonField? = null + private var chunkingStrategy: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -111,13 +157,26 @@ constructor( * A [File](https://platform.openai.com/docs/api-reference/files) ID that the vector * store should use. Useful for tools like `file_search` that can access files. */ - fun fileId(fileId: String) = apply { this.fileId = fileId } + fun fileId(fileId: String) = fileId(JsonField.of(fileId)) + + /** + * A [File](https://platform.openai.com/docs/api-reference/files) ID that the vector + * store should use. Useful for tools like `file_search` that can access files. + */ + fun fileId(fileId: JsonField) = apply { this.fileId = fileId } + + /** + * The chunking strategy used to chunk the file(s). If not set, will use the `auto` + * strategy. Only applicable if `file_ids` is non-empty. + */ + fun chunkingStrategy(chunkingStrategy: FileChunkingStrategyParam) = + chunkingStrategy(JsonField.of(chunkingStrategy)) /** * The chunking strategy used to chunk the file(s). If not set, will use the `auto` * strategy. Only applicable if `file_ids` is non-empty. */ - fun chunkingStrategy(chunkingStrategy: FileChunkingStrategyParam) = apply { + fun chunkingStrategy(chunkingStrategy: JsonField) = apply { this.chunkingStrategy = chunkingStrategy } @@ -126,20 +185,18 @@ constructor( * and `chunk_overlap_tokens` of `400`. */ fun chunkingStrategy(autoFileChunkingStrategyParam: AutoFileChunkingStrategyParam) = - apply { - this.chunkingStrategy = - FileChunkingStrategyParam.ofAutoFileChunkingStrategyParam( - autoFileChunkingStrategyParam - ) - } + chunkingStrategy( + FileChunkingStrategyParam.ofAutoFileChunkingStrategyParam( + autoFileChunkingStrategyParam + ) + ) fun chunkingStrategy(staticFileChunkingStrategyParam: StaticFileChunkingStrategyParam) = - apply { - this.chunkingStrategy = - FileChunkingStrategyParam.ofStaticFileChunkingStrategyParam( - staticFileChunkingStrategyParam - ) - } + chunkingStrategy( + FileChunkingStrategyParam.ofStaticFileChunkingStrategyParam( + staticFileChunkingStrategyParam + ) + ) fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() @@ -220,6 +277,12 @@ constructor( */ fun fileId(fileId: String) = apply { body.fileId(fileId) } + /** + * A [File](https://platform.openai.com/docs/api-reference/files) ID that the vector store + * should use. Useful for tools like `file_search` that can access files. + */ + fun fileId(fileId: JsonField) = apply { body.fileId(fileId) } + /** * The chunking strategy used to chunk the file(s). If not set, will use the `auto` * strategy. Only applicable if `file_ids` is non-empty. @@ -228,6 +291,14 @@ constructor( body.chunkingStrategy(chunkingStrategy) } + /** + * The chunking strategy used to chunk the file(s). If not set, will use the `auto` + * strategy. Only applicable if `file_ids` is non-empty. + */ + fun chunkingStrategy(chunkingStrategy: JsonField) = apply { + body.chunkingStrategy(chunkingStrategy) + } + /** * The default strategy. This strategy currently uses a `max_chunk_size_tokens` of `800` and * `chunk_overlap_tokens` of `400`. @@ -241,6 +312,25 @@ constructor( body.chunkingStrategy(staticFileChunkingStrategyParam) } + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } + fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() putAllAdditionalHeaders(additionalHeaders) @@ -339,25 +429,6 @@ constructor( additionalQueryParams.removeAll(keys) } - fun additionalBodyProperties(additionalBodyProperties: Map) = apply { - body.additionalProperties(additionalBodyProperties) - } - - fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { - body.putAdditionalProperty(key, value) - } - - fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = - apply { - body.putAllAdditionalProperties(additionalBodyProperties) - } - - fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } - - fun removeAllAdditionalBodyProperties(keys: Set) = apply { - body.removeAllAdditionalProperties(keys) - } - fun build(): BetaVectorStoreFileCreateParams = BetaVectorStoreFileCreateParams( checkNotNull(vectorStoreId) { "`vectorStoreId` is required but was not set" }, diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileDeleteParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileDeleteParams.kt index c04cfbaf0..88e8b89e2 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileDeleteParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileDeleteParams.kt @@ -10,6 +10,11 @@ import com.openai.core.toImmutable import java.util.Objects import java.util.Optional +/** + * Delete a vector store file. This will remove the file from the vector store but the file itself + * will not be deleted. To delete the file, use the + * [delete file](https://platform.openai.com/docs/api-reference/files/delete) endpoint. + */ class BetaVectorStoreFileDeleteParams constructor( private val vectorStoreId: String, diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileListParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileListParams.kt index 41f81f6c6..35d3c8a2b 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileListParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileListParams.kt @@ -12,6 +12,7 @@ import com.openai.errors.OpenAIInvalidDataException import java.util.Objects import java.util.Optional +/** Returns a list of vector store files. */ class BetaVectorStoreFileListParams constructor( private val vectorStoreId: String, @@ -119,7 +120,23 @@ constructor( * obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page * of the list. */ - fun after(after: String) = apply { this.after = after } + fun after(after: String?) = apply { this.after = after } + + /** + * 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. + */ + fun after(after: Optional) = after(after.orElse(null)) + + /** + * 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, starting with + * obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous + * page of the list. + */ + fun before(before: String?) = apply { this.before = before } /** * A cursor for use in pagination. `before` is an object ID that defines your place in the @@ -127,22 +144,44 @@ constructor( * obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous * page of the list. */ - fun before(before: String) = apply { this.before = before } + fun before(before: Optional) = before(before.orElse(null)) + + /** Filter by file status. One of `in_progress`, `completed`, `failed`, `cancelled`. */ + fun filter(filter: Filter?) = apply { this.filter = filter } /** Filter by file status. One of `in_progress`, `completed`, `failed`, `cancelled`. */ - fun filter(filter: Filter) = apply { this.filter = filter } + fun filter(filter: Optional) = filter(filter.orElse(null)) /** * A limit on the number of objects to be returned. Limit can range between 1 and 100, and * the default is 20. */ - fun limit(limit: Long) = apply { this.limit = limit } + fun limit(limit: Long?) = apply { this.limit = limit } + + /** + * A limit on the number of objects to be returned. Limit can range between 1 and 100, and + * the default is 20. + */ + fun limit(limit: Long) = limit(limit as Long?) + + /** + * A limit on the number of objects to be returned. Limit can range between 1 and 100, and + * the default is 20. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun limit(limit: Optional) = limit(limit.orElse(null) as Long?) + + /** + * Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and + * `desc` for descending order. + */ + fun order(order: Order?) = apply { this.order = order } /** * Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and * `desc` for descending order. */ - fun order(order: Order) = apply { this.order = order } + fun order(order: Optional) = order(order.orElse(null)) fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileRetrieveParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileRetrieveParams.kt index 1527b25fc..5ec5b6c34 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileRetrieveParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreFileRetrieveParams.kt @@ -7,6 +7,7 @@ import com.openai.core.http.Headers import com.openai.core.http.QueryParams import java.util.Objects +/** Retrieves a vector store file. */ class BetaVectorStoreFileRetrieveParams constructor( private val vectorStoreId: String, diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreListParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreListParams.kt index 1a5c1bd88..2918d6b23 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreListParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreListParams.kt @@ -12,6 +12,7 @@ import com.openai.errors.OpenAIInvalidDataException import java.util.Objects import java.util.Optional +/** Returns a list of vector stores. */ class BetaVectorStoreListParams constructor( private val after: String?, @@ -98,7 +99,15 @@ constructor( * obj_foo, your subsequent call can include after=obj_foo in order to fetch the next page * of the list. */ - fun after(after: String) = apply { this.after = after } + fun after(after: String?) = apply { this.after = after } + + /** + * 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. + */ + fun after(after: Optional) = after(after.orElse(null)) /** * A cursor for use in pagination. `before` is an object ID that defines your place in the @@ -106,19 +115,46 @@ constructor( * obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous * page of the list. */ - fun before(before: String) = apply { this.before = before } + fun before(before: String?) = apply { this.before = before } + + /** + * 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, starting with + * obj_foo, your subsequent call can include before=obj_foo in order to fetch the previous + * page of the list. + */ + fun before(before: Optional) = before(before.orElse(null)) /** * A limit on the number of objects to be returned. Limit can range between 1 and 100, and * the default is 20. */ - fun limit(limit: Long) = apply { this.limit = limit } + fun limit(limit: Long?) = apply { this.limit = limit } + + /** + * A limit on the number of objects to be returned. Limit can range between 1 and 100, and + * the default is 20. + */ + fun limit(limit: Long) = limit(limit as Long?) + + /** + * A limit on the number of objects to be returned. Limit can range between 1 and 100, and + * the default is 20. + */ + @Suppress("USELESS_CAST") // See https://youtrack.jetbrains.com/issue/KT-74228 + fun limit(limit: Optional) = limit(limit.orElse(null) as Long?) + + /** + * Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and + * `desc` for descending order. + */ + fun order(order: Order?) = apply { this.order = order } /** * Sort order by the `created_at` timestamp of the objects. `asc` for ascending order and * `desc` for descending order. */ - fun order(order: Order) = apply { this.order = order } + fun order(order: Optional) = order(order.orElse(null)) fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreRetrieveParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreRetrieveParams.kt index 19b6ff3a4..593eefd80 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreRetrieveParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreRetrieveParams.kt @@ -7,6 +7,7 @@ import com.openai.core.http.Headers import com.openai.core.http.QueryParams import java.util.Objects +/** Retrieves a vector store. */ class BetaVectorStoreRetrieveParams constructor( private val vectorStoreId: String, diff --git a/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreUpdateParams.kt b/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreUpdateParams.kt index 7e5f30e90..6968677fb 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreUpdateParams.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/BetaVectorStoreUpdateParams.kt @@ -9,6 +9,7 @@ import com.fasterxml.jackson.annotation.JsonProperty import com.openai.core.Enum import com.openai.core.ExcludeMissing import com.openai.core.JsonField +import com.openai.core.JsonMissing import com.openai.core.JsonValue import com.openai.core.NoAutoDetect import com.openai.core.http.Headers @@ -19,6 +20,7 @@ import com.openai.errors.OpenAIInvalidDataException import java.util.Objects import java.util.Optional +/** Modifies a vector store. */ class BetaVectorStoreUpdateParams constructor( private val vectorStoreId: String, @@ -37,17 +39,23 @@ constructor( * additional information about the object in a structured format. Keys can be a maximum of 64 * characters long and values can be a maximum of 512 characters long. */ - fun metadata(): Optional = body.metadata() + fun _metadata(): JsonValue = body._metadata() /** The name of the vector store. */ fun name(): Optional = body.name() - fun _additionalHeaders(): Headers = additionalHeaders + /** The expiration policy for a vector store. */ + fun _expiresAfter(): JsonField = body._expiresAfter() - fun _additionalQueryParams(): QueryParams = additionalQueryParams + /** The name of the vector store. */ + fun _name(): JsonField = body._name() fun _additionalBodyProperties(): Map = body._additionalProperties() + fun _additionalHeaders(): Headers = additionalHeaders + + fun _additionalQueryParams(): QueryParams = additionalQueryParams + @JvmSynthetic internal fun getBody(): BetaVectorStoreUpdateBody = body @JvmSynthetic internal fun getHeaders(): Headers = additionalHeaders @@ -65,32 +73,55 @@ constructor( class BetaVectorStoreUpdateBody @JsonCreator internal constructor( - @JsonProperty("expires_after") private val expiresAfter: ExpiresAfter?, - @JsonProperty("metadata") private val metadata: JsonValue?, - @JsonProperty("name") private val name: String?, + @JsonProperty("expires_after") + @ExcludeMissing + private val expiresAfter: JsonField = JsonMissing.of(), + @JsonProperty("metadata") + @ExcludeMissing + private val metadata: JsonValue = JsonMissing.of(), + @JsonProperty("name") + @ExcludeMissing + private val name: JsonField = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { /** The expiration policy for a vector store. */ - @JsonProperty("expires_after") - fun expiresAfter(): Optional = Optional.ofNullable(expiresAfter) + fun expiresAfter(): Optional = + Optional.ofNullable(expiresAfter.getNullable("expires_after")) /** * 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 maximum of 512 characters long. */ - @JsonProperty("metadata") - fun metadata(): Optional = Optional.ofNullable(metadata) + @JsonProperty("metadata") @ExcludeMissing fun _metadata(): JsonValue = metadata + + /** The name of the vector store. */ + fun name(): Optional = Optional.ofNullable(name.getNullable("name")) + + /** The expiration policy for a vector store. */ + @JsonProperty("expires_after") + @ExcludeMissing + fun _expiresAfter(): JsonField = expiresAfter /** The name of the vector store. */ - @JsonProperty("name") fun name(): Optional = Optional.ofNullable(name) + @JsonProperty("name") @ExcludeMissing fun _name(): JsonField = name @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): BetaVectorStoreUpdateBody = apply { + if (!validated) { + expiresAfter().map { it.validate() } + name() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -100,9 +131,9 @@ constructor( class Builder { - private var expiresAfter: ExpiresAfter? = null - private var metadata: JsonValue? = null - private var name: String? = null + private var expiresAfter: JsonField = JsonMissing.of() + private var metadata: JsonValue = JsonMissing.of() + private var name: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -114,7 +145,15 @@ constructor( } /** The expiration policy for a vector store. */ - fun expiresAfter(expiresAfter: ExpiresAfter) = apply { + fun expiresAfter(expiresAfter: ExpiresAfter?) = + expiresAfter(JsonField.ofNullable(expiresAfter)) + + /** The expiration policy for a vector store. */ + fun expiresAfter(expiresAfter: Optional) = + expiresAfter(expiresAfter.orElse(null)) + + /** The expiration policy for a vector store. */ + fun expiresAfter(expiresAfter: JsonField) = apply { this.expiresAfter = expiresAfter } @@ -126,7 +165,13 @@ constructor( fun metadata(metadata: JsonValue) = apply { this.metadata = metadata } /** The name of the vector store. */ - fun name(name: String) = apply { this.name = name } + fun name(name: String?) = name(JsonField.ofNullable(name)) + + /** The name of the vector store. */ + fun name(name: Optional) = name(name.orElse(null)) + + /** The name of the vector store. */ + fun name(name: JsonField) = apply { this.name = name } fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() @@ -200,7 +245,16 @@ constructor( fun vectorStoreId(vectorStoreId: String) = apply { this.vectorStoreId = vectorStoreId } /** The expiration policy for a vector store. */ - fun expiresAfter(expiresAfter: ExpiresAfter) = apply { body.expiresAfter(expiresAfter) } + fun expiresAfter(expiresAfter: ExpiresAfter?) = apply { body.expiresAfter(expiresAfter) } + + /** The expiration policy for a vector store. */ + fun expiresAfter(expiresAfter: Optional) = + expiresAfter(expiresAfter.orElse(null)) + + /** The expiration policy for a vector store. */ + fun expiresAfter(expiresAfter: JsonField) = apply { + body.expiresAfter(expiresAfter) + } /** * Set of 16 key-value pairs that can be attached to an object. This can be useful for @@ -210,7 +264,32 @@ constructor( fun metadata(metadata: JsonValue) = apply { body.metadata(metadata) } /** The name of the vector store. */ - fun name(name: String) = apply { body.name(name) } + fun name(name: String?) = apply { body.name(name) } + + /** The name of the vector store. */ + fun name(name: Optional) = name(name.orElse(null)) + + /** The name of the vector store. */ + fun name(name: JsonField) = apply { body.name(name) } + + fun additionalBodyProperties(additionalBodyProperties: Map) = apply { + body.additionalProperties(additionalBodyProperties) + } + + fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { + body.putAdditionalProperty(key, value) + } + + fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = + apply { + body.putAllAdditionalProperties(additionalBodyProperties) + } + + fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } + + fun removeAllAdditionalBodyProperties(keys: Set) = apply { + body.removeAllAdditionalProperties(keys) + } fun additionalHeaders(additionalHeaders: Headers) = apply { this.additionalHeaders.clear() @@ -310,25 +389,6 @@ constructor( additionalQueryParams.removeAll(keys) } - fun additionalBodyProperties(additionalBodyProperties: Map) = apply { - body.additionalProperties(additionalBodyProperties) - } - - fun putAdditionalBodyProperty(key: String, value: JsonValue) = apply { - body.putAdditionalProperty(key, value) - } - - fun putAllAdditionalBodyProperties(additionalBodyProperties: Map) = - apply { - body.putAllAdditionalProperties(additionalBodyProperties) - } - - fun removeAdditionalBodyProperty(key: String) = apply { body.removeAdditionalProperty(key) } - - fun removeAllAdditionalBodyProperties(keys: Set) = apply { - body.removeAllAdditionalProperties(keys) - } - fun build(): BetaVectorStoreUpdateParams = BetaVectorStoreUpdateParams( checkNotNull(vectorStoreId) { "`vectorStoreId` is required but was not set" }, @@ -343,8 +403,10 @@ constructor( class ExpiresAfter @JsonCreator private constructor( - @JsonProperty("anchor") private val anchor: Anchor, - @JsonProperty("days") private val days: Long, + @JsonProperty("anchor") + @ExcludeMissing + private val anchor: JsonField = JsonMissing.of(), + @JsonProperty("days") @ExcludeMissing private val days: JsonField = JsonMissing.of(), @JsonAnySetter private val additionalProperties: Map = immutableEmptyMap(), ) { @@ -353,15 +415,34 @@ constructor( * Anchor timestamp after which the expiration policy applies. Supported anchors: * `last_active_at`. */ - @JsonProperty("anchor") fun anchor(): Anchor = anchor + fun anchor(): Anchor = anchor.getRequired("anchor") + + /** The number of days after the anchor time that the vector store will expire. */ + fun days(): Long = days.getRequired("days") + + /** + * Anchor timestamp after which the expiration policy applies. Supported anchors: + * `last_active_at`. + */ + @JsonProperty("anchor") @ExcludeMissing fun _anchor(): JsonField = anchor /** The number of days after the anchor time that the vector store will expire. */ - @JsonProperty("days") fun days(): Long = days + @JsonProperty("days") @ExcludeMissing fun _days(): JsonField = days @JsonAnyGetter @ExcludeMissing fun _additionalProperties(): Map = additionalProperties + private var validated: Boolean = false + + fun validate(): ExpiresAfter = apply { + if (!validated) { + anchor() + days() + validated = true + } + } + fun toBuilder() = Builder().from(this) companion object { @@ -371,8 +452,8 @@ constructor( class Builder { - private var anchor: Anchor? = null - private var days: Long? = null + private var anchor: JsonField? = null + private var days: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -386,10 +467,19 @@ constructor( * Anchor timestamp after which the expiration policy applies. Supported anchors: * `last_active_at`. */ - fun anchor(anchor: Anchor) = apply { this.anchor = anchor } + fun anchor(anchor: Anchor) = anchor(JsonField.of(anchor)) + + /** + * Anchor timestamp after which the expiration policy applies. Supported anchors: + * `last_active_at`. + */ + fun anchor(anchor: JsonField) = apply { this.anchor = anchor } + + /** The number of days after the anchor time that the vector store will expire. */ + fun days(days: Long) = days(JsonField.of(days)) /** The number of days after the anchor time that the vector store will expire. */ - fun days(days: Long) = apply { this.days = days } + fun days(days: JsonField) = apply { this.days = days } fun additionalProperties(additionalProperties: Map) = apply { this.additionalProperties.clear() diff --git a/openai-java-core/src/main/kotlin/com/openai/models/ChatCompletion.kt b/openai-java-core/src/main/kotlin/com/openai/models/ChatCompletion.kt index c87623512..57b4ffe10 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/ChatCompletion.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/ChatCompletion.kt @@ -81,25 +81,27 @@ private constructor( fun usage(): Optional = Optional.ofNullable(usage.getNullable("usage")) /** A unique identifier for the chat completion. */ - @JsonProperty("id") @ExcludeMissing fun _id() = id + @JsonProperty("id") @ExcludeMissing fun _id(): JsonField = id /** A list of chat completion choices. Can be more than one if `n` is greater than 1. */ - @JsonProperty("choices") @ExcludeMissing fun _choices() = choices + @JsonProperty("choices") @ExcludeMissing fun _choices(): JsonField> = choices /** The Unix timestamp (in seconds) of when the chat completion was created. */ - @JsonProperty("created") @ExcludeMissing fun _created() = created + @JsonProperty("created") @ExcludeMissing fun _created(): JsonField = created /** The model used for the chat completion. */ - @JsonProperty("model") @ExcludeMissing fun _model() = model + @JsonProperty("model") @ExcludeMissing fun _model(): JsonField = model /** The object type, which is always `chat.completion`. */ - @JsonProperty("object") @ExcludeMissing fun _object_() = object_ + @JsonProperty("object") @ExcludeMissing fun _object_(): JsonField = object_ /** * The service tier used for processing the request. This field is only included if the * `service_tier` parameter is specified in the request. */ - @JsonProperty("service_tier") @ExcludeMissing fun _serviceTier() = serviceTier + @JsonProperty("service_tier") + @ExcludeMissing + fun _serviceTier(): JsonField = serviceTier /** * This fingerprint represents the backend configuration that the model runs with. @@ -107,10 +109,12 @@ private constructor( * Can be used in conjunction with the `seed` request parameter to understand when backend * changes have been made that might impact determinism. */ - @JsonProperty("system_fingerprint") @ExcludeMissing fun _systemFingerprint() = systemFingerprint + @JsonProperty("system_fingerprint") + @ExcludeMissing + fun _systemFingerprint(): JsonField = systemFingerprint /** Usage statistics for the completion request. */ - @JsonProperty("usage") @ExcludeMissing fun _usage() = usage + @JsonProperty("usage") @ExcludeMissing fun _usage(): JsonField = usage @JsonAnyGetter @ExcludeMissing @@ -141,11 +145,11 @@ private constructor( class Builder { - private var id: JsonField = JsonMissing.of() - private var choices: JsonField> = JsonMissing.of() - private var created: JsonField = JsonMissing.of() - private var model: JsonField = JsonMissing.of() - private var object_: JsonField = JsonMissing.of() + private var id: JsonField? = null + private var choices: JsonField>? = null + private var created: JsonField? = null + private var model: JsonField? = null + private var object_: JsonField? = null private var serviceTier: JsonField = JsonMissing.of() private var systemFingerprint: JsonField = JsonMissing.of() private var usage: JsonField = JsonMissing.of() @@ -154,7 +158,7 @@ private constructor( @JvmSynthetic internal fun from(chatCompletion: ChatCompletion) = apply { id = chatCompletion.id - choices = chatCompletion.choices + choices = chatCompletion.choices.map { it.toMutableList() } created = chatCompletion.created model = chatCompletion.model object_ = chatCompletion.object_ @@ -174,7 +178,23 @@ private constructor( fun choices(choices: List) = choices(JsonField.of(choices)) /** A list of chat completion choices. Can be more than one if `n` is greater than 1. */ - fun choices(choices: JsonField>) = apply { this.choices = choices } + fun choices(choices: JsonField>) = apply { + this.choices = choices.map { it.toMutableList() } + } + + /** A list of chat completion choices. Can be more than one if `n` is greater than 1. */ + fun addChoice(choice: Choice) = apply { + choices = + (choices ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(choice) + } + } /** The Unix timestamp (in seconds) of when the chat completion was created. */ fun created(created: Long) = created(JsonField.of(created)) @@ -198,7 +218,13 @@ private constructor( * The service tier used for processing the request. This field is only included if the * `service_tier` parameter is specified in the request. */ - fun serviceTier(serviceTier: ServiceTier) = serviceTier(JsonField.of(serviceTier)) + fun serviceTier(serviceTier: ServiceTier?) = serviceTier(JsonField.ofNullable(serviceTier)) + + /** + * The service tier used for processing the request. This field is only included if the + * `service_tier` parameter is specified in the request. + */ + fun serviceTier(serviceTier: Optional) = serviceTier(serviceTier.orElse(null)) /** * The service tier used for processing the request. This field is only included if the @@ -254,11 +280,12 @@ private constructor( fun build(): ChatCompletion = ChatCompletion( - id, - choices.map { it.toImmutable() }, - created, - model, - object_, + checkNotNull(id) { "`id` is required but was not set" }, + checkNotNull(choices) { "`choices` is required but was not set" } + .map { it.toImmutable() }, + checkNotNull(created) { "`created` is required but was not set" }, + checkNotNull(model) { "`model` is required but was not set" }, + checkNotNull(object_) { "`object_` is required but was not set" }, serviceTier, systemFingerprint, usage, @@ -311,16 +338,20 @@ private constructor( * flag from our content filters, `tool_calls` if the model called a tool, or * `function_call` (deprecated) if the model called a function. */ - @JsonProperty("finish_reason") @ExcludeMissing fun _finishReason() = finishReason + @JsonProperty("finish_reason") + @ExcludeMissing + fun _finishReason(): JsonField = finishReason /** The index of the choice in the list of choices. */ - @JsonProperty("index") @ExcludeMissing fun _index() = index + @JsonProperty("index") @ExcludeMissing fun _index(): JsonField = index /** Log probability information for the choice. */ - @JsonProperty("logprobs") @ExcludeMissing fun _logprobs() = logprobs + @JsonProperty("logprobs") @ExcludeMissing fun _logprobs(): JsonField = logprobs /** A chat completion message generated by the model. */ - @JsonProperty("message") @ExcludeMissing fun _message() = message + @JsonProperty("message") + @ExcludeMissing + fun _message(): JsonField = message @JsonAnyGetter @ExcludeMissing @@ -347,10 +378,10 @@ private constructor( class Builder { - private var finishReason: JsonField = JsonMissing.of() - private var index: JsonField = JsonMissing.of() - private var logprobs: JsonField = JsonMissing.of() - private var message: JsonField = JsonMissing.of() + private var finishReason: JsonField? = null + private var index: JsonField? = null + private var logprobs: JsonField? = null + private var message: JsonField? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic @@ -389,7 +420,10 @@ private constructor( fun index(index: JsonField) = apply { this.index = index } /** Log probability information for the choice. */ - fun logprobs(logprobs: Logprobs) = logprobs(JsonField.of(logprobs)) + fun logprobs(logprobs: Logprobs?) = logprobs(JsonField.ofNullable(logprobs)) + + /** Log probability information for the choice. */ + fun logprobs(logprobs: Optional) = logprobs(logprobs.orElse(null)) /** Log probability information for the choice. */ fun logprobs(logprobs: JsonField) = apply { this.logprobs = logprobs } @@ -423,10 +457,10 @@ private constructor( fun build(): Choice = Choice( - finishReason, - index, - logprobs, - message, + checkNotNull(finishReason) { "`finishReason` is required but was not set" }, + checkNotNull(index) { "`index` is required but was not set" }, + checkNotNull(logprobs) { "`logprobs` is required but was not set" }, + checkNotNull(message) { "`message` is required but was not set" }, additionalProperties.toImmutable(), ) } @@ -530,10 +564,14 @@ private constructor( Optional.ofNullable(refusal.getNullable("refusal")) /** A list of message content tokens with log probability information. */ - @JsonProperty("content") @ExcludeMissing fun _content() = content + @JsonProperty("content") + @ExcludeMissing + fun _content(): JsonField> = content /** A list of message refusal tokens with log probability information. */ - @JsonProperty("refusal") @ExcludeMissing fun _refusal() = refusal + @JsonProperty("refusal") + @ExcludeMissing + fun _refusal(): JsonField> = refusal @JsonAnyGetter @ExcludeMissing @@ -558,33 +596,69 @@ private constructor( class Builder { - private var content: JsonField> = JsonMissing.of() - private var refusal: JsonField> = JsonMissing.of() + private var content: JsonField>? = null + private var refusal: JsonField>? = null private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(logprobs: Logprobs) = apply { - content = logprobs.content - refusal = logprobs.refusal + content = logprobs.content.map { it.toMutableList() } + refusal = logprobs.refusal.map { it.toMutableList() } additionalProperties = logprobs.additionalProperties.toMutableMap() } /** A list of message content tokens with log probability information. */ - fun content(content: List) = - content(JsonField.of(content)) + fun content(content: List?) = + content(JsonField.ofNullable(content)) + + /** A list of message content tokens with log probability information. */ + fun content(content: Optional>) = + content(content.orElse(null)) /** A list of message content tokens with log probability information. */ fun content(content: JsonField>) = apply { - this.content = content + this.content = content.map { it.toMutableList() } } + /** A list of message content tokens with log probability information. */ + fun addContent(content: ChatCompletionTokenLogprob) = apply { + this.content = + (this.content ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(content) + } + } + + /** A list of message refusal tokens with log probability information. */ + fun refusal(refusal: List?) = + refusal(JsonField.ofNullable(refusal)) + /** A list of message refusal tokens with log probability information. */ - fun refusal(refusal: List) = - refusal(JsonField.of(refusal)) + fun refusal(refusal: Optional>) = + refusal(refusal.orElse(null)) /** A list of message refusal tokens with log probability information. */ fun refusal(refusal: JsonField>) = apply { - this.refusal = refusal + this.refusal = refusal.map { it.toMutableList() } + } + + /** A list of message refusal tokens with log probability information. */ + fun addRefusal(refusal: ChatCompletionTokenLogprob) = apply { + this.refusal = + (this.refusal ?: JsonField.of(mutableListOf())).apply { + asKnown() + .orElseThrow { + IllegalStateException( + "Field was set to non-list type: ${javaClass.simpleName}" + ) + } + .add(refusal) + } } fun additionalProperties(additionalProperties: Map) = apply { @@ -611,8 +685,10 @@ private constructor( fun build(): Logprobs = Logprobs( - content.map { it.toImmutable() }, - refusal.map { it.toImmutable() }, + checkNotNull(content) { "`content` is required but was not set" } + .map { it.toImmutable() }, + checkNotNull(refusal) { "`refusal` is required but was not set" } + .map { it.toImmutable() }, additionalProperties.toImmutable(), ) } diff --git a/openai-java-core/src/main/kotlin/com/openai/models/ChatCompletionAssistantMessageParam.kt b/openai-java-core/src/main/kotlin/com/openai/models/ChatCompletionAssistantMessageParam.kt index 4a1a25f24..debbeecf1 100644 --- a/openai-java-core/src/main/kotlin/com/openai/models/ChatCompletionAssistantMessageParam.kt +++ b/openai-java-core/src/main/kotlin/com/openai/models/ChatCompletionAssistantMessageParam.kt @@ -88,37 +88,41 @@ private constructor( Optional.ofNullable(toolCalls.getNullable("tool_calls")) /** The role of the messages author, in this case `assistant`. */ - @JsonProperty("role") @ExcludeMissing fun _role() = role + @JsonProperty("role") @ExcludeMissing fun _role(): JsonField = role /** * Data about a previous audio response from the model. * [Learn more](https://platform.openai.com/docs/guides/audio). */ - @JsonProperty("audio") @ExcludeMissing fun _audio() = audio + @JsonProperty("audio") @ExcludeMissing fun _audio(): JsonField