From 7f3b85bebe37c8ef63618bf3143f18dedeb97fae Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Mon, 24 Jun 2024 15:47:13 +0200 Subject: [PATCH 1/8] Integrate OpenAPI-kt generated client --- core/build.gradle.kts | 8 +- .../generator/config => core}/openai-api.yaml | 0 .../kotlin/com/xebia/functional/xef/AI.kt | 12 +- .../kotlin/com/xebia/functional/xef/Config.kt | 17 +- .../com/xebia/functional/xef/DefaultAI.kt | 29 +- .../com/xebia/functional/xef/llm/Chat.kt | 10 +- .../functional/xef/llm/ChatWithFunctions.kt | 15 +- .../xebia/functional/xef/llm/Embeddings.kt | 14 +- .../com/xebia/functional/xef/llm/LLM.kt | 2 +- .../functional/xef/llm/MemoryManagement.kt | 14 +- .../functional/xef/llm/MetricManagement.kt | 6 +- .../functional/xef/llm/PromptCalculator.kt | 2 +- .../functional/xef/llm/StreamedFunction.kt | 15 +- .../com/xebia/functional/xef/llm/Vision.kt | 13 +- .../xef/llm/assistants/Assistant.kt | 50 +-- .../xef/llm/assistants/AssistantThread.kt | 96 +++--- .../functional/xef/llm/assistants/RunDelta.kt | 15 +- .../functional/xef/llm/assistants/Tool.kt | 2 +- .../functional/xef/llm/models/OpenAIClient.kt | 8 +- .../functional/xef/metrics/LogsMetric.kt | 6 +- .../xebia/functional/xef/metrics/Metric.kt | 6 +- .../xef/prompt/PlatformPromptBuilder.kt | 10 +- .../com/xebia/functional/xef/prompt/Prompt.kt | 14 +- .../functional/xef/prompt/PromptBuilder.kt | 38 +-- .../configuration/PromptConfiguration.kt | 4 +- .../xef/store/CombinedVectorStore.kt | 6 +- .../functional/xef/store/LocalVectorStore.kt | 13 +- .../functional/xef/store/MemorizedMessage.kt | 23 +- .../xebia/functional/xef/store/VectorStore.kt | 8 +- .../xef/conversation/ConversationSpec.kt | 2 +- .../xebia/functional/xef/data/TestChatApi.kt | 2 +- .../functional/xef/data/TestEmbeddings.kt | 6 +- .../xef/prompt/PromptBuilderSpec.kt | 2 +- .../xef/store/CombinedVectorStoreSpec.kt | 2 +- .../xef/store/LocalVectorStoreSpec.kt | 2 +- .../xebia/functional/xef/store/MemoryData.kt | 8 +- evaluator/build.gradle.kts | 1 - .../functional/xef/evaluator/SuiteBuilder.kt | 2 +- .../xef/assistants/AssistantStreaming.kt | 2 +- .../xef/conversation/conversations/Animal.kt | 2 +- .../functional/xef/dsl/audio/SimpleSpeech.kt | 6 +- .../xebia/functional/xef/dsl/chat/Classes.kt | 2 +- .../xef/dsl/classify/AnswerAccuracy.kt | 2 +- .../xef/dsl/images/ImagesExamples.kt | 2 +- .../functional/xef/evaluator/TestExample.kt | 2 +- .../OpenTelemetryAssistantState.kt | 2 +- .../xef/opentelemetry/OpenTelemetryMetric.kt | 6 +- .../xef/store/PostgreSQLVectorStore.kt | 8 +- .../src/test/kotlin/xef/MemoryData.kt | 8 +- .../src/test/kotlin/xef/PGVectorStoreSpec.kt | 6 +- .../src/test/kotlin/xef/TestEmbeddings.kt | 2 +- .../com/xebia/functional/xef/sql/SQL.kt | 2 +- .../functional/xef/sql/jdbc/JdbcConfig.kt | 2 +- .../client/.openapi-generator-ignore | 15 - openai-client/client/build.gradle.kts | 138 -------- .../xebia/functional/openai/AssistantEvent.kt | 8 - .../com/xebia/functional/openai/Config.kt | 12 - .../xebia/functional/openai/FormBuilderOps.kt | 39 --- .../com/xebia/functional/openai/OneOfOps.kt | 53 --- .../functional/openai/ServerSentEvent.kt | 10 - .../xebia/functional/openai/StreamingOps.kt | 59 ---- .../com/xebia/functional/openai/UploadFile.kt | 11 - .../generator/.openapi-generator-ignore | 7 - openai-client/generator/README.md | 77 ----- openai-client/generator/build.gradle.kts | 42 --- openai-client/generator/config/api.mustache | 193 ----------- .../generator/config/data_class.mustache | 68 ---- .../config/data_class_opt_var.mustache | 7 - .../config/data_class_req_var.mustache | 7 - .../generator/config/enum_class.mustache | 53 --- openai-client/generator/config/model.mustache | 17 - .../generator/config/model_oneof.mustache | 41 --- .../generator/config/openai-api-commit | 1 - .../generator/config/openai.mustache | 26 -- openai-client/generator/gradle.properties | 1 - .../openai/generator/DownloadOpenAIAPI.java | 40 --- .../openai/generator/KMMGeneratorConfig.java | 308 ------------------ .../services/PostgresVectorStoreService.kt | 2 +- settings.gradle.kts | 8 +- 79 files changed, 269 insertions(+), 1511 deletions(-) rename {openai-client/generator/config => core}/openai-api.yaml (100%) delete mode 100644 openai-client/client/.openapi-generator-ignore delete mode 100644 openai-client/client/build.gradle.kts delete mode 100644 openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/AssistantEvent.kt delete mode 100644 openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/Config.kt delete mode 100644 openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/FormBuilderOps.kt delete mode 100644 openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/OneOfOps.kt delete mode 100644 openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/ServerSentEvent.kt delete mode 100644 openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/StreamingOps.kt delete mode 100644 openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/UploadFile.kt delete mode 100644 openai-client/generator/.openapi-generator-ignore delete mode 100644 openai-client/generator/README.md delete mode 100644 openai-client/generator/build.gradle.kts delete mode 100644 openai-client/generator/config/api.mustache delete mode 100644 openai-client/generator/config/data_class.mustache delete mode 100644 openai-client/generator/config/data_class_opt_var.mustache delete mode 100644 openai-client/generator/config/data_class_req_var.mustache delete mode 100644 openai-client/generator/config/enum_class.mustache delete mode 100644 openai-client/generator/config/model.mustache delete mode 100644 openai-client/generator/config/model_oneof.mustache delete mode 100644 openai-client/generator/config/openai-api-commit delete mode 100644 openai-client/generator/config/openai.mustache delete mode 100644 openai-client/generator/gradle.properties delete mode 100644 openai-client/generator/src/main/java/ai/xef/openai/generator/DownloadOpenAIAPI.java delete mode 100644 openai-client/generator/src/main/java/ai/xef/openai/generator/KMMGeneratorConfig.java diff --git a/core/build.gradle.kts b/core/build.gradle.kts index de1530459..378f77f2b 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -16,6 +16,11 @@ plugins { alias(libs.plugins.arrow.gradle.publish) alias(libs.plugins.semver.gradle) alias(libs.plugins.detekt) + id("io.github.nomisrev.openapi-kt-plugin") version "0.0.2" +} + +openApiConfig { + spec.set(file("openai-api.yaml")) } dependencies { @@ -66,13 +71,14 @@ kotlin { languageSettings.optIn("kotlin.ExperimentalStdlibApi") } val commonMain by getting { + kotlin.srcDir(project.file("build/generated/openapi/src/commonMain/kotlin")) + dependencies { api(libs.bundles.arrow) api(libs.kotlinx.serialization.json) api(libs.kotlinx.serialization.yaml) api(libs.ktor.utils) api(projects.xefTokenizer) - api(projects.xefOpenaiClient) implementation(libs.bundles.ktor.client) implementation(libs.klogging) implementation(libs.uuid) diff --git a/openai-client/generator/config/openai-api.yaml b/core/openai-api.yaml similarity index 100% rename from openai-client/generator/config/openai-api.yaml rename to core/openai-api.yaml diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/AI.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/AI.kt index 81276970b..ebe7f6f79 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/AI.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/AI.kt @@ -1,11 +1,11 @@ package com.xebia.functional.xef -import com.xebia.functional.openai.generated.api.Chat -import com.xebia.functional.openai.generated.api.Images -import com.xebia.functional.openai.generated.model.CreateChatCompletionRequestModel import com.xebia.functional.xef.conversation.AiDsl import com.xebia.functional.xef.conversation.Conversation import com.xebia.functional.xef.prompt.Prompt +import io.github.nomisrev.openapi.Chat +import io.github.nomisrev.openapi.CreateChatCompletionRequest +import io.github.nomisrev.openapi.Images import kotlin.coroutines.cancellation.CancellationException import kotlin.reflect.KClass import kotlin.reflect.KType @@ -26,7 +26,7 @@ sealed interface AI { fun chat( target: KType, - model: CreateChatCompletionRequestModel, + model: CreateChatCompletionRequest.Model, api: Chat, conversation: Conversation, enumSerializer: ((case: String) -> A)?, @@ -86,7 +86,7 @@ sealed interface AI { input: String, output: String, context: String, - model: CreateChatCompletionRequestModel = CreateChatCompletionRequestModel.gpt_4_1106_preview, + model: CreateChatCompletionRequest.Model = CreateChatCompletionRequest.Model.Gpt41106Preview, target: KType = typeOf(), config: Config = Config(), api: Chat = OpenAI(config).chat, @@ -107,7 +107,7 @@ sealed interface AI { suspend inline operator fun invoke( prompt: String, target: KType = typeOf(), - model: CreateChatCompletionRequestModel = CreateChatCompletionRequestModel.gpt_3_5_turbo_0125, + model: CreateChatCompletionRequest.Model = CreateChatCompletionRequest.Model.Gpt35Turbo0125, config: Config = Config(), api: Chat = OpenAI(config).chat, conversation: Conversation = Conversation() diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/Config.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/Config.kt index 4645fbd4f..76814d73f 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/Config.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/Config.kt @@ -1,9 +1,8 @@ package com.xebia.functional.xef import arrow.core.nonEmptyListOf -import com.xebia.functional.openai.Config as OpenAIConfig -import com.xebia.functional.openai.generated.api.OpenAI import com.xebia.functional.xef.env.getenv +import io.github.nomisrev.openapi.OpenAPI import io.ktor.client.* import io.ktor.client.engine.* import io.ktor.client.plugins.* @@ -46,7 +45,7 @@ fun OpenAI( httpClientEngine: HttpClientEngine? = null, httpClientConfig: ((HttpClientConfig<*>) -> Unit)? = null, logRequests: Boolean = false -): OpenAI { +): OpenAPI { val token = config.token ?: getenv(KEY_ENV_VAR) @@ -73,15 +72,5 @@ fun OpenAI( } } val client = httpClientEngine?.let { HttpClient(it, clientConfig) } ?: HttpClient(clientConfig) - return OpenAI( - client, - OpenAIConfig( - baseUrl = config.baseUrl, - token = token, - org = config.org, - json = config.json, - streamingPrefix = config.streamingPrefix, - streamingDelimiter = config.streamingDelimiter - ) - ) + return OpenAPI(client) } diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/DefaultAI.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/DefaultAI.kt index 4d3b1b9cd..31f2b6932 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/DefaultAI.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/DefaultAI.kt @@ -1,24 +1,25 @@ package com.xebia.functional.xef -import com.xebia.functional.openai.generated.api.Chat -import com.xebia.functional.openai.generated.model.CreateChatCompletionRequest -import com.xebia.functional.openai.generated.model.CreateChatCompletionRequestModel import com.xebia.functional.xef.conversation.Conversation import com.xebia.functional.xef.llm.StreamedFunction import com.xebia.functional.xef.llm.models.modelType import com.xebia.functional.xef.llm.prompt import com.xebia.functional.xef.llm.promptStreaming import com.xebia.functional.xef.prompt.Prompt +import io.github.nomisrev.openapi.Chat +import io.github.nomisrev.openapi.CreateChatCompletionRequest import kotlin.reflect.KClass import kotlin.reflect.KType import kotlin.reflect.typeOf import kotlinx.coroutines.flow.Flow import kotlinx.serialization.* import kotlinx.serialization.descriptors.* +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.JsonPrimitive data class DefaultAI( val target: KType, - val model: CreateChatCompletionRequestModel, + val model: CreateChatCompletionRequest.Model, val api: Chat, val serializer: () -> KSerializer, val conversation: Conversation, @@ -88,17 +89,19 @@ data class DefaultAI( val cases = serializer.descriptor.elementDescriptors.map { it.serialName.substringAfterLast(".") } val logitBias = - cases - .flatMap { - val result = encoding.encode(it) - if (result.size > 1) { - error("Cannot encode enum case $it into one token") + JsonObject( + cases + .flatMap { + val result = encoding.encode(it) + if (result.size > 1) { + error("Cannot encode enum case $it into one token") + } + result } - result - } - .associate { "$it" to 100 } + .associate { "$it" to JsonPrimitive(100) } + ) val result = - api.createChatCompletion( + api.completions.createChatCompletion( CreateChatCompletionRequest( messages = prompt.messages, model = model, diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/Chat.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/Chat.kt index 3dc16adb8..c39d534f9 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/Chat.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/Chat.kt @@ -1,12 +1,12 @@ package com.xebia.functional.xef.llm -import com.xebia.functional.openai.generated.api.Chat -import com.xebia.functional.openai.generated.model.CreateChatCompletionRequest import com.xebia.functional.xef.AIError import com.xebia.functional.xef.conversation.AiDsl import com.xebia.functional.xef.conversation.Conversation import com.xebia.functional.xef.prompt.Prompt import com.xebia.functional.xef.prompt.PromptBuilder +import io.github.nomisrev.openapi.Chat +import io.github.nomisrev.openapi.CreateChatCompletionRequest import kotlinx.coroutines.flow.* @AiDsl @@ -28,7 +28,8 @@ fun Chat.promptStreaming(prompt: Prompt, scope: Conversation = Conversation()): val buffer = StringBuilder() - this@promptStreaming.createChatCompletionStream(request) + completions + .createChatCompletionStream(request) .mapNotNull { val content = it.choices.firstOrNull()?.delta?.content if (content != null) { @@ -72,7 +73,8 @@ suspend fun Chat.promptMessages( seed = adaptedPrompt.configuration.seed, ) - createChatCompletion(request) + completions + .createChatCompletion(request) .addMetrics(scope) .choices .addChoiceToMemory( diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/ChatWithFunctions.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/ChatWithFunctions.kt index e2d081397..f5d7b389b 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/ChatWithFunctions.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/ChatWithFunctions.kt @@ -2,13 +2,13 @@ package com.xebia.functional.xef.llm import arrow.core.nonFatalOrThrow import arrow.core.raise.catch -import com.xebia.functional.openai.generated.api.Chat -import com.xebia.functional.openai.generated.model.* import com.xebia.functional.xef.AIError import com.xebia.functional.xef.conversation.AiDsl import com.xebia.functional.xef.conversation.Conversation import com.xebia.functional.xef.llm.models.functions.buildJsonSchema import com.xebia.functional.xef.prompt.Prompt +import io.github.nomisrev.openapi.* +import io.github.nomisrev.openapi.ChatCompletionToolChoiceOption.NoneOrAuto import io.github.oshai.kotlinlogging.KotlinLogging import kotlinx.coroutines.flow.* import kotlinx.serialization.ExperimentalSerializationApi @@ -85,7 +85,8 @@ suspend fun Chat.prompt( val request = createChatCompletionRequest(adaptedPrompt) tryDeserialize(serializer, promptWithFunctions.configuration.maxDeserializationAttempts) { val requestedMemories = prompt.messages.toMemory(scope) - createChatCompletion(request) + completions + .createChatCompletion(request) .addMetrics(scope) .choices .addChoiceWithFunctionsToMemory( @@ -120,15 +121,15 @@ private fun chatCompletionToolChoiceOption(adaptedPrompt: Prompt): ChatCompletio if (adaptedPrompt.functions.size == 1) ChatCompletionToolChoiceOption.CaseChatCompletionNamedToolChoice( ChatCompletionNamedToolChoice( - type = ChatCompletionNamedToolChoice.Type.function, - function = ChatCompletionNamedToolChoiceFunction(adaptedPrompt.functions.first().name) + type = ChatCompletionNamedToolChoice.Type.Function, + function = ChatCompletionNamedToolChoice.Function(adaptedPrompt.functions.first().name) ) ) - else ChatCompletionToolChoiceOption.CaseString("auto") + else ChatCompletionToolChoiceOption.CaseNoneOrAuto(NoneOrAuto.Auto) private fun chatCompletionTools(adaptedPrompt: Prompt): List = adaptedPrompt.functions.map { - ChatCompletionTool(type = ChatCompletionTool.Type.function, function = it) + ChatCompletionTool(type = ChatCompletionTool.Type.Function, function = it) } @AiDsl diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/Embeddings.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/Embeddings.kt index 981d52fa5..0c87dd0a0 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/Embeddings.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/Embeddings.kt @@ -1,17 +1,13 @@ package com.xebia.functional.xef.llm import arrow.fx.coroutines.parMap -import com.xebia.functional.openai.generated.api.Embeddings -import com.xebia.functional.openai.generated.model.CreateEmbeddingRequest -import com.xebia.functional.openai.generated.model.CreateEmbeddingRequestInput -import com.xebia.functional.openai.generated.model.CreateEmbeddingRequestModel -import com.xebia.functional.openai.generated.model.Embedding +import io.github.nomisrev.openapi.* suspend fun Embeddings.embedDocuments( texts: List, chunkSize: Int = 400, - embeddingRequestModel: CreateEmbeddingRequestModel = - CreateEmbeddingRequestModel.text_embedding_ada_002 + embeddingRequestModel: CreateEmbeddingRequest.Model = + CreateEmbeddingRequest.Model.TextEmbeddingAda002 ): List = if (texts.isEmpty()) emptyList() else @@ -21,7 +17,7 @@ suspend fun Embeddings.embedDocuments( createEmbedding( CreateEmbeddingRequest( model = embeddingRequestModel, - input = CreateEmbeddingRequestInput.CaseStrings(it) + input = CreateEmbeddingRequest.Input.CaseStrings(it) ) ) .data @@ -30,7 +26,7 @@ suspend fun Embeddings.embedDocuments( suspend fun Embeddings.embedQuery( text: String, - embeddingRequestModel: CreateEmbeddingRequestModel + embeddingRequestModel: CreateEmbeddingRequest.Model ): List = if (text.isNotEmpty()) embedDocuments(texts = listOf(text), embeddingRequestModel = embeddingRequestModel) diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/LLM.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/LLM.kt index 928de8425..479bc245f 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/LLM.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/LLM.kt @@ -1,10 +1,10 @@ package com.xebia.functional.xef.llm -import com.xebia.functional.openai.generated.model.ChatCompletionRequestMessage import com.xebia.functional.tokenizer.Encoding import com.xebia.functional.tokenizer.ModelType import com.xebia.functional.xef.prompt.completionRole import com.xebia.functional.xef.prompt.contentAsString +import io.github.nomisrev.openapi.ChatCompletionRequestMessage fun ModelType.tokensFromMessages( messages: List, diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/MemoryManagement.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/MemoryManagement.kt index 9ea8a63ed..b134837d9 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/MemoryManagement.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/MemoryManagement.kt @@ -1,12 +1,12 @@ package com.xebia.functional.xef.llm -import com.xebia.functional.openai.generated.model.* import com.xebia.functional.xef.conversation.Conversation import com.xebia.functional.xef.conversation.MessagesToHistory import com.xebia.functional.xef.store.ConversationId import com.xebia.functional.xef.store.MemorizedMessage import com.xebia.functional.xef.store.Memory import com.xebia.functional.xef.store.VectorStore +import io.github.nomisrev.openapi.* internal suspend fun List.addToMemory( scope: Conversation, @@ -32,11 +32,11 @@ internal fun List.toMemory(scope: Conversation): L } else emptyList() } -internal suspend fun List.addChoiceWithFunctionsToMemory( +internal suspend fun List.addChoiceWithFunctionsToMemory( scope: Conversation, previousMemories: List, history: MessagesToHistory -): List = also { +): List = also { val cid = scope.conversationId if (history != MessagesToHistory.NONE && isNotEmpty() && cid != null) { val aiMemory = this.map { it.message.toMemory(cid, scope.store.incrementIndexAndGet()) } @@ -45,11 +45,11 @@ internal suspend fun List.addChoiceWit } } -internal suspend fun List.addChoiceToMemory( +internal suspend fun List.addChoiceToMemory( scope: Conversation, previousMemories: List, history: MessagesToHistory -): List = also { +): List = also { val cid = scope.conversationId if (history != MessagesToHistory.NONE && isNotEmpty() && cid != null) { val aiMemory = @@ -65,10 +65,10 @@ suspend fun VectorStore.addMemoriesByHistory(history: MessagesToHistory, memorie addMemories(memories) } MessagesToHistory.ONLY_SYSTEM_MESSAGES -> { - addMemories(memories.filter { it.content.role == ChatCompletionRole.system }) + addMemories(memories.filter { it.content.role == ChatCompletionRole.System }) } MessagesToHistory.NOT_SYSTEM_MESSAGES -> { - addMemories(memories.filter { it.content.role != ChatCompletionRole.system }) + addMemories(memories.filter { it.content.role != ChatCompletionRole.System }) } MessagesToHistory.NONE -> {} } diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/MetricManagement.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/MetricManagement.kt index c98eb8ae6..92ea48741 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/MetricManagement.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/MetricManagement.kt @@ -1,14 +1,14 @@ package com.xebia.functional.xef.llm -import com.xebia.functional.openai.generated.model.CreateChatCompletionResponse -import com.xebia.functional.openai.generated.model.RunObject -import com.xebia.functional.openai.generated.model.RunStepObject import com.xebia.functional.xef.conversation.Conversation import com.xebia.functional.xef.llm.assistants.RunDelta import com.xebia.functional.xef.metrics.Metric import com.xebia.functional.xef.prompt.Prompt import com.xebia.functional.xef.prompt.completionRole import com.xebia.functional.xef.prompt.contentAsString +import io.github.nomisrev.openapi.CreateChatCompletionResponse +import io.github.nomisrev.openapi.RunObject +import io.github.nomisrev.openapi.RunStepObject suspend fun CreateChatCompletionResponse.addMetrics( conversation: Conversation diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/PromptCalculator.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/PromptCalculator.kt index b50051eee..41c8698ca 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/PromptCalculator.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/PromptCalculator.kt @@ -1,6 +1,5 @@ package com.xebia.functional.xef.llm -import com.xebia.functional.openai.generated.model.ChatCompletionRequestMessage import com.xebia.functional.tokenizer.truncateText import com.xebia.functional.xef.AIError import com.xebia.functional.xef.conversation.Conversation @@ -10,6 +9,7 @@ import com.xebia.functional.xef.prompt.Prompt import com.xebia.functional.xef.prompt.PromptBuilder.Companion.assistant import com.xebia.functional.xef.prompt.contentAsString import com.xebia.functional.xef.store.Memory +import io.github.nomisrev.openapi.ChatCompletionRequestMessage internal object PromptCalculator { diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/StreamedFunction.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/StreamedFunction.kt index cd14ebef4..839f1bf38 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/StreamedFunction.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/StreamedFunction.kt @@ -1,11 +1,10 @@ package com.xebia.functional.xef.llm -import com.xebia.functional.openai.generated.api.Chat -import com.xebia.functional.openai.generated.model.* import com.xebia.functional.xef.conversation.Conversation import com.xebia.functional.xef.llm.StreamedFunction.Companion.PropertyType.* import com.xebia.functional.xef.prompt.Prompt import com.xebia.functional.xef.prompt.PromptBuilder +import io.github.nomisrev.openapi.* import kotlin.jvm.JvmSynthetic import kotlinx.coroutines.flow.FlowCollector import kotlinx.coroutines.flow.onCompletion @@ -48,7 +47,7 @@ sealed class StreamedFunction { ) { val messages = mutableListOf() // this function call is mutable and will be updated as the stream progresses - var functionCall = ChatCompletionMessageToolCallFunction("", "") + var functionCall = ChatCompletionMessageToolCall.Function("", "") // the current property is mutable and will be updated as the stream progresses var currentProperty: String? = null // we keep track to not emit the same property multiple times @@ -61,7 +60,7 @@ sealed class StreamedFunction { // as the LLM is sending us chunks with malformed JSON if (schema != null) { val example = createExampleFromSchema(schema) - chat + chat.completions .createChatCompletionStream(request) .onCompletion { val newMessages = prompt.messages + messages @@ -128,7 +127,7 @@ sealed class StreamedFunction { } private suspend fun FlowCollector>.streamResult( - functionCall: ChatCompletionMessageToolCallFunction, + functionCall: ChatCompletionMessageToolCall.Function, messages: MutableList, serializer: (json: String) -> A ) { @@ -290,13 +289,13 @@ sealed class StreamedFunction { } private fun mergeArgumentsWithDelta( - functionCall: ChatCompletionMessageToolCallFunction, + functionCall: ChatCompletionMessageToolCall.Function, functionCall0: ChatCompletionMessageToolCallChunk - ): ChatCompletionMessageToolCallFunction = + ): ChatCompletionMessageToolCall.Function = functionCall.copy(arguments = functionCall.arguments + (functionCall0.function?.arguments)) private fun getLastReferencedPropertyInArguments( - functionCall: ChatCompletionMessageToolCallFunction + functionCall: ChatCompletionMessageToolCall.Function ): String? = """"(.*?)":""" .toRegex() diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/Vision.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/Vision.kt index bf5b10e95..4daf99515 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/Vision.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/Vision.kt @@ -1,13 +1,10 @@ package com.xebia.functional.xef.llm -import com.xebia.functional.openai.UploadFile -import com.xebia.functional.openai.generated.api.Chat -import com.xebia.functional.openai.generated.model.CreateChatCompletionRequestModel -import com.xebia.functional.openai.generated.model.Image import com.xebia.functional.xef.conversation.Conversation import com.xebia.functional.xef.prompt.Prompt import com.xebia.functional.xef.prompt.PromptBuilder.Companion.image import com.xebia.functional.xef.prompt.PromptBuilder.Companion.user +import io.github.nomisrev.openapi.* import io.ktor.client.* import io.ktor.client.call.* import io.ktor.client.request.* @@ -20,9 +17,9 @@ suspend inline fun Chat.visionStructured( prompt: String, url: String, conversation: Conversation = Conversation(), - model: CreateChatCompletionRequestModel = CreateChatCompletionRequestModel.gpt_4_vision_preview, - functionsModel: CreateChatCompletionRequestModel = - CreateChatCompletionRequestModel.gpt_3_5_turbo_0125 + model: CreateChatCompletionRequest.Model = CreateChatCompletionRequest.Model.Gpt4VisionPreview, + functionsModel: CreateChatCompletionRequest.Model = + CreateChatCompletionRequest.Model.Gpt35Turbo0125 ): A { val response = vision(prompt, url, model, conversation).toList().joinToString("") { it } return prompt(Prompt(functionsModel) { +user(response) }, conversation, serializer()) @@ -31,7 +28,7 @@ suspend inline fun Chat.visionStructured( fun Chat.vision( prompt: String, url: String, - model: CreateChatCompletionRequestModel = CreateChatCompletionRequestModel.gpt_4_vision_preview, + model: CreateChatCompletionRequest.Model = CreateChatCompletionRequest.Model.Gpt4VisionPreview, conversation: Conversation = Conversation() ): Flow = promptStreaming(prompt = Prompt(model) { +image(url, prompt) }, scope = conversation) diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/Assistant.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/Assistant.kt index 48053d436..3d2f15e83 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/Assistant.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/Assistant.kt @@ -1,11 +1,10 @@ package com.xebia.functional.xef.llm.assistants -import com.xebia.functional.openai.generated.api.Assistants -import com.xebia.functional.openai.generated.model.* import com.xebia.functional.xef.Config import com.xebia.functional.xef.OpenAI import com.xebia.functional.xef.llm.assistants.AssistantThread.Companion.defaultConfig import com.xebia.functional.xef.llm.models.functions.buildJsonSchema +import io.github.nomisrev.openapi.* import io.ktor.util.logging.* import kotlinx.serialization.KSerializer import kotlinx.serialization.Serializable @@ -74,11 +73,11 @@ class Assistant( @Serializable data class ToolOutput(val schema: JsonObject, val result: JsonElement) suspend operator fun invoke( - model: String, + model: CreateAssistantRequest.Model, name: String? = null, description: String? = null, instructions: String? = null, - tools: List = arrayListOf(), + tools: List = arrayListOf(), fileIds: List = arrayListOf(), metadata: JsonObject? = null, toolsConfig: List> = emptyList(), @@ -150,7 +149,7 @@ class Assistant( functionObject.name, functionObject.description ?: "", functionObject.parameters?.let { el -> - Json.encodeToString(JsonObject.serializer(), el) + Json.encodeToString(JsonElement.serializer(), el) } ?: "" ) } else { @@ -178,11 +177,17 @@ class Assistant( assistant.modify( ModifyAssistantRequest( - model = assistantRequest.model, + model = ModifyAssistantRequest.Model.CaseString(assistantRequest.model), name = assistantRequest.name, description = assistantRequest.description, instructions = assistantRequest.instructions, - tools = assistantTools(assistantRequest), + tools = + assistantTools( + assistantRequest, + code = ModifyAssistantRequest.Tools::CaseAssistantToolsCode, + retrieval = ModifyAssistantRequest.Tools::CaseAssistantToolsRetrieval, + function = ModifyAssistantRequest.Tools::CaseAssistantToolsFunction + ), fileIds = assistantRequest.fileIds, metadata = null // assistantRequest.metadata ) @@ -191,11 +196,17 @@ class Assistant( Assistant( request = CreateAssistantRequest( - model = assistantRequest.model, + model = CreateAssistantRequest.Model.CaseString(assistantRequest.model), name = assistantRequest.name, description = assistantRequest.description, instructions = assistantRequest.instructions, - tools = assistantTools(assistantRequest), + tools = + assistantTools( + assistantRequest, + code = CreateAssistantRequest.Tools::CaseAssistantToolsCode, + retrieval = CreateAssistantRequest.Tools::CaseAssistantToolsRetrieval, + function = CreateAssistantRequest.Tools::CaseAssistantToolsFunction + ), fileIds = assistantRequest.fileIds, metadata = null // assistantRequest.metadata ), @@ -205,23 +216,22 @@ class Assistant( ) } - private fun assistantTools( - assistantRequest: AssistantRequest - ): List = + private fun assistantTools( + assistantRequest: AssistantRequest, + code: (AssistantToolsCode) -> A, + retrieval: (AssistantToolsRetrieval) -> A, + function: (AssistantToolsFunction) -> A + ): List = assistantRequest.tools.orEmpty().map { when (it) { is AssistantTool.CodeInterpreter -> - AssistantObjectToolsInner.CaseAssistantToolsCode( - AssistantToolsCode(type = AssistantToolsCode.Type.code_interpreter) - ) + code(AssistantToolsCode(type = AssistantToolsCode.Type.CodeInterpreter)) is AssistantTool.Retrieval -> - AssistantObjectToolsInner.CaseAssistantToolsRetrieval( - AssistantToolsRetrieval(type = AssistantToolsRetrieval.Type.retrieval) - ) + retrieval(AssistantToolsRetrieval(type = AssistantToolsRetrieval.Type.Retrieval)) is AssistantTool.Function -> - AssistantObjectToolsInner.CaseAssistantToolsFunction( + function( AssistantToolsFunction( - type = AssistantToolsFunction.Type.function, + type = AssistantToolsFunction.Type.Function, function = FunctionObject( name = it.name, diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/AssistantThread.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/AssistantThread.kt index 9f6851d49..9dbffcbc7 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/AssistantThread.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/AssistantThread.kt @@ -1,12 +1,11 @@ package com.xebia.functional.xef.llm.assistants import arrow.fx.coroutines.parMapNotNull -import com.xebia.functional.openai.generated.api.Assistants -import com.xebia.functional.openai.generated.model.* import com.xebia.functional.xef.Config import com.xebia.functional.xef.OpenAI import com.xebia.functional.xef.llm.addMetrics import com.xebia.functional.xef.metrics.Metric +import io.github.nomisrev.openapi.* import io.ktor.client.request.* import kotlin.jvm.JvmName import kotlinx.coroutines.flow.* @@ -18,37 +17,37 @@ class AssistantThread( val threadId: String, val metric: Metric = Metric.EMPTY, private val config: Config = Config(), - private val api: Assistants = OpenAI(config).assistants + private val api: OpenAPI = OpenAI(config) ) { suspend fun delete(): Boolean = - api.deleteThread(threadId = threadId, configure = ::defaultConfig).deleted + api.threads.deleteThread(threadId = threadId, configure = ::defaultConfig).deleted suspend fun modify(request: ModifyThreadRequest): AssistantThread = - AssistantThread(api.modifyThread(threadId, request, configure = ::defaultConfig).id) + AssistantThread(api.threads.modifyThread(threadId, request, configure = ::defaultConfig).id) suspend fun createMessage(message: MessageWithFiles): MessageObject = createMessage( request = CreateMessageRequest( - role = CreateMessageRequest.Role.user, + role = CreateMessageRequest.Role.User, content = message.content, fileIds = message.fileIds ), ) suspend fun createMessage(content: String): MessageObject = - createMessage(CreateMessageRequest(role = CreateMessageRequest.Role.user, content = content)) + createMessage(CreateMessageRequest(role = CreateMessageRequest.Role.User, content = content)) suspend fun createMessage(request: CreateMessageRequest): MessageObject = - api.createMessage(threadId, request, configure = ::defaultConfig) + api.threads.messages.createMessage(threadId, request, configure = ::defaultConfig) suspend fun getMessage(messageId: String): MessageObject = - api.getMessage(threadId, messageId, configure = ::defaultConfig) + api.threads.messages.getMessage(threadId, messageId, configure = ::defaultConfig) data class ThreadMessagesFilter( val limit: Int? = 20, - val order: Assistants.OrderListMessages? = Assistants.OrderListMessages.desc, + val order: Threads.Messages.ListMessagesOrder = Threads.Messages.ListMessagesOrder.Desc, val after: String? = null, val before: String? = null ) @@ -56,7 +55,7 @@ class AssistantThread( suspend fun listMessages( filter: ThreadMessagesFilter = ThreadMessagesFilter() ): List = - api + api.threads.messages .listMessages( threadId = threadId, limit = filter.limit, @@ -71,10 +70,10 @@ class AssistantThread( createRun(CreateRunRequest(assistantId = assistant.assistantId)) suspend fun createRun(request: CreateRunRequest): RunObject = - api.createRun(threadId, request, configure = ::defaultConfig).addMetrics(metric) + api.threads.runs.createRun(threadId, request, configure = ::defaultConfig).addMetrics(metric) fun createRunStream(assistant: Assistant, request: CreateRunRequest): Flow = flow { - api + api.threads.runs .createRunStream(threadId, request, configure = ::defaultConfig) .map { RunDelta.fromServerSentEvent(it) } .map { it.addMetrics(metric) } @@ -100,8 +99,8 @@ class AssistantThread( flowCollector: FlowCollector ) { if ( - event.run.status == RunObject.Status.requires_action && - event.run.requiredAction?.type == RunObjectRequiredAction.Type.submit_tool_outputs + event.run.status == RunObject.Status.RequiresAction && + event.run.requiredAction?.type == RunObject.RequiredAction.Type.SubmitToolOutputs ) { val calls = event.run.requiredAction?.submitToolOutputs?.toolCalls.orEmpty() val callsResult: List> = @@ -111,7 +110,7 @@ class AssistantThread( SubmitToolOutputsRunRequest( toolOutputs = results.map { (toolCallId, result) -> - SubmitToolOutputsRunRequestToolOutputsInner( + SubmitToolOutputsRunRequest.ToolOutputs( toolCallId = toolCallId, output = Json.encodeToString(Assistant.Companion.ToolOutput.serializer(), result) ) @@ -119,11 +118,11 @@ class AssistantThread( ) val run = metric.assistantToolOutputsRun(event.run.id) { - api + api.threads.runs.submitToolOutputs .submitToolOuputsToRunStream( threadId = threadId, runId = event.run.id, - submitToolOutputsRunRequest = toolOutputsRequest, + body = toolOutputsRequest, configure = ::defaultConfig ) .collect { @@ -136,20 +135,20 @@ class AssistantThread( val run = getRun(event.run.id) val finalEvent = when (run.status) { - RunObject.Status.queued -> RunDelta.RunQueued(run) - RunObject.Status.in_progress -> RunDelta.RunInProgress(run) - RunObject.Status.requires_action -> RunDelta.RunRequiresAction(run) - RunObject.Status.cancelling -> RunDelta.RunCancelling(run) - RunObject.Status.cancelled -> RunDelta.RunCancelled(run) - RunObject.Status.failed -> RunDelta.RunFailed(run) - RunObject.Status.completed -> RunDelta.RunCompleted(run) - RunObject.Status.expired -> RunDelta.RunExpired(run) + RunObject.Status.Queued -> RunDelta.RunQueued(run) + RunObject.Status.InProgress -> RunDelta.RunInProgress(run) + RunObject.Status.RequiresAction -> RunDelta.RunRequiresAction(run) + RunObject.Status.Cancelling -> RunDelta.RunCancelling(run) + RunObject.Status.Cancelled -> RunDelta.RunCancelled(run) + RunObject.Status.Failed -> RunDelta.RunFailed(run) + RunObject.Status.Completed -> RunDelta.RunCompleted(run) + RunObject.Status.Expired -> RunDelta.RunExpired(run) } flowCollector.emit(finalEvent) run } - if (run.status == RunObject.Status.requires_action) { + if (run.status == RunObject.Status.RequiresAction) { takeRequiredAction( depth + 1, RunDelta.RunRequiresAction(run), @@ -186,22 +185,21 @@ class AssistantThread( } suspend fun getRun(runId: String): RunObject = - api.getRun(threadId, runId, configure = ::defaultConfig) + api.threads.runs.getRun(threadId, runId, configure = ::defaultConfig) fun run(assistant: Assistant): Flow = createRunStream(assistant, CreateRunRequest(assistantId = assistant.assistantId)) suspend fun cancelRun(runId: String): RunObject = - api.cancelRun(threadId, runId, configure = ::defaultConfig) + api.threads.runs.cancel.cancelRun(threadId, runId, configure = ::defaultConfig) suspend fun runSteps(runId: String): List = - api.listRunSteps(threadId, runId, configure = ::defaultConfig).data + api.threads.runs.steps.listRunSteps(threadId, runId, configure = ::defaultConfig).data - private fun RunStepObjectStepDetails.toolCalls(): - List = + private fun RunStepObject.StepDetails.toolCalls(): List = when (val step = this) { - is RunStepObjectStepDetails.CaseRunStepDetailsMessageCreationObject -> emptyList() - is RunStepObjectStepDetails.CaseRunStepDetailsToolCallsObject -> step.value.toolCalls + is RunStepObject.StepDetails.CaseRunStepDetailsMessageCreationObject -> emptyList() + is RunStepObject.StepDetails.CaseRunStepDetailsToolCallsObject -> step.value.toolCalls } companion object { @@ -217,17 +215,17 @@ class AssistantThread( metadata: JsonObject? = null, metric: Metric = Metric.EMPTY, config: Config = Config(), - api: Assistants = OpenAI(config).assistants + api: OpenAPI = OpenAI(config) ): AssistantThread = AssistantThread( threadId = - api + api.threads .createThread( - createThreadRequest = + body = CreateThreadRequest( messages.map { CreateMessageRequest( - role = CreateMessageRequest.Role.user, + role = CreateMessageRequest.Role.User, content = it.content, fileIds = it.fileIds ) @@ -248,15 +246,15 @@ class AssistantThread( metadata: JsonObject? = null, metric: Metric = Metric.EMPTY, config: Config = Config(), - api: Assistants = OpenAI(config).assistants + api: OpenAPI = OpenAI(config) ): AssistantThread = AssistantThread( - api + api.threads .createThread( - createThreadRequest = + body = CreateThreadRequest( messages.map { - CreateMessageRequest(role = CreateMessageRequest.Role.user, content = it) + CreateMessageRequest(role = CreateMessageRequest.Role.User, content = it) }, metadata ), @@ -274,10 +272,12 @@ class AssistantThread( metadata: JsonObject? = null, metric: Metric = Metric.EMPTY, config: Config = Config(), - api: Assistants = OpenAI(config).assistants + api: OpenAPI = OpenAI(config) ): AssistantThread = AssistantThread( - api.createThread(CreateThreadRequest(messages, metadata), configure = ::defaultConfig).id, + api.threads + .createThread(CreateThreadRequest(messages, metadata), configure = ::defaultConfig) + .id, metric, config, api @@ -287,10 +287,10 @@ class AssistantThread( request: CreateThreadRequest, metric: Metric = Metric.EMPTY, config: Config = Config(), - api: Assistants = OpenAI(config).assistants + api: OpenAPI = OpenAI(config) ): AssistantThread = AssistantThread( - api.createThread(request, configure = ::defaultConfig).id, + api.threads.createThread(request, configure = ::defaultConfig).id, metric, config, api @@ -300,10 +300,10 @@ class AssistantThread( request: CreateThreadAndRunRequest, metric: Metric = Metric.EMPTY, config: Config = Config(), - api: Assistants = OpenAI(config).assistants + api: OpenAPI = OpenAI(config) ): AssistantThread = AssistantThread( - api.createThreadAndRun(request, configure = ::defaultConfig).id, + api.threads.runs.createThreadAndRun(request, configure = ::defaultConfig).id, metric, config, api diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/RunDelta.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/RunDelta.kt index 24315c5cb..102c1595c 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/RunDelta.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/RunDelta.kt @@ -1,8 +1,7 @@ package com.xebia.functional.xef.llm.assistants -import com.xebia.functional.openai.ServerSentEvent -import com.xebia.functional.openai.generated.model.* import com.xebia.functional.xef.Config +import io.github.nomisrev.openapi.* import kotlin.jvm.JvmInline import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @@ -72,7 +71,7 @@ sealed interface RunDelta { @Serializable data class RunStepDeltaObjectInner( - @SerialName("step_details") val stepDetails: RunStepObjectStepDetails + @SerialName("step_details") val stepDetails: RunStepObject.StepDetails ) /** [RunDeltaEvent.thread_run_step_completed] */ @@ -234,19 +233,19 @@ sealed interface RunDelta { } is RunStepCompleted -> { when (val details = runStep.stepDetails) { - is RunStepObjectStepDetails.CaseRunStepDetailsMessageCreationObject -> + is RunStepObject.StepDetails.CaseRunStepDetailsMessageCreationObject -> println("Creating msg: ${details.value.messageCreation.messageId}") - is RunStepObjectStepDetails.CaseRunStepDetailsToolCallsObject -> + is RunStepObject.StepDetails.CaseRunStepDetailsToolCallsObject -> println( "Tool calls: ${details.value.toolCalls.map { when (it) { - is RunStepDetailsToolCallsObjectToolCallsInner.CaseRunStepDetailsToolCallsCodeObject -> + is RunStepDetailsToolCallsObject.ToolCalls.CaseRunStepDetailsToolCallsCodeObject -> "Code: ${it.value.codeInterpreter.input}" - is RunStepDetailsToolCallsObjectToolCallsInner.CaseRunStepDetailsToolCallsFunctionObject -> { + is RunStepDetailsToolCallsObject.ToolCalls.CaseRunStepDetailsToolCallsFunctionObject -> { val function = it.value.function "Function: ${function.name}(${function.arguments})" } - is RunStepDetailsToolCallsObjectToolCallsInner.CaseRunStepDetailsToolCallsRetrievalObject -> { + is RunStepDetailsToolCallsObject.ToolCalls.CaseRunStepDetailsToolCallsRetrievalObject -> { val retrieval = it.value.retrieval "Retrieval: $retrieval" } diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/Tool.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/Tool.kt index 5789961f0..db6adc2bb 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/Tool.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/Tool.kt @@ -1,7 +1,7 @@ package com.xebia.functional.xef.llm.assistants -import com.xebia.functional.openai.generated.model.FunctionObject import com.xebia.functional.xef.llm.chatFunction +import io.github.nomisrev.openapi.FunctionObject import kotlinx.serialization.KSerializer import kotlinx.serialization.serializer diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/models/OpenAIClient.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/models/OpenAIClient.kt index ba9b824f5..66c7f8dd0 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/models/OpenAIClient.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/models/OpenAIClient.kt @@ -1,17 +1,17 @@ package com.xebia.functional.xef.llm.models -import com.xebia.functional.openai.generated.model.CreateChatCompletionRequestModel -import com.xebia.functional.openai.generated.model.CreateEmbeddingRequestModel import com.xebia.functional.tokenizer.ModelType +import io.github.nomisrev.openapi.CreateChatCompletionRequest +import io.github.nomisrev.openapi.CreateEmbeddingRequest -fun CreateChatCompletionRequestModel.modelType(forFunctions: Boolean = false): ModelType { +fun CreateChatCompletionRequest.Model.modelType(forFunctions: Boolean = false): ModelType { val stringValue = value val forFunctionsModel = ModelType.functionSpecific.find { forFunctions && it.name == stringValue } return forFunctionsModel ?: (ModelType.all.find { it.name == stringValue } ?: ModelType.TODO(stringValue)) } -fun CreateEmbeddingRequestModel.modelType(): ModelType { +fun CreateEmbeddingRequest.Model.modelType(): ModelType { val stringValue = value return ModelType.all.find { it.name == stringValue } ?: ModelType.TODO(stringValue) } diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/metrics/LogsMetric.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/metrics/LogsMetric.kt index b5bd1562f..5c97517ba 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/metrics/LogsMetric.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/metrics/LogsMetric.kt @@ -1,11 +1,11 @@ package com.xebia.functional.xef.metrics import arrow.atomic.AtomicInt -import com.xebia.functional.openai.generated.model.MessageObject -import com.xebia.functional.openai.generated.model.RunObject -import com.xebia.functional.openai.generated.model.RunStepObject import com.xebia.functional.xef.prompt.Prompt import com.xebia.functional.xef.prompt.contentAsString +import io.github.nomisrev.openapi.MessageObject +import io.github.nomisrev.openapi.RunObject +import io.github.nomisrev.openapi.RunStepObject import io.github.oshai.kotlinlogging.KotlinLogging import io.github.oshai.kotlinlogging.Level import io.ktor.util.date.* diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/metrics/Metric.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/metrics/Metric.kt index 62661f070..86ff9ac88 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/metrics/Metric.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/metrics/Metric.kt @@ -1,9 +1,9 @@ package com.xebia.functional.xef.metrics -import com.xebia.functional.openai.generated.model.MessageObject -import com.xebia.functional.openai.generated.model.RunObject -import com.xebia.functional.openai.generated.model.RunStepObject import com.xebia.functional.xef.prompt.Prompt +import io.github.nomisrev.openapi.MessageObject +import io.github.nomisrev.openapi.RunObject +import io.github.nomisrev.openapi.RunStepObject interface Metric { suspend fun customSpan(name: String, block: suspend Metric.() -> A): A diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/PlatformPromptBuilder.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/PlatformPromptBuilder.kt index 0a80019a0..16b04077a 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/PlatformPromptBuilder.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/PlatformPromptBuilder.kt @@ -1,12 +1,12 @@ package com.xebia.functional.xef.prompt -import com.xebia.functional.openai.generated.model.ChatCompletionRequestMessage -import com.xebia.functional.openai.generated.model.CreateChatCompletionRequestModel -import com.xebia.functional.openai.generated.model.FunctionObject import com.xebia.functional.xef.prompt.configuration.PromptConfiguration +import io.github.nomisrev.openapi.ChatCompletionRequestMessage +import io.github.nomisrev.openapi.CreateChatCompletionRequest +import io.github.nomisrev.openapi.FunctionObject class PlatformPromptBuilder( - private val model: CreateChatCompletionRequestModel, + private val model: CreateChatCompletionRequest.Model, private val functions: List, private val configuration: PromptConfiguration ) : PromptBuilder { @@ -21,7 +21,7 @@ class PlatformPromptBuilder( companion object { fun create( - model: CreateChatCompletionRequestModel, + model: CreateChatCompletionRequest.Model, functions: List, configuration: PromptConfiguration ): PlatformPromptBuilder = PlatformPromptBuilder(model, functions, configuration) diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/Prompt.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/Prompt.kt index 62ad2d355..80bf38741 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/Prompt.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/Prompt.kt @@ -1,9 +1,9 @@ package com.xebia.functional.xef.prompt -import com.xebia.functional.openai.generated.model.ChatCompletionRequestMessage -import com.xebia.functional.openai.generated.model.CreateChatCompletionRequestModel -import com.xebia.functional.openai.generated.model.FunctionObject import com.xebia.functional.xef.prompt.configuration.PromptConfiguration +import io.github.nomisrev.openapi.ChatCompletionRequestMessage +import io.github.nomisrev.openapi.CreateChatCompletionRequest +import io.github.nomisrev.openapi.FunctionObject import kotlin.jvm.JvmOverloads import kotlin.jvm.JvmSynthetic @@ -14,19 +14,19 @@ import kotlin.jvm.JvmSynthetic data class Prompt @JvmOverloads constructor( - val model: CreateChatCompletionRequestModel, + val model: CreateChatCompletionRequest.Model, val messages: List, val functions: List = emptyList(), val configuration: PromptConfiguration = PromptConfiguration.DEFAULTS ) { constructor( - model: CreateChatCompletionRequestModel, + model: CreateChatCompletionRequest.Model, value: String ) : this(model, listOf(PromptBuilder.user(value)), emptyList()) constructor( - model: CreateChatCompletionRequestModel, + model: CreateChatCompletionRequest.Model, value: String, configuration: PromptConfiguration ) : this(model, listOf(PromptBuilder.user(value)), emptyList(), configuration) @@ -34,7 +34,7 @@ constructor( companion object { @JvmSynthetic operator fun invoke( - model: CreateChatCompletionRequestModel, + model: CreateChatCompletionRequest.Model, functions: List = emptyList(), configuration: PromptConfiguration = PromptConfiguration.DEFAULTS, block: PlatformPromptBuilder.() -> Unit diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/PromptBuilder.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/PromptBuilder.kt index ee3588efd..ca1419d57 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/PromptBuilder.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/PromptBuilder.kt @@ -1,7 +1,8 @@ package com.xebia.functional.xef.prompt -import com.xebia.functional.openai.generated.model.* import com.xebia.functional.xef.prompt.configuration.PromptConfiguration +import io.github.nomisrev.openapi.* +import io.github.nomisrev.openapi.ChatCompletionRequestMessage import kotlin.jvm.JvmSynthetic interface PromptBuilder { @@ -26,12 +27,11 @@ interface PromptBuilder { ): ChatCompletionRequestMessage { val content = "${contentAsString()}\n${message.contentAsString()}" return when (completionRole()) { - ChatCompletionRole.Supported.system -> system(content) - ChatCompletionRole.Supported.user -> user(content) - ChatCompletionRole.Supported.assistant -> assistant(content) - ChatCompletionRole.Supported.tool -> error("Tool role is not supported") - ChatCompletionRole.Supported.function -> error("Function role is not supported") - is ChatCompletionRole.Custom -> error("Custom roles are not supported") + ChatCompletionRole.System -> system(content) + ChatCompletionRole.User -> user(content) + ChatCompletionRole.Assistant -> assistant(content) + ChatCompletionRole.Tool -> error("Tool role is not supported") + ChatCompletionRole.Function -> error("Function role is not supported") } } @@ -79,7 +79,7 @@ interface PromptBuilder { companion object { operator fun invoke( - model: CreateChatCompletionRequestModel, + model: CreateChatCompletionRequest.Model, functions: List, configuration: PromptConfiguration ): PlatformPromptBuilder = PlatformPromptBuilder.create(model, functions, configuration) @@ -87,7 +87,7 @@ interface PromptBuilder { fun assistant(value: String): ChatCompletionRequestMessage = ChatCompletionRequestMessage.CaseChatCompletionRequestAssistantMessage( ChatCompletionRequestAssistantMessage( - role = ChatCompletionRequestAssistantMessage.Role.assistant, + role = ChatCompletionRequestAssistantMessage.Role.Assistant, content = value ) ) @@ -95,15 +95,15 @@ interface PromptBuilder { fun user(value: String): ChatCompletionRequestMessage = ChatCompletionRequestMessage.CaseChatCompletionRequestUserMessage( ChatCompletionRequestUserMessage( - role = ChatCompletionRequestUserMessage.Role.user, - content = ChatCompletionRequestUserMessageContent.CaseString(value) + role = ChatCompletionRequestUserMessage.Role.User, + content = ChatCompletionRequestUserMessage.Content.CaseString(value) ) ) fun system(value: String): ChatCompletionRequestMessage = ChatCompletionRequestMessage.CaseChatCompletionRequestSystemMessage( ChatCompletionRequestSystemMessage( - role = ChatCompletionRequestSystemMessage.Role.system, + role = ChatCompletionRequestSystemMessage.Role.System, content = value ) ) @@ -111,21 +111,21 @@ interface PromptBuilder { fun image(url: String, text: String): ChatCompletionRequestMessage = ChatCompletionRequestMessage.CaseChatCompletionRequestUserMessage( ChatCompletionRequestUserMessage( - role = ChatCompletionRequestUserMessage.Role.user, + role = ChatCompletionRequestUserMessage.Role.User, content = - ChatCompletionRequestUserMessageContent.CaseChatCompletionRequestMessageContentParts( + ChatCompletionRequestUserMessage.Content.CaseChatCompletionRequestMessageContentParts( listOf( ChatCompletionRequestMessageContentPart .CaseChatCompletionRequestMessageContentPartImage( ChatCompletionRequestMessageContentPartImage( - type = ChatCompletionRequestMessageContentPartImage.Type.image_url, - imageUrl = ChatCompletionRequestMessageContentPartImageImageUrl(url) + type = ChatCompletionRequestMessageContentPartImage.Type.ImageUrl, + imageUrl = ChatCompletionRequestMessageContentPartImage.ImageUrl(url) ) ), ChatCompletionRequestMessageContentPart .CaseChatCompletionRequestMessageContentPartText( ChatCompletionRequestMessageContentPartText( - type = ChatCompletionRequestMessageContentPartText.Type.text, + type = ChatCompletionRequestMessageContentPartText.Type.Text, text = text ) ) @@ -140,8 +140,8 @@ fun ChatCompletionRequestMessage.contentAsString(): String = when (this) { is ChatCompletionRequestMessage.CaseChatCompletionRequestUserMessage -> when (val content = value.content) { - is ChatCompletionRequestUserMessageContent.CaseString -> content.value - is ChatCompletionRequestUserMessageContent.CaseChatCompletionRequestMessageContentParts -> + is ChatCompletionRequestUserMessage.Content.CaseString -> content.value + is ChatCompletionRequestUserMessage.Content.CaseChatCompletionRequestMessageContentParts -> content.value.joinToString { when (it) { is ChatCompletionRequestMessageContentPart.CaseChatCompletionRequestMessageContentPartImage -> diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/configuration/PromptConfiguration.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/configuration/PromptConfiguration.kt index b8d42db2b..de79896b4 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/configuration/PromptConfiguration.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/configuration/PromptConfiguration.kt @@ -1,7 +1,7 @@ package com.xebia.functional.xef.prompt.configuration -import com.xebia.functional.openai.generated.model.ChatCompletionRole import com.xebia.functional.xef.conversation.MessagePolicy +import io.github.nomisrev.openapi.ChatCompletionRole import kotlin.jvm.JvmField import kotlin.jvm.JvmOverloads import kotlinx.serialization.Serializable @@ -11,7 +11,7 @@ data class PromptConfiguration @JvmOverloads constructor( var maxDeserializationAttempts: Int = 3, - var user: String = ChatCompletionRole.user.value, + var user: String = ChatCompletionRole.User.value, var temperature: Double = 0.4, var numberOfPredictions: Int = 1, var docsInContext: Int = 5, diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/store/CombinedVectorStore.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/store/CombinedVectorStore.kt index 4e10fb1de..7fe838b38 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/store/CombinedVectorStore.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/store/CombinedVectorStore.kt @@ -1,8 +1,8 @@ package com.xebia.functional.xef.store -import com.xebia.functional.openai.generated.model.CreateChatCompletionRequestModel -import com.xebia.functional.openai.generated.model.Embedding import com.xebia.functional.xef.llm.models.modelType +import io.github.nomisrev.openapi.CreateChatCompletionRequest +import io.github.nomisrev.openapi.Embedding /** * A way of composing two [VectorStore] instances together, this class will **first search** [top], @@ -14,7 +14,7 @@ class CombinedVectorStore(private val top: VectorStore, private val bottom: Vect VectorStore by top { override suspend fun memories( - model: CreateChatCompletionRequestModel, + model: CreateChatCompletionRequest.Model, conversationId: ConversationId, limitTokens: Int ): List { diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/store/LocalVectorStore.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/store/LocalVectorStore.kt index 67908be24..bdb91534b 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/store/LocalVectorStore.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/store/LocalVectorStore.kt @@ -4,13 +4,10 @@ import arrow.atomic.Atomic import arrow.atomic.AtomicInt import arrow.atomic.getAndUpdate import arrow.atomic.update -import com.xebia.functional.openai.generated.api.Embeddings -import com.xebia.functional.openai.generated.model.CreateChatCompletionRequestModel -import com.xebia.functional.openai.generated.model.CreateEmbeddingRequestModel -import com.xebia.functional.openai.generated.model.Embedding import com.xebia.functional.xef.llm.embedDocuments import com.xebia.functional.xef.llm.embedQuery import com.xebia.functional.xef.llm.models.modelType +import io.github.nomisrev.openapi.* import kotlin.math.sqrt private data class State( @@ -29,12 +26,12 @@ class LocalVectorStore private constructor( private val embeddings: Embeddings, private val state: AtomicState, - private val embeddingRequestModel: CreateEmbeddingRequestModel + private val embeddingRequestModel: CreateEmbeddingRequest.Model ) : VectorStore { constructor( embeddings: Embeddings, - embeddingRequestModel: CreateEmbeddingRequestModel = - CreateEmbeddingRequestModel.text_embedding_ada_002 + embeddingRequestModel: CreateEmbeddingRequest.Model = + CreateEmbeddingRequest.Model.TextEmbeddingAda002 ) : this(embeddings, Atomic(State.empty()), embeddingRequestModel) override val indexValue: AtomicInt = AtomicInt(0) @@ -63,7 +60,7 @@ private constructor( } override suspend fun memories( - model: CreateChatCompletionRequestModel, + model: CreateChatCompletionRequest.Model, conversationId: ConversationId, limitTokens: Int ): List { diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/store/MemorizedMessage.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/store/MemorizedMessage.kt index 723690b45..643a9fe7c 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/store/MemorizedMessage.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/store/MemorizedMessage.kt @@ -1,7 +1,7 @@ package com.xebia.functional.xef.store -import com.xebia.functional.openai.generated.model.* import com.xebia.functional.xef.prompt.completionRole +import io.github.nomisrev.openapi.* sealed class MemorizedMessage { val role: ChatCompletionRole @@ -17,7 +17,7 @@ sealed class MemorizedMessage { is Response -> ChatCompletionRequestMessage.CaseChatCompletionRequestAssistantMessage( ChatCompletionRequestAssistantMessage( - role = ChatCompletionRequestAssistantMessage.Role.assistant, + role = ChatCompletionRequestAssistantMessage.Role.Assistant, // TODO: Find a new strategy to save the tool calls as content content = message.content ?: message.toolCalls?.firstOrNull()?.toString() ) @@ -31,32 +31,31 @@ sealed class MemorizedMessage { fun memorizedMessage(role: ChatCompletionRole, content: String): MemorizedMessage = when (role) { - ChatCompletionRole.Supported.system -> + ChatCompletionRole.System -> MemorizedMessage.Request( ChatCompletionRequestMessage.CaseChatCompletionRequestSystemMessage( ChatCompletionRequestSystemMessage( content = content, - role = ChatCompletionRequestSystemMessage.Role.system + role = ChatCompletionRequestSystemMessage.Role.System ) ) ) - ChatCompletionRole.Supported.user -> + ChatCompletionRole.User -> MemorizedMessage.Request( ChatCompletionRequestMessage.CaseChatCompletionRequestUserMessage( ChatCompletionRequestUserMessage( - content = ChatCompletionRequestUserMessageContent.CaseString(content), - role = ChatCompletionRequestUserMessage.Role.user + content = ChatCompletionRequestUserMessage.Content.CaseString(content), + role = ChatCompletionRequestUserMessage.Role.User ) ) ) - ChatCompletionRole.Supported.assistant -> + ChatCompletionRole.Assistant -> MemorizedMessage.Response( ChatCompletionResponseMessage( content = content, - role = ChatCompletionResponseMessage.Role.assistant + role = ChatCompletionResponseMessage.Role.Assistant ) ) - ChatCompletionRole.Supported.tool -> error("Tool messages are not supported") - ChatCompletionRole.Supported.function -> error("Function messages are not supported") - is ChatCompletionRole.Custom -> error("Custom messages are not supported") + ChatCompletionRole.Tool -> error("Tool messages are not supported") + ChatCompletionRole.Function -> error("Function messages are not supported") } diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/store/VectorStore.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/store/VectorStore.kt index 65d13dce8..90daa85bc 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/store/VectorStore.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/store/VectorStore.kt @@ -1,8 +1,8 @@ package com.xebia.functional.xef.store import arrow.atomic.AtomicInt -import com.xebia.functional.openai.generated.model.CreateChatCompletionRequestModel -import com.xebia.functional.openai.generated.model.Embedding +import io.github.nomisrev.openapi.CreateChatCompletionRequest +import io.github.nomisrev.openapi.Embedding import kotlin.jvm.JvmStatic interface VectorStore { @@ -16,7 +16,7 @@ interface VectorStore { suspend fun addMemories(memories: List) suspend fun memories( - model: CreateChatCompletionRequestModel, + model: CreateChatCompletionRequest.Model, conversationId: ConversationId, limitTokens: Int ): List @@ -60,7 +60,7 @@ interface VectorStore { override suspend fun addMemories(memories: List) {} override suspend fun memories( - model: CreateChatCompletionRequestModel, + model: CreateChatCompletionRequest.Model, conversationId: ConversationId, limitTokens: Int ): List = emptyList() diff --git a/core/src/commonTest/kotlin/com/xebia/functional/xef/conversation/ConversationSpec.kt b/core/src/commonTest/kotlin/com/xebia/functional/xef/conversation/ConversationSpec.kt index 2b6d85324..eadbe1015 100644 --- a/core/src/commonTest/kotlin/com/xebia/functional/xef/conversation/ConversationSpec.kt +++ b/core/src/commonTest/kotlin/com/xebia/functional/xef/conversation/ConversationSpec.kt @@ -1,6 +1,5 @@ package com.xebia.functional.xef.conversation -import com.xebia.functional.openai.generated.model.* import com.xebia.functional.xef.data.* import com.xebia.functional.xef.llm.models.modelType import com.xebia.functional.xef.llm.prompt @@ -16,6 +15,7 @@ import com.xebia.functional.xef.prompt.configuration.PromptConfiguration import com.xebia.functional.xef.prompt.contentAsString import com.xebia.functional.xef.store.ConversationId import com.xebia.functional.xef.store.LocalVectorStore +import io.github.nomisrev.openapi.* import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.comparables.shouldBeLessThan import io.kotest.matchers.shouldBe diff --git a/core/src/commonTest/kotlin/com/xebia/functional/xef/data/TestChatApi.kt b/core/src/commonTest/kotlin/com/xebia/functional/xef/data/TestChatApi.kt index 003214979..d0ea2553c 100644 --- a/core/src/commonTest/kotlin/com/xebia/functional/xef/data/TestChatApi.kt +++ b/core/src/commonTest/kotlin/com/xebia/functional/xef/data/TestChatApi.kt @@ -1,8 +1,8 @@ package com.xebia.functional.xef.data import com.xebia.functional.openai.generated.api.Chat -import com.xebia.functional.openai.generated.model.* import com.xebia.functional.xef.prompt.contentAsString +import io.github.nomisrev.openapi.* import io.ktor.client.request.* import kotlinx.coroutines.flow.Flow diff --git a/core/src/commonTest/kotlin/com/xebia/functional/xef/data/TestEmbeddings.kt b/core/src/commonTest/kotlin/com/xebia/functional/xef/data/TestEmbeddings.kt index b607b7fc3..cba871576 100644 --- a/core/src/commonTest/kotlin/com/xebia/functional/xef/data/TestEmbeddings.kt +++ b/core/src/commonTest/kotlin/com/xebia/functional/xef/data/TestEmbeddings.kt @@ -1,9 +1,9 @@ package com.xebia.functional.xef.data import com.xebia.functional.openai.generated.api.Embeddings -import com.xebia.functional.openai.generated.model.CreateEmbeddingRequest -import com.xebia.functional.openai.generated.model.CreateEmbeddingResponse -import com.xebia.functional.openai.generated.model.CreateEmbeddingResponseUsage +import io.github.nomisrev.openapi.CreateEmbeddingRequest +import io.github.nomisrev.openapi.CreateEmbeddingResponse +import io.github.nomisrev.openapi.CreateEmbeddingResponseUsage import io.ktor.client.request.* class TestEmbeddings : Embeddings, AutoCloseable { diff --git a/core/src/commonTest/kotlin/com/xebia/functional/xef/prompt/PromptBuilderSpec.kt b/core/src/commonTest/kotlin/com/xebia/functional/xef/prompt/PromptBuilderSpec.kt index 45ee78648..2f23a2227 100644 --- a/core/src/commonTest/kotlin/com/xebia/functional/xef/prompt/PromptBuilderSpec.kt +++ b/core/src/commonTest/kotlin/com/xebia/functional/xef/prompt/PromptBuilderSpec.kt @@ -1,9 +1,9 @@ package com.xebia.functional.xef.prompt -import com.xebia.functional.openai.generated.model.CreateChatCompletionRequestModel import com.xebia.functional.xef.prompt.PromptBuilder.Companion.assistant import com.xebia.functional.xef.prompt.PromptBuilder.Companion.system import com.xebia.functional.xef.prompt.PromptBuilder.Companion.user +import io.github.nomisrev.openapi.CreateChatCompletionRequestModel import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe diff --git a/core/src/commonTest/kotlin/com/xebia/functional/xef/store/CombinedVectorStoreSpec.kt b/core/src/commonTest/kotlin/com/xebia/functional/xef/store/CombinedVectorStoreSpec.kt index 54cca47ab..27ab176c9 100644 --- a/core/src/commonTest/kotlin/com/xebia/functional/xef/store/CombinedVectorStoreSpec.kt +++ b/core/src/commonTest/kotlin/com/xebia/functional/xef/store/CombinedVectorStoreSpec.kt @@ -1,9 +1,9 @@ package com.xebia.functional.xef.store -import com.xebia.functional.openai.generated.model.CreateChatCompletionRequestModel import com.xebia.functional.xef.data.TestEmbeddings import com.xebia.functional.xef.llm.models.modelType import com.xebia.functional.xef.llm.tokensFromMessages +import io.github.nomisrev.openapi.CreateChatCompletionRequestModel import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe diff --git a/core/src/commonTest/kotlin/com/xebia/functional/xef/store/LocalVectorStoreSpec.kt b/core/src/commonTest/kotlin/com/xebia/functional/xef/store/LocalVectorStoreSpec.kt index abc6a22d4..4a23ee314 100644 --- a/core/src/commonTest/kotlin/com/xebia/functional/xef/store/LocalVectorStoreSpec.kt +++ b/core/src/commonTest/kotlin/com/xebia/functional/xef/store/LocalVectorStoreSpec.kt @@ -1,9 +1,9 @@ package com.xebia.functional.xef.store -import com.xebia.functional.openai.generated.model.CreateChatCompletionRequestModel import com.xebia.functional.xef.data.TestEmbeddings import com.xebia.functional.xef.llm.models.modelType import com.xebia.functional.xef.llm.tokensFromMessages +import io.github.nomisrev.openapi.CreateChatCompletionRequestModel import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe diff --git a/core/src/commonTest/kotlin/com/xebia/functional/xef/store/MemoryData.kt b/core/src/commonTest/kotlin/com/xebia/functional/xef/store/MemoryData.kt index fd6ed7f02..6888e301b 100644 --- a/core/src/commonTest/kotlin/com/xebia/functional/xef/store/MemoryData.kt +++ b/core/src/commonTest/kotlin/com/xebia/functional/xef/store/MemoryData.kt @@ -1,10 +1,10 @@ package com.xebia.functional.xef.store import arrow.atomic.AtomicInt -import com.xebia.functional.openai.generated.model.ChatCompletionRequestAssistantMessage -import com.xebia.functional.openai.generated.model.ChatCompletionRequestMessage -import com.xebia.functional.openai.generated.model.ChatCompletionRequestUserMessage -import com.xebia.functional.openai.generated.model.ChatCompletionRequestUserMessageContent +import io.github.nomisrev.openapi.ChatCompletionRequestAssistantMessage +import io.github.nomisrev.openapi.ChatCompletionRequestMessage +import io.github.nomisrev.openapi.ChatCompletionRequestUserMessage +import io.github.nomisrev.openapi.ChatCompletionRequestUserMessageContent class MemoryData { val defaultConversationId = ConversationId("default-id") diff --git a/evaluator/build.gradle.kts b/evaluator/build.gradle.kts index 56ddda484..eb3355939 100644 --- a/evaluator/build.gradle.kts +++ b/evaluator/build.gradle.kts @@ -19,7 +19,6 @@ dependencies { api(libs.kotlinx.serialization.json) detektPlugins(project(":detekt-rules")) implementation(projects.xefCore) - implementation(projects.xefOpenaiClient) } detekt { diff --git a/evaluator/src/main/kotlin/com/xebia/functional/xef/evaluator/SuiteBuilder.kt b/evaluator/src/main/kotlin/com/xebia/functional/xef/evaluator/SuiteBuilder.kt index 1df855b86..2c631b47f 100644 --- a/evaluator/src/main/kotlin/com/xebia/functional/xef/evaluator/SuiteBuilder.kt +++ b/evaluator/src/main/kotlin/com/xebia/functional/xef/evaluator/SuiteBuilder.kt @@ -1,8 +1,8 @@ package com.xebia.functional.xef.evaluator -import com.xebia.functional.openai.generated.model.CreateChatCompletionRequestModel import com.xebia.functional.xef.AI import com.xebia.functional.xef.evaluator.models.* +import io.github.nomisrev.openapi.CreateChatCompletionRequestModel import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json diff --git a/examples/src/main/kotlin/com/xebia/functional/xef/assistants/AssistantStreaming.kt b/examples/src/main/kotlin/com/xebia/functional/xef/assistants/AssistantStreaming.kt index a5dc63842..54e82823a 100644 --- a/examples/src/main/kotlin/com/xebia/functional/xef/assistants/AssistantStreaming.kt +++ b/examples/src/main/kotlin/com/xebia/functional/xef/assistants/AssistantStreaming.kt @@ -1,11 +1,11 @@ package com.xebia.functional.xef.assistants -import com.xebia.functional.openai.generated.model.CreateRunRequest import com.xebia.functional.xef.OpenAI import com.xebia.functional.xef.llm.assistants.Assistant import com.xebia.functional.xef.llm.assistants.AssistantThread import com.xebia.functional.xef.llm.assistants.Tool import com.xebia.functional.xef.metrics.Metric +import io.github.nomisrev.openapi.CreateRunRequest suspend fun main() { diff --git a/examples/src/main/kotlin/com/xebia/functional/xef/conversation/conversations/Animal.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/conversations/Animal.kt index 330450f7b..783b43d55 100644 --- a/examples/src/main/kotlin/com/xebia/functional/xef/conversation/conversations/Animal.kt +++ b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/conversations/Animal.kt @@ -1,6 +1,5 @@ package com.xebia.functional.xef.conversation.conversations -import com.xebia.functional.openai.generated.model.CreateChatCompletionRequestModel import com.xebia.functional.xef.AI import com.xebia.functional.xef.OpenAI import com.xebia.functional.xef.conversation.Conversation @@ -12,6 +11,7 @@ import com.xebia.functional.xef.prompt.PromptBuilder.Companion.system import com.xebia.functional.xef.prompt.PromptBuilder.Companion.user import com.xebia.functional.xef.prompt.configuration.PromptConfiguration import com.xebia.functional.xef.store.LocalVectorStore +import io.github.nomisrev.openapi.CreateChatCompletionRequestModel import kotlinx.serialization.Serializable @Serializable data class Animal(val name: String, val habitat: String, val diet: String) diff --git a/examples/src/main/kotlin/com/xebia/functional/xef/dsl/audio/SimpleSpeech.kt b/examples/src/main/kotlin/com/xebia/functional/xef/dsl/audio/SimpleSpeech.kt index 5a942d26b..7dc25c0e6 100644 --- a/examples/src/main/kotlin/com/xebia/functional/xef/dsl/audio/SimpleSpeech.kt +++ b/examples/src/main/kotlin/com/xebia/functional/xef/dsl/audio/SimpleSpeech.kt @@ -2,12 +2,12 @@ package com.xebia.functional.xef.dsl.audio import com.sipgate.mp3wav.Converter import com.xebia.functional.openai.UploadFile -import com.xebia.functional.openai.generated.model.CreateSpeechRequest -import com.xebia.functional.openai.generated.model.CreateSpeechRequestModel -import com.xebia.functional.openai.generated.model.CreateTranscriptionRequestModel import com.xebia.functional.xef.AI import com.xebia.functional.xef.Config import com.xebia.functional.xef.OpenAI +import io.github.nomisrev.openapi.CreateSpeechRequest +import io.github.nomisrev.openapi.CreateSpeechRequestModel +import io.github.nomisrev.openapi.CreateTranscriptionRequestModel import io.ktor.client.statement.* import io.ktor.utils.io.jvm.javaio.* import java.io.File diff --git a/examples/src/main/kotlin/com/xebia/functional/xef/dsl/chat/Classes.kt b/examples/src/main/kotlin/com/xebia/functional/xef/dsl/chat/Classes.kt index 329acbccf..69cd8e3c8 100644 --- a/examples/src/main/kotlin/com/xebia/functional/xef/dsl/chat/Classes.kt +++ b/examples/src/main/kotlin/com/xebia/functional/xef/dsl/chat/Classes.kt @@ -1,6 +1,5 @@ package com.xebia.functional.xef.dsl.chat -import com.xebia.functional.openai.generated.model.CreateChatCompletionRequestModel import com.xebia.functional.xef.AI import com.xebia.functional.xef.conversation.Description import com.xebia.functional.xef.conversation.MessagePolicy @@ -11,6 +10,7 @@ import com.xebia.functional.xef.prompt.PromptBuilder.Companion.assistant import com.xebia.functional.xef.prompt.PromptBuilder.Companion.system import com.xebia.functional.xef.prompt.PromptBuilder.Companion.user import com.xebia.functional.xef.prompt.configuration.PromptConfiguration +import io.github.nomisrev.openapi.CreateChatCompletionRequestModel import kotlinx.serialization.Serializable @Serializable diff --git a/examples/src/main/kotlin/com/xebia/functional/xef/dsl/classify/AnswerAccuracy.kt b/examples/src/main/kotlin/com/xebia/functional/xef/dsl/classify/AnswerAccuracy.kt index 363ea4275..352f19a1a 100644 --- a/examples/src/main/kotlin/com/xebia/functional/xef/dsl/classify/AnswerAccuracy.kt +++ b/examples/src/main/kotlin/com/xebia/functional/xef/dsl/classify/AnswerAccuracy.kt @@ -1,8 +1,8 @@ package com.xebia.functional.xef.dsl.classify -import com.xebia.functional.openai.generated.model.CreateChatCompletionRequestModel import com.xebia.functional.xef.AI import com.xebia.functional.xef.evaluator.metrics.AnswerAccuracy +import io.github.nomisrev.openapi.CreateChatCompletionRequestModel /** * This is a simple example of how to use the `AI.classify` function to classify the accuracy of an diff --git a/examples/src/main/kotlin/com/xebia/functional/xef/dsl/images/ImagesExamples.kt b/examples/src/main/kotlin/com/xebia/functional/xef/dsl/images/ImagesExamples.kt index beab77ab9..409815f10 100644 --- a/examples/src/main/kotlin/com/xebia/functional/xef/dsl/images/ImagesExamples.kt +++ b/examples/src/main/kotlin/com/xebia/functional/xef/dsl/images/ImagesExamples.kt @@ -1,8 +1,8 @@ package com.xebia.functional.xef.dsl.images -import com.xebia.functional.openai.generated.model.CreateImageRequest import com.xebia.functional.xef.OpenAI import com.xebia.functional.xef.llm.asInputProvider +import io.github.nomisrev.openapi.CreateImageRequest suspend fun main() { val openAI = OpenAI(logRequests = true) diff --git a/examples/src/main/kotlin/com/xebia/functional/xef/evaluator/TestExample.kt b/examples/src/main/kotlin/com/xebia/functional/xef/evaluator/TestExample.kt index fb8ce532b..aadb066f7 100644 --- a/examples/src/main/kotlin/com/xebia/functional/xef/evaluator/TestExample.kt +++ b/examples/src/main/kotlin/com/xebia/functional/xef/evaluator/TestExample.kt @@ -1,7 +1,6 @@ package com.xebia.functional.xef.evaluator import arrow.continuations.SuspendApp -import com.xebia.functional.openai.generated.model.CreateChatCompletionRequestModel import com.xebia.functional.xef.OpenAI import com.xebia.functional.xef.conversation.Conversation import com.xebia.functional.xef.evaluator.metrics.AnswerAccuracy @@ -10,6 +9,7 @@ import com.xebia.functional.xef.evaluator.models.OutputResponse import com.xebia.functional.xef.llm.promptMessage import com.xebia.functional.xef.prompt.Prompt import com.xebia.functional.xef.prompt.PromptBuilder.Companion.user +import io.github.nomisrev.openapi.CreateChatCompletionRequestModel object TestExample { diff --git a/integrations/opentelemetry/src/main/kotlin/com/xebia/functional/xef/opentelemetry/OpenTelemetryAssistantState.kt b/integrations/opentelemetry/src/main/kotlin/com/xebia/functional/xef/opentelemetry/OpenTelemetryAssistantState.kt index ad2d09f36..1c1579eb1 100644 --- a/integrations/opentelemetry/src/main/kotlin/com/xebia/functional/xef/opentelemetry/OpenTelemetryAssistantState.kt +++ b/integrations/opentelemetry/src/main/kotlin/com/xebia/functional/xef/opentelemetry/OpenTelemetryAssistantState.kt @@ -1,6 +1,6 @@ package com.xebia.functional.xef.opentelemetry -import com.xebia.functional.openai.generated.model.* +import io.github.nomisrev.openapi.* import io.opentelemetry.api.trace.Span import io.opentelemetry.api.trace.SpanKind import io.opentelemetry.api.trace.Tracer diff --git a/integrations/opentelemetry/src/main/kotlin/com/xebia/functional/xef/opentelemetry/OpenTelemetryMetric.kt b/integrations/opentelemetry/src/main/kotlin/com/xebia/functional/xef/opentelemetry/OpenTelemetryMetric.kt index 3ee6c4728..4d653daba 100644 --- a/integrations/opentelemetry/src/main/kotlin/com/xebia/functional/xef/opentelemetry/OpenTelemetryMetric.kt +++ b/integrations/opentelemetry/src/main/kotlin/com/xebia/functional/xef/opentelemetry/OpenTelemetryMetric.kt @@ -1,11 +1,11 @@ package com.xebia.functional.xef.opentelemetry -import com.xebia.functional.openai.generated.model.MessageObject -import com.xebia.functional.openai.generated.model.RunObject -import com.xebia.functional.openai.generated.model.RunStepObject import com.xebia.functional.xef.metrics.Metric import com.xebia.functional.xef.prompt.Prompt import com.xebia.functional.xef.prompt.contentAsString +import io.github.nomisrev.openapi.MessageObject +import io.github.nomisrev.openapi.RunObject +import io.github.nomisrev.openapi.RunStepObject import io.opentelemetry.api.trace.* class OpenTelemetryMetric( diff --git a/integrations/postgresql/src/main/kotlin/com/xebia/functional/xef/store/PostgreSQLVectorStore.kt b/integrations/postgresql/src/main/kotlin/com/xebia/functional/xef/store/PostgreSQLVectorStore.kt index cd32df067..f34578c9e 100644 --- a/integrations/postgresql/src/main/kotlin/com/xebia/functional/xef/store/PostgreSQLVectorStore.kt +++ b/integrations/postgresql/src/main/kotlin/com/xebia/functional/xef/store/PostgreSQLVectorStore.kt @@ -2,10 +2,10 @@ package com.xebia.functional.xef.store import arrow.atomic.AtomicInt import com.xebia.functional.openai.generated.api.Embeddings -import com.xebia.functional.openai.generated.model.ChatCompletionRole -import com.xebia.functional.openai.generated.model.CreateChatCompletionRequestModel -import com.xebia.functional.openai.generated.model.CreateEmbeddingRequestModel -import com.xebia.functional.openai.generated.model.Embedding +import io.github.nomisrev.openapi.ChatCompletionRole +import io.github.nomisrev.openapi.CreateChatCompletionRequestModel +import io.github.nomisrev.openapi.CreateEmbeddingRequestModel +import io.github.nomisrev.openapi.Embedding import com.xebia.functional.xef.llm.embedDocuments import com.xebia.functional.xef.llm.embedQuery import com.xebia.functional.xef.llm.models.modelType diff --git a/integrations/postgresql/src/test/kotlin/xef/MemoryData.kt b/integrations/postgresql/src/test/kotlin/xef/MemoryData.kt index 00e7a76b9..5e85fd535 100644 --- a/integrations/postgresql/src/test/kotlin/xef/MemoryData.kt +++ b/integrations/postgresql/src/test/kotlin/xef/MemoryData.kt @@ -1,10 +1,10 @@ package xef import arrow.atomic.AtomicInt -import com.xebia.functional.openai.generated.model.ChatCompletionRequestAssistantMessage -import com.xebia.functional.openai.generated.model.ChatCompletionRequestMessage -import com.xebia.functional.openai.generated.model.ChatCompletionRequestUserMessage -import com.xebia.functional.openai.generated.model.ChatCompletionRequestUserMessageContent +import io.github.nomisrev.openapi.ChatCompletionRequestAssistantMessage +import io.github.nomisrev.openapi.ChatCompletionRequestMessage +import io.github.nomisrev.openapi.ChatCompletionRequestUserMessage +import io.github.nomisrev.openapi.ChatCompletionRequestUserMessageContent import com.xebia.functional.xef.store.ConversationId import com.xebia.functional.xef.store.MemorizedMessage import com.xebia.functional.xef.store.Memory diff --git a/integrations/postgresql/src/test/kotlin/xef/PGVectorStoreSpec.kt b/integrations/postgresql/src/test/kotlin/xef/PGVectorStoreSpec.kt index c7e5ab83b..8a1c17e75 100644 --- a/integrations/postgresql/src/test/kotlin/xef/PGVectorStoreSpec.kt +++ b/integrations/postgresql/src/test/kotlin/xef/PGVectorStoreSpec.kt @@ -1,8 +1,8 @@ package xef -import com.xebia.functional.openai.generated.model.CreateChatCompletionRequestModel -import com.xebia.functional.openai.generated.model.CreateEmbeddingRequestModel -import com.xebia.functional.openai.generated.model.Embedding +import io.github.nomisrev.openapi.CreateChatCompletionRequestModel +import io.github.nomisrev.openapi.CreateEmbeddingRequestModel +import io.github.nomisrev.openapi.Embedding import com.xebia.functional.xef.store.PGVectorStore import com.xebia.functional.xef.store.migrations.runDatabaseMigrations import com.xebia.functional.xef.store.postgresql.PGDistanceStrategy diff --git a/integrations/postgresql/src/test/kotlin/xef/TestEmbeddings.kt b/integrations/postgresql/src/test/kotlin/xef/TestEmbeddings.kt index a56584375..081633e0c 100644 --- a/integrations/postgresql/src/test/kotlin/xef/TestEmbeddings.kt +++ b/integrations/postgresql/src/test/kotlin/xef/TestEmbeddings.kt @@ -1,7 +1,7 @@ package xef import com.xebia.functional.openai.generated.api.Embeddings -import com.xebia.functional.openai.generated.model.* +import io.github.nomisrev.openapi.* import io.ktor.client.request.* class TestEmbeddings : Embeddings, AutoCloseable { diff --git a/integrations/sql/src/main/kotlin/com/xebia/functional/xef/sql/SQL.kt b/integrations/sql/src/main/kotlin/com/xebia/functional/xef/sql/SQL.kt index 7ff4bb2f1..57d7b833e 100644 --- a/integrations/sql/src/main/kotlin/com/xebia/functional/xef/sql/SQL.kt +++ b/integrations/sql/src/main/kotlin/com/xebia/functional/xef/sql/SQL.kt @@ -1,7 +1,7 @@ package com.xebia.functional.xef.sql import com.xebia.functional.openai.generated.api.Chat -import com.xebia.functional.openai.generated.model.CreateChatCompletionRequestModel +import io.github.nomisrev.openapi.CreateChatCompletionRequestModel import com.xebia.functional.xef.conversation.AiDsl import com.xebia.functional.xef.conversation.Conversation import com.xebia.functional.xef.conversation.Description diff --git a/integrations/sql/src/main/kotlin/com/xebia/functional/xef/sql/jdbc/JdbcConfig.kt b/integrations/sql/src/main/kotlin/com/xebia/functional/xef/sql/jdbc/JdbcConfig.kt index c740a3dc5..30e3d928c 100644 --- a/integrations/sql/src/main/kotlin/com/xebia/functional/xef/sql/jdbc/JdbcConfig.kt +++ b/integrations/sql/src/main/kotlin/com/xebia/functional/xef/sql/jdbc/JdbcConfig.kt @@ -1,7 +1,7 @@ package com.xebia.functional.xef.sql.jdbc import com.xebia.functional.openai.generated.api.Chat -import com.xebia.functional.openai.generated.model.CreateChatCompletionRequestModel +import io.github.nomisrev.openapi.CreateChatCompletionRequestModel class JdbcConfig( val vendor: String, diff --git a/openai-client/client/.openapi-generator-ignore b/openai-client/client/.openapi-generator-ignore deleted file mode 100644 index 4b8839f00..000000000 --- a/openai-client/client/.openapi-generator-ignore +++ /dev/null @@ -1,15 +0,0 @@ -.gitignore -build.gradle.kts -settings.gradle.kts -gradle/** -gradlew -gradlew.bat -README.md -docs/** - -build.gradle -settings.gradle - -**/src/test/ -/**/org/openapitools/client/infrastructure/ -**/proguard-rules.pro diff --git a/openai-client/client/build.gradle.kts b/openai-client/client/build.gradle.kts deleted file mode 100644 index 7beb5a2a1..000000000 --- a/openai-client/client/build.gradle.kts +++ /dev/null @@ -1,138 +0,0 @@ -@file:Suppress("DSL_SCOPE_VIOLATION") - -import org.jetbrains.dokka.gradle.DokkaTask - -repositories { mavenCentral() } - -plugins { - base - alias(libs.plugins.kotlin.multiplatform) - alias(libs.plugins.kotest.multiplatform) - alias(libs.plugins.kotlinx.serialization) - alias(libs.plugins.spotless) - alias(libs.plugins.dokka) - alias(libs.plugins.arrow.gradle.publish) - alias(libs.plugins.semver.gradle) - alias(libs.plugins.detekt) -} - -dependencies { detektPlugins(project(":detekt-rules")) } - -java { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - toolchain { languageVersion = JavaLanguageVersion.of(11) } -} - -kotlin { - sourceSets.commonMain { - kotlin.srcDir(project.file("build/generated/OpenAI/src/commonMain/kotlin")) - } -} - -// Automatically run the generator when importing -tasks.maybeCreate("prepareKotlinIdeaImport") - .dependsOn(":xef-openai-client-generator:openaiClientGenerate") - -detekt { - toolVersion = "1.23.1" - source.setFrom("src/commonMain/kotlin", "src/jvmMain/kotlin") - config.setFrom("../../config/detekt/detekt.yml") - autoCorrect = true -} - -kotlin { - jvm() - js(IR) { - browser() - nodejs() - // TODO support wasm, etc - } - linuxX64() - macosX64() - macosArm64() - mingwX64() - // iOS, Android, etc? - sourceSets { - all { languageSettings.optIn("kotlin.ExperimentalStdlibApi") } - val commonMain by getting { - dependencies { - api(projects.xefTokenizer) - implementation(libs.ktor.client.content.negotiation) - implementation(libs.ktor.client.serialization) - implementation(libs.ktor.client.logging) - implementation(libs.klogging) - } - } - val commonTest by getting { - dependencies { - implementation(kotlin("test")) - implementation(libs.kotest.property) - implementation(libs.kotest.assertions) - } - } - val jvmMain by getting { - dependencies { - api(libs.ktor.client.cio) - } - } - val jsMain by getting { dependencies { api(libs.ktor.client.js) } } - val jvmTest by getting { dependencies { implementation(libs.kotest.junit5) } } - val linuxX64Main by getting { dependencies { api(libs.ktor.client.cio) } } - val macosX64Main by getting { dependencies { api(libs.ktor.client.cio) } } - val macosArm64Main by getting { dependencies { api(libs.ktor.client.cio) } } - val mingwX64Main by getting { dependencies { api(libs.ktor.client.winhttp) } } - } -} - -spotless { - kotlin { - target("**/*.kt") - ktfmt().googleStyle().configure { it.setRemoveUnusedImport(true) } - } -} - -tasks { - withType().configureEach { - dependsOn(":detekt-rules:assemble") - autoCorrect = true - } - named("detektJvmMain") { - dependsOn(":detekt-rules:assemble") - getByName("build").dependsOn(this) - } - named("detekt") { - dependsOn(":detekt-rules:assemble") - getByName("build").dependsOn(this) - } - withType().configureEach { - maxParallelForks = Runtime.getRuntime().availableProcessors() - useJUnitPlatform() - testLogging { - setExceptionFormat("full") - setEvents(listOf("passed", "skipped", "failed", "standardOut", "standardError")) - } - } - withType().configureEach { - kotlin.sourceSets.forEach { kotlinSourceSet -> - dokkaSourceSets.named(kotlinSourceSet.name) { - perPackageOption { - matchingRegex.set(".*\\.internal.*") - suppress.set(true) - } - skipDeprecated.set(true) - reportUndocumented.set(false) - val baseUrl = checkNotNull(project.properties["pom.smc.url"]?.toString()) - kotlinSourceSet.kotlin.srcDirs.filter { it.exists() }.forEach { srcDir -> - sourceLink { - localDirectory.set(srcDir) - remoteUrl.set(uri("$baseUrl/blob/main/${srcDir.relativeTo(rootProject.rootDir)}").toURL()) - remoteLineSuffix.set("#L") - } - } - } - } - } -} - -tasks.withType { dependsOn(tasks.withType()) } diff --git a/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/AssistantEvent.kt b/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/AssistantEvent.kt deleted file mode 100644 index 64f9e266d..000000000 --- a/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/AssistantEvent.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.xebia.functional.openai - -import kotlinx.serialization.Serializable - -// TODO write proper AssistantEvent -// According to: -// https://platform.openai.com/docs/api-reference/assistants-streaming/message-delta-object -@Serializable data class AssistantEvent(val todo: String) diff --git a/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/Config.kt b/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/Config.kt deleted file mode 100644 index 3efb3c9b9..000000000 --- a/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/Config.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.xebia.functional.openai - -import kotlinx.serialization.json.Json - -data class Config( - val baseUrl: String, - val token: String, - val org: String?, - val json: Json, - val streamingPrefix: String, - val streamingDelimiter: String -) diff --git a/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/FormBuilderOps.kt b/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/FormBuilderOps.kt deleted file mode 100644 index 13fed8050..000000000 --- a/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/FormBuilderOps.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.xebia.functional.openai - -import io.ktor.client.request.forms.* -import io.ktor.http.* -import io.ktor.util.* -import io.ktor.utils.io.core.* -import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.InternalSerializationApi -import kotlinx.serialization.serializerOrNull - -@OptIn(InternalAPI::class) -fun FormBuilder.appendGen(key: String, value: T, headers: Headers = Headers.Empty): Unit { - when (value) { - is String -> append(key, value, headers) - is Number -> append(key, value, headers) - is Boolean -> append(key, value, headers) - is ByteArray -> append(key, value, headers) - is ByteReadPacket -> append(key, value, headers) - is InputProvider -> append(key, value, headers) - is ChannelProvider -> append(key, value, headers) - is UploadFile -> appendUploadedFile(key, value) - is Enum<*> -> append(key, serialNameOrEnumValue(value), headers) - else -> append(key, value, headers) - } -} - -internal fun FormBuilder.appendUploadedFile(key: String, file: UploadFile) { - append( - key = key, - filename = file.filename, - contentType = file.contentType ?: ContentType.Application.OctetStream, - size = file.size, - bodyBuilder = file.bodyBuilder - ) -} - -@OptIn(InternalSerializationApi::class, ExperimentalSerializationApi::class) -fun > serialNameOrEnumValue(v: Enum): String = - v::class.serializerOrNull()?.descriptor?.getElementName(v.ordinal) ?: v.toString() diff --git a/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/OneOfOps.kt b/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/OneOfOps.kt deleted file mode 100644 index 0cd3ed386..000000000 --- a/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/OneOfOps.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.xebia.functional.openai - -import kotlin.reflect.KClass -import kotlinx.serialization.SerializationException -import kotlinx.serialization.json.JsonElement - -class OneOfSerializationException( - val payload: JsonElement, - val errors: Map, SerializationException>, - override val message: String = - """ - Failed to deserialize Json: $payload. - Errors: ${ - errors.entries.joinToString(separator = "\n") { (type, error) -> - "$type - failed to deserialize: ${error.stackTraceToString()}" - } - } - """ - .trimIndent() -) : SerializationException(message) - -/** - * OpenAI makes a lot of use of oneOf types (sum types, or unions types), but it **never** relies on - * a discriminator field to differentiate between the types. - * - * Typically, what OpenAI does is attach a common field like `type` (a single value enum). I.e. - * `MessageObjectContentInner` has a type field with `image` or `text`. Depending on the `type` - * property, the other properties will be different. - * - * Due to the use of these fields, it **seems** there are no overlapping objects in the schema. So - * to deserialize these types, we can try to deserialize each type and return the first one that - * succeeds. In the case **all** fail, we throw [OneOfSerializationException] which includes all the - * attempted types with their errors. - * - * This method relies on 'peeking', which is not possible in KotlinX Serialization. So to achieve - * peeking, we first deserialize the raw Json to JsonElement, which safely consumes the buffer. And - * then we can attempt to deserialize the JsonElement to the desired type, without breaking the - * internal parser buffer. - */ -internal fun attemptDeserialize( - json: JsonElement, - vararg block: Pair, (json: JsonElement) -> A> -): A { - val errors = linkedMapOf, SerializationException>() - block.forEach { (kclass, f) -> - try { - return f(json) - } catch (e: SerializationException) { - errors[kclass] = e - } - } - throw OneOfSerializationException(json, errors) -} diff --git a/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/ServerSentEvent.kt b/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/ServerSentEvent.kt deleted file mode 100644 index a3427178b..000000000 --- a/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/ServerSentEvent.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.xebia.functional.openai - -import kotlinx.serialization.Serializable -import kotlinx.serialization.json.JsonElement - -@Serializable -data class ServerSentEvent( - val event: String? = null, - val data: JsonElement? = null, -) diff --git a/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/StreamingOps.kt b/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/StreamingOps.kt deleted file mode 100644 index 6727ce030..000000000 --- a/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/StreamingOps.kt +++ /dev/null @@ -1,59 +0,0 @@ -package com.xebia.functional.openai - -import io.ktor.client.statement.HttpResponse -import io.ktor.client.statement.bodyAsChannel -import io.ktor.utils.io.ByteReadChannel -import io.ktor.utils.io.readUTF8Line -import kotlinx.coroutines.flow.FlowCollector -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonObject -import kotlinx.serialization.serializer - -// ServerSentEvent, INTERNAL TO THIS MODULE -// RunDelta | CreateChatCompletionStreamResponse -internal suspend inline fun FlowCollector.streamEvents( - response: HttpResponse, - json: Json, - prefix: String, - end: String -) { - val channel: ByteReadChannel = response.bodyAsChannel() - var nextEvent: String? = null - while (!channel.isClosedForRead) { - val line = channel.readUTF8Line() ?: continue - - // break when we reach the end of the stream - if (line.startsWith(end)) { - break - } - - // if the line is an event like "event: thread.created" we want to ensure - // A is of type ServerSentEvent and we skip the line treating next `prefix` as a JsonObject - // otherwise we treat the line as a json object if it starts with the prefix - // and emit the value - - // if the line is an event like "event: thread.created" we want to ensure - // A is of type ServerSentEvent and we skip the line treating next `prefix` as a JsonObject - if (line.startsWith("event:")) { - nextEvent = line.removePrefix("event:").trim() - continue - } - // otherwise we treat the line as a json object if it starts with the prefix - else if (line.startsWith(prefix) && nextEvent == null) { - val data = line.removePrefix(prefix).trim() - val value: A = json.decodeFromString(serializer(), data) - emit(value) - } - // emit the value for the next event - if (nextEvent != null) { - val data = line.removePrefix(prefix).trim() - if (data.isNotBlank()) { - val eventData = json.decodeFromString(JsonObject.serializer(), data) - val value: A = ServerSentEvent(event = nextEvent, data = eventData) as A - emit(value) - } - } - } - - // serverevent as A -} diff --git a/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/UploadFile.kt b/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/UploadFile.kt deleted file mode 100644 index d97aaac84..000000000 --- a/openai-client/client/src/commonMain/kotlin/com/xebia/functional/openai/UploadFile.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.xebia.functional.openai - -import io.ktor.http.* -import io.ktor.utils.io.core.* - -data class UploadFile( - val filename: String, - val contentType: ContentType? = null, - val size: Long? = null, - val bodyBuilder: BytePacketBuilder.() -> Unit -) diff --git a/openai-client/generator/.openapi-generator-ignore b/openai-client/generator/.openapi-generator-ignore deleted file mode 100644 index 47c8f224b..000000000 --- a/openai-client/generator/.openapi-generator-ignore +++ /dev/null @@ -1,7 +0,0 @@ -**/docs/** -**/README.md -**/test/** -**/org/openapitools/** -**/proguard-rules.pro -**/build.gradle -**/settings.gradle \ No newline at end of file diff --git a/openai-client/generator/README.md b/openai-client/generator/README.md deleted file mode 100644 index 97e0f75c0..000000000 --- a/openai-client/generator/README.md +++ /dev/null @@ -1,77 +0,0 @@ -# OpenAI Client - -Autogenerated client for OpenAI using the OpenAPI specification and [OpenAPI Generator](https://openapi-generator.tech/) - -## Download API Specification - -Requirements: -* File `openai-client/generator/config/openai-api-commit` with the desired commit of the OpenAI API - -Running the task `downloadOpenAIAPI` will read that commit and download the specification into `openai-client/generator/config/openai-api.yaml` - -```shell -./gradlew downloadOpenAIAPI -``` - -## Generate code - -Requirements: -* File `openai-client/generator/config/openai-api.yaml` with the API specification - -Running the task `openaiClientGenerate` will: -* Generate the code with OpenAI Generator using the configuration -* Run the task `spotlessApply` - -```shell -./gradlew openaiClientGenerate -``` - -## Further Customization - -We choose for a semi-manual approach to generate the code. -With a preference for a more controlled way of generating the code, so prefer custom template over workarounds. -This generator add support for `oneOf`, and potentially more in the future. - -Since we focus on KMP, we use KotlinX Serialization and Ktor. -So by being opinionated, we can heavily simply the templates. Which is great for maintainability. - -- [KMMGenerator](src/main/kotlin/com/openai/generator/KMMGenerator.kt) that generates the code. -- config/*.mustache files with the templates for the code generation. - - api.mustache: invoked for each API endpoint. Generates interface, and smart-constructor. - - openai.mustache: the OpenAI interface that exposes all the API endpoints, with fluent syntax. - - model.mustache: invoked for each model. Delegate to the model templates (data, enum, oneOf). - - data.mustache: generates the data class for the model (including nested models). - - enum.mustache: generates the enum class for the model (including nested models). - - oneOf.mustache: generates the sealed class for the model (including nested models). - -### Debugging - -``` -./gradlew openaiClientGenerate -PdebugModels=true > model.log -``` -``` -./gradlew openaiClientGenerate -PdebugOperations=true > operations.log -``` - -You can only debug one of the two properties at a time. _operations_ are used to debug the API endpoints, _models_ are used to debug the models. -It's best to dump the output in a file, such that you can inspect them in a more controlled way, -but they should be included in git! - -### Mustache - -[Mustache(5)](https://mustache.github.io) is being used as template engine, -with [Mustache Java](https://github.com/spullara/mustache.java). - -Quick reference: - - triple `{`: {{{var_name}}} is (HTML escaped) - - double `{{`: {{var_name}} is plain value - - {{#var_name}} ... {{/var_name}} is a section, drill down into model, for each, value present, etc. - - {{^var_name}} ... {{/var_name}} is a negative section, if var_name is empty, or false, etc. - - {{! comment }} is a comment - - {{> partial }} is a partial, include another template - - {{& var_name }} is a triple mustache without escaping - - {{#-first}} ... {{/-first}} only execute for first/last element in an array - - {{^-last}} ... {{/-last}} only execute for first/last element in an array - - {{#lambda.name}} ... {{/lambda.name}} is a lambda, a function that can be called with a parameter - - Following are available: (uppercase, snakecase, titlecase, kebabcase, camelcase, pascalcase, forwardslash, backslash, doublequote, indented, indented_8, indented_12, indented_16, escapeDollar) - - And our custom ones: (oneOfName, capitalised, unquote, jsname) diff --git a/openai-client/generator/build.gradle.kts b/openai-client/generator/build.gradle.kts deleted file mode 100644 index 8e3398049..000000000 --- a/openai-client/generator/build.gradle.kts +++ /dev/null @@ -1,42 +0,0 @@ -@file:Suppress("DSL_SCOPE_VIOLATION") - -plugins { - java - alias(libs.plugins.spotless) -} - -dependencies { - implementation("org.openapitools:openapi-generator-cli:7.4.0") -} - -tasks.test { - useJUnitPlatform() -} - -task("downloadOpenAIAPI", JavaExec::class) { - group = "GenerateTasks" - mainClass = "ai.xef.openai.generator.DownloadOpenAIAPI" - classpath = sourceSets["main"].runtimeClasspath -} - -task("openaiClientGenerate", JavaExec::class) { - group = "GenerateTasks" - mainClass = "org.openapitools.codegen.OpenAPIGenerator" - val command = (listOf( - "generate", - "-i", - "config/openai-api.yaml", - "-g", - "ai.xef.openai.generator.KMMGeneratorConfig", - "-o", - "../client/build/generated/OpenAI/", - "--skip-validate-spec" - ) + if (project.hasProperty("debugModels") && !project.hasProperty("debugOperations")) { - listOf("--global-property", "debugModels=true") - } else if(!project.hasProperty("debugModels") && project.hasProperty("debugOperations")) { - listOf("--global-property", "debugOperations=true") - } else emptyList()) - - args = command - classpath = sourceSets["main"].runtimeClasspath -} diff --git a/openai-client/generator/config/api.mustache b/openai-client/generator/config/api.mustache deleted file mode 100644 index 026d62207..000000000 --- a/openai-client/generator/config/api.mustache +++ /dev/null @@ -1,193 +0,0 @@ -{{>licenseInfo}} -package {{apiPackage}} - -{{#imports}}import {{import}} -{{/imports}} -import com.xebia.functional.openai.Config -import com.xebia.functional.openai.UploadFile -import com.xebia.functional.openai.appendGen -import com.xebia.functional.openai.generated.api.{{classname}}.* -import com.xebia.functional.openai.streamEvents -import io.ktor.client.HttpClient -import io.ktor.client.call.body -import io.ktor.client.plugins.timeout -import io.ktor.client.request.HttpRequestBuilder -import io.ktor.client.request.accept -import io.ktor.client.request.header -import io.ktor.client.request.forms.formData -import io.ktor.client.request.parameter -import io.ktor.client.request.prepareRequest -import io.ktor.client.request.request -import io.ktor.client.request.setBody -import io.ktor.client.statement.HttpResponse -import io.ktor.client.statement.HttpStatement -import io.ktor.http.ContentType -import io.ktor.http.HttpHeaders -import io.ktor.http.HttpMethod -import io.ktor.http.contentType -import io.ktor.http.path -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.flow -import kotlinx.serialization.* -import kotlinx.serialization.descriptors.* -import kotlinx.serialization.encoding.* -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonObject -import kotlinx.serialization.json.jsonObject -import kotlinx.serialization.json.JsonPrimitive -import kotlin.time.Duration.Companion.seconds -import kotlin.time.DurationUnit - -{{#operations}} -/** - * - */ -interface {{classname}} { - {{#operation}} - {{#allParams}} - {{#isEnum}} - - /** - * enum for parameter {{paramName}} - */ - @Serializable - {{#nonPublicApi}}internal {{/nonPublicApi}}enum class {{enumName}}{{operationIdCamelCase}}(val value: {{^isContainer}}{{dataType}}{{/isContainer}}{{#isContainer}}kotlin.String{{/isContainer}}) { - {{^enumUnknownDefaultCase}} - {{#allowableValues}}{{#enumVars}} - @SerialName(value = {{^isString}}"{{/isString}}{{{value}}}{{^isString}}"{{/isString}}) - {{&name}}({{{value}}}){{^-last}},{{/-last}} - {{/enumVars}}{{/allowableValues}} - {{/enumUnknownDefaultCase}} - {{#enumUnknownDefaultCase}} - {{#allowableValues}}{{#enumVars}}{{^-last}} - @SerialName(value = {{^isString}}"{{/isString}}{{{value}}}{{^isString}}"{{/isString}}) - {{&name}}({{{value}}}), - {{/-last}}{{/enumVars}}{{/allowableValues}} - {{/enumUnknownDefaultCase}} - } - - {{/isEnum}} - {{/allParams}} - - /** - * {{summary}} - * {{notes}} - {{#allParams}} * @param {{{paramName}}} {{description}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{#required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}}{{/required}} - {{/allParams}} * @param configure optional configuration for the request, allows overriding the default configuration. - * @return {{{returnType}}}{{^returnType}}void{{/returnType}} - */ - suspend fun {{operationId}}({{#allParams}}{{{paramName}}}: {{#isEnum}}{{# isContainer}}kotlin.collections.List<{{enumName}}{{operationIdCamelCase}}>{{/isContainer}}{{^isContainer}}{{enumName}}{{operationIdCamelCase}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#required}}{{#defaultValue}} = {{^isNumber}}{{#isEnum}}{{enumName}}{{operationIdCamelCase}}.{{enumDefaultValue}}{{/isEnum}}{{^isEnum}}{{{defaultValue}}}{{/isEnum}}{{/isNumber}}{{#isNumber}}{{{defaultValue}}}.toDouble(){{/isNumber}}{{/defaultValue}}{{/required}}{{^required}}?{{#defaultValue}} = {{^isNumber}}{{#isEnum}}{{enumName}}{{operationIdCamelCase}}.{{enumDefaultValue}}{{/isEnum}}{{^isEnum}}{{{defaultValue}}}{{/isEnum}}{{/isNumber}}{{#isNumber}}{{{defaultValue}}}.toDouble(){{/isNumber}}{{/defaultValue}}{{^defaultValue}} = null{{/defaultValue}}{{/required}}, {{/allParams}}configure: HttpRequestBuilder.() -> Unit = {}): {{#returnProperty}}{{#isFile}}HttpResponse{{/isFile}}{{^isFile}}{{{returnType}}}{{^returnType}}Unit{{/returnType}}{{/isFile}}{{/returnProperty}} - - {{#vendorExtensions.x-streaming}} - /** - * Streaming variant: {{summary}} - * By default, the client is modified to timeout after 60 seconds. Which is overridable by the [configure]. - * {{notes}} - {{#allParams}} * @param {{{paramName}}} {{description}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{#required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}}{{/required}} - {{/allParams}} * @param configure optional configuration for the request, allows overriding the default configuration. - * @return [Flow]<[{{{vendorExtensions.x-streaming-return}}}]> - */ - fun {{operationId}}Stream({{#allParams}}{{{paramName}}}: {{#isEnum}}{{# isContainer}}kotlin.collections.List<{{enumName}}{{operationIdCamelCase}}>{{/isContainer}}{{^isContainer}}{{enumName}}{{operationIdCamelCase}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#required}}{{#defaultValue}} = {{^isNumber}}{{#isEnum}}{{enumName}}{{operationIdCamelCase}}.{{enumDefaultValue}}{{/isEnum}}{{^isEnum}}{{{defaultValue}}}{{/isEnum}}{{/isNumber}}{{#isNumber}}{{{defaultValue}}}.toDouble(){{/isNumber}}{{/defaultValue}}{{/required}}{{^required}}?{{#defaultValue}} = {{^isNumber}}{{#isEnum}}{{enumName}}{{operationIdCamelCase}}.{{enumDefaultValue}}{{/isEnum}}{{^isEnum}}{{{defaultValue}}}{{/isEnum}}{{/isNumber}}{{#isNumber}}{{{defaultValue}}}.toDouble(){{/isNumber}}{{/defaultValue}}{{^defaultValue}} = null{{/defaultValue}}{{/required}}, {{/allParams}}configure: HttpRequestBuilder.() -> Unit = {}): Flow<{{{vendorExtensions.x-streaming-return}}}> - {{/vendorExtensions.x-streaming}} - {{/operation}} -} -{{/operations}} - -{{#operations}} -fun {{classname}}(client: HttpClient, config: Config): {{classname}} = object : {{classname}} { - {{#operation}} - override suspend fun {{operationId}}({{#allParams}}{{{paramName}}}: {{#isEnum}}{{# isContainer}}kotlin.collections.List<{{enumName}}{{operationIdCamelCase}}>{{/isContainer}}{{^isContainer}}{{enumName}}{{operationIdCamelCase}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}?{{/required}},{{/allParams}} configure: HttpRequestBuilder.() -> Unit): {{#returnProperty}}{{#isFile}}HttpResponse{{/isFile}}{{^isFile}}{{{returnType}}}{{^returnType}}Unit{{/returnType}}{{/isFile}}{{/returnProperty}} = - client.request { - configure() - method = HttpMethod.{{#lambda.capitalised}}{{httpMethod}}{{/lambda.capitalised}} - {{#headerParams}} - header("{{baseName}}", {{#isContainer}}this.joinToString(separator = collectionDelimiter("{{collectionFormat}}")){{/isContainer}}{{^isContainer}}this.toString(){{/isContainer}}) - {{/headerParams}} - contentType(ContentType.Application.Json) - {{#queryParams}} - parameter("{{baseName}}", {{#isContainer}}toMultiValue(this, "{{collectionFormat}}"){{/isContainer}}{{^isContainer}}{{{paramName}}}{{/isContainer}}) - {{/queryParams}} - url { path("{{#lambda.dropslash}}{{path}}{{/lambda.dropslash}}"{{#pathParams}}.replace("{" + "{{baseName}}" + "}", {{#isContainer}}{{paramName}}.joinToString(","){{/isContainer}}{{^isContainer}}"${{{paramName}}}"{{/isContainer}}){{/pathParams}}) } - setBody({{#hasBodyParam}}{{#bodyParam}}{{#isArray}}{{operationIdCamelCase}}Request({{{paramName}}}{{^isList}}.asList(){{/isList}}){{/isArray}}{{^isArray}}{{#isMap}}{{operationIdCamelCase}}Request({{{paramName}}}){{/isMap}}{{^isMap}}{{{paramName}}}{{/isMap}}{{/isArray}}{{/bodyParam}}{{/hasBodyParam}} - {{^hasBodyParam}} - {{#hasFormParams}} - {{#isMultipart}} - formData { - {{#formParams}} - {{#isArray}} - {{{paramName}}}?.onEach { appendGen("{{{baseName}}}[]", it) } - {{/isArray}} - {{^isArray}} - {{{paramName}}}?.apply { appendGen("{{{baseName}}}", {{{paramName}}}) } - {{/isArray}} - {{/formParams}} - } - {{/isMultipart}} - {{^isMultipart}} - ParametersBuilder().also { - {{#formParams}} - {{{paramName}}}?.apply { it.append("{{{baseName}}}", {{{paramName}}}.toString()) } - {{/formParams}} - }.build() - {{/isMultipart}} - {{/hasFormParams}} - {{^hasFormParams}} - io.ktor.client.utils.EmptyContent - {{/hasFormParams}} - {{/hasBodyParam}}) - }{{#returnProperty}}{{^isFile}}.body(){{/isFile}}{{/returnProperty}} - - {{#vendorExtensions.x-streaming}} - override fun {{operationId}}Stream({{#allParams}}{{{paramName}}}: {{#isEnum}}{{# isContainer}}kotlin.collections.List<{{enumName}}{{operationIdCamelCase}}>{{/isContainer}}{{^isContainer}}{{enumName}}{{operationIdCamelCase}}{{/isContainer}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{#required}}{{#defaultValue}} = {{^isNumber}}{{#isEnum}}{{enumName}}{{operationIdCamelCase}}.{{enumDefaultValue}}{{/isEnum}}{{^isEnum}}{{{defaultValue}}}{{/isEnum}}{{/isNumber}}{{#isNumber}}{{{defaultValue}}}.toDouble(){{/isNumber}}{{/defaultValue}}{{/required}}{{^required}}?{{#defaultValue}} = {{^isNumber}}{{#isEnum}}{{enumName}}{{operationIdCamelCase}}.{{enumDefaultValue}}{{/isEnum}}{{^isEnum}}{{{defaultValue}}}{{/isEnum}}{{/isNumber}}{{#isNumber}}{{{defaultValue}}}.toDouble(){{/isNumber}}{{/defaultValue}}{{^defaultValue}} = null{{/defaultValue}}{{/required}}, {{/allParams}}configure: HttpRequestBuilder.() -> Unit): Flow<{{{vendorExtensions.x-streaming-return}}}> = flow { - client.prepareRequest { - timeout { - requestTimeoutMillis = 60.seconds.toLong(DurationUnit.MILLISECONDS) - socketTimeoutMillis = 60.seconds.toLong(DurationUnit.MILLISECONDS) - } - configure() - method = HttpMethod.{{#lambda.capitalised}}{{httpMethod}}{{/lambda.capitalised}} - accept(ContentType.Text.EventStream) - header(HttpHeaders.CacheControl, "no-cache") - header(HttpHeaders.Connection, "keep-alive") - {{#headerParams}} - header("{{baseName}}", {{#isContainer}}this.joinToString(separator = collectionDelimiter("{{collectionFormat}}")){{/isContainer}}{{^isContainer}}this.toString(){{/isContainer}}) - {{/headerParams}} - contentType(ContentType.Application.Json) - {{#queryParams}} - parameter("{{baseName}}", {{#isContainer}}toMultiValue(this, "{{collectionFormat}}"){{/isContainer}}{{^isContainer}}listOf("${{{paramName}}}"){{/isContainer}}) - {{/queryParams}} - url { path("{{path}}"{{#pathParams}}.replace("{" + "{{baseName}}" + "}", {{#isContainer}}{{paramName}}.joinToString(","){{/isContainer}}{{^isContainer}}"${{{paramName}}}"{{/isContainer}}){{/pathParams}}) } - {{#hasBodyParam}} - val element = Json.encodeToJsonElement({{#lambda.serializer}}{{#bodyParam}}{{{baseName}}}{{/bodyParam}}{{/lambda.serializer}}, {{#bodyParam}}{{{paramName}}}{{/bodyParam}}) - val jsObject = JsonObject(element.jsonObject + Pair("stream", JsonPrimitive(true))) - setBody(jsObject) - {{/hasBodyParam}} - {{^hasBodyParam}} - {{#hasFormParams}} - {{#isMultipart}} - formData { - {{#formParams}} - {{#isArray}} - {{{paramName}}}?.onEach { appendGen("{{{baseName}}}[]", it) } - {{/isArray}} - {{^isArray}} - {{{paramName}}}?.apply { appendGen("{{{baseName}}}", {{{paramName}}}) } - {{/isArray}} - {{/formParams}} - } - {{/isMultipart}} - {{^isMultipart}} - ParametersBuilder().also { - {{#formParams}} - {{{paramName}}}?.apply { it.append("{{{baseName}}}", {{{paramName}}}.toString()) } - {{/formParams}} - }.build() - {{/isMultipart}} - {{/hasFormParams}} - {{/hasBodyParam}} - }.execute { streamEvents(it, config.json, config.streamingPrefix, config.streamingDelimiter) } - } - {{/vendorExtensions.x-streaming}} -{{/operation}} -} -{{/operations}} \ No newline at end of file diff --git a/openai-client/generator/config/data_class.mustache b/openai-client/generator/config/data_class.mustache deleted file mode 100644 index 6ccb7d95f..000000000 --- a/openai-client/generator/config/data_class.mustache +++ /dev/null @@ -1,68 +0,0 @@ -import kotlinx.serialization.Serializable -import kotlinx.serialization.SerialName -import kotlinx.serialization.Contextual -import kotlin.js.JsName -import kotlinx.serialization.json.* -{{#enumUnknownDefaultCase}} -import kotlinx.serialization.KSerializer -import kotlinx.serialization.Serializer -import kotlinx.serialization.builtins.serializer -import kotlinx.serialization.encoding.Decoder -import kotlinx.serialization.encoding.Encoder -{{/enumUnknownDefaultCase}} -{{#hasEnums}} -{{/hasEnums}} - -/** -* {{{description}}} -* -{{#allVars}} - * @param {{{name}}} {{{description}}} -{{/allVars}} -*/ -{{^discriminator}}@Serializable{{/discriminator}} -{{#isDeprecated}}@Deprecated(message = "This schema is deprecated."){{/isDeprecated}} -{{>additionalModelTypeAnnotations}} -{{#nonPublicApi}}internal {{/nonPublicApi}}{{#discriminator}}interface{{/discriminator}}{{^discriminator}}data class{{/discriminator}} {{classname}}{{^discriminator}} ( -{{#allVars}} - {{#required}}{{>data_class_req_var}}{{/required}}{{^required}}{{>data_class_opt_var}}{{/required}}{{^-last}},{{/-last}} -{{/allVars}} -){{/discriminator}}{{#parent}} : {{{parent}}}{{#isMap}}(){{/isMap}}{{#isArray}}(){{/isArray}}{{/parent}} { -{{#discriminator}}{{#vars}}{{#required}} - {{>interface_req_var}}{{/required}}{{^required}} - {{>interface_opt_var}}{{/required}}{{/vars}}{{/discriminator}} -{{#hasEnums}} - {{#vars}} - {{#isEnum}} - /** - * {{{description}}} - * - * Values: {{#allowableValues}}{{#enumVars}}{{&name}}{{^-last}},{{/-last}}{{/enumVars}}{{/allowableValues}} - */ - @Serializable{{#enumUnknownDefaultCase}}(with = {{classname}}Serializer::class){{/enumUnknownDefaultCase}} - {{#nonPublicApi}}internal {{/nonPublicApi}}enum class {{{nameInCamelCase}}}(val value: {{dataType}}) { - {{#allowableValues}} - {{#enumVars}} - @SerialName(value = {{#lambda.doublequote}}{{{value}}}{{/lambda.doublequote}}) {{#lambda.jsname}}{{&name}}{{/lambda.jsname}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}} - {{/enumVars}} - {{/allowableValues}} - }{{#kotlinx_serialization}}{{#enumUnknownDefaultCase}} - - @Serializer(forClass = {{{nameInCamelCase}}}::class) - internal object {{nameInCamelCase}}Serializer : KSerializer<{{nameInCamelCase}}> { - override val descriptor = {{{dataType}}}.serializer().descriptor - - override fun deserialize(decoder: Decoder): {{nameInCamelCase}} { - val value = decoder.decodeSerializableValue({{{dataType}}}.serializer()) - return {{nameInCamelCase}}.values().firstOrNull { it.value == value } - ?: {{nameInCamelCase}}.{{#allowableValues}}{{#enumVars}}{{#-last}}{{&name}}{{/-last}}{{/enumVars}}{{/allowableValues}} - } - - override fun serialize(encoder: Encoder, value: {{nameInCamelCase}}) { - encoder.encodeSerializableValue({{{dataType}}}.serializer(), value.value) - } - }{{/enumUnknownDefaultCase}}{{/kotlinx_serialization}} - {{/isEnum}} - {{/vars}} -{{/hasEnums}} -} \ No newline at end of file diff --git a/openai-client/generator/config/data_class_opt_var.mustache b/openai-client/generator/config/data_class_opt_var.mustache deleted file mode 100644 index d59b528d1..000000000 --- a/openai-client/generator/config/data_class_opt_var.mustache +++ /dev/null @@ -1,7 +0,0 @@ -{{#description}} - /* {{{.}}} */ -{{/description}} - {{#deprecated}} - @Deprecated(message = "This property is deprecated.") - {{/deprecated}} - @SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}") {{#isInherited}}override {{/isInherited}}{{>modelMutable}} {{{name}}}: {{#isArray}}{{#isList}}{{#uniqueItems}}kotlin.collections.{{#modelMutable}}Mutable{{/modelMutable}}Set{{/uniqueItems}}{{^uniqueItems}}kotlin.collections.{{#modelMutable}}Mutable{{/modelMutable}}List{{/uniqueItems}}{{/isList}}{{^isList}}kotlin.Array{{/isList}}<{{^items.isEnum}}{{^items.isPrimitiveType}}{{^items.isModel}}{{#kotlinx_serialization}}@Contextual {{/kotlinx_serialization}}{{/items.isModel}}{{/items.isPrimitiveType}}{{{items.dataType}}}{{/items.isEnum}}{{#items.isEnum}}{{classname}}.{{{nameInCamelCase}}}{{/items.isEnum}}>{{/isArray}}{{^isEnum}}{{^isArray}}{{{dataType}}}{{/isArray}}{{/isEnum}}{{#isEnum}}{{^isArray}}{{classname}}.{{{nameInCamelCase}}}{{/isArray}}{{/isEnum}}? = {{^defaultValue}}null{{/defaultValue}}{{#defaultValue}}{{^isNumber}}{{{defaultValue}}}{{/isNumber}}{{#isNumber}}({{{defaultValue}}}).toDouble(){{/isNumber}}{{/defaultValue}} \ No newline at end of file diff --git a/openai-client/generator/config/data_class_req_var.mustache b/openai-client/generator/config/data_class_req_var.mustache deleted file mode 100644 index 17b800584..000000000 --- a/openai-client/generator/config/data_class_req_var.mustache +++ /dev/null @@ -1,7 +0,0 @@ -{{#description}} - /* {{{.}}} */ -{{/description}} - {{#deprecated}} - @Deprecated(message = "This property is deprecated.") - {{/deprecated}} - @SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}") {{#isInherited}}override {{/isInherited}}val {{{name}}}: {{#isArray}}{{#isList}}{{#uniqueItems}}kotlin.collections.Set{{/uniqueItems}}{{^uniqueItems}}kotlin.collections.List{{/uniqueItems}}{{/isList}}{{^isList}}kotlin.Array{{/isList}}<{{^items.isEnum}}{{^items.isPrimitiveType}}{{^items.isModel}}@Contextual {{/items.isModel}}{{/items.isPrimitiveType}}{{{items.dataType}}}{{/items.isEnum}}{{#items.isEnum}}{{classname}}.{{{nameInCamelCase}}}{{/items.isEnum}}>{{/isArray}}{{^isEnum}}{{^isArray}}{{{dataType}}}{{/isArray}}{{/isEnum}}{{#isEnum}}{{^isArray}}{{classname}}.{{{nameInCamelCase}}}{{/isArray}}{{/isEnum}}{{#isNullable}}?{{/isNullable}}{{#defaultValue}} = {{^isNumber}}{{{defaultValue}}}{{/isNumber}}{{#isNumber}}({{{defaultValue}}}).toDouble(){{/isNumber}}{{/defaultValue}} \ No newline at end of file diff --git a/openai-client/generator/config/enum_class.mustache b/openai-client/generator/config/enum_class.mustache deleted file mode 100644 index 535b97aa5..000000000 --- a/openai-client/generator/config/enum_class.mustache +++ /dev/null @@ -1,53 +0,0 @@ -import kotlinx.serialization.* -import kotlinx.serialization.builtins.* -import kotlinx.serialization.encoding.* -import kotlin.jvm.JvmStatic -{{#allowableValues}}{{#enumVars}}import com.xebia.functional.openai.generated.model.{{classname}}.Supported.{{#lambda.unquote}}{{&value}}{{/lambda.unquote}} -{{/enumVars}}{{/allowableValues}} - -/** - * {{{description}}} - */ -// We define a serializer for the parent sum type, and then use it to serialize the child types -@Suppress("SERIALIZER_TYPE_INCOMPATIBLE") -@Serializable(with = {{classname}}Serializer::class) -sealed interface {{classname}} { - val value: {{{dataType}}} - - @Serializable(with = {{classname}}Serializer::class) - enum class Supported(override val value: {{{dataType}}}) : {{classname}} { - {{#allowableValues}}{{#enumVars}}@SerialName(value = {{{value}}}) {{#lambda.unquote}}{{&value}}{{/lambda.unquote}}({{#isArray}}{{#isList}}listOf({{{value}}})){{/isList}}{{^isList}}arrayOf({{{value}}})){{/isList}}{{/isArray}}{{^isArray}}{{#isString}}{{#lambda.doublequote}}{{{value}}}{{/lambda.doublequote}}{{/isString}}{{^isString}}{{{value}}}{{/isString}}{{/isArray}}){{^-last}},{{/-last}}{{#-last}};{{/-last}}{{/enumVars}}{{/allowableValues}} - - override fun toString(): kotlin.String = value{{^isString}}.toString(){{/isString}} - } - - @Serializable(with = {{classname}}Serializer::class) - data class Custom(override val value: kotlin.String) : {{classname}} - - companion object { - @JvmStatic - fun valueOf(value: {{{dataType}}}): {{classname}} = - values().firstOrNull { it.value == value } ?: Custom(value) - - {{#allowableValues}}{{#enumVars}} - inline val {{#lambda.unquote}}{{&value}}{{/lambda.unquote}}: {{classname}} - get() = Supported.{{#lambda.unquote}}{{&value}}{{/lambda.unquote}} - {{/enumVars}}{{/allowableValues}} - - @JvmStatic fun values(): List<{{classname}}> = Supported.entries - } -} - -object {{classname}}Serializer : KSerializer<{{classname}}> { - private val valueSerializer = {{{dataType}}}.serializer() - override val descriptor = valueSerializer.descriptor - - override fun deserialize(decoder: Decoder): {{classname}} { - val value = decoder.decodeSerializableValue(valueSerializer) - return {{classname}}.valueOf(value) - } - - override fun serialize(encoder: Encoder, value: {{classname}}) { - encoder.encodeSerializableValue(valueSerializer, value.value) - } -} diff --git a/openai-client/generator/config/model.mustache b/openai-client/generator/config/model.mustache deleted file mode 100644 index bf6667742..000000000 --- a/openai-client/generator/config/model.mustache +++ /dev/null @@ -1,17 +0,0 @@ -{{>licenseInfo}} -package {{modelPackage}} - -{{#imports}}import {{import}} -{{/imports}} -{{#models}} -{{#model}} -{{! We execute this block only for the _first_ element: if oneOf is not empty, execute the template }} -{{#oneOf}}{{#-first}}{{>model_oneof}}{{/-first}}{{/oneOf}}{{^oneOf}} -{{#isEnum}}{{>enum_class}}{{/isEnum}}{{^isEnum}} -{{#isAlias}}typealias {{classname}} = {{{dataType}}}{{/isAlias}}{{^isAlias}} -{{>data_class}} -{{/isAlias}} -{{/isEnum}} -{{/oneOf}} -{{/model}} -{{/models}} \ No newline at end of file diff --git a/openai-client/generator/config/model_oneof.mustache b/openai-client/generator/config/model_oneof.mustache deleted file mode 100644 index 132176c5d..000000000 --- a/openai-client/generator/config/model_oneof.mustache +++ /dev/null @@ -1,41 +0,0 @@ -import com.xebia.functional.openai.attemptDeserialize -import kotlin.jvm.JvmInline -import kotlinx.serialization.* -import kotlinx.serialization.builtins.* -import kotlinx.serialization.descriptors.* -import kotlinx.serialization.encoding.* -import kotlinx.serialization.json.* - -@Serializable(with = {{classname}}Serializer::class) -sealed interface {{classname}} { - - {{#oneOf}} - @JvmInline - @Serializable - value class Case{{#lambda.oneOfName}}{{{.}}}{{/lambda.oneOfName}}(val value: {{{.}}}): {{classname}} - {{/oneOf}} - -} - -object {{classname}}Serializer : KSerializer<{{classname}}> { - @OptIn(InternalSerializationApi::class, ExperimentalSerializationApi::class) - override val descriptor: SerialDescriptor = buildSerialDescriptor("{{classname}}", PolymorphicKind.SEALED) { {{#oneOf}} - element("{{#lambda.oneOfName}}{{-index}}{{/lambda.oneOfName}}", {{#lambda.serializer}}{{{.}}}{{/lambda.serializer}}.descriptor){{/oneOf}} - } - - override fun deserialize(decoder: Decoder): {{classname}} { - val jsonSerde = Json { ignoreUnknownKeys = true } - val json = decoder.decodeSerializableValue(JsonElement.serializer()) - return attemptDeserialize(json, {{#oneOf}} - Pair({{classname}}.Case{{#lambda.oneOfName}}{{{.}}}{{/lambda.oneOfName}}::class) { - {{classname}}.Case{{#lambda.oneOfName}}{{{.}}}{{/lambda.oneOfName}}(jsonSerde.decodeFromJsonElement({{#lambda.serializer}}{{{.}}}{{/lambda.serializer}}, json)) - }{{#-last}}){{/-last}}{{^-last}},{{/-last}}{{/oneOf}} - } - - override fun serialize(encoder: Encoder, value: {{classname}}) = - when(value) { {{#oneOf}} - is {{classname}}.Case{{#lambda.oneOfName}}{{{.}}}{{/lambda.oneOfName}} -> - encoder.encodeSerializableValue({{#lambda.serializer}}{{{.}}}{{/lambda.serializer}}, value.value) - {{/oneOf}} - } -} diff --git a/openai-client/generator/config/openai-api-commit b/openai-client/generator/config/openai-api-commit deleted file mode 100644 index 7965a2453..000000000 --- a/openai-client/generator/config/openai-api-commit +++ /dev/null @@ -1 +0,0 @@ -44306c2f4534144e169721e2ad160e00b6823bc7 diff --git a/openai-client/generator/config/openai.mustache b/openai-client/generator/config/openai.mustache deleted file mode 100644 index f9cc7a5fc..000000000 --- a/openai-client/generator/config/openai.mustache +++ /dev/null @@ -1,26 +0,0 @@ -{{#apiInfo}} -{{>licenseInfo}} -package {{apiPackage}} - -import com.xebia.functional.openai.Config -import io.ktor.client.HttpClient -{{#imports}}import {{import}} -{{/imports}} -{{#apis}}import com.xebia.functional.openai.generated.api.{{classFilename}} -{{/apis}} - -interface OpenAI : AutoCloseable { -{{#apis}} - val {{#lambda.camelcase}}{{classFilename}}{{/lambda.camelcase}}: {{classFilename}} -{{/apis}} -} - -fun OpenAI(client: HttpClient, config: Config): OpenAI = object : OpenAI, AutoCloseable { -{{#apis}} - override val {{#lambda.camelcase}}{{classFilename}}{{/lambda.camelcase}} = {{classFilename}}(client, config) -{{/apis}} - - override fun close() = client.close() -} - -{{/apiInfo}} \ No newline at end of file diff --git a/openai-client/generator/gradle.properties b/openai-client/generator/gradle.properties deleted file mode 100644 index 1eda1733c..000000000 --- a/openai-client/generator/gradle.properties +++ /dev/null @@ -1 +0,0 @@ -org.gradle.jvmargs="-Dlog.level=debug --global-property debugModels" \ No newline at end of file diff --git a/openai-client/generator/src/main/java/ai/xef/openai/generator/DownloadOpenAIAPI.java b/openai-client/generator/src/main/java/ai/xef/openai/generator/DownloadOpenAIAPI.java deleted file mode 100644 index e0570e9fc..000000000 --- a/openai-client/generator/src/main/java/ai/xef/openai/generator/DownloadOpenAIAPI.java +++ /dev/null @@ -1,40 +0,0 @@ -package ai.xef.openai.generator; - -import java.io.*; -import java.net.URL; -import java.nio.channels.Channels; -import java.nio.channels.FileChannel; -import java.nio.channels.ReadableByteChannel; - -public class DownloadOpenAIAPI { - public static void main(String[] args) { - try { - String commit = readCommit(); - downloadAPI(commit); - - // list streaming methods - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - private static String readCommit() throws IOException { - StringBuilder resultStringBuilder = new StringBuilder(); - try (BufferedReader br = new BufferedReader(new FileReader("config/openai-api-commit"))) { - String line; - while ((line = br.readLine()) != null) { - resultStringBuilder.append(line).append("\n"); - } - } - return resultStringBuilder.toString().trim(); - } - - private static void downloadAPI(String commit) throws IOException { - URL url = new URL("https://raw.githubusercontent.com/openai/openai-openapi/%s/openapi.yaml".formatted(commit)); - ReadableByteChannel readableByteChannel = Channels.newChannel(url.openStream()); - try (FileOutputStream fileOutputStream = new FileOutputStream("config/openai-api.yaml")) { - FileChannel fileChannel = fileOutputStream.getChannel(); - fileChannel.transferFrom(readableByteChannel, 0, Long.MAX_VALUE); - } - } -} diff --git a/openai-client/generator/src/main/java/ai/xef/openai/generator/KMMGeneratorConfig.java b/openai-client/generator/src/main/java/ai/xef/openai/generator/KMMGeneratorConfig.java deleted file mode 100644 index 6e732cb7b..000000000 --- a/openai-client/generator/src/main/java/ai/xef/openai/generator/KMMGeneratorConfig.java +++ /dev/null @@ -1,308 +0,0 @@ -package ai.xef.openai.generator; - -import com.google.common.collect.ImmutableMap; -import com.samskivert.mustache.Mustache; -import com.samskivert.mustache.Template; -import org.apache.commons.lang3.NotImplementedException; -import org.apache.commons.lang3.tuple.Pair; -import org.openapitools.codegen.*; -import org.openapitools.codegen.languages.KotlinClientCodegen; -import org.openapitools.codegen.model.ModelMap; -import org.openapitools.codegen.model.ModelsMap; -import org.openapitools.codegen.model.OperationsMap; - -import java.io.IOException; -import java.io.Writer; -import java.util.*; - -import static java.util.Map.entry; - -@SuppressWarnings("unused") -public class KMMGeneratorConfig extends KotlinClientCodegen { - - - private final Map> nonRequiredFields = new LinkedHashMap<>(); - - @Override - public String getIgnoreFilePathOverride() { - return ".openapi-generator-ignore"; - } - - public KMMGeneratorConfig() { - super(); - - // Generate in src/commonMain/kotlin, not /src/main/kotlin - additionalProperties.put("sourceFolder", "src/commonMain/kotlin"); - additionalProperties.put("generateModelTests", false); - additionalProperties.put("generateApiTests", false); - additionalProperties.put("generateInfrastructure", false); - setModelPackage("com.xebia.functional.openai.generated.model"); - setApiPackage("com.xebia.functional.openai.generated.api"); - additionalProperties.put("apiSuffix", ""); - additionalProperties.put("modelSuffix", ""); - - // Configure OpenAI `object` to be mapped to `JsonObject` - typeMapping.put("object", "JsonObject"); - importMapping.put("JsonObject", "kotlinx.serialization.json.JsonObject"); - - typeMapping.put("java.net.URI", "kotlin.String"); - - typeMapping.put("java.math.BigDecimal", "kotlin.Double"); - importMapping.put("BigDecimal", "kotlin.Double"); - - typeMapping.put("java.io.File", "UploadFile"); - importMapping.put("java.io.File", "com.xebia.functional.openai.UploadFile"); - - // Maps `Map` to `JsonObject` - schemaMapping.put("FunctionParameters", "kotlinx.serialization.json.JsonObject"); - - // Configure the template directory - templateDir = "config"; - supportingFiles.add(new SupportingFile("openai.mustache", "src/commonMain/kotlin/" + apiPackage.replace(".", "/"), "OpenAI.kt")); - - omitGradleWrapper = true; - serializationLibrary = SERIALIZATION_LIBRARY_TYPE.kotlinx_serialization; - - defaultIncludes.remove("io.ktor.client.request.forms.InputProvider"); - defaultIncludes.add("com.xebia.functional.openai.apis.UploadFile"); - - importMapping.remove("InputProvider"); - importMapping.put("UploadFile", "com.xebia.functional.openai.apis.UploadFile"); - - // Fixes for DateTime - dateLibrary = DateLibrary.KOTLINX_DATETIME.value; - typeMapping.put("date", "kotlinx.datetime.LocalDate"); - typeMapping.put("date-time", "kotlinx.datetime.Instant"); - typeMapping.put("DateTime", "Instant"); - importMapping.put("Instant", "kotlinx.datetime.Instant"); - - specialCharReplacements.put("-", "_"); - specialCharReplacements.put(".", "_"); - // TODO PascalCase!?! - enumPropertyNaming = CodegenConstants.ENUM_PROPERTY_NAMING_TYPE.snake_case; - nonRequiredFields.putAll( - Map.ofEntries( - entry("ListAssistantFilesResponse", List.of("firstId", "lastId")), - entry("ListAssistantsResponse", List.of("firstId", "lastId")), - entry("ListMessageFilesResponse", List.of("firstId", "lastId")), - entry("ListMessagesResponse", List.of("firstId", "lastId")), - entry("ListRunsResponse", List.of("firstId", "lastId")), - entry("ListRunStepsResponse", List.of("firstId", "lastId")), - entry("ListThreadsResponse", List.of("firstId", "lastId")), - entry("MessageObject", List.of("metadata")), - entry("MessageObjectContentInner", List.of("imageFile", "text")), - entry("RunObject", List.of("expiresAt", "requiredAction")), - entry("RunStepDetailsToolCallsCodeObjectCodeInterpreterOutputsInner", List.of("logs", "image")), - entry("RunStepDetailsToolCallsFunctionObjectFunction", List.of("name", "arguments", "output")), - entry("RunStepDetailsToolCallsFunctionObject", List.of("id")), - entry("RunStepDetailsToolCallsObjectToolCallsInner", List.of("codeInterpreter", "retrieval", "function")), - entry("RunStepDetailsToolCallsRetrievalObject", List.of("retrieval")), - entry("RunStepObject", List.of("expiredAt", "metadata")), - entry("MessageContentTextObjectTextAnnotationsInner", List.of("filePath", "fileCitation")) - ) - ); - } - - private Optional readEnumModel(List all) { - if (all.size() == 2) { - CodegenProperty first = all.get(0); - CodegenProperty second = all.get(1); - if (first.isString && second.isEnum) { - return Optional.of(second); - } - } - return Optional.empty(); - } - - /** - * Map - * Used to generate additional code for operations that support streaming. - *

- * Extra streaming operation will be generated for OperationId, and the return type will be Flow. - */ - private final static Map> streamingOps = Map.of( - "createThreadAndRun", Pair.of("com.xebia.functional.openai", "ServerSentEvent"), - "createRun", Pair.of("com.xebia.functional.openai", "ServerSentEvent"), - "submitToolOuputsToRun", Pair.of("com.xebia.functional.openai", "ServerSentEvent"), - "createChatCompletion", Pair.of("com.xebia.functional.openai.generated.model", "CreateChatCompletionStreamResponse") - ); - - /** - * Add the `x-streaming` vendor extension to the operations that are streaming, - * and add `x-streaming-return` of the return type of the operation. - *

- * This is used in the mustache template to generate additional code for operations that support streaming. - */ - @Override - public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List allModels) { - objs.getOperations() - .getOperation() - .forEach((op) -> { - if (streamingOps.containsKey(op.operationId)) { - op.vendorExtensions.put("x-streaming", true); - Pair returnType = streamingOps.get(op.operationId); - Map imports = Map.of( - "import", returnType.getKey() + "." + returnType.getValue(), - "classname", returnType.getValue() - ); - if(!objs.getImports().contains(imports)) { - objs.getImports().add(imports); - } - op.vendorExtensions.put("x-streaming-return", returnType.getValue()); - } - } - ); - return super.postProcessOperationsWithModels(objs, allModels); - } - - @Override - public ModelsMap postProcessModels(ModelsMap objs) { - for (ModelMap mo : objs.getModels()) { - CodegenModel cm = mo.getModel(); - if (cm.anyOf != null && !cm.anyOf.isEmpty()) { - Optional codegenProperty = readEnumModel(cm.getComposedSchemas().getAnyOf()); - codegenProperty.ifPresent((enumProp) -> { - cm.modelJson = enumProp.jsonSchema; - cm.interfaces = null; - cm.anyOf = new HashSet<>(); - cm.dataType = enumProp.dataType; - cm.isString = enumProp.isString; - cm.allowableValues = enumProp.allowableValues; - cm.isEnum = enumProp.isEnum; - cm.setIsAnyType(enumProp.isAnyType); - cm.setComposedSchemas(null); - }); - } else if (nonRequiredFields.containsKey(cm.classname)) { - List fields = nonRequiredFields.getOrDefault(cm.classname, Collections.emptyList()); - cm - .allVars - .stream() - .filter(p -> fields.contains(p.name)) - .forEach(p -> p.setRequired(false)); - } - } - return super.postProcessModels(objs); - } - - @Override - protected ImmutableMap.Builder addMustacheLambdas() { - return super.addMustacheLambdas() - .put("oneOfName", new OneOfName()) - .put("capitalised", new Capitalised()) - .put("unquote", new Unquote()) - .put("jsname", new JsName()) - .put("serializer", new Serializer()) - .put("dropslash", new DropSlash()); - } - - /* Mechanism to do array access in mustache... - * We need to generate names for the cases of `oneOf`, - * where we generate a `sealed interface` with the Schema name, - * and a `data class CaseInnerType(val value: InnerType)` for each of the `oneOf` cases. */ - public static class OneOfName implements Mustache.Lambda { - public void execute(Template.Fragment fragment, Writer writer) throws IOException { - serializer(writer, fragment.execute().trim(), 0); - } - - private void serializer( - Writer buffer, - String text, - int depth - ) throws IOException { - if (text.startsWith("kotlin.collections.List<")) { - String inner = text.substring(24, text.length() - 1); - serializer(buffer, inner, depth + 1); - } else if (text.startsWith("kotlin.collections.")) { - throw new NotImplementedException(text + " collection serialization not supported **yet**"); - } else { - if (text.startsWith("kotlin.")) { - text = text.substring(7); - } - buffer.write(text); - if (depth > 0) { - buffer.write("s"); - depth--; - } - while (depth-- > 0) { - buffer.write("List"); - } - } - } - } - - /* Lambda to generate the `@JsName` annotation for the `length` property, - * can be generalised to other properties/names if needed */ - public static class JsName implements Mustache.Lambda { - public void execute(Template.Fragment fragment, Writer writer) throws IOException { - String text = fragment.execute(); - if (text.equals("length")) { - writer.write("@JsName(\"length_type\") length"); - } else { - writer.write(text); - } - } - } - - /* Lambda to capitalise the first letter of a string, and lowercase the rest */ - public static class Capitalised implements Mustache.Lambda { - public void execute(Template.Fragment fragment, Writer writer) throws IOException { - String text = fragment.execute(); - writer.write(text.substring(0, 1).toUpperCase() + text.substring(1).toLowerCase(Locale.ROOT)); - } - } - - /* Drop first `/` from a path */ - public static class DropSlash implements Mustache.Lambda { - public void execute(Template.Fragment fragment, Writer writer) throws IOException { - String text = fragment.execute(); - if (text.startsWith("/")) { - writer.write(text.substring(1)); - } else { - writer.write(text); - } - } - } - - /* enum with `gpt-` are trimmed by `gpt_`, the raw value needs to trim the surrounding `"` */ - public static class Unquote implements Mustache.Lambda { - public void execute(Template.Fragment fragment, Writer writer) throws IOException { - String text = snakeCase(fragment.execute()); - if (text.startsWith("\"") && text.endsWith("\"")) { - writer.write(text.substring(1, text.length() - 1)); - } else { - writer.write(text); - } - } - - // Poor man lower snakeCase - private String snakeCase(String text) { - return text.replace("-", "_").replace(".", "_"); - } - } - - /* Most advanced lambda, to generate the `serializer()` call for the `kotlinx.serialization` library. - * This works for ListSerializer, but can work for much more!! */ - public static class Serializer implements Mustache.Lambda { - public void execute(Template.Fragment fragment, Writer writer) throws IOException { - serializer(writer, fragment.execute().trim(), 0); - } - - private void serializer( - Writer buffer, - String text, - int depth - ) throws IOException { - if (text.startsWith("kotlin.collections.List<")) { - String inner = text.substring(24, text.length() - 1); - buffer.write("ListSerializer("); - serializer(buffer, inner, depth + 1); - } else if (text.startsWith("Map<")) { - throw new NotImplementedException("Map serialization not supported **yet**"); - } else { - buffer.write(text); - buffer.write(".serializer()"); - buffer.write(")".repeat(Math.max(0, depth))); - } - } - } -} diff --git a/server/src/main/kotlin/com/xebia/functional/xef/server/services/PostgresVectorStoreService.kt b/server/src/main/kotlin/com/xebia/functional/xef/server/services/PostgresVectorStoreService.kt index 6f764ea4e..d18886477 100644 --- a/server/src/main/kotlin/com/xebia/functional/xef/server/services/PostgresVectorStoreService.kt +++ b/server/src/main/kotlin/com/xebia/functional/xef/server/services/PostgresVectorStoreService.kt @@ -1,6 +1,5 @@ package com.xebia.functional.xef.server.services -import com.xebia.functional.openai.generated.model.CreateEmbeddingRequestModel import com.xebia.functional.xef.Config import com.xebia.functional.xef.OpenAI import com.xebia.functional.xef.store.PGVectorStore @@ -8,6 +7,7 @@ import com.xebia.functional.xef.store.VectorStore import com.xebia.functional.xef.store.postgresql.PGDistanceStrategy import com.xebia.functional.xef.store.postgresql.addNewCollection import com.xebia.functional.xef.store.postgresql.connection +import io.github.nomisrev.openapi.CreateEmbeddingRequestModel import io.github.oshai.kotlinlogging.KLogger import javax.sql.DataSource import kotlinx.uuid.UUID diff --git a/settings.gradle.kts b/settings.gradle.kts index dbb1da79e..76e37a56a 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -8,6 +8,7 @@ dependencyResolutionManagement { pluginManagement { repositories { + mavenLocal() mavenCentral() gradlePluginPortal() } @@ -26,13 +27,6 @@ project(":xef-filesystem").projectDir = file("filesystem") include("xef-tokenizer") project(":xef-tokenizer").projectDir = file("tokenizer") - -include("xef-openai-client") -project(":xef-openai-client").projectDir = file("openai-client/client") - -include("xef-openai-client-generator") -project(":xef-openai-client-generator").projectDir = file("openai-client/generator") - // // From 0dfefeb679757a404ed13c7d50b69365e6effeef Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Tue, 25 Jun 2024 10:48:43 +0200 Subject: [PATCH 2/8] Building. 1st run --- .../xef/llm/assistants/Assistant.kt | 6 +- .../xef/llm/assistants/AssistantThread.kt | 66 ++++++------ .../functional/xef/store/MemorizedMessage.kt | 2 +- .../xef/conversation/ConversationSpec.kt | 44 ++++---- .../xebia/functional/xef/data/TestChatApi.kt | 100 +++++++++--------- .../functional/xef/data/TestEmbeddings.kt | 7 +- .../xef/prompt/PromptBuilderSpec.kt | 4 +- .../xef/store/CombinedVectorStoreSpec.kt | 4 +- .../xef/store/LocalVectorStoreSpec.kt | 4 +- .../xebia/functional/xef/store/MemoryData.kt | 7 +- .../functional/xef/evaluator/SuiteBuilder.kt | 8 +- .../xef/assistants/AssistantStreaming.kt | 2 +- .../xebia/functional/xef/assistants/DSL.kt | 2 +- .../xef/conversation/conversations/Animal.kt | 4 +- .../functional/xef/dsl/audio/SimpleSpeech.kt | 34 +++--- .../xebia/functional/xef/dsl/chat/Classes.kt | 4 +- .../xef/dsl/classify/AnswerAccuracy.kt | 4 +- .../xef/dsl/images/ImagesExamples.kt | 11 +- .../functional/xef/evaluator/TestExample.kt | 6 +- .../OpenTelemetryAssistantState.kt | 24 ++--- .../xef/store/PostgreSQLVectorStore.kt | 14 +-- .../src/test/kotlin/xef/MemoryData.kt | 7 +- .../src/test/kotlin/xef/PGVectorStoreSpec.kt | 12 +-- .../src/test/kotlin/xef/TestEmbeddings.kt | 17 ++- .../com/xebia/functional/xef/sql/SQL.kt | 6 +- .../functional/xef/sql/jdbc/JdbcConfig.kt | 6 +- .../services/PostgresVectorStoreService.kt | 6 +- 27 files changed, 200 insertions(+), 211 deletions(-) diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/Assistant.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/Assistant.kt index 3d2f15e83..84b29d06c 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/Assistant.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/Assistant.kt @@ -73,7 +73,7 @@ class Assistant( @Serializable data class ToolOutput(val schema: JsonObject, val result: JsonElement) suspend operator fun invoke( - model: CreateAssistantRequest.Model, + model: String, name: String? = null, description: String? = null, instructions: String? = null, @@ -177,7 +177,7 @@ class Assistant( assistant.modify( ModifyAssistantRequest( - model = ModifyAssistantRequest.Model.CaseString(assistantRequest.model), + model = assistantRequest.model, name = assistantRequest.name, description = assistantRequest.description, instructions = assistantRequest.instructions, @@ -196,7 +196,7 @@ class Assistant( Assistant( request = CreateAssistantRequest( - model = CreateAssistantRequest.Model.CaseString(assistantRequest.model), + model = assistantRequest.model, name = assistantRequest.name, description = assistantRequest.description, instructions = assistantRequest.instructions, diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/AssistantThread.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/AssistantThread.kt index 9dbffcbc7..8828ce398 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/AssistantThread.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/AssistantThread.kt @@ -17,14 +17,14 @@ class AssistantThread( val threadId: String, val metric: Metric = Metric.EMPTY, private val config: Config = Config(), - private val api: OpenAPI = OpenAI(config) + private val threads: Threads = OpenAI(config).threads ) { suspend fun delete(): Boolean = - api.threads.deleteThread(threadId = threadId, configure = ::defaultConfig).deleted + threads.deleteThread(threadId = threadId, configure = ::defaultConfig).deleted suspend fun modify(request: ModifyThreadRequest): AssistantThread = - AssistantThread(api.threads.modifyThread(threadId, request, configure = ::defaultConfig).id) + AssistantThread(threads.modifyThread(threadId, request, configure = ::defaultConfig).id) suspend fun createMessage(message: MessageWithFiles): MessageObject = createMessage( @@ -40,10 +40,10 @@ class AssistantThread( createMessage(CreateMessageRequest(role = CreateMessageRequest.Role.User, content = content)) suspend fun createMessage(request: CreateMessageRequest): MessageObject = - api.threads.messages.createMessage(threadId, request, configure = ::defaultConfig) + threads.messages.createMessage(threadId, request, configure = ::defaultConfig) suspend fun getMessage(messageId: String): MessageObject = - api.threads.messages.getMessage(threadId, messageId, configure = ::defaultConfig) + threads.messages.getMessage(threadId, messageId, configure = ::defaultConfig) data class ThreadMessagesFilter( val limit: Int? = 20, @@ -55,7 +55,7 @@ class AssistantThread( suspend fun listMessages( filter: ThreadMessagesFilter = ThreadMessagesFilter() ): List = - api.threads.messages + threads.messages .listMessages( threadId = threadId, limit = filter.limit, @@ -70,10 +70,10 @@ class AssistantThread( createRun(CreateRunRequest(assistantId = assistant.assistantId)) suspend fun createRun(request: CreateRunRequest): RunObject = - api.threads.runs.createRun(threadId, request, configure = ::defaultConfig).addMetrics(metric) + threads.runs.createRun(threadId, request, configure = ::defaultConfig).addMetrics(metric) fun createRunStream(assistant: Assistant, request: CreateRunRequest): Flow = flow { - api.threads.runs + threads.runs .createRunStream(threadId, request, configure = ::defaultConfig) .map { RunDelta.fromServerSentEvent(it) } .map { it.addMetrics(metric) } @@ -102,7 +102,7 @@ class AssistantThread( event.run.status == RunObject.Status.RequiresAction && event.run.requiredAction?.type == RunObject.RequiredAction.Type.SubmitToolOutputs ) { - val calls = event.run.requiredAction?.submitToolOutputs?.toolCalls.orEmpty() + val calls = event.run.requiredAction.submitToolOutputs.toolCalls val callsResult: List> = calls.parMapNotNull { toolCall -> assistantThread.executeToolCall(toolCall, assistant) } val results: Map = callsResult.toMap() @@ -118,7 +118,7 @@ class AssistantThread( ) val run = metric.assistantToolOutputsRun(event.run.id) { - api.threads.runs.submitToolOutputs + threads.runs.submitToolOutputs .submitToolOuputsToRunStream( threadId = threadId, runId = event.run.id, @@ -168,13 +168,9 @@ class AssistantThread( val function = toolCall.function val functionName = function.name val functionArguments = function.arguments - return if (functionName != null && functionArguments != null) { - val result = assistant.getToolRegistered(functionName, functionArguments) - val callId = toolCall.id - if (callId != null) { - callId to result - } else null - } else null + val result = assistant.getToolRegistered(functionName, functionArguments) + val callId = toolCall.id + return callId to result } catch (e: Throwable) { toolCall.id to Assistant.Companion.ToolOutput( @@ -185,16 +181,16 @@ class AssistantThread( } suspend fun getRun(runId: String): RunObject = - api.threads.runs.getRun(threadId, runId, configure = ::defaultConfig) + threads.runs.getRun(threadId, runId, configure = ::defaultConfig) fun run(assistant: Assistant): Flow = createRunStream(assistant, CreateRunRequest(assistantId = assistant.assistantId)) suspend fun cancelRun(runId: String): RunObject = - api.threads.runs.cancel.cancelRun(threadId, runId, configure = ::defaultConfig) + threads.runs.cancel.cancelRun(threadId, runId, configure = ::defaultConfig) suspend fun runSteps(runId: String): List = - api.threads.runs.steps.listRunSteps(threadId, runId, configure = ::defaultConfig).data + threads.runs.steps.listRunSteps(threadId, runId, configure = ::defaultConfig).data private fun RunStepObject.StepDetails.toolCalls(): List = when (val step = this) { @@ -215,11 +211,11 @@ class AssistantThread( metadata: JsonObject? = null, metric: Metric = Metric.EMPTY, config: Config = Config(), - api: OpenAPI = OpenAI(config) + threads: Threads = OpenAI(config).threads ): AssistantThread = AssistantThread( threadId = - api.threads + threads .createThread( body = CreateThreadRequest( @@ -237,7 +233,7 @@ class AssistantThread( .id, metric = metric, config = config, - api = api + threads = threads ) @JvmName("createWithMessages") @@ -246,10 +242,10 @@ class AssistantThread( metadata: JsonObject? = null, metric: Metric = Metric.EMPTY, config: Config = Config(), - api: OpenAPI = OpenAI(config) + threads: Threads = OpenAI(config).threads ): AssistantThread = AssistantThread( - api.threads + threads .createThread( body = CreateThreadRequest( @@ -263,7 +259,7 @@ class AssistantThread( .id, metric, config, - api + threads ) @JvmName("createWithRequests") @@ -272,41 +268,41 @@ class AssistantThread( metadata: JsonObject? = null, metric: Metric = Metric.EMPTY, config: Config = Config(), - api: OpenAPI = OpenAI(config) + threads: Threads = OpenAI(config).threads ): AssistantThread = AssistantThread( - api.threads + threads .createThread(CreateThreadRequest(messages, metadata), configure = ::defaultConfig) .id, metric, config, - api + threads ) suspend operator fun invoke( request: CreateThreadRequest, metric: Metric = Metric.EMPTY, config: Config = Config(), - api: OpenAPI = OpenAI(config) + threads: Threads = OpenAI(config).threads ): AssistantThread = AssistantThread( - api.threads.createThread(request, configure = ::defaultConfig).id, + threads.createThread(request, configure = ::defaultConfig).id, metric, config, - api + threads ) suspend operator fun invoke( request: CreateThreadAndRunRequest, metric: Metric = Metric.EMPTY, config: Config = Config(), - api: OpenAPI = OpenAI(config) + threads: Threads = OpenAI(config).threads ): AssistantThread = AssistantThread( - api.threads.runs.createThreadAndRun(request, configure = ::defaultConfig).id, + threads.runs.createThreadAndRun(request, configure = ::defaultConfig).id, metric, config, - api + threads ) } } diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/store/MemorizedMessage.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/store/MemorizedMessage.kt index 643a9fe7c..b46ee4af5 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/store/MemorizedMessage.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/store/MemorizedMessage.kt @@ -7,7 +7,7 @@ sealed class MemorizedMessage { val role: ChatCompletionRole get() = when (this) { - is Request -> ChatCompletionRole.valueOf(message.completionRole().value) + is Request -> message.completionRole() is Response -> ChatCompletionRole.valueOf(message.role.name) } diff --git a/core/src/commonTest/kotlin/com/xebia/functional/xef/conversation/ConversationSpec.kt b/core/src/commonTest/kotlin/com/xebia/functional/xef/conversation/ConversationSpec.kt index eadbe1015..b42ae4ebd 100644 --- a/core/src/commonTest/kotlin/com/xebia/functional/xef/conversation/ConversationSpec.kt +++ b/core/src/commonTest/kotlin/com/xebia/functional/xef/conversation/ConversationSpec.kt @@ -31,7 +31,7 @@ class ConversationSpec : val conversationId = ConversationId(UUID.generateUUID().toString()) val chatApi = TestChatApi() - val model = CreateChatCompletionRequestModel.gpt_4 + val model = CreateChatCompletionRequest.Model.Gpt4 val scope = Conversation( @@ -69,7 +69,7 @@ class ConversationSpec : val vectorStore = scope.store val chatApi = TestChatApi(responses = messages) - val model = CreateChatCompletionRequestModel.gpt_3_5_turbo + val model = CreateChatCompletionRequest.Model.Gpt35Turbo val totalTokens = model.modelType().tokensFromMessages(messages.flatMap(::chatCompletionRequestMessages)) @@ -105,7 +105,7 @@ class ConversationSpec : val vectorStore = scope.store val chatApi = TestChatApi(responses = messages) - val model = CreateChatCompletionRequestModel.gpt_3_5_turbo_16k + val model = CreateChatCompletionRequest.Model.Gpt35Turbo16k val totalTokens = model.modelType().tokensFromMessages(messages.flatMap(::chatCompletionRequestMessages)) @@ -139,7 +139,7 @@ class ConversationSpec : ) val chatApi = TestChatApi(message) - val model = CreateChatCompletionRequestModel.gpt_3_5_turbo_16k + val model = CreateChatCompletionRequest.Model.Gpt35Turbo16k val response: Answer = chatApi.prompt( @@ -172,7 +172,7 @@ class ConversationSpec : ) val chatApi = TestChatApi(message) - val model = CreateChatCompletionRequestModel.gpt_3_5_turbo_0613 + val model = CreateChatCompletionRequest.Model.Gpt35Turbo0613 val response: Answer = chatApi.prompt( @@ -192,7 +192,7 @@ class ConversationSpec : val conversationId = ConversationId(UUID.generateUUID().toString()) val chatApi = TestChatApi() - val model = CreateChatCompletionRequestModel.gpt_3_5_turbo + val model = CreateChatCompletionRequest.Model.Gpt35Turbo val scope = Conversation( @@ -212,7 +212,7 @@ class ConversationSpec : val firstResponse = chatApi.promptMessage(prompt = firstPrompt, scope = scope) val aiFirstMessage = ChatCompletionRequestAssistantMessage( - role = ChatCompletionRequestAssistantMessage.Role.assistant, + role = ChatCompletionRequestAssistantMessage.Role.Assistant, content = firstResponse ) @@ -221,7 +221,7 @@ class ConversationSpec : val secondResponse = chatApi.promptMessage(prompt = secondPrompt, scope = scope) val aiSecondMessage = ChatCompletionRequestAssistantMessage( - role = ChatCompletionRequestAssistantMessage.Role.assistant, + role = ChatCompletionRequestAssistantMessage.Role.Assistant, content = secondResponse ) @@ -234,7 +234,7 @@ class ConversationSpec : val thirdResponse = chatApi.promptMessage(prompt = thirdPrompt, scope = scope) val aiThirdMessage = ChatCompletionRequestAssistantMessage( - role = ChatCompletionRequestAssistantMessage.Role.assistant, + role = ChatCompletionRequestAssistantMessage.Role.Assistant, content = secondResponse ) @@ -257,7 +257,7 @@ class ConversationSpec : val conversationId = ConversationId(UUID.generateUUID().toString()) val chatApi = TestChatApi() - val model = CreateChatCompletionRequestModel.gpt_3_5_turbo + val model = CreateChatCompletionRequest.Model.Gpt35Turbo val vectorStore = LocalVectorStore(TestEmbeddings()) @@ -290,7 +290,7 @@ class ConversationSpec : val conversationId = ConversationId(UUID.generateUUID().toString()) val chatApi = TestChatApi() - val model = CreateChatCompletionRequestModel.gpt_3_5_turbo + val model = CreateChatCompletionRequest.Model.Gpt35Turbo val vectorStore = LocalVectorStore(TestEmbeddings()) @@ -319,7 +319,7 @@ class ConversationSpec : val conversationId = ConversationId(UUID.generateUUID().toString()) val chatApi = TestChatApi() - val model = CreateChatCompletionRequestModel.gpt_3_5_turbo + val model = CreateChatCompletionRequest.Model.Gpt35Turbo val vectorStore = LocalVectorStore(TestEmbeddings()) @@ -343,14 +343,14 @@ class ConversationSpec : println(messagesStored) - messagesStored.filter { it.content.role == ChatCompletionRole.system } shouldBe messagesStored + messagesStored.filter { it.content.role == ChatCompletionRole.System } shouldBe messagesStored } "when using MessagesToHistory.NOT_SYSTEM_MESSAGES policy, the scope's store shouldn't contains system messages" { val conversationId = ConversationId(UUID.generateUUID().toString()) val chatApi = TestChatApi() - val model = CreateChatCompletionRequestModel.gpt_3_5_turbo + val model = CreateChatCompletionRequest.Model.Gpt35Turbo val vectorStore = LocalVectorStore(TestEmbeddings()) @@ -372,14 +372,14 @@ class ConversationSpec : val messagesStored = scope.store.memories(model, conversationId, Int.MAX_VALUE) - messagesStored.filter { it.content.role != ChatCompletionRole.system } shouldBe messagesStored + messagesStored.filter { it.content.role != ChatCompletionRole.System } shouldBe messagesStored } "when using MessagesToHistory.NONE policy, the scope's store shouldn't contains messages" { val conversationId = ConversationId(UUID.generateUUID().toString()) val chatApi = TestChatApi() - val model = CreateChatCompletionRequestModel.gpt_3_5_turbo + val model = CreateChatCompletionRequest.Model.Gpt35Turbo val vectorStore = LocalVectorStore(TestEmbeddings()) @@ -401,7 +401,7 @@ class ConversationSpec : val messagesStored = scope.store.memories(model, conversationId, Int.MAX_VALUE).filter { - it.content.role == ChatCompletionRole.system + it.content.role == ChatCompletionRole.System } messagesStored.size shouldBe 0 @@ -411,7 +411,7 @@ class ConversationSpec : val conversationId = ConversationId(UUID.generateUUID().toString()) val chatApi = TestChatApi() - val model = CreateChatCompletionRequestModel.gpt_3_5_turbo + val model = CreateChatCompletionRequest.Model.Gpt35Turbo val vectorStore = LocalVectorStore(TestEmbeddings()) @@ -447,7 +447,7 @@ class ConversationSpec : val conversationId = ConversationId(UUID.generateUUID().toString()) val chatApi = TestChatApi() - val model = CreateChatCompletionRequestModel.gpt_3_5_turbo + val model = CreateChatCompletionRequest.Model.Gpt35Turbo val vectorStore = LocalVectorStore(TestEmbeddings()) @@ -484,13 +484,13 @@ private fun chatCompletionRequestMessages(it: Map.Entry) = listOf( ChatCompletionRequestMessage.CaseChatCompletionRequestUserMessage( ChatCompletionRequestUserMessage( - role = ChatCompletionRequestUserMessage.Role.user, - content = ChatCompletionRequestUserMessageContent.CaseString(it.key) + role = ChatCompletionRequestUserMessage.Role.User, + content = ChatCompletionRequestUserMessage.Content.CaseString(it.key) ) ), ChatCompletionRequestMessage.CaseChatCompletionRequestAssistantMessage( ChatCompletionRequestAssistantMessage( - role = ChatCompletionRequestAssistantMessage.Role.assistant, + role = ChatCompletionRequestAssistantMessage.Role.Assistant, content = it.value ) ), diff --git a/core/src/commonTest/kotlin/com/xebia/functional/xef/data/TestChatApi.kt b/core/src/commonTest/kotlin/com/xebia/functional/xef/data/TestChatApi.kt index d0ea2553c..afd7cc724 100644 --- a/core/src/commonTest/kotlin/com/xebia/functional/xef/data/TestChatApi.kt +++ b/core/src/commonTest/kotlin/com/xebia/functional/xef/data/TestChatApi.kt @@ -1,64 +1,62 @@ package com.xebia.functional.xef.data -import com.xebia.functional.openai.generated.api.Chat import com.xebia.functional.xef.prompt.contentAsString import io.github.nomisrev.openapi.* import io.ktor.client.request.* import kotlinx.coroutines.flow.Flow -class TestChatApi(private val responses: Map = emptyMap()) : Chat, AutoCloseable { +class TestChatApi(private val responses: Map = emptyMap()) : Chat { var requests: MutableList = mutableListOf() - override suspend fun createChatCompletion( - createChatCompletionRequest: CreateChatCompletionRequest, - configure: HttpRequestBuilder.() -> Unit - ): CreateChatCompletionResponse { - requests.add(createChatCompletionRequest) - val response = - CreateChatCompletionResponse( - id = "fake-id", - `object` = CreateChatCompletionResponse.Object.chat_completion, - created = 0, - model = "fake-model", - choices = - listOf( - CreateChatCompletionResponseChoicesInner( - message = - ChatCompletionResponseMessage( - role = ChatCompletionResponseMessage.Role.assistant, - content = - responses[createChatCompletionRequest.messages.last().contentAsString()] - ?: "fake-content", - toolCalls = - listOf( - ChatCompletionMessageToolCall( - id = "fake-tool-id", - type = ChatCompletionMessageToolCall.Type.function, - function = - ChatCompletionMessageToolCallFunction( - "fake-function-name", - """{ "bar": "fake-answer" }""" + override val completions: Chat.Completions = + object : Chat.Completions { + override suspend fun createChatCompletion( + body: CreateChatCompletionRequest, + configure: HttpRequestBuilder.() -> Unit + ): CreateChatCompletionResponse { + requests.add(body) + val response = + CreateChatCompletionResponse( + id = "fake-id", + `object` = CreateChatCompletionResponse.Object.ChatCompletion, + created = 0, + model = "fake-model", + choices = + listOf( + CreateChatCompletionResponse.Choices( + message = + ChatCompletionResponseMessage( + role = ChatCompletionResponseMessage.Role.Assistant, + content = responses[body.messages.last().contentAsString()] ?: "fake-content", + toolCalls = + listOf( + ChatCompletionMessageToolCall( + id = "fake-tool-id", + type = ChatCompletionMessageToolCall.Type.Function, + function = + ChatCompletionMessageToolCall.Function( + "fake-function-name", + """{ "bar": "fake-answer" }""" + ) ) - ) - ) - ), - finishReason = CreateChatCompletionResponseChoicesInner.FinishReason.stop, - index = 0, - logprobs = null - ) - ), - usage = CompletionUsage(0, 0, 0) - ) - return response - } + ) + ), + finishReason = CreateChatCompletionResponse.Choices.FinishReason.Stop, + index = 0, + logprobs = null + ) + ), + usage = CompletionUsage(0, 0, 0) + ) + return response + } - override fun createChatCompletionStream( - createChatCompletionRequest: CreateChatCompletionRequest, - configure: HttpRequestBuilder.() -> Unit - ): Flow { - throw NotImplementedError("Not implemented") - } - - override fun close() {} + override suspend fun createChatCompletionStream( + body: CreateChatCompletionRequest, + configure: HttpRequestBuilder.() -> Unit + ): Flow { + TODO("Not yet implemented") + } + } } diff --git a/core/src/commonTest/kotlin/com/xebia/functional/xef/data/TestEmbeddings.kt b/core/src/commonTest/kotlin/com/xebia/functional/xef/data/TestEmbeddings.kt index cba871576..2186f5724 100644 --- a/core/src/commonTest/kotlin/com/xebia/functional/xef/data/TestEmbeddings.kt +++ b/core/src/commonTest/kotlin/com/xebia/functional/xef/data/TestEmbeddings.kt @@ -1,9 +1,8 @@ package com.xebia.functional.xef.data -import com.xebia.functional.openai.generated.api.Embeddings import io.github.nomisrev.openapi.CreateEmbeddingRequest import io.github.nomisrev.openapi.CreateEmbeddingResponse -import io.github.nomisrev.openapi.CreateEmbeddingResponseUsage +import io.github.nomisrev.openapi.Embeddings import io.ktor.client.request.* class TestEmbeddings : Embeddings, AutoCloseable { @@ -19,8 +18,8 @@ class TestEmbeddings : Embeddings, AutoCloseable { CreateEmbeddingResponse( data = emptyList(), model = "", - `object` = CreateEmbeddingResponse.Object.list, - usage = CreateEmbeddingResponseUsage(0, 0) + `object` = CreateEmbeddingResponse.Object.List, + usage = CreateEmbeddingResponse.Usage(0, 0) ) return response } diff --git a/core/src/commonTest/kotlin/com/xebia/functional/xef/prompt/PromptBuilderSpec.kt b/core/src/commonTest/kotlin/com/xebia/functional/xef/prompt/PromptBuilderSpec.kt index 2f23a2227..1daaddcce 100644 --- a/core/src/commonTest/kotlin/com/xebia/functional/xef/prompt/PromptBuilderSpec.kt +++ b/core/src/commonTest/kotlin/com/xebia/functional/xef/prompt/PromptBuilderSpec.kt @@ -3,13 +3,13 @@ package com.xebia.functional.xef.prompt import com.xebia.functional.xef.prompt.PromptBuilder.Companion.assistant import com.xebia.functional.xef.prompt.PromptBuilder.Companion.system import com.xebia.functional.xef.prompt.PromptBuilder.Companion.user -import io.github.nomisrev.openapi.CreateChatCompletionRequestModel +import io.github.nomisrev.openapi.CreateChatCompletionRequest import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe class PromptBuilderSpec : StringSpec({ - val model = CreateChatCompletionRequestModel.gpt_4 + val model = CreateChatCompletionRequest.Model.Gpt4 "buildPrompt should return the expected messages" { val messages = Prompt(model) { diff --git a/core/src/commonTest/kotlin/com/xebia/functional/xef/store/CombinedVectorStoreSpec.kt b/core/src/commonTest/kotlin/com/xebia/functional/xef/store/CombinedVectorStoreSpec.kt index 27ab176c9..263a60e6c 100644 --- a/core/src/commonTest/kotlin/com/xebia/functional/xef/store/CombinedVectorStoreSpec.kt +++ b/core/src/commonTest/kotlin/com/xebia/functional/xef/store/CombinedVectorStoreSpec.kt @@ -3,13 +3,13 @@ package com.xebia.functional.xef.store import com.xebia.functional.xef.data.TestEmbeddings import com.xebia.functional.xef.llm.models.modelType import com.xebia.functional.xef.llm.tokensFromMessages -import io.github.nomisrev.openapi.CreateChatCompletionRequestModel +import io.github.nomisrev.openapi.CreateChatCompletionRequest import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe class CombinedVectorStoreSpec : StringSpec({ - val model = CreateChatCompletionRequestModel.gpt_3_5_turbo + val model = CreateChatCompletionRequest.Model.Gpt35Turbo "memories function should return all of messages combined in the right order" { val memoryData = MemoryData() diff --git a/core/src/commonTest/kotlin/com/xebia/functional/xef/store/LocalVectorStoreSpec.kt b/core/src/commonTest/kotlin/com/xebia/functional/xef/store/LocalVectorStoreSpec.kt index 4a23ee314..5fefbbb74 100644 --- a/core/src/commonTest/kotlin/com/xebia/functional/xef/store/LocalVectorStoreSpec.kt +++ b/core/src/commonTest/kotlin/com/xebia/functional/xef/store/LocalVectorStoreSpec.kt @@ -3,13 +3,13 @@ package com.xebia.functional.xef.store import com.xebia.functional.xef.data.TestEmbeddings import com.xebia.functional.xef.llm.models.modelType import com.xebia.functional.xef.llm.tokensFromMessages -import io.github.nomisrev.openapi.CreateChatCompletionRequestModel +import io.github.nomisrev.openapi.CreateChatCompletionRequest import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe class LocalVectorStoreSpec : StringSpec({ - val model = CreateChatCompletionRequestModel.gpt_3_5_turbo + val model = CreateChatCompletionRequest.Model.Gpt35Turbo "memories function should return all of messages in the right order when the limit is greater than the number of stored messages" { val localVectorStore = LocalVectorStore(TestEmbeddings()) diff --git a/core/src/commonTest/kotlin/com/xebia/functional/xef/store/MemoryData.kt b/core/src/commonTest/kotlin/com/xebia/functional/xef/store/MemoryData.kt index 6888e301b..7958c7f4c 100644 --- a/core/src/commonTest/kotlin/com/xebia/functional/xef/store/MemoryData.kt +++ b/core/src/commonTest/kotlin/com/xebia/functional/xef/store/MemoryData.kt @@ -4,7 +4,6 @@ import arrow.atomic.AtomicInt import io.github.nomisrev.openapi.ChatCompletionRequestAssistantMessage import io.github.nomisrev.openapi.ChatCompletionRequestMessage import io.github.nomisrev.openapi.ChatCompletionRequestUserMessage -import io.github.nomisrev.openapi.ChatCompletionRequestUserMessageContent class MemoryData { val defaultConversationId = ConversationId("default-id") @@ -19,15 +18,15 @@ class MemoryData { (0 until n).flatMap { val m1 = ChatCompletionRequestUserMessage( - role = ChatCompletionRequestUserMessage.Role.user, + role = ChatCompletionRequestUserMessage.Role.User, content = - ChatCompletionRequestUserMessageContent.CaseString( + ChatCompletionRequestUserMessage.Content.CaseString( "Question $it${append?.let { ": $it" } ?: ""}" ) ) val m2 = ChatCompletionRequestAssistantMessage( - role = ChatCompletionRequestAssistantMessage.Role.assistant, + role = ChatCompletionRequestAssistantMessage.Role.Assistant, content = "Response $it${append?.let { ": $it" } ?: ""}" ) listOf( diff --git a/evaluator/src/main/kotlin/com/xebia/functional/xef/evaluator/SuiteBuilder.kt b/evaluator/src/main/kotlin/com/xebia/functional/xef/evaluator/SuiteBuilder.kt index 2c631b47f..12b646b91 100644 --- a/evaluator/src/main/kotlin/com/xebia/functional/xef/evaluator/SuiteBuilder.kt +++ b/evaluator/src/main/kotlin/com/xebia/functional/xef/evaluator/SuiteBuilder.kt @@ -2,7 +2,7 @@ package com.xebia.functional.xef.evaluator import com.xebia.functional.xef.AI import com.xebia.functional.xef.evaluator.models.* -import io.github.nomisrev.openapi.CreateChatCompletionRequestModel +import io.github.nomisrev.openapi.CreateChatCompletionRequest import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json @@ -10,7 +10,7 @@ import kotlinx.serialization.serializer class SuiteBuilder( private val description: String, - private val model: CreateChatCompletionRequestModel + private val model: CreateChatCompletionRequest.Model ) { private val items = mutableListOf() @@ -26,7 +26,7 @@ class SuiteBuilder( data class SuiteSpec( val description: String, val items: List, - val model: CreateChatCompletionRequestModel + val model: CreateChatCompletionRequest.Model ) { suspend inline fun evaluate(success: List): SuiteResults where @@ -58,7 +58,7 @@ data class SuiteSpec( @JvmSynthetic suspend operator fun invoke( description: String, - model: CreateChatCompletionRequestModel, + model: CreateChatCompletionRequest.Model, block: suspend SuiteBuilder.() -> Unit ): SuiteSpec = SuiteBuilder(description, model).apply { block() }.build() diff --git a/examples/src/main/kotlin/com/xebia/functional/xef/assistants/AssistantStreaming.kt b/examples/src/main/kotlin/com/xebia/functional/xef/assistants/AssistantStreaming.kt index 54e82823a..f18e5f01a 100644 --- a/examples/src/main/kotlin/com/xebia/functional/xef/assistants/AssistantStreaming.kt +++ b/examples/src/main/kotlin/com/xebia/functional/xef/assistants/AssistantStreaming.kt @@ -17,7 +17,7 @@ suspend fun main() { assistantId = "asst_UxczzpJkysC0l424ood87DAk", toolsConfig = listOf(Tool.toolOf(SumTool())) ) - val thread = AssistantThread(api = OpenAI().assistants, metric = metric) + val thread = AssistantThread(threads = OpenAI().threads, metric = metric) println("Welcome to the Math tutor, ask me anything about math:") val userInput = "What is 1+1, explain all the steps and tools you used to solve it." thread.createMessage(userInput) diff --git a/examples/src/main/kotlin/com/xebia/functional/xef/assistants/DSL.kt b/examples/src/main/kotlin/com/xebia/functional/xef/assistants/DSL.kt index ff00ac381..ffd1596f9 100644 --- a/examples/src/main/kotlin/com/xebia/functional/xef/assistants/DSL.kt +++ b/examples/src/main/kotlin/com/xebia/functional/xef/assistants/DSL.kt @@ -50,7 +50,7 @@ suspend fun main() { assistantId = "asst_UxczzpJkysC0l424ood87DAk", toolsConfig = listOf(Tool.toolOf(SumTool())) ) - val thread = AssistantThread(api = OpenAI(logRequests = false).assistants, metric = metric) + val thread = AssistantThread(threads = OpenAI(logRequests = false).threads, metric = metric) println("Welcome to the Math tutor, ask me anything about math:") while (true) { println() diff --git a/examples/src/main/kotlin/com/xebia/functional/xef/conversation/conversations/Animal.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/conversations/Animal.kt index 783b43d55..ffc4dfc06 100644 --- a/examples/src/main/kotlin/com/xebia/functional/xef/conversation/conversations/Animal.kt +++ b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/conversations/Animal.kt @@ -11,7 +11,7 @@ import com.xebia.functional.xef.prompt.PromptBuilder.Companion.system import com.xebia.functional.xef.prompt.PromptBuilder.Companion.user import com.xebia.functional.xef.prompt.configuration.PromptConfiguration import com.xebia.functional.xef.store.LocalVectorStore -import io.github.nomisrev.openapi.CreateChatCompletionRequestModel +import io.github.nomisrev.openapi.CreateChatCompletionRequest import kotlinx.serialization.Serializable @Serializable data class Animal(val name: String, val habitat: String, val diet: String) @@ -35,7 +35,7 @@ suspend fun main() { val configNoneFromConversation = PromptConfiguration { messagePolicy { addMessagesFromConversation = MessagesFromHistory.NONE } } - val model = CreateChatCompletionRequestModel.gpt_3_5_turbo_16k_0613 + val model = CreateChatCompletionRequest.Model.Gpt35Turbo16k0613 val animal: Animal = AI( Prompt(model) { +user("A unique animal species.") } diff --git a/examples/src/main/kotlin/com/xebia/functional/xef/dsl/audio/SimpleSpeech.kt b/examples/src/main/kotlin/com/xebia/functional/xef/dsl/audio/SimpleSpeech.kt index 7dc25c0e6..a44250931 100644 --- a/examples/src/main/kotlin/com/xebia/functional/xef/dsl/audio/SimpleSpeech.kt +++ b/examples/src/main/kotlin/com/xebia/functional/xef/dsl/audio/SimpleSpeech.kt @@ -1,13 +1,13 @@ package com.xebia.functional.xef.dsl.audio import com.sipgate.mp3wav.Converter -import com.xebia.functional.openai.UploadFile import com.xebia.functional.xef.AI import com.xebia.functional.xef.Config import com.xebia.functional.xef.OpenAI import io.github.nomisrev.openapi.CreateSpeechRequest -import io.github.nomisrev.openapi.CreateSpeechRequestModel -import io.github.nomisrev.openapi.CreateTranscriptionRequestModel +import io.github.nomisrev.openapi.CreateTranscriptionRequest +import io.github.nomisrev.openapi.CreateTranslationRequest +import io.github.nomisrev.openapi.UploadFile import io.ktor.client.statement.* import io.ktor.utils.io.jvm.javaio.* import java.io.File @@ -28,11 +28,11 @@ suspend fun main() { .trimIndent() ) val channel = - audio.createSpeech( + audio.speech.createSpeech( CreateSpeechRequest( - model = CreateSpeechRequestModel.tts_1, + model = CreateSpeechRequest.Model.Tts1, input = modelResponse, - voice = CreateSpeechRequest.Voice.nova + voice = CreateSpeechRequest.Voice.Nova ) ) val wavConverter = Converter(channel.bodyAsChannel().toInputStream()) @@ -51,19 +51,23 @@ suspend fun main() { bodyBuilder = { file.readBytes().forEach { writeByte(it) } } ) val transcription = - audio.createTranscription( - model = CreateTranscriptionRequestModel.whisper_1, - prompt = "Translate to spanish", - file = uploadFile, - language = "es", + audio.transcriptions.createTranscription( + CreateTranscriptionRequest( + file = uploadFile, + model = CreateTranscriptionRequest.Model.Whisper1, + prompt = "Translate to spanish", + language = "es" + ) ) println("transcription in `es`:") println(transcription) val translation = - audio.createTranslation( - model = CreateTranscriptionRequestModel.whisper_1, - prompt = "Translate", - file = uploadFile, + audio.translations.createTranslation( + CreateTranslationRequest( + file = uploadFile, + model = CreateTranslationRequest.Model.Whisper1, + prompt = "Translate" + ) ) println("translation to english:") println(translation) diff --git a/examples/src/main/kotlin/com/xebia/functional/xef/dsl/chat/Classes.kt b/examples/src/main/kotlin/com/xebia/functional/xef/dsl/chat/Classes.kt index 69cd8e3c8..01049ab74 100644 --- a/examples/src/main/kotlin/com/xebia/functional/xef/dsl/chat/Classes.kt +++ b/examples/src/main/kotlin/com/xebia/functional/xef/dsl/chat/Classes.kt @@ -10,7 +10,7 @@ import com.xebia.functional.xef.prompt.PromptBuilder.Companion.assistant import com.xebia.functional.xef.prompt.PromptBuilder.Companion.system import com.xebia.functional.xef.prompt.PromptBuilder.Companion.user import com.xebia.functional.xef.prompt.configuration.PromptConfiguration -import io.github.nomisrev.openapi.CreateChatCompletionRequestModel +import io.github.nomisrev.openapi.CreateChatCompletionRequest import kotlinx.serialization.Serializable @Serializable @@ -26,7 +26,7 @@ data class Book( ) suspend fun books(topic: String): Books { - val model = CreateChatCompletionRequestModel.gpt_4_turbo_preview + val model = CreateChatCompletionRequest.Model.Gpt4TurboPreview val myCustomPrompt = Prompt( diff --git a/examples/src/main/kotlin/com/xebia/functional/xef/dsl/classify/AnswerAccuracy.kt b/examples/src/main/kotlin/com/xebia/functional/xef/dsl/classify/AnswerAccuracy.kt index 352f19a1a..bb18163a9 100644 --- a/examples/src/main/kotlin/com/xebia/functional/xef/dsl/classify/AnswerAccuracy.kt +++ b/examples/src/main/kotlin/com/xebia/functional/xef/dsl/classify/AnswerAccuracy.kt @@ -2,7 +2,7 @@ package com.xebia.functional.xef.dsl.classify import com.xebia.functional.xef.AI import com.xebia.functional.xef.evaluator.metrics.AnswerAccuracy -import io.github.nomisrev.openapi.CreateChatCompletionRequestModel +import io.github.nomisrev.openapi.CreateChatCompletionRequest /** * This is a simple example of how to use the `AI.classify` function to classify the accuracy of an @@ -21,7 +21,7 @@ suspend fun main() { input = "Do I love Xef?", output = "I have three opened PRs", context = "The answer responds the question", - model = CreateChatCompletionRequestModel.gpt_3_5_turbo_0125 + model = CreateChatCompletionRequest.Model.Gpt35Turbo0125 ) ) } diff --git a/examples/src/main/kotlin/com/xebia/functional/xef/dsl/images/ImagesExamples.kt b/examples/src/main/kotlin/com/xebia/functional/xef/dsl/images/ImagesExamples.kt index 409815f10..8f56d88d4 100644 --- a/examples/src/main/kotlin/com/xebia/functional/xef/dsl/images/ImagesExamples.kt +++ b/examples/src/main/kotlin/com/xebia/functional/xef/dsl/images/ImagesExamples.kt @@ -3,16 +3,17 @@ package com.xebia.functional.xef.dsl.images import com.xebia.functional.xef.OpenAI import com.xebia.functional.xef.llm.asInputProvider import io.github.nomisrev.openapi.CreateImageRequest +import io.github.nomisrev.openapi.CreateImageVariationRequest suspend fun main() { val openAI = OpenAI(logRequests = true) val ai = openAI.images - val image = - ai.createImage( - createImageRequest = CreateImageRequest(prompt = "Event horizon in a black hole") - ) + val image = ai.generations.createImage(CreateImageRequest("Event horizon in a black hole")) val generatedImage = image.data.first() println("Image: $generatedImage") - val variant = ai.createImageVariation(generatedImage.asInputProvider()) + val variant = + ai.variations.createImageVariation( + CreateImageVariationRequest(generatedImage.asInputProvider()) + ) println("Variant: $variant") } diff --git a/examples/src/main/kotlin/com/xebia/functional/xef/evaluator/TestExample.kt b/examples/src/main/kotlin/com/xebia/functional/xef/evaluator/TestExample.kt index aadb066f7..bcd43d2eb 100644 --- a/examples/src/main/kotlin/com/xebia/functional/xef/evaluator/TestExample.kt +++ b/examples/src/main/kotlin/com/xebia/functional/xef/evaluator/TestExample.kt @@ -9,19 +9,19 @@ import com.xebia.functional.xef.evaluator.models.OutputResponse import com.xebia.functional.xef.llm.promptMessage import com.xebia.functional.xef.prompt.Prompt import com.xebia.functional.xef.prompt.PromptBuilder.Companion.user -import io.github.nomisrev.openapi.CreateChatCompletionRequestModel +import io.github.nomisrev.openapi.CreateChatCompletionRequest object TestExample { @JvmStatic fun main(args: Array) = SuspendApp { - val model = CreateChatCompletionRequestModel.gpt_3_5_turbo_16k + val model = CreateChatCompletionRequest.Model.Gpt35Turbo16k val chat = OpenAI(logRequests = true).chat val spec = SuiteSpec( description = "Check GTP3.5 and fake outputs", - model = CreateChatCompletionRequestModel.gpt_4_turbo_preview + model = CreateChatCompletionRequest.Model.Gpt4TurboPreview ) { val gpt35Description = OutputDescription("Using GPT3.5") val fakeOutputs = OutputDescription("Fake outputs with errors") diff --git a/integrations/opentelemetry/src/main/kotlin/com/xebia/functional/xef/opentelemetry/OpenTelemetryAssistantState.kt b/integrations/opentelemetry/src/main/kotlin/com/xebia/functional/xef/opentelemetry/OpenTelemetryAssistantState.kt index 1c1579eb1..c2048082a 100644 --- a/integrations/opentelemetry/src/main/kotlin/com/xebia/functional/xef/opentelemetry/OpenTelemetryAssistantState.kt +++ b/integrations/opentelemetry/src/main/kotlin/com/xebia/functional/xef/opentelemetry/OpenTelemetryAssistantState.kt @@ -107,15 +107,15 @@ class OpenTelemetryAssistantState(private val tracer: Tracer) { val output = block() currentSpan.makeCurrent().use { when (val detail = output.stepDetails) { - is RunStepObjectStepDetails.CaseRunStepDetailsMessageCreationObject -> + is RunStepObject.StepDetails.CaseRunStepDetailsMessageCreationObject -> currentSpan.updateName("Creating message: ${output.status.name}") - is RunStepObjectStepDetails.CaseRunStepDetailsToolCallsObject -> + is RunStepObject.StepDetails.CaseRunStepDetailsToolCallsObject -> currentSpan.updateName( "Tools: ${detail.value.toolCalls.joinToString { when (it) { - is RunStepDetailsToolCallsObjectToolCallsInner.CaseRunStepDetailsToolCallsCodeObject -> it.value.type.name - is RunStepDetailsToolCallsObjectToolCallsInner.CaseRunStepDetailsToolCallsFunctionObject -> it.value.function.name ?: "" - is RunStepDetailsToolCallsObjectToolCallsInner.CaseRunStepDetailsToolCallsRetrievalObject -> it.value.type.name + is RunStepDetailsToolCallsObject.ToolCalls.CaseRunStepDetailsToolCallsCodeObject -> it.value.type.name + is RunStepDetailsToolCallsObject.ToolCalls.CaseRunStepDetailsToolCallsFunctionObject -> it.value.function.name ?: "" + is RunStepDetailsToolCallsObject.ToolCalls.CaseRunStepDetailsToolCallsRetrievalObject -> it.value.type.name } }}: ${output.status.name}" ) @@ -188,23 +188,23 @@ class OpenTelemetryAssistantState(private val tracer: Tracer) { span.setAttribute("openai.assistant.runStep.id", id) span.setAttribute("openai.assistant.status", status.name) when (val detail = stepDetails) { - is RunStepObjectStepDetails.CaseRunStepDetailsMessageCreationObject -> { + is RunStepObject.StepDetails.CaseRunStepDetailsMessageCreationObject -> { span.setAttribute( "openai.assistant.messageCreation.id", detail.value.messageCreation.messageId ) } - is RunStepObjectStepDetails.CaseRunStepDetailsToolCallsObject -> { + is RunStepObject.StepDetails.CaseRunStepDetailsToolCallsObject -> { detail.value.toolCalls.forEachIndexed { index, toolCall -> when (toolCall) { - is RunStepDetailsToolCallsObjectToolCallsInner.CaseRunStepDetailsToolCallsCodeObject -> { + is RunStepDetailsToolCallsObject.ToolCalls.CaseRunStepDetailsToolCallsCodeObject -> { span.setAttribute("openai.assistant.toolCalls.$index.type", toolCall.value.type.name) span.setAttribute( "openai.assistant.toolCalls.$index.function.name", "code_interpreter" ) } - is RunStepDetailsToolCallsObjectToolCallsInner.CaseRunStepDetailsToolCallsFunctionObject -> { + is RunStepDetailsToolCallsObject.ToolCalls.CaseRunStepDetailsToolCallsFunctionObject -> { span.setAttribute("openai.assistant.toolCalls.$index.type", toolCall.value.type.name) span.setAttribute( "openai.assistant.toolCalls.$index.function.name", @@ -215,7 +215,7 @@ class OpenTelemetryAssistantState(private val tracer: Tracer) { toolCall.value.function.arguments ?: "" ) } - is RunStepDetailsToolCallsObjectToolCallsInner.CaseRunStepDetailsToolCallsRetrievalObject -> { + is RunStepDetailsToolCallsObject.ToolCalls.CaseRunStepDetailsToolCallsRetrievalObject -> { span.setAttribute("openai.assistant.toolCalls.$index.type", toolCall.value.type.name) span.setAttribute("openai.assistant.toolCalls.$index.function.name", "retrieval") } @@ -230,13 +230,13 @@ class OpenTelemetryAssistantState(private val tracer: Tracer) { forEach { span.setAttribute("openai.assistant.messages.${indexOf(it)}.role", it.role.name) when (val inner = it.content.firstOrNull()) { - is MessageObjectContentInner.CaseMessageContentImageFileObject -> { + is MessageObject.Content.CaseMessageContentImageFileObject -> { span.setAttribute( "openai.assistant.messages.${indexOf(it)}.content", inner.value.imageFile.fileId ) } - is MessageObjectContentInner.CaseMessageContentTextObject -> { + is MessageObject.Content.CaseMessageContentTextObject -> { span.setAttribute( "openai.assistant.messages.${indexOf(it)}.content", inner.value.text.value diff --git a/integrations/postgresql/src/main/kotlin/com/xebia/functional/xef/store/PostgreSQLVectorStore.kt b/integrations/postgresql/src/main/kotlin/com/xebia/functional/xef/store/PostgreSQLVectorStore.kt index f34578c9e..18c72b7d8 100644 --- a/integrations/postgresql/src/main/kotlin/com/xebia/functional/xef/store/PostgreSQLVectorStore.kt +++ b/integrations/postgresql/src/main/kotlin/com/xebia/functional/xef/store/PostgreSQLVectorStore.kt @@ -1,16 +1,12 @@ package com.xebia.functional.xef.store import arrow.atomic.AtomicInt -import com.xebia.functional.openai.generated.api.Embeddings -import io.github.nomisrev.openapi.ChatCompletionRole -import io.github.nomisrev.openapi.CreateChatCompletionRequestModel -import io.github.nomisrev.openapi.CreateEmbeddingRequestModel -import io.github.nomisrev.openapi.Embedding import com.xebia.functional.xef.llm.embedDocuments import com.xebia.functional.xef.llm.embedQuery import com.xebia.functional.xef.llm.models.modelType import com.xebia.functional.xef.prompt.contentAsString import com.xebia.functional.xef.store.postgresql.* +import io.github.nomisrev.openapi.* import kotlinx.uuid.UUID import kotlinx.uuid.generateUUID import javax.sql.DataSource @@ -22,7 +18,7 @@ class PGVectorStore( private val collectionName: String, private val distanceStrategy: PGDistanceStrategy, private val preDeleteCollection: Boolean, - private val embeddingRequestModel: CreateEmbeddingRequestModel, + private val embeddingRequestModel: CreateEmbeddingRequest.Model, private val chunkSize: Int = 400 ) : VectorStore { @@ -38,7 +34,7 @@ class PGVectorStore( update(addNewMemory) { bind(UUID.generateUUID().toString()) bind(memory.conversationId.value) - bind(memory.content.role.value.lowercase()) + bind(memory.content.role.name) bind(memory.content.asRequestMessage().contentAsString()) bind(memory.index) } @@ -46,7 +42,7 @@ class PGVectorStore( } } - override suspend fun memories(model: CreateChatCompletionRequestModel, conversationId: ConversationId, limitTokens: Int): List = + override suspend fun memories(model: CreateChatCompletionRequest.Model, conversationId: ConversationId, limitTokens: Int): List = getMemoryByConversationId(conversationId).reduceByLimitToken(model.modelType(), limitTokens).reversed() private fun JDBCSyntax.getCollection(collectionName: String): PGCollection = @@ -153,7 +149,7 @@ class PGVectorStore( val index = int() Memory( conversationId = ConversationId(cId), - content = memorizedMessage(ChatCompletionRole.valueOf(role.lowercase()), content), + content = memorizedMessage(ChatCompletionRole.valueOf(role), content), index = index ) } diff --git a/integrations/postgresql/src/test/kotlin/xef/MemoryData.kt b/integrations/postgresql/src/test/kotlin/xef/MemoryData.kt index 5e85fd535..a2c8f74e0 100644 --- a/integrations/postgresql/src/test/kotlin/xef/MemoryData.kt +++ b/integrations/postgresql/src/test/kotlin/xef/MemoryData.kt @@ -4,7 +4,6 @@ import arrow.atomic.AtomicInt import io.github.nomisrev.openapi.ChatCompletionRequestAssistantMessage import io.github.nomisrev.openapi.ChatCompletionRequestMessage import io.github.nomisrev.openapi.ChatCompletionRequestUserMessage -import io.github.nomisrev.openapi.ChatCompletionRequestUserMessageContent import com.xebia.functional.xef.store.ConversationId import com.xebia.functional.xef.store.MemorizedMessage import com.xebia.functional.xef.store.Memory @@ -22,13 +21,13 @@ class MemoryData { (0 until n).flatMap { val m1 = ChatCompletionRequestMessage.CaseChatCompletionRequestUserMessage( ChatCompletionRequestUserMessage( - role = ChatCompletionRequestUserMessage.Role.user, - content = ChatCompletionRequestUserMessageContent.CaseString("Question $it${append?.let { ": $it" } ?: ""}") + role = ChatCompletionRequestUserMessage.Role.User, + content = ChatCompletionRequestUserMessage.Content.CaseString("Question $it${append?.let { ": $it" } ?: ""}") ) ) val m2 = ChatCompletionRequestMessage.CaseChatCompletionRequestAssistantMessage( ChatCompletionRequestAssistantMessage( - role = ChatCompletionRequestAssistantMessage.Role.assistant, + role = ChatCompletionRequestAssistantMessage.Role.Assistant, content = "Answer $it${append?.let { ": $it" } ?: ""}" ) ) diff --git a/integrations/postgresql/src/test/kotlin/xef/PGVectorStoreSpec.kt b/integrations/postgresql/src/test/kotlin/xef/PGVectorStoreSpec.kt index 8a1c17e75..e9af1f78e 100644 --- a/integrations/postgresql/src/test/kotlin/xef/PGVectorStoreSpec.kt +++ b/integrations/postgresql/src/test/kotlin/xef/PGVectorStoreSpec.kt @@ -1,13 +1,11 @@ package xef -import io.github.nomisrev.openapi.CreateChatCompletionRequestModel -import io.github.nomisrev.openapi.CreateEmbeddingRequestModel -import io.github.nomisrev.openapi.Embedding import com.xebia.functional.xef.store.PGVectorStore import com.xebia.functional.xef.store.migrations.runDatabaseMigrations import com.xebia.functional.xef.store.postgresql.PGDistanceStrategy import com.zaxxer.hikari.HikariConfig import com.zaxxer.hikari.HikariDataSource +import io.github.nomisrev.openapi.* import io.kotest.core.Tuple3 import io.kotest.core.extensions.install import io.kotest.core.spec.style.StringSpec @@ -39,7 +37,7 @@ class PGVectorStoreSpec : ) ) - val embeddingsRequestModel = CreateEmbeddingRequestModel.text_embedding_ada_002 + val embeddingsRequestModel = CreateEmbeddingRequest.Model.TextEmbeddingAda002 fun StringSpecScope.pg() = PGVectorStore( @@ -87,7 +85,7 @@ class PGVectorStoreSpec : "similaritySearchByVector should return both documents" { pg().addTexts(listOf("bar", "foo")) - pg().similaritySearchByVector(Embedding(0, listOf(4.0, 5.0, 6.0), Embedding.Object.embedding), 2) shouldBe + pg().similaritySearchByVector(Embedding(0, listOf(4.0, 5.0, 6.0), Embedding.Object.Embedding), 2) shouldBe listOf("bar", "foo") } @@ -102,14 +100,14 @@ class PGVectorStoreSpec : "similaritySearchByVector should return document" { pg().similaritySearchByVector( - Embedding(0, listOf(1.0, 2.0, 3.0), Embedding.Object.embedding), + Embedding(0, listOf(1.0, 2.0, 3.0), Embedding.Object.Embedding), 1 ) shouldBe listOf("foo") } "the added memories sorted by index should be obtained in the same order" { val memoryData = MemoryData() - val model = CreateChatCompletionRequestModel.gpt_4 + val model = CreateChatCompletionRequest.Model.Gpt4 val memories = memoryData.generateRandomMessages(10) pg().addMemories(memories) memories.map { Tuple3(it.index, it.conversationId, it.content.asRequestMessage()) } shouldBe diff --git a/integrations/postgresql/src/test/kotlin/xef/TestEmbeddings.kt b/integrations/postgresql/src/test/kotlin/xef/TestEmbeddings.kt index 081633e0c..f43f4f9aa 100644 --- a/integrations/postgresql/src/test/kotlin/xef/TestEmbeddings.kt +++ b/integrations/postgresql/src/test/kotlin/xef/TestEmbeddings.kt @@ -1,6 +1,5 @@ package xef -import com.xebia.functional.openai.generated.api.Embeddings import io.github.nomisrev.openapi.* import io.ktor.client.request.* @@ -14,25 +13,25 @@ class TestEmbeddings : Embeddings, AutoCloseable { ): CreateEmbeddingResponse { requests.add(createEmbeddingRequest) val maybeTextInput = when(val input = createEmbeddingRequest.input) { - is CreateEmbeddingRequestInput.CaseStrings -> input.value.firstOrNull() - is CreateEmbeddingRequestInput.CaseString -> input.value + is CreateEmbeddingRequest.Input.CaseStrings -> input.value.firstOrNull() + is CreateEmbeddingRequest.Input.CaseString -> input.value else -> null } val data = when(maybeTextInput) { "fooz" -> listOf( - Embedding(0, listOf(7.0, 8.0, 9.0), Embedding.Object.embedding), - Embedding(1, listOf(7.5, 8.5, 9.5), Embedding.Object.embedding) + Embedding(0, listOf(7.0, 8.0, 9.0), Embedding.Object.Embedding), + Embedding(1, listOf(7.5, 8.5, 9.5), Embedding.Object.Embedding) ) - "foo" -> listOf(Embedding(0, listOf(1.0, 2.0, 3.0), Embedding.Object.embedding)) - "bar" -> listOf(Embedding(0, listOf(4.0, 5.0, 6.0), Embedding.Object.embedding)) + "foo" -> listOf(Embedding(0, listOf(1.0, 2.0, 3.0), Embedding.Object.Embedding)) + "bar" -> listOf(Embedding(0, listOf(4.0, 5.0, 6.0), Embedding.Object.Embedding)) "baz" -> listOf() else -> listOf() } return CreateEmbeddingResponse( data = data, model = "test-model", - `object` = CreateEmbeddingResponse.Object.list, - usage = CreateEmbeddingResponseUsage(0, 0) + `object` = CreateEmbeddingResponse.Object.List, + usage = CreateEmbeddingResponse.Usage(0, 0) ) } diff --git a/integrations/sql/src/main/kotlin/com/xebia/functional/xef/sql/SQL.kt b/integrations/sql/src/main/kotlin/com/xebia/functional/xef/sql/SQL.kt index 57d7b833e..f57487f39 100644 --- a/integrations/sql/src/main/kotlin/com/xebia/functional/xef/sql/SQL.kt +++ b/integrations/sql/src/main/kotlin/com/xebia/functional/xef/sql/SQL.kt @@ -1,7 +1,5 @@ package com.xebia.functional.xef.sql -import com.xebia.functional.openai.generated.api.Chat -import io.github.nomisrev.openapi.CreateChatCompletionRequestModel import com.xebia.functional.xef.conversation.AiDsl import com.xebia.functional.xef.conversation.Conversation import com.xebia.functional.xef.conversation.Description @@ -11,6 +9,8 @@ import com.xebia.functional.xef.prompt.PromptBuilder.Companion.system import com.xebia.functional.xef.prompt.PromptBuilder.Companion.user import com.xebia.functional.xef.sql.ResultSetOps.toQueryResult import com.xebia.functional.xef.sql.jdbc.JdbcConfig +import io.github.nomisrev.openapi.Chat +import io.github.nomisrev.openapi.CreateChatCompletionRequest import io.github.oshai.kotlinlogging.KotlinLogging import kotlinx.serialization.Serializable import kotlinx.serialization.serializer @@ -43,7 +43,7 @@ interface SQL { suspend fun Conversation.promptQuery(prompt: String, tableNames: List, context: String?): AnswerResponse } -class SQLImpl(private val chatApi: Chat, private val model: CreateChatCompletionRequestModel, private val db: Database) : SQL { +class SQLImpl(private val chatApi: Chat, private val model: CreateChatCompletionRequest.Model, private val db: Database) : SQL { private val logger = KotlinLogging.logger {} override suspend fun Conversation.promptQuery( diff --git a/integrations/sql/src/main/kotlin/com/xebia/functional/xef/sql/jdbc/JdbcConfig.kt b/integrations/sql/src/main/kotlin/com/xebia/functional/xef/sql/jdbc/JdbcConfig.kt index 30e3d928c..9e39829b3 100644 --- a/integrations/sql/src/main/kotlin/com/xebia/functional/xef/sql/jdbc/JdbcConfig.kt +++ b/integrations/sql/src/main/kotlin/com/xebia/functional/xef/sql/jdbc/JdbcConfig.kt @@ -1,7 +1,7 @@ package com.xebia.functional.xef.sql.jdbc -import com.xebia.functional.openai.generated.api.Chat -import io.github.nomisrev.openapi.CreateChatCompletionRequestModel +import io.github.nomisrev.openapi.Chat +import io.github.nomisrev.openapi.CreateChatCompletionRequest class JdbcConfig( val vendor: String, @@ -11,7 +11,7 @@ class JdbcConfig( val port: Int, val database: String, val chatApi: Chat, - val model: CreateChatCompletionRequestModel + val model: CreateChatCompletionRequest.Model ) { fun toJDBCUrl(): String = "jdbc:$vendor://$host:$port/$database" } diff --git a/server/src/main/kotlin/com/xebia/functional/xef/server/services/PostgresVectorStoreService.kt b/server/src/main/kotlin/com/xebia/functional/xef/server/services/PostgresVectorStoreService.kt index d18886477..22d9da0d1 100644 --- a/server/src/main/kotlin/com/xebia/functional/xef/server/services/PostgresVectorStoreService.kt +++ b/server/src/main/kotlin/com/xebia/functional/xef/server/services/PostgresVectorStoreService.kt @@ -7,7 +7,7 @@ import com.xebia.functional.xef.store.VectorStore import com.xebia.functional.xef.store.postgresql.PGDistanceStrategy import com.xebia.functional.xef.store.postgresql.addNewCollection import com.xebia.functional.xef.store.postgresql.connection -import io.github.nomisrev.openapi.CreateEmbeddingRequestModel +import io.github.nomisrev.openapi.CreateEmbeddingRequest import io.github.oshai.kotlinlogging.KLogger import javax.sql.DataSource import kotlinx.uuid.UUID @@ -21,8 +21,8 @@ class PostgresVectorStoreService( private val preDeleteCollection: Boolean = false, private val chunkSize: Int = 400, private val distanceStrategy: PGDistanceStrategy = PGDistanceStrategy.Euclidean, - private val embeddingRequestModel: CreateEmbeddingRequestModel = - CreateEmbeddingRequestModel.text_embedding_3_small + private val embeddingRequestModel: CreateEmbeddingRequest.Model = + CreateEmbeddingRequest.Model.TextEmbedding3Small ) : VectorStoreService() { fun addCollection() { From e9ec224558d8cd64139dc08d56d90b9942931b23 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Tue, 25 Jun 2024 19:07:17 +0200 Subject: [PATCH 3/8] Update Gradle plugin --- core/build.gradle.kts | 148 +++++++++--------- .../kotlin/com/xebia/functional/xef/Config.kt | 6 +- 2 files changed, 78 insertions(+), 76 deletions(-) diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 378f77f2b..af6a76522 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -20,7 +20,9 @@ plugins { } openApiConfig { - spec.set(file("openai-api.yaml")) + spec("OpenAI", "openai-api.yaml") { + packageName = "io.github.nomisrev.openapi" + } } dependencies { @@ -52,11 +54,11 @@ kotlin { classpath = compileDependencyFiles + runtimeDependencyFiles + output.allOutputs testClassesDirs = output.classesDirs testLogging { events("passed") } - } - } - val test by compilations.getting - integrationTest.associateWith(test) - } + } + } + val test by compilations.getting + integrationTest.associateWith(test) + } } js(IR) { browser() @@ -67,74 +69,74 @@ kotlin { macosArm64() mingwX64() sourceSets { - all { - languageSettings.optIn("kotlin.ExperimentalStdlibApi") - } - val commonMain by getting { - kotlin.srcDir(project.file("build/generated/openapi/src/commonMain/kotlin")) + all { + languageSettings.optIn("kotlin.ExperimentalStdlibApi") + } + val commonMain by getting { + kotlin.srcDir(project.file("build/generated/openapi/src/commonMain/kotlin")) - dependencies { - api(libs.bundles.arrow) - api(libs.kotlinx.serialization.json) - api(libs.kotlinx.serialization.yaml) - api(libs.ktor.utils) - api(projects.xefTokenizer) - implementation(libs.bundles.ktor.client) - implementation(libs.klogging) - implementation(libs.uuid) - implementation(libs.ktor.client.logging) - implementation(libs.klogging) - } - } - val commonTest by getting { - dependencies { - implementation(libs.kotest.property) - implementation(libs.kotest.framework) - implementation(libs.kotest.assertions) - } - } - val jvmMain by getting { - dependencies { - implementation(libs.ktor.http) - implementation(libs.rss.reader) - api(libs.jackson) - api(libs.jackson.schema) - api(libs.jackson.schema.jakarta) - api(libs.jakarta.validation) - implementation(libs.kotlinx.coroutines.reactive) - api(libs.ktor.client.cio) - } - } - val jsMain by getting { - dependencies { - api(libs.ktor.client.js) - } - } - val jvmTest by getting { - dependencies { - implementation(libs.kotest.junit5) - } - } - val linuxX64Main by getting { - dependencies { - implementation(libs.ktor.client.cio) - } - } - val macosX64Main by getting { - dependencies { - implementation(libs.ktor.client.cio) - } - } - val macosArm64Main by getting { - dependencies { - implementation(libs.ktor.client.cio) - } - } - val mingwX64Main by getting { - dependencies { - implementation(libs.ktor.client.winhttp) - } - } + dependencies { + api(libs.bundles.arrow) + api(libs.kotlinx.serialization.json) + api(libs.kotlinx.serialization.yaml) + api(libs.ktor.utils) + api(projects.xefTokenizer) + implementation(libs.bundles.ktor.client) + implementation(libs.klogging) + implementation(libs.uuid) + implementation(libs.ktor.client.logging) + implementation(libs.klogging) + } + } + val commonTest by getting { + dependencies { + implementation(libs.kotest.property) + implementation(libs.kotest.framework) + implementation(libs.kotest.assertions) + } + } + val jvmMain by getting { + dependencies { + implementation(libs.ktor.http) + implementation(libs.rss.reader) + api(libs.jackson) + api(libs.jackson.schema) + api(libs.jackson.schema.jakarta) + api(libs.jakarta.validation) + implementation(libs.kotlinx.coroutines.reactive) + api(libs.ktor.client.cio) + } + } + val jsMain by getting { + dependencies { + api(libs.ktor.client.js) + } + } + val jvmTest by getting { + dependencies { + implementation(libs.kotest.junit5) + } + } + val linuxX64Main by getting { + dependencies { + implementation(libs.ktor.client.cio) + } + } + val macosX64Main by getting { + dependencies { + implementation(libs.ktor.client.cio) + } + } + val macosArm64Main by getting { + dependencies { + implementation(libs.ktor.client.cio) + } + } + val mingwX64Main by getting { + dependencies { + implementation(libs.ktor.client.winhttp) + } + } } } diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/Config.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/Config.kt index 76814d73f..05a842859 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/Config.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/Config.kt @@ -2,7 +2,7 @@ package com.xebia.functional.xef import arrow.core.nonEmptyListOf import com.xebia.functional.xef.env.getenv -import io.github.nomisrev.openapi.OpenAPI +import io.github.nomisrev.openapi.OpenAI import io.ktor.client.* import io.ktor.client.engine.* import io.ktor.client.plugins.* @@ -45,7 +45,7 @@ fun OpenAI( httpClientEngine: HttpClientEngine? = null, httpClientConfig: ((HttpClientConfig<*>) -> Unit)? = null, logRequests: Boolean = false -): OpenAPI { +): OpenAI { val token = config.token ?: getenv(KEY_ENV_VAR) @@ -72,5 +72,5 @@ fun OpenAI( } } val client = httpClientEngine?.let { HttpClient(it, clientConfig) } ?: HttpClient(clientConfig) - return OpenAPI(client) + return OpenAI(client) } From 38f8527c515f193091ad3da8e01f68941a83ab77 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Wed, 26 Jun 2024 11:13:28 +0200 Subject: [PATCH 4/8] Update packageName --- core/build.gradle.kts | 2 +- core/src/commonMain/kotlin/com/xebia/functional/xef/AI.kt | 6 +++--- .../commonMain/kotlin/com/xebia/functional/xef/Config.kt | 2 +- .../kotlin/com/xebia/functional/xef/DefaultAI.kt | 4 ++-- .../kotlin/com/xebia/functional/xef/llm/Chat.kt | 4 ++-- .../com/xebia/functional/xef/llm/ChatWithFunctions.kt | 4 ++-- .../kotlin/com/xebia/functional/xef/llm/Embeddings.kt | 2 +- .../commonMain/kotlin/com/xebia/functional/xef/llm/LLM.kt | 2 +- .../com/xebia/functional/xef/llm/MemoryManagement.kt | 2 +- .../com/xebia/functional/xef/llm/MetricManagement.kt | 6 +++--- .../com/xebia/functional/xef/llm/PromptCalculator.kt | 2 +- .../com/xebia/functional/xef/llm/StreamedFunction.kt | 2 +- .../kotlin/com/xebia/functional/xef/llm/Vision.kt | 2 +- .../com/xebia/functional/xef/llm/assistants/Assistant.kt | 2 +- .../functional/xef/llm/assistants/AssistantThread.kt | 2 +- .../com/xebia/functional/xef/llm/assistants/RunDelta.kt | 2 +- .../com/xebia/functional/xef/llm/assistants/Tool.kt | 2 +- .../com/xebia/functional/xef/llm/models/OpenAIClient.kt | 4 ++-- .../kotlin/com/xebia/functional/xef/metrics/LogsMetric.kt | 6 +++--- .../kotlin/com/xebia/functional/xef/metrics/Metric.kt | 6 +++--- .../xebia/functional/xef/prompt/PlatformPromptBuilder.kt | 6 +++--- .../kotlin/com/xebia/functional/xef/prompt/Prompt.kt | 6 +++--- .../com/xebia/functional/xef/prompt/PromptBuilder.kt | 4 ++-- .../xef/prompt/configuration/PromptConfiguration.kt | 2 +- .../com/xebia/functional/xef/store/CombinedVectorStore.kt | 4 ++-- .../com/xebia/functional/xef/store/LocalVectorStore.kt | 2 +- .../com/xebia/functional/xef/store/MemorizedMessage.kt | 2 +- .../kotlin/com/xebia/functional/xef/store/VectorStore.kt | 4 ++-- .../xebia/functional/xef/conversation/ConversationSpec.kt | 2 +- .../kotlin/com/xebia/functional/xef/data/TestChatApi.kt | 2 +- .../com/xebia/functional/xef/data/TestEmbeddings.kt | 6 +++--- .../com/xebia/functional/xef/prompt/PromptBuilderSpec.kt | 2 +- .../xebia/functional/xef/store/CombinedVectorStoreSpec.kt | 2 +- .../xebia/functional/xef/store/LocalVectorStoreSpec.kt | 2 +- .../kotlin/com/xebia/functional/xef/store/MemoryData.kt | 6 +++--- .../com/xebia/functional/xef/evaluator/SuiteBuilder.kt | 2 +- .../xebia/functional/xef/assistants/AssistantStreaming.kt | 2 +- .../functional/xef/conversation/conversations/Animal.kt | 2 +- .../com/xebia/functional/xef/dsl/audio/SimpleSpeech.kt | 8 ++++---- .../kotlin/com/xebia/functional/xef/dsl/chat/Classes.kt | 2 +- .../xebia/functional/xef/dsl/classify/AnswerAccuracy.kt | 2 +- .../com/xebia/functional/xef/dsl/images/ImagesExamples.kt | 4 ++-- .../com/xebia/functional/xef/evaluator/TestExample.kt | 2 +- .../xef/opentelemetry/OpenTelemetryAssistantState.kt | 2 +- .../functional/xef/opentelemetry/OpenTelemetryMetric.kt | 6 +++--- .../xebia/functional/xef/store/PostgreSQLVectorStore.kt | 2 +- integrations/postgresql/src/test/kotlin/xef/MemoryData.kt | 6 +++--- .../postgresql/src/test/kotlin/xef/PGVectorStoreSpec.kt | 2 +- .../postgresql/src/test/kotlin/xef/TestEmbeddings.kt | 2 +- .../src/main/kotlin/com/xebia/functional/xef/sql/SQL.kt | 4 ++-- .../com/xebia/functional/xef/sql/jdbc/JdbcConfig.kt | 4 ++-- .../xef/server/services/PostgresVectorStoreService.kt | 2 +- 52 files changed, 85 insertions(+), 85 deletions(-) diff --git a/core/build.gradle.kts b/core/build.gradle.kts index af6a76522..0f02aa0f2 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -21,7 +21,7 @@ plugins { openApiConfig { spec("OpenAI", "openai-api.yaml") { - packageName = "io.github.nomisrev.openapi" + packageName = "com.xebia.functional.xef.openapi" } } diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/AI.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/AI.kt index ebe7f6f79..81dc26209 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/AI.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/AI.kt @@ -2,10 +2,10 @@ package com.xebia.functional.xef import com.xebia.functional.xef.conversation.AiDsl import com.xebia.functional.xef.conversation.Conversation +import com.xebia.functional.xef.openapi.Chat +import com.xebia.functional.xef.openapi.CreateChatCompletionRequest +import com.xebia.functional.xef.openapi.Images import com.xebia.functional.xef.prompt.Prompt -import io.github.nomisrev.openapi.Chat -import io.github.nomisrev.openapi.CreateChatCompletionRequest -import io.github.nomisrev.openapi.Images import kotlin.coroutines.cancellation.CancellationException import kotlin.reflect.KClass import kotlin.reflect.KType diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/Config.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/Config.kt index 05a842859..71fbe1fa3 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/Config.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/Config.kt @@ -2,7 +2,7 @@ package com.xebia.functional.xef import arrow.core.nonEmptyListOf import com.xebia.functional.xef.env.getenv -import io.github.nomisrev.openapi.OpenAI +import com.xebia.functional.xef.openapi.OpenAI import io.ktor.client.* import io.ktor.client.engine.* import io.ktor.client.plugins.* diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/DefaultAI.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/DefaultAI.kt index 31f2b6932..6b99546ec 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/DefaultAI.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/DefaultAI.kt @@ -5,9 +5,9 @@ import com.xebia.functional.xef.llm.StreamedFunction import com.xebia.functional.xef.llm.models.modelType import com.xebia.functional.xef.llm.prompt import com.xebia.functional.xef.llm.promptStreaming +import com.xebia.functional.xef.openapi.Chat +import com.xebia.functional.xef.openapi.CreateChatCompletionRequest import com.xebia.functional.xef.prompt.Prompt -import io.github.nomisrev.openapi.Chat -import io.github.nomisrev.openapi.CreateChatCompletionRequest import kotlin.reflect.KClass import kotlin.reflect.KType import kotlin.reflect.typeOf diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/Chat.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/Chat.kt index c39d534f9..951d2e6bd 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/Chat.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/Chat.kt @@ -3,10 +3,10 @@ package com.xebia.functional.xef.llm import com.xebia.functional.xef.AIError import com.xebia.functional.xef.conversation.AiDsl import com.xebia.functional.xef.conversation.Conversation +import com.xebia.functional.xef.openapi.Chat +import com.xebia.functional.xef.openapi.CreateChatCompletionRequest import com.xebia.functional.xef.prompt.Prompt import com.xebia.functional.xef.prompt.PromptBuilder -import io.github.nomisrev.openapi.Chat -import io.github.nomisrev.openapi.CreateChatCompletionRequest import kotlinx.coroutines.flow.* @AiDsl diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/ChatWithFunctions.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/ChatWithFunctions.kt index f5d7b389b..ca925087b 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/ChatWithFunctions.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/ChatWithFunctions.kt @@ -6,9 +6,9 @@ import com.xebia.functional.xef.AIError import com.xebia.functional.xef.conversation.AiDsl import com.xebia.functional.xef.conversation.Conversation import com.xebia.functional.xef.llm.models.functions.buildJsonSchema +import com.xebia.functional.xef.openapi.* +import com.xebia.functional.xef.openapi.ChatCompletionToolChoiceOption.NoneOrAuto import com.xebia.functional.xef.prompt.Prompt -import io.github.nomisrev.openapi.* -import io.github.nomisrev.openapi.ChatCompletionToolChoiceOption.NoneOrAuto import io.github.oshai.kotlinlogging.KotlinLogging import kotlinx.coroutines.flow.* import kotlinx.serialization.ExperimentalSerializationApi diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/Embeddings.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/Embeddings.kt index 0c87dd0a0..d68810e6c 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/Embeddings.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/Embeddings.kt @@ -1,7 +1,7 @@ package com.xebia.functional.xef.llm import arrow.fx.coroutines.parMap -import io.github.nomisrev.openapi.* +import com.xebia.functional.xef.openapi.* suspend fun Embeddings.embedDocuments( texts: List, diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/LLM.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/LLM.kt index 479bc245f..fe79bf5c8 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/LLM.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/LLM.kt @@ -2,9 +2,9 @@ package com.xebia.functional.xef.llm import com.xebia.functional.tokenizer.Encoding import com.xebia.functional.tokenizer.ModelType +import com.xebia.functional.xef.openapi.ChatCompletionRequestMessage import com.xebia.functional.xef.prompt.completionRole import com.xebia.functional.xef.prompt.contentAsString -import io.github.nomisrev.openapi.ChatCompletionRequestMessage fun ModelType.tokensFromMessages( messages: List, diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/MemoryManagement.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/MemoryManagement.kt index b134837d9..df9a65249 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/MemoryManagement.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/MemoryManagement.kt @@ -2,11 +2,11 @@ package com.xebia.functional.xef.llm import com.xebia.functional.xef.conversation.Conversation import com.xebia.functional.xef.conversation.MessagesToHistory +import com.xebia.functional.xef.openapi.* import com.xebia.functional.xef.store.ConversationId import com.xebia.functional.xef.store.MemorizedMessage import com.xebia.functional.xef.store.Memory import com.xebia.functional.xef.store.VectorStore -import io.github.nomisrev.openapi.* internal suspend fun List.addToMemory( scope: Conversation, diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/MetricManagement.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/MetricManagement.kt index 92ea48741..d5fb61aac 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/MetricManagement.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/MetricManagement.kt @@ -3,12 +3,12 @@ package com.xebia.functional.xef.llm import com.xebia.functional.xef.conversation.Conversation import com.xebia.functional.xef.llm.assistants.RunDelta import com.xebia.functional.xef.metrics.Metric +import com.xebia.functional.xef.openapi.CreateChatCompletionResponse +import com.xebia.functional.xef.openapi.RunObject +import com.xebia.functional.xef.openapi.RunStepObject import com.xebia.functional.xef.prompt.Prompt import com.xebia.functional.xef.prompt.completionRole import com.xebia.functional.xef.prompt.contentAsString -import io.github.nomisrev.openapi.CreateChatCompletionResponse -import io.github.nomisrev.openapi.RunObject -import io.github.nomisrev.openapi.RunStepObject suspend fun CreateChatCompletionResponse.addMetrics( conversation: Conversation diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/PromptCalculator.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/PromptCalculator.kt index 41c8698ca..fce9f9ff7 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/PromptCalculator.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/PromptCalculator.kt @@ -5,11 +5,11 @@ import com.xebia.functional.xef.AIError import com.xebia.functional.xef.conversation.Conversation import com.xebia.functional.xef.conversation.MessagesFromHistory import com.xebia.functional.xef.llm.models.modelType +import com.xebia.functional.xef.openapi.ChatCompletionRequestMessage import com.xebia.functional.xef.prompt.Prompt import com.xebia.functional.xef.prompt.PromptBuilder.Companion.assistant import com.xebia.functional.xef.prompt.contentAsString import com.xebia.functional.xef.store.Memory -import io.github.nomisrev.openapi.ChatCompletionRequestMessage internal object PromptCalculator { diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/StreamedFunction.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/StreamedFunction.kt index 839f1bf38..7dbfc3cc6 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/StreamedFunction.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/StreamedFunction.kt @@ -2,9 +2,9 @@ package com.xebia.functional.xef.llm import com.xebia.functional.xef.conversation.Conversation import com.xebia.functional.xef.llm.StreamedFunction.Companion.PropertyType.* +import com.xebia.functional.xef.openapi.* import com.xebia.functional.xef.prompt.Prompt import com.xebia.functional.xef.prompt.PromptBuilder -import io.github.nomisrev.openapi.* import kotlin.jvm.JvmSynthetic import kotlinx.coroutines.flow.FlowCollector import kotlinx.coroutines.flow.onCompletion diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/Vision.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/Vision.kt index 4daf99515..d7b529706 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/Vision.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/Vision.kt @@ -1,10 +1,10 @@ package com.xebia.functional.xef.llm import com.xebia.functional.xef.conversation.Conversation +import com.xebia.functional.xef.openapi.* import com.xebia.functional.xef.prompt.Prompt import com.xebia.functional.xef.prompt.PromptBuilder.Companion.image import com.xebia.functional.xef.prompt.PromptBuilder.Companion.user -import io.github.nomisrev.openapi.* import io.ktor.client.* import io.ktor.client.call.* import io.ktor.client.request.* diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/Assistant.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/Assistant.kt index 84b29d06c..5ae916eaf 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/Assistant.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/Assistant.kt @@ -4,7 +4,7 @@ import com.xebia.functional.xef.Config import com.xebia.functional.xef.OpenAI import com.xebia.functional.xef.llm.assistants.AssistantThread.Companion.defaultConfig import com.xebia.functional.xef.llm.models.functions.buildJsonSchema -import io.github.nomisrev.openapi.* +import com.xebia.functional.xef.openapi.* import io.ktor.util.logging.* import kotlinx.serialization.KSerializer import kotlinx.serialization.Serializable diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/AssistantThread.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/AssistantThread.kt index 8828ce398..344188da3 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/AssistantThread.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/AssistantThread.kt @@ -5,7 +5,7 @@ import com.xebia.functional.xef.Config import com.xebia.functional.xef.OpenAI import com.xebia.functional.xef.llm.addMetrics import com.xebia.functional.xef.metrics.Metric -import io.github.nomisrev.openapi.* +import com.xebia.functional.xef.openapi.* import io.ktor.client.request.* import kotlin.jvm.JvmName import kotlinx.coroutines.flow.* diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/RunDelta.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/RunDelta.kt index 102c1595c..d691b5019 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/RunDelta.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/RunDelta.kt @@ -1,7 +1,7 @@ package com.xebia.functional.xef.llm.assistants import com.xebia.functional.xef.Config -import io.github.nomisrev.openapi.* +import com.xebia.functional.xef.openapi.* import kotlin.jvm.JvmInline import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/Tool.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/Tool.kt index db6adc2bb..331c20445 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/Tool.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/assistants/Tool.kt @@ -1,7 +1,7 @@ package com.xebia.functional.xef.llm.assistants import com.xebia.functional.xef.llm.chatFunction -import io.github.nomisrev.openapi.FunctionObject +import com.xebia.functional.xef.openapi.FunctionObject import kotlinx.serialization.KSerializer import kotlinx.serialization.serializer diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/models/OpenAIClient.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/models/OpenAIClient.kt index 66c7f8dd0..41e4114bf 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/models/OpenAIClient.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/llm/models/OpenAIClient.kt @@ -1,8 +1,8 @@ package com.xebia.functional.xef.llm.models import com.xebia.functional.tokenizer.ModelType -import io.github.nomisrev.openapi.CreateChatCompletionRequest -import io.github.nomisrev.openapi.CreateEmbeddingRequest +import com.xebia.functional.xef.openapi.CreateChatCompletionRequest +import com.xebia.functional.xef.openapi.CreateEmbeddingRequest fun CreateChatCompletionRequest.Model.modelType(forFunctions: Boolean = false): ModelType { val stringValue = value diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/metrics/LogsMetric.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/metrics/LogsMetric.kt index 5c97517ba..9348b7d15 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/metrics/LogsMetric.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/metrics/LogsMetric.kt @@ -1,11 +1,11 @@ package com.xebia.functional.xef.metrics import arrow.atomic.AtomicInt +import com.xebia.functional.xef.openapi.MessageObject +import com.xebia.functional.xef.openapi.RunObject +import com.xebia.functional.xef.openapi.RunStepObject import com.xebia.functional.xef.prompt.Prompt import com.xebia.functional.xef.prompt.contentAsString -import io.github.nomisrev.openapi.MessageObject -import io.github.nomisrev.openapi.RunObject -import io.github.nomisrev.openapi.RunStepObject import io.github.oshai.kotlinlogging.KotlinLogging import io.github.oshai.kotlinlogging.Level import io.ktor.util.date.* diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/metrics/Metric.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/metrics/Metric.kt index 86ff9ac88..bfa18ec2d 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/metrics/Metric.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/metrics/Metric.kt @@ -1,9 +1,9 @@ package com.xebia.functional.xef.metrics +import com.xebia.functional.xef.openapi.MessageObject +import com.xebia.functional.xef.openapi.RunObject +import com.xebia.functional.xef.openapi.RunStepObject import com.xebia.functional.xef.prompt.Prompt -import io.github.nomisrev.openapi.MessageObject -import io.github.nomisrev.openapi.RunObject -import io.github.nomisrev.openapi.RunStepObject interface Metric { suspend fun customSpan(name: String, block: suspend Metric.() -> A): A diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/PlatformPromptBuilder.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/PlatformPromptBuilder.kt index 16b04077a..d39d64227 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/PlatformPromptBuilder.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/PlatformPromptBuilder.kt @@ -1,9 +1,9 @@ package com.xebia.functional.xef.prompt +import com.xebia.functional.xef.openapi.ChatCompletionRequestMessage +import com.xebia.functional.xef.openapi.CreateChatCompletionRequest +import com.xebia.functional.xef.openapi.FunctionObject import com.xebia.functional.xef.prompt.configuration.PromptConfiguration -import io.github.nomisrev.openapi.ChatCompletionRequestMessage -import io.github.nomisrev.openapi.CreateChatCompletionRequest -import io.github.nomisrev.openapi.FunctionObject class PlatformPromptBuilder( private val model: CreateChatCompletionRequest.Model, diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/Prompt.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/Prompt.kt index 80bf38741..1db9b6921 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/Prompt.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/Prompt.kt @@ -1,9 +1,9 @@ package com.xebia.functional.xef.prompt +import com.xebia.functional.xef.openapi.ChatCompletionRequestMessage +import com.xebia.functional.xef.openapi.CreateChatCompletionRequest +import com.xebia.functional.xef.openapi.FunctionObject import com.xebia.functional.xef.prompt.configuration.PromptConfiguration -import io.github.nomisrev.openapi.ChatCompletionRequestMessage -import io.github.nomisrev.openapi.CreateChatCompletionRequest -import io.github.nomisrev.openapi.FunctionObject import kotlin.jvm.JvmOverloads import kotlin.jvm.JvmSynthetic diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/PromptBuilder.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/PromptBuilder.kt index ca1419d57..d3f271740 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/PromptBuilder.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/PromptBuilder.kt @@ -1,8 +1,8 @@ package com.xebia.functional.xef.prompt +import com.xebia.functional.xef.openapi.* +import com.xebia.functional.xef.openapi.ChatCompletionRequestMessage import com.xebia.functional.xef.prompt.configuration.PromptConfiguration -import io.github.nomisrev.openapi.* -import io.github.nomisrev.openapi.ChatCompletionRequestMessage import kotlin.jvm.JvmSynthetic interface PromptBuilder { diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/configuration/PromptConfiguration.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/configuration/PromptConfiguration.kt index de79896b4..02f2e8c65 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/configuration/PromptConfiguration.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/prompt/configuration/PromptConfiguration.kt @@ -1,7 +1,7 @@ package com.xebia.functional.xef.prompt.configuration import com.xebia.functional.xef.conversation.MessagePolicy -import io.github.nomisrev.openapi.ChatCompletionRole +import com.xebia.functional.xef.openapi.ChatCompletionRole import kotlin.jvm.JvmField import kotlin.jvm.JvmOverloads import kotlinx.serialization.Serializable diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/store/CombinedVectorStore.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/store/CombinedVectorStore.kt index 7fe838b38..97fb955e4 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/store/CombinedVectorStore.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/store/CombinedVectorStore.kt @@ -1,8 +1,8 @@ package com.xebia.functional.xef.store import com.xebia.functional.xef.llm.models.modelType -import io.github.nomisrev.openapi.CreateChatCompletionRequest -import io.github.nomisrev.openapi.Embedding +import com.xebia.functional.xef.openapi.CreateChatCompletionRequest +import com.xebia.functional.xef.openapi.Embedding /** * A way of composing two [VectorStore] instances together, this class will **first search** [top], diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/store/LocalVectorStore.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/store/LocalVectorStore.kt index bdb91534b..7e8755486 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/store/LocalVectorStore.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/store/LocalVectorStore.kt @@ -7,7 +7,7 @@ import arrow.atomic.update import com.xebia.functional.xef.llm.embedDocuments import com.xebia.functional.xef.llm.embedQuery import com.xebia.functional.xef.llm.models.modelType -import io.github.nomisrev.openapi.* +import com.xebia.functional.xef.openapi.* import kotlin.math.sqrt private data class State( diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/store/MemorizedMessage.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/store/MemorizedMessage.kt index b46ee4af5..aaf1ea1a4 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/store/MemorizedMessage.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/store/MemorizedMessage.kt @@ -1,7 +1,7 @@ package com.xebia.functional.xef.store +import com.xebia.functional.xef.openapi.* import com.xebia.functional.xef.prompt.completionRole -import io.github.nomisrev.openapi.* sealed class MemorizedMessage { val role: ChatCompletionRole diff --git a/core/src/commonMain/kotlin/com/xebia/functional/xef/store/VectorStore.kt b/core/src/commonMain/kotlin/com/xebia/functional/xef/store/VectorStore.kt index 90daa85bc..fb81a9508 100644 --- a/core/src/commonMain/kotlin/com/xebia/functional/xef/store/VectorStore.kt +++ b/core/src/commonMain/kotlin/com/xebia/functional/xef/store/VectorStore.kt @@ -1,8 +1,8 @@ package com.xebia.functional.xef.store import arrow.atomic.AtomicInt -import io.github.nomisrev.openapi.CreateChatCompletionRequest -import io.github.nomisrev.openapi.Embedding +import com.xebia.functional.xef.openapi.CreateChatCompletionRequest +import com.xebia.functional.xef.openapi.Embedding import kotlin.jvm.JvmStatic interface VectorStore { diff --git a/core/src/commonTest/kotlin/com/xebia/functional/xef/conversation/ConversationSpec.kt b/core/src/commonTest/kotlin/com/xebia/functional/xef/conversation/ConversationSpec.kt index b42ae4ebd..8e639f611 100644 --- a/core/src/commonTest/kotlin/com/xebia/functional/xef/conversation/ConversationSpec.kt +++ b/core/src/commonTest/kotlin/com/xebia/functional/xef/conversation/ConversationSpec.kt @@ -7,6 +7,7 @@ import com.xebia.functional.xef.llm.promptMessage import com.xebia.functional.xef.llm.promptMessages import com.xebia.functional.xef.llm.tokensFromMessages import com.xebia.functional.xef.metrics.LogsMetric +import com.xebia.functional.xef.openapi.* import com.xebia.functional.xef.prompt.Prompt import com.xebia.functional.xef.prompt.PromptBuilder.Companion.assistant import com.xebia.functional.xef.prompt.PromptBuilder.Companion.system @@ -15,7 +16,6 @@ import com.xebia.functional.xef.prompt.configuration.PromptConfiguration import com.xebia.functional.xef.prompt.contentAsString import com.xebia.functional.xef.store.ConversationId import com.xebia.functional.xef.store.LocalVectorStore -import io.github.nomisrev.openapi.* import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.comparables.shouldBeLessThan import io.kotest.matchers.shouldBe diff --git a/core/src/commonTest/kotlin/com/xebia/functional/xef/data/TestChatApi.kt b/core/src/commonTest/kotlin/com/xebia/functional/xef/data/TestChatApi.kt index afd7cc724..7eaf29288 100644 --- a/core/src/commonTest/kotlin/com/xebia/functional/xef/data/TestChatApi.kt +++ b/core/src/commonTest/kotlin/com/xebia/functional/xef/data/TestChatApi.kt @@ -1,7 +1,7 @@ package com.xebia.functional.xef.data +import com.xebia.functional.xef.openapi.* import com.xebia.functional.xef.prompt.contentAsString -import io.github.nomisrev.openapi.* import io.ktor.client.request.* import kotlinx.coroutines.flow.Flow diff --git a/core/src/commonTest/kotlin/com/xebia/functional/xef/data/TestEmbeddings.kt b/core/src/commonTest/kotlin/com/xebia/functional/xef/data/TestEmbeddings.kt index 2186f5724..5dab226bb 100644 --- a/core/src/commonTest/kotlin/com/xebia/functional/xef/data/TestEmbeddings.kt +++ b/core/src/commonTest/kotlin/com/xebia/functional/xef/data/TestEmbeddings.kt @@ -1,8 +1,8 @@ package com.xebia.functional.xef.data -import io.github.nomisrev.openapi.CreateEmbeddingRequest -import io.github.nomisrev.openapi.CreateEmbeddingResponse -import io.github.nomisrev.openapi.Embeddings +import com.xebia.functional.xef.openapi.CreateEmbeddingRequest +import com.xebia.functional.xef.openapi.CreateEmbeddingResponse +import com.xebia.functional.xef.openapi.Embeddings import io.ktor.client.request.* class TestEmbeddings : Embeddings, AutoCloseable { diff --git a/core/src/commonTest/kotlin/com/xebia/functional/xef/prompt/PromptBuilderSpec.kt b/core/src/commonTest/kotlin/com/xebia/functional/xef/prompt/PromptBuilderSpec.kt index 1daaddcce..1ba9144aa 100644 --- a/core/src/commonTest/kotlin/com/xebia/functional/xef/prompt/PromptBuilderSpec.kt +++ b/core/src/commonTest/kotlin/com/xebia/functional/xef/prompt/PromptBuilderSpec.kt @@ -1,9 +1,9 @@ package com.xebia.functional.xef.prompt +import com.xebia.functional.xef.openapi.CreateChatCompletionRequest import com.xebia.functional.xef.prompt.PromptBuilder.Companion.assistant import com.xebia.functional.xef.prompt.PromptBuilder.Companion.system import com.xebia.functional.xef.prompt.PromptBuilder.Companion.user -import io.github.nomisrev.openapi.CreateChatCompletionRequest import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe diff --git a/core/src/commonTest/kotlin/com/xebia/functional/xef/store/CombinedVectorStoreSpec.kt b/core/src/commonTest/kotlin/com/xebia/functional/xef/store/CombinedVectorStoreSpec.kt index 263a60e6c..956cd8b63 100644 --- a/core/src/commonTest/kotlin/com/xebia/functional/xef/store/CombinedVectorStoreSpec.kt +++ b/core/src/commonTest/kotlin/com/xebia/functional/xef/store/CombinedVectorStoreSpec.kt @@ -3,7 +3,7 @@ package com.xebia.functional.xef.store import com.xebia.functional.xef.data.TestEmbeddings import com.xebia.functional.xef.llm.models.modelType import com.xebia.functional.xef.llm.tokensFromMessages -import io.github.nomisrev.openapi.CreateChatCompletionRequest +import com.xebia.functional.xef.openapi.CreateChatCompletionRequest import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe diff --git a/core/src/commonTest/kotlin/com/xebia/functional/xef/store/LocalVectorStoreSpec.kt b/core/src/commonTest/kotlin/com/xebia/functional/xef/store/LocalVectorStoreSpec.kt index 5fefbbb74..48afc1ee7 100644 --- a/core/src/commonTest/kotlin/com/xebia/functional/xef/store/LocalVectorStoreSpec.kt +++ b/core/src/commonTest/kotlin/com/xebia/functional/xef/store/LocalVectorStoreSpec.kt @@ -3,7 +3,7 @@ package com.xebia.functional.xef.store import com.xebia.functional.xef.data.TestEmbeddings import com.xebia.functional.xef.llm.models.modelType import com.xebia.functional.xef.llm.tokensFromMessages -import io.github.nomisrev.openapi.CreateChatCompletionRequest +import com.xebia.functional.xef.openapi.CreateChatCompletionRequest import io.kotest.core.spec.style.StringSpec import io.kotest.matchers.shouldBe diff --git a/core/src/commonTest/kotlin/com/xebia/functional/xef/store/MemoryData.kt b/core/src/commonTest/kotlin/com/xebia/functional/xef/store/MemoryData.kt index 7958c7f4c..59b200773 100644 --- a/core/src/commonTest/kotlin/com/xebia/functional/xef/store/MemoryData.kt +++ b/core/src/commonTest/kotlin/com/xebia/functional/xef/store/MemoryData.kt @@ -1,9 +1,9 @@ package com.xebia.functional.xef.store import arrow.atomic.AtomicInt -import io.github.nomisrev.openapi.ChatCompletionRequestAssistantMessage -import io.github.nomisrev.openapi.ChatCompletionRequestMessage -import io.github.nomisrev.openapi.ChatCompletionRequestUserMessage +import com.xebia.functional.xef.openapi.ChatCompletionRequestAssistantMessage +import com.xebia.functional.xef.openapi.ChatCompletionRequestMessage +import com.xebia.functional.xef.openapi.ChatCompletionRequestUserMessage class MemoryData { val defaultConversationId = ConversationId("default-id") diff --git a/evaluator/src/main/kotlin/com/xebia/functional/xef/evaluator/SuiteBuilder.kt b/evaluator/src/main/kotlin/com/xebia/functional/xef/evaluator/SuiteBuilder.kt index 12b646b91..9f6978e5f 100644 --- a/evaluator/src/main/kotlin/com/xebia/functional/xef/evaluator/SuiteBuilder.kt +++ b/evaluator/src/main/kotlin/com/xebia/functional/xef/evaluator/SuiteBuilder.kt @@ -2,7 +2,7 @@ package com.xebia.functional.xef.evaluator import com.xebia.functional.xef.AI import com.xebia.functional.xef.evaluator.models.* -import io.github.nomisrev.openapi.CreateChatCompletionRequest +import com.xebia.functional.xef.openapi.CreateChatCompletionRequest import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json diff --git a/examples/src/main/kotlin/com/xebia/functional/xef/assistants/AssistantStreaming.kt b/examples/src/main/kotlin/com/xebia/functional/xef/assistants/AssistantStreaming.kt index f18e5f01a..e678b1e1f 100644 --- a/examples/src/main/kotlin/com/xebia/functional/xef/assistants/AssistantStreaming.kt +++ b/examples/src/main/kotlin/com/xebia/functional/xef/assistants/AssistantStreaming.kt @@ -5,7 +5,7 @@ import com.xebia.functional.xef.llm.assistants.Assistant import com.xebia.functional.xef.llm.assistants.AssistantThread import com.xebia.functional.xef.llm.assistants.Tool import com.xebia.functional.xef.metrics.Metric -import io.github.nomisrev.openapi.CreateRunRequest +import com.xebia.functional.xef.openapi.CreateRunRequest suspend fun main() { diff --git a/examples/src/main/kotlin/com/xebia/functional/xef/conversation/conversations/Animal.kt b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/conversations/Animal.kt index ffc4dfc06..8205d7822 100644 --- a/examples/src/main/kotlin/com/xebia/functional/xef/conversation/conversations/Animal.kt +++ b/examples/src/main/kotlin/com/xebia/functional/xef/conversation/conversations/Animal.kt @@ -6,12 +6,12 @@ import com.xebia.functional.xef.conversation.Conversation import com.xebia.functional.xef.conversation.MessagesFromHistory import com.xebia.functional.xef.conversation.MessagesToHistory import com.xebia.functional.xef.llm.promptMessage +import com.xebia.functional.xef.openapi.CreateChatCompletionRequest import com.xebia.functional.xef.prompt.Prompt import com.xebia.functional.xef.prompt.PromptBuilder.Companion.system import com.xebia.functional.xef.prompt.PromptBuilder.Companion.user import com.xebia.functional.xef.prompt.configuration.PromptConfiguration import com.xebia.functional.xef.store.LocalVectorStore -import io.github.nomisrev.openapi.CreateChatCompletionRequest import kotlinx.serialization.Serializable @Serializable data class Animal(val name: String, val habitat: String, val diet: String) diff --git a/examples/src/main/kotlin/com/xebia/functional/xef/dsl/audio/SimpleSpeech.kt b/examples/src/main/kotlin/com/xebia/functional/xef/dsl/audio/SimpleSpeech.kt index a44250931..5cec92a9b 100644 --- a/examples/src/main/kotlin/com/xebia/functional/xef/dsl/audio/SimpleSpeech.kt +++ b/examples/src/main/kotlin/com/xebia/functional/xef/dsl/audio/SimpleSpeech.kt @@ -4,10 +4,10 @@ import com.sipgate.mp3wav.Converter import com.xebia.functional.xef.AI import com.xebia.functional.xef.Config import com.xebia.functional.xef.OpenAI -import io.github.nomisrev.openapi.CreateSpeechRequest -import io.github.nomisrev.openapi.CreateTranscriptionRequest -import io.github.nomisrev.openapi.CreateTranslationRequest -import io.github.nomisrev.openapi.UploadFile +import com.xebia.functional.xef.openapi.CreateSpeechRequest +import com.xebia.functional.xef.openapi.CreateTranscriptionRequest +import com.xebia.functional.xef.openapi.CreateTranslationRequest +import com.xebia.functional.xef.openapi.UploadFile import io.ktor.client.statement.* import io.ktor.utils.io.jvm.javaio.* import java.io.File diff --git a/examples/src/main/kotlin/com/xebia/functional/xef/dsl/chat/Classes.kt b/examples/src/main/kotlin/com/xebia/functional/xef/dsl/chat/Classes.kt index 01049ab74..f4ebecafe 100644 --- a/examples/src/main/kotlin/com/xebia/functional/xef/dsl/chat/Classes.kt +++ b/examples/src/main/kotlin/com/xebia/functional/xef/dsl/chat/Classes.kt @@ -5,12 +5,12 @@ import com.xebia.functional.xef.conversation.Description import com.xebia.functional.xef.conversation.MessagePolicy import com.xebia.functional.xef.conversation.MessagesFromHistory import com.xebia.functional.xef.conversation.MessagesToHistory +import com.xebia.functional.xef.openapi.CreateChatCompletionRequest import com.xebia.functional.xef.prompt.Prompt import com.xebia.functional.xef.prompt.PromptBuilder.Companion.assistant import com.xebia.functional.xef.prompt.PromptBuilder.Companion.system import com.xebia.functional.xef.prompt.PromptBuilder.Companion.user import com.xebia.functional.xef.prompt.configuration.PromptConfiguration -import io.github.nomisrev.openapi.CreateChatCompletionRequest import kotlinx.serialization.Serializable @Serializable diff --git a/examples/src/main/kotlin/com/xebia/functional/xef/dsl/classify/AnswerAccuracy.kt b/examples/src/main/kotlin/com/xebia/functional/xef/dsl/classify/AnswerAccuracy.kt index bb18163a9..71422cbf6 100644 --- a/examples/src/main/kotlin/com/xebia/functional/xef/dsl/classify/AnswerAccuracy.kt +++ b/examples/src/main/kotlin/com/xebia/functional/xef/dsl/classify/AnswerAccuracy.kt @@ -2,7 +2,7 @@ package com.xebia.functional.xef.dsl.classify import com.xebia.functional.xef.AI import com.xebia.functional.xef.evaluator.metrics.AnswerAccuracy -import io.github.nomisrev.openapi.CreateChatCompletionRequest +import com.xebia.functional.xef.openapi.CreateChatCompletionRequest /** * This is a simple example of how to use the `AI.classify` function to classify the accuracy of an diff --git a/examples/src/main/kotlin/com/xebia/functional/xef/dsl/images/ImagesExamples.kt b/examples/src/main/kotlin/com/xebia/functional/xef/dsl/images/ImagesExamples.kt index 8f56d88d4..a7181360b 100644 --- a/examples/src/main/kotlin/com/xebia/functional/xef/dsl/images/ImagesExamples.kt +++ b/examples/src/main/kotlin/com/xebia/functional/xef/dsl/images/ImagesExamples.kt @@ -2,8 +2,8 @@ package com.xebia.functional.xef.dsl.images import com.xebia.functional.xef.OpenAI import com.xebia.functional.xef.llm.asInputProvider -import io.github.nomisrev.openapi.CreateImageRequest -import io.github.nomisrev.openapi.CreateImageVariationRequest +import com.xebia.functional.xef.openapi.CreateImageRequest +import com.xebia.functional.xef.openapi.CreateImageVariationRequest suspend fun main() { val openAI = OpenAI(logRequests = true) diff --git a/examples/src/main/kotlin/com/xebia/functional/xef/evaluator/TestExample.kt b/examples/src/main/kotlin/com/xebia/functional/xef/evaluator/TestExample.kt index bcd43d2eb..15d075d0e 100644 --- a/examples/src/main/kotlin/com/xebia/functional/xef/evaluator/TestExample.kt +++ b/examples/src/main/kotlin/com/xebia/functional/xef/evaluator/TestExample.kt @@ -7,9 +7,9 @@ import com.xebia.functional.xef.evaluator.metrics.AnswerAccuracy import com.xebia.functional.xef.evaluator.models.OutputDescription import com.xebia.functional.xef.evaluator.models.OutputResponse import com.xebia.functional.xef.llm.promptMessage +import com.xebia.functional.xef.openapi.CreateChatCompletionRequest import com.xebia.functional.xef.prompt.Prompt import com.xebia.functional.xef.prompt.PromptBuilder.Companion.user -import io.github.nomisrev.openapi.CreateChatCompletionRequest object TestExample { diff --git a/integrations/opentelemetry/src/main/kotlin/com/xebia/functional/xef/opentelemetry/OpenTelemetryAssistantState.kt b/integrations/opentelemetry/src/main/kotlin/com/xebia/functional/xef/opentelemetry/OpenTelemetryAssistantState.kt index c2048082a..eeb13fa5b 100644 --- a/integrations/opentelemetry/src/main/kotlin/com/xebia/functional/xef/opentelemetry/OpenTelemetryAssistantState.kt +++ b/integrations/opentelemetry/src/main/kotlin/com/xebia/functional/xef/opentelemetry/OpenTelemetryAssistantState.kt @@ -1,6 +1,6 @@ package com.xebia.functional.xef.opentelemetry -import io.github.nomisrev.openapi.* +import com.xebia.functional.xef.openapi.* import io.opentelemetry.api.trace.Span import io.opentelemetry.api.trace.SpanKind import io.opentelemetry.api.trace.Tracer diff --git a/integrations/opentelemetry/src/main/kotlin/com/xebia/functional/xef/opentelemetry/OpenTelemetryMetric.kt b/integrations/opentelemetry/src/main/kotlin/com/xebia/functional/xef/opentelemetry/OpenTelemetryMetric.kt index 4d653daba..b2143d773 100644 --- a/integrations/opentelemetry/src/main/kotlin/com/xebia/functional/xef/opentelemetry/OpenTelemetryMetric.kt +++ b/integrations/opentelemetry/src/main/kotlin/com/xebia/functional/xef/opentelemetry/OpenTelemetryMetric.kt @@ -1,11 +1,11 @@ package com.xebia.functional.xef.opentelemetry import com.xebia.functional.xef.metrics.Metric +import com.xebia.functional.xef.openapi.MessageObject +import com.xebia.functional.xef.openapi.RunObject +import com.xebia.functional.xef.openapi.RunStepObject import com.xebia.functional.xef.prompt.Prompt import com.xebia.functional.xef.prompt.contentAsString -import io.github.nomisrev.openapi.MessageObject -import io.github.nomisrev.openapi.RunObject -import io.github.nomisrev.openapi.RunStepObject import io.opentelemetry.api.trace.* class OpenTelemetryMetric( diff --git a/integrations/postgresql/src/main/kotlin/com/xebia/functional/xef/store/PostgreSQLVectorStore.kt b/integrations/postgresql/src/main/kotlin/com/xebia/functional/xef/store/PostgreSQLVectorStore.kt index 18c72b7d8..1e82b8287 100644 --- a/integrations/postgresql/src/main/kotlin/com/xebia/functional/xef/store/PostgreSQLVectorStore.kt +++ b/integrations/postgresql/src/main/kotlin/com/xebia/functional/xef/store/PostgreSQLVectorStore.kt @@ -6,7 +6,7 @@ import com.xebia.functional.xef.llm.embedQuery import com.xebia.functional.xef.llm.models.modelType import com.xebia.functional.xef.prompt.contentAsString import com.xebia.functional.xef.store.postgresql.* -import io.github.nomisrev.openapi.* +import com.xebia.functional.xef.openapi.* import kotlinx.uuid.UUID import kotlinx.uuid.generateUUID import javax.sql.DataSource diff --git a/integrations/postgresql/src/test/kotlin/xef/MemoryData.kt b/integrations/postgresql/src/test/kotlin/xef/MemoryData.kt index a2c8f74e0..541c42772 100644 --- a/integrations/postgresql/src/test/kotlin/xef/MemoryData.kt +++ b/integrations/postgresql/src/test/kotlin/xef/MemoryData.kt @@ -1,9 +1,9 @@ package xef import arrow.atomic.AtomicInt -import io.github.nomisrev.openapi.ChatCompletionRequestAssistantMessage -import io.github.nomisrev.openapi.ChatCompletionRequestMessage -import io.github.nomisrev.openapi.ChatCompletionRequestUserMessage +import com.xebia.functional.xef.openapi.ChatCompletionRequestAssistantMessage +import com.xebia.functional.xef.openapi.ChatCompletionRequestMessage +import com.xebia.functional.xef.openapi.ChatCompletionRequestUserMessage import com.xebia.functional.xef.store.ConversationId import com.xebia.functional.xef.store.MemorizedMessage import com.xebia.functional.xef.store.Memory diff --git a/integrations/postgresql/src/test/kotlin/xef/PGVectorStoreSpec.kt b/integrations/postgresql/src/test/kotlin/xef/PGVectorStoreSpec.kt index e9af1f78e..f916e26de 100644 --- a/integrations/postgresql/src/test/kotlin/xef/PGVectorStoreSpec.kt +++ b/integrations/postgresql/src/test/kotlin/xef/PGVectorStoreSpec.kt @@ -5,7 +5,7 @@ import com.xebia.functional.xef.store.migrations.runDatabaseMigrations import com.xebia.functional.xef.store.postgresql.PGDistanceStrategy import com.zaxxer.hikari.HikariConfig import com.zaxxer.hikari.HikariDataSource -import io.github.nomisrev.openapi.* +import com.xebia.functional.xef.openapi.* import io.kotest.core.Tuple3 import io.kotest.core.extensions.install import io.kotest.core.spec.style.StringSpec diff --git a/integrations/postgresql/src/test/kotlin/xef/TestEmbeddings.kt b/integrations/postgresql/src/test/kotlin/xef/TestEmbeddings.kt index f43f4f9aa..3b614e49d 100644 --- a/integrations/postgresql/src/test/kotlin/xef/TestEmbeddings.kt +++ b/integrations/postgresql/src/test/kotlin/xef/TestEmbeddings.kt @@ -1,6 +1,6 @@ package xef -import io.github.nomisrev.openapi.* +import com.xebia.functional.xef.openapi.* import io.ktor.client.request.* class TestEmbeddings : Embeddings, AutoCloseable { diff --git a/integrations/sql/src/main/kotlin/com/xebia/functional/xef/sql/SQL.kt b/integrations/sql/src/main/kotlin/com/xebia/functional/xef/sql/SQL.kt index f57487f39..64c8c9769 100644 --- a/integrations/sql/src/main/kotlin/com/xebia/functional/xef/sql/SQL.kt +++ b/integrations/sql/src/main/kotlin/com/xebia/functional/xef/sql/SQL.kt @@ -9,8 +9,8 @@ import com.xebia.functional.xef.prompt.PromptBuilder.Companion.system import com.xebia.functional.xef.prompt.PromptBuilder.Companion.user import com.xebia.functional.xef.sql.ResultSetOps.toQueryResult import com.xebia.functional.xef.sql.jdbc.JdbcConfig -import io.github.nomisrev.openapi.Chat -import io.github.nomisrev.openapi.CreateChatCompletionRequest +import com.xebia.functional.xef.openapi.Chat +import com.xebia.functional.xef.openapi.CreateChatCompletionRequest import io.github.oshai.kotlinlogging.KotlinLogging import kotlinx.serialization.Serializable import kotlinx.serialization.serializer diff --git a/integrations/sql/src/main/kotlin/com/xebia/functional/xef/sql/jdbc/JdbcConfig.kt b/integrations/sql/src/main/kotlin/com/xebia/functional/xef/sql/jdbc/JdbcConfig.kt index 9e39829b3..ac5e56193 100644 --- a/integrations/sql/src/main/kotlin/com/xebia/functional/xef/sql/jdbc/JdbcConfig.kt +++ b/integrations/sql/src/main/kotlin/com/xebia/functional/xef/sql/jdbc/JdbcConfig.kt @@ -1,7 +1,7 @@ package com.xebia.functional.xef.sql.jdbc -import io.github.nomisrev.openapi.Chat -import io.github.nomisrev.openapi.CreateChatCompletionRequest +import com.xebia.functional.xef.openapi.Chat +import com.xebia.functional.xef.openapi.CreateChatCompletionRequest class JdbcConfig( val vendor: String, diff --git a/server/src/main/kotlin/com/xebia/functional/xef/server/services/PostgresVectorStoreService.kt b/server/src/main/kotlin/com/xebia/functional/xef/server/services/PostgresVectorStoreService.kt index 22d9da0d1..6b8f74d81 100644 --- a/server/src/main/kotlin/com/xebia/functional/xef/server/services/PostgresVectorStoreService.kt +++ b/server/src/main/kotlin/com/xebia/functional/xef/server/services/PostgresVectorStoreService.kt @@ -2,12 +2,12 @@ package com.xebia.functional.xef.server.services import com.xebia.functional.xef.Config import com.xebia.functional.xef.OpenAI +import com.xebia.functional.xef.openapi.CreateEmbeddingRequest import com.xebia.functional.xef.store.PGVectorStore import com.xebia.functional.xef.store.VectorStore import com.xebia.functional.xef.store.postgresql.PGDistanceStrategy import com.xebia.functional.xef.store.postgresql.addNewCollection import com.xebia.functional.xef.store.postgresql.connection -import io.github.nomisrev.openapi.CreateEmbeddingRequest import io.github.oshai.kotlinlogging.KLogger import javax.sql.DataSource import kotlinx.uuid.UUID From d0737f500c2e6645217e3e990a70fd8ff814c7ab Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Fri, 28 Jun 2024 09:59:20 +0200 Subject: [PATCH 5/8] Move OpenAPI-kt into version.toml --- core/build.gradle.kts | 2 +- gradle/libs.versions.toml | 3 ++- settings.gradle.kts | 1 - 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 0f02aa0f2..80e14c303 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -16,7 +16,7 @@ plugins { alias(libs.plugins.arrow.gradle.publish) alias(libs.plugins.semver.gradle) alias(libs.plugins.detekt) - id("io.github.nomisrev.openapi-kt-plugin") version "0.0.2" + alias(libs.plugins.openapi.kt) } openApiConfig { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e064e4c66..8f453ddbb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -39,7 +39,7 @@ progressbar = "0.10.0" jmf = "2.1.1e" mp3-wav-converter = "1.0.4" yamlkt="0.13.0" - +openapi-kt="0.0.2" [libraries] arrow-core = { module = "io.arrow-kt:arrow-core", version.ref = "arrow" } @@ -143,3 +143,4 @@ semver-gradle = { id="com.javiersc.semver", version.ref="semverGradle" } resources = { id="com.goncalossilva.resources", version.ref="resources-kmp" } detekt = { id="io.gitlab.arturbosch.detekt", version.ref="detekt"} node-gradle = { id = "com.github.node-gradle.node", version.ref = "node-gradle" } +openapi-kt = { id= "io.github.nomisrev.openapi-kt-plugin", version.ref = "openapi-kt" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 76e37a56a..ebf2bdfed 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -8,7 +8,6 @@ dependencyResolutionManagement { pluginManagement { repositories { - mavenLocal() mavenCentral() gradlePluginPortal() } From eaa2471bc8981083def3b83fa77dd801dc5da371 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Wed, 3 Jul 2024 09:53:58 +0200 Subject: [PATCH 6/8] Move downloadOpenAIAPI to Gradle --- .github/workflows/openai-api-check.yml | 6 +- build.gradle.kts | 6 +- buildSrc/src/main/kotlin/DownloadOpenAI.kt | 16 +- core/openai-api-commit | 1 + core/openai-api.yaml | 1575 ++++++++------------ 5 files changed, 603 insertions(+), 1001 deletions(-) create mode 100644 core/openai-api-commit diff --git a/.github/workflows/openai-api-check.yml b/.github/workflows/openai-api-check.yml index 2bb319f84..9db55909d 100644 --- a/.github/workflows/openai-api-check.yml +++ b/.github/workflows/openai-api-check.yml @@ -50,7 +50,7 @@ jobs: const octokit = new Octokit(); const owner = ''xebia-functional''; const repo = ''xef''; - const filePath = ''openai-client/generator/config/openai-api-commit''; + const filePath = ''core/openai-api-commit''; const branch = ''main''; const response = await octokit.repos.getContent({ owner, @@ -78,7 +78,7 @@ jobs: const octokit = new Octokit(); const owner = ''xebia-functional''; const repo = ''xef''; - const filePath = ''openai-client/generator/config/openai-api-commit''; + const filePath = ''core/openai-api-commit''; const existing = await octokit.pulls.list({ owner, repo, @@ -121,7 +121,7 @@ jobs: - name: Update commit if: env.CURRENT_API_COMMIT != env.LATEST_API_COMMIT run: | - echo $LATEST_API_COMMIT > $GITHUB_WORKSPACE/openai-client/generator/config/openai-api-commit + echo $LATEST_API_COMMIT > $GITHUB_WORKSPACE/core/openai-api-commit - name: Set up Java if: env.CURRENT_API_COMMIT != env.LATEST_API_COMMIT uses: actions/setup-java@v4 diff --git a/build.gradle.kts b/build.gradle.kts index 273753d72..031f04b0a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -65,7 +65,7 @@ fun getGradleCommand(platform: String): String { configureBuildAndTestTask("buildAndTestMultip", ModulePlatformType.MULTI) configureBuildAndTestTask("buildAndTestSinglep", ModulePlatformType.SINGLE) -tasks.register("downloadOpenAI") { - input.set(file("openai-openapi-commit")) - output.set(file("openapi.yaml")) +tasks.register("downloadOpenAIAPI") { + input.set(file("core/openai-api-commit")) + output.set(file("core/openai-api.yaml")) } diff --git a/buildSrc/src/main/kotlin/DownloadOpenAI.kt b/buildSrc/src/main/kotlin/DownloadOpenAI.kt index 5665b7d7f..09900038f 100644 --- a/buildSrc/src/main/kotlin/DownloadOpenAI.kt +++ b/buildSrc/src/main/kotlin/DownloadOpenAI.kt @@ -1,9 +1,6 @@ import org.gradle.api.DefaultTask import org.gradle.api.file.RegularFileProperty -import org.gradle.api.tasks.CacheableTask -import org.gradle.api.tasks.InputFile -import org.gradle.api.tasks.OutputFile -import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.* import org.gradle.api.tasks.options.Option import java.net.URL import java.nio.channels.Channels @@ -17,6 +14,7 @@ abstract class DownloadOpenAI : DefaultTask() { @get:InputFile @get:Option(description = "Commit hash of the fetched OpenAI OpenAPI Yaml file") + @get:PathSensitive(PathSensitivity.RELATIVE) abstract val input: RegularFileProperty @get:OutputFile @@ -29,11 +27,15 @@ abstract class DownloadOpenAI : DefaultTask() { downloadAPI(commit) } - private fun readCommit(): String = - input.get().asFile.readText().trim { it <= ' ' } + private fun readCommit(): String { + val asFile = input.get().asFile + val readText = asFile.readText() + require(readText.isNotEmpty()) { "${asFile.path} Commit hash is empty" } + return readText.trim { it <= ' ' } + } private fun downloadAPI(commit: String) { - val url = URL("https://raw.githubusercontent.com/openai/openai-openapi/%s/openapi.yaml".formatted(commit)) + val url = URL("https://raw.githubusercontent.com/openai/openai-openapi/$commit/openapi.yaml") Channels.newChannel(url.openStream()).use { channel -> output.asFile.get().outputStream().use { output -> output.channel.transferFrom(channel, 0, Long.MAX_VALUE) diff --git a/core/openai-api-commit b/core/openai-api-commit new file mode 100644 index 000000000..4746a6be6 --- /dev/null +++ b/core/openai-api-commit @@ -0,0 +1 @@ +df5699f5c48fe455d9d036198e77fdb637edee29 \ No newline at end of file diff --git a/core/openai-api.yaml b/core/openai-api.yaml index 3ac187ed9..030518faf 100644 --- a/core/openai-api.yaml +++ b/core/openai-api.yaml @@ -2,7 +2,7 @@ openapi: 3.0.0 info: title: OpenAI API description: The OpenAI REST API. Please see https://platform.openai.com/docs/api-reference for more details. - version: "2.1.0" + version: "2.0.0" termsOfService: https://openai.com/policies/terms-of-use contact: name: OpenAI Support @@ -16,7 +16,7 @@ tags: - name: Assistants description: Build Assistants that can call models and use tools. - name: Audio - description: Turn audio into text or text into audio. + description: Learn how to turn audio into text or text into audio. - name: Chat description: Given a list of messages comprising a conversation, the model will return a response. - name: Completions @@ -87,7 +87,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + completion = client.chat.completions.create( model="VAR_model_id", messages=[ @@ -95,22 +95,22 @@ paths: {"role": "user", "content": "Hello!"} ] ) - + print(completion.choices[0].message) node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const completion = await openai.chat.completions.create({ messages: [{ role: "system", content: "You are a helpful assistant." }], model: "VAR_model_id", }); - + console.log(completion.choices[0]); } - + main(); response: &chat_completion_example | { @@ -163,9 +163,9 @@ paths: }' python: | from openai import OpenAI - + client = OpenAI() - + response = client.chat.completions.create( model="gpt-4-turbo", messages=[ @@ -182,13 +182,13 @@ paths: ], max_tokens=300, ) - + print(response.choices[0]) node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const response = await openai.chat.completions.create({ model: "gpt-4-turbo", @@ -254,7 +254,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + completion = client.chat.completions.create( model="VAR_model_id", messages=[ @@ -263,15 +263,15 @@ paths: ], stream=True ) - + for chunk in completion: print(chunk.choices[0].delta) node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const completion = await openai.chat.completions.create({ model: "VAR_model_id", @@ -281,20 +281,20 @@ paths: ], stream: true, }); - + for await (const chunk of completion) { console.log(chunk.choices[0].delta.content); } } - + main(); response: &chat_completion_chunk_example | {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1694268190,"model":"gpt-3.5-turbo-0125", "system_fingerprint": "fp_44709d6fcb", "choices":[{"index":0,"delta":{"role":"assistant","content":""},"logprobs":null,"finish_reason":null}]} - + {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1694268190,"model":"gpt-3.5-turbo-0125", "system_fingerprint": "fp_44709d6fcb", "choices":[{"index":0,"delta":{"content":"Hello"},"logprobs":null,"finish_reason":null}]} - + .... - + {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1694268190,"model":"gpt-3.5-turbo-0125", "system_fingerprint": "fp_44709d6fcb", "choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}]} - title: Functions request: @@ -338,7 +338,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + tools = [ { "type": "function", @@ -366,13 +366,13 @@ paths: tools=tools, tool_choice="auto" ) - + print(completion) node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const messages = [{"role": "user", "content": "What's the weather like in Boston today?"}]; const tools = [ @@ -395,17 +395,17 @@ paths: } } ]; - + const response = await openai.chat.completions.create({ model: "gpt-4-turbo", messages: messages, tools: tools, tool_choice: "auto", }); - + console.log(response); } - + main(); response: &chat_completion_function_example | { @@ -460,7 +460,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + completion = client.chat.completions.create( model="VAR_model_id", messages=[ @@ -469,14 +469,14 @@ paths: logprobs=True, top_logprobs=2 ) - + print(completion.choices[0].message) print(completion.choices[0].logprobs) node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const completion = await openai.chat.completions.create({ messages: [{ role: "user", content: "Hello!" }], @@ -484,10 +484,10 @@ paths: logprobs: true, top_logprobs: 2, }); - + console.log(completion.choices[0]); } - + main(); response: | { @@ -716,7 +716,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + client.completions.create( model="VAR_model_id", prompt="Say this is a test", @@ -725,9 +725,9 @@ paths: ) node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const completion = await openai.completions.create({ model: "VAR_model_id", @@ -735,7 +735,7 @@ paths: max_tokens: 7, temperature: 0, }); - + console.log(completion); } main(); @@ -776,7 +776,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + for chunk in client.completions.create( model="VAR_model_id", prompt="Say this is a test", @@ -787,16 +787,16 @@ paths: print(chunk.choices[0].text) node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const stream = await openai.completions.create({ model: "VAR_model_id", prompt: "Say this is a test.", stream: true, }); - + for await (const chunk of stream) { console.log(chunk.choices[0].text) } @@ -857,7 +857,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + client.images.generate( model="dall-e-3", prompt="A cute baby sea otter", @@ -866,12 +866,12 @@ paths: ) node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const image = await openai.images.generate({ model: "dall-e-3", prompt: "A cute baby sea otter" }); - + console.log(image.data); } main(); @@ -923,7 +923,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + client.images.edit( image=open("otter.png", "rb"), mask=open("mask.png", "rb"), @@ -934,16 +934,16 @@ paths: node.js: |- import fs from "fs"; import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const image = await openai.images.edit({ image: fs.createReadStream("otter.png"), mask: fs.createReadStream("mask.png"), prompt: "A cute baby sea otter wearing a beret", }); - + console.log(image.data); } main(); @@ -993,7 +993,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + response = client.images.create_variation( image=open("image_edit_original.png", "rb"), n=2, @@ -1002,14 +1002,14 @@ paths: node.js: |- import fs from "fs"; import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const image = await openai.images.createVariation({ image: fs.createReadStream("otter.png"), }); - + console.log(image.data); } main(); @@ -1063,7 +1063,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + client.embeddings.create( model="text-embedding-ada-002", input="The food was delicious and the waiter...", @@ -1071,19 +1071,19 @@ paths: ) node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const embedding = await openai.embeddings.create({ model: "text-embedding-ada-002", input: "The quick brown fox jumped over the lazy dog", encoding_format: "float", }); - + console.log(embedding); } - + main(); response: | { @@ -1151,7 +1151,7 @@ paths: python: | from pathlib import Path import openai - + speech_file_path = Path(__file__).parent / "speech.mp3" response = openai.audio.speech.create( model="tts-1", @@ -1163,11 +1163,11 @@ paths: import fs from "fs"; import path from "path"; import OpenAI from "openai"; - + const openai = new OpenAI(); - + const speechFile = path.resolve("./speech.mp3"); - + async function main() { const mp3 = await openai.audio.speech.create({ model: "tts-1", @@ -1216,7 +1216,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + audio_file = open("speech.mp3", "rb") transcript = client.audio.transcriptions.create( model="whisper-1", @@ -1225,15 +1225,15 @@ paths: node: | import fs from "fs"; import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const transcription = await openai.audio.transcriptions.create({ file: fs.createReadStream("audio.mp3"), model: "whisper-1", }); - + console.log(transcription.text); } main(); @@ -1254,7 +1254,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + audio_file = open("speech.mp3", "rb") transcript = client.audio.transcriptions.create( file=audio_file, @@ -1262,14 +1262,14 @@ paths: response_format="verbose_json", timestamp_granularities=["word"] ) - + print(transcript.words) node: | import fs from "fs"; import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const transcription = await openai.audio.transcriptions.create({ file: fs.createReadStream("audio.mp3"), @@ -1277,7 +1277,7 @@ paths: response_format: "verbose_json", timestamp_granularities: ["word"] }); - + console.log(transcription.text); } main(); @@ -1314,7 +1314,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + audio_file = open("speech.mp3", "rb") transcript = client.audio.transcriptions.create( file=audio_file, @@ -1322,14 +1322,14 @@ paths: response_format="verbose_json", timestamp_granularities=["segment"] ) - + print(transcript.words) node: | import fs from "fs"; import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const transcription = await openai.audio.transcriptions.create({ file: fs.createReadStream("audio.mp3"), @@ -1337,7 +1337,7 @@ paths: response_format: "verbose_json", timestamp_granularities: ["segment"] }); - + console.log(transcription.text); } main(); @@ -1401,7 +1401,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + audio_file = open("speech.mp3", "rb") transcript = client.audio.translations.create( model="whisper-1", @@ -1410,15 +1410,15 @@ paths: node: | import fs from "fs"; import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const translation = await openai.audio.translations.create({ file: fs.createReadStream("speech.mp3"), model: "whisper-1", }); - + console.log(translation.text); } main(); @@ -1459,21 +1459,21 @@ paths: python: | from openai import OpenAI client = OpenAI() - + client.files.list() node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const list = await openai.files.list(); - + for await (const file of list) { console.log(file); } } - + main(); response: | { @@ -1503,13 +1503,13 @@ paths: - Files summary: | Upload a file that can be used across various endpoints. Individual files can be up to 512 MB, and the size of all files uploaded by one organization can be up to 100 GB. - + The Assistants API supports files up to 2 million tokens and of specific file types. See the [Assistants Tools guide](/docs/assistants/tools) for details. - - The Fine-tuning API only supports `.jsonl` files. The input also has certain required formats for fine-tuning [chat](/docs/api-reference/fine-tuning/chat-input) or [completions](/docs/api-reference/fine-tuning/completions-input) models. - - The Batch API only supports `.jsonl` files up to 100 MB in size. The input also has a specific required [format](/docs/api-reference/batch/request-input). - + + The Fine-tuning API only supports `.jsonl` files. + + The Batch API only supports `.jsonl` files up to 100 MB in size. + Please [contact us](https://help.openai.com/) if you need to increase these storage limits. requestBody: required: true @@ -1538,7 +1538,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + client.files.create( file=open("mydata.jsonl", "rb"), purpose="fine-tune" @@ -1546,18 +1546,18 @@ paths: node.js: |- import fs from "fs"; import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const file = await openai.files.create({ file: fs.createReadStream("mydata.jsonl"), purpose: "fine-tune", }); - + console.log(file); } - + main(); response: | { @@ -1601,19 +1601,19 @@ paths: python: | from openai import OpenAI client = OpenAI() - + client.files.delete("file-abc123") node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const file = await openai.files.del("file-abc123"); - + console.log(file); } - + main(); response: | { @@ -1652,19 +1652,19 @@ paths: python: | from openai import OpenAI client = OpenAI() - + client.files.retrieve("file-abc123") node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const file = await openai.files.retrieve("file-abc123"); - + console.log(file); } - + main(); response: | { @@ -1707,19 +1707,19 @@ paths: python: | from openai import OpenAI client = OpenAI() - + content = client.files.content("file-abc123") node.js: | import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const file = await openai.files.content("file-abc123"); - + console.log(file); } - + main(); /fine_tuning/jobs: @@ -1729,9 +1729,9 @@ paths: - Fine-tuning summary: | Creates a fine-tuning job which begins the process of creating a new model from a given dataset. - + Response includes details of the enqueued job including job status and the name of the fine-tuned models once complete. - + [Learn more about fine-tuning](/docs/guides/fine-tuning) requestBody: required: true @@ -1764,24 +1764,24 @@ paths: python: | from openai import OpenAI client = OpenAI() - + client.fine_tuning.jobs.create( training_file="file-abc123", model="gpt-3.5-turbo" ) node.js: | import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const fineTune = await openai.fineTuning.jobs.create({ training_file: "file-abc123" }); - + console.log(fineTune); } - + main(); response: | { @@ -1812,7 +1812,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + client.fine_tuning.jobs.create( training_file="file-abc123", model="gpt-3.5-turbo", @@ -1822,19 +1822,19 @@ paths: ) node.js: | import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const fineTune = await openai.fineTuning.jobs.create({ training_file: "file-abc123", model: "gpt-3.5-turbo", hyperparameters: { n_epochs: 2 } }); - + console.log(fineTune); } - + main(); response: | { @@ -1864,7 +1864,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + client.fine_tuning.jobs.create( training_file="file-abc123", validation_file="file-def456", @@ -1872,18 +1872,18 @@ paths: ) node.js: | import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const fineTune = await openai.fineTuning.jobs.create({ training_file: "file-abc123", validation_file: "file-abc123" }); - + console.log(fineTune); } - + main(); response: | { @@ -1983,21 +1983,21 @@ paths: python: | from openai import OpenAI client = OpenAI() - + client.fine_tuning.jobs.list() node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const list = await openai.fineTuning.jobs.list(); - + for await (const fineTune of list) { console.log(fineTune); } } - + main(); response: | { @@ -2023,7 +2023,7 @@ paths: - Fine-tuning summary: | Get info about a fine-tuning job. - + [Learn more about fine-tuning](/docs/guides/fine-tuning) parameters: - in: path @@ -2053,19 +2053,19 @@ paths: python: | from openai import OpenAI client = OpenAI() - + client.fine_tuning.jobs.retrieve("ftjob-abc123") node.js: | import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const fineTune = await openai.fineTuning.jobs.retrieve("ftjob-abc123"); - + console.log(fineTune); } - + main(); response: &fine_tuning_example | { @@ -2140,24 +2140,24 @@ paths: python: | from openai import OpenAI client = OpenAI() - + client.fine_tuning.jobs.list_events( fine_tuning_job_id="ftjob-abc123", limit=2 ) node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const list = await openai.fineTuning.list_events(id="ftjob-abc123", limit=2); - + for await (const fineTune of list) { console.log(fineTune); } } - + main(); response: | { @@ -2219,16 +2219,16 @@ paths: python: | from openai import OpenAI client = OpenAI() - + client.fine_tuning.jobs.cancel("ftjob-abc123") node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const fineTune = await openai.fineTuning.jobs.cancel("ftjob-abc123"); - + console.log(fineTune); } main(); @@ -2352,16 +2352,16 @@ paths: python: | from openai import OpenAI client = OpenAI() - + client.models.list() node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const list = await openai.models.list(); - + for await (const model of list) { console.log(model); } @@ -2426,19 +2426,19 @@ paths: python: | from openai import OpenAI client = OpenAI() - + client.models.retrieve("VAR_model_id") node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const model = await openai.models.retrieve("VAR_model_id"); - + console.log(model); } - + main(); response: &retrieve_model_response | { @@ -2480,16 +2480,16 @@ paths: python: | from openai import OpenAI client = OpenAI() - + client.models.delete("ft:gpt-3.5-turbo:acemeco:suffix:abc123") node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const model = await openai.models.del("ft:gpt-3.5-turbo:acemeco:suffix:abc123"); - + console.log(model); } main(); @@ -2535,17 +2535,17 @@ paths: python: | from openai import OpenAI client = OpenAI() - + moderation = client.moderations.create(input="I want to kill them.") print(moderation) node.js: | import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const moderation = await openai.moderations.create({ input: "I want to kill them." }); - + console.log(moderation); } main(); @@ -2643,7 +2643,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + my_assistants = client.beta.assistants.list( order="desc", limit="20", @@ -2651,18 +2651,18 @@ paths: print(my_assistants.data) node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const myAssistants = await openai.beta.assistants.list({ order: "desc", limit: "20", }); - + console.log(myAssistants.data); } - + main(); response: &list_assistants_example | { @@ -2759,7 +2759,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + my_assistant = client.beta.assistants.create( instructions="You are a personal math tutor. When asked a question, write and run Python code to answer the question.", name="Math Tutor", @@ -2769,9 +2769,9 @@ paths: print(my_assistant) node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const myAssistant = await openai.beta.assistants.create({ instructions: @@ -2780,10 +2780,10 @@ paths: tools: [{ type: "code_interpreter" }], model: "gpt-4-turbo", }); - + console.log(myAssistant); } - + main(); response: &create_assistants_example | { @@ -2820,7 +2820,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + my_assistant = client.beta.assistants.create( instructions="You are an HR bot, and you have access to files to answer employee questions about company policies.", name="HR Helper", @@ -2831,9 +2831,9 @@ paths: print(my_assistant) node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const myAssistant = await openai.beta.assistants.create({ instructions: @@ -2847,10 +2847,10 @@ paths: }, model: "gpt-4-turbo" }); - + console.log(myAssistant); } - + main(); response: | { @@ -2912,22 +2912,22 @@ paths: python: | from openai import OpenAI client = OpenAI() - + my_assistant = client.beta.assistants.retrieve("asst_abc123") print(my_assistant) node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const myAssistant = await openai.beta.assistants.retrieve( "asst_abc123" ); - + console.log(myAssistant); } - + main(); response: | { @@ -2993,7 +2993,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + my_updated_assistant = client.beta.assistants.update( "asst_abc123", instructions="You are an HR bot, and you have access to files to answer employee questions about company policies. Always response with info from either of the files.", @@ -3001,13 +3001,13 @@ paths: tools=[{"type": "file_search"}], model="gpt-4-turbo" ) - + print(my_updated_assistant) node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const myUpdatedAssistant = await openai.beta.assistants.update( "asst_abc123", @@ -3019,10 +3019,10 @@ paths: model: "gpt-4-turbo" } ); - + console.log(myUpdatedAssistant); } - + main(); response: | { @@ -3083,17 +3083,17 @@ paths: python: | from openai import OpenAI client = OpenAI() - + response = client.beta.assistants.delete("asst_abc123") print(response) node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const response = await openai.beta.assistants.del("asst_abc123"); - + console.log(response); } main(); @@ -3139,20 +3139,20 @@ paths: python: | from openai import OpenAI client = OpenAI() - + empty_thread = client.beta.threads.create() print(empty_thread) node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const emptyThread = await openai.beta.threads.create(); - + console.log(emptyThread); } - + main(); response: | { @@ -3181,7 +3181,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + message_thread = client.beta.threads.create( messages=[ { @@ -3194,13 +3194,13 @@ paths: }, ] ) - + print(message_thread) node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const messageThread = await openai.beta.threads.create({ messages: [ @@ -3214,10 +3214,10 @@ paths: }, ], }); - + console.log(messageThread); } - + main(); response: | { @@ -3263,22 +3263,22 @@ paths: python: | from openai import OpenAI client = OpenAI() - + my_thread = client.beta.threads.retrieve("thread_abc123") print(my_thread) node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const myThread = await openai.beta.threads.retrieve( "thread_abc123" ); - + console.log(myThread); } - + main(); response: | { @@ -3338,7 +3338,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + my_updated_thread = client.beta.threads.update( "thread_abc123", metadata={ @@ -3349,9 +3349,9 @@ paths: print(my_updated_thread) node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const updatedThread = await openai.beta.threads.update( "thread_abc123", @@ -3359,10 +3359,10 @@ paths: metadata: { modified: "true", user: "abc123" }, } ); - + console.log(updatedThread); } - + main(); response: | { @@ -3410,17 +3410,17 @@ paths: python: | from openai import OpenAI client = OpenAI() - + response = client.beta.threads.delete("thread_abc123") print(response) node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const response = await openai.beta.threads.del("thread_abc123"); - + console.log(response); } main(); @@ -3496,22 +3496,22 @@ paths: python: | from openai import OpenAI client = OpenAI() - + thread_messages = client.beta.threads.messages.list("thread_abc123") print(thread_messages.data) node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const threadMessages = await openai.beta.threads.messages.list( "thread_abc123" ); - + console.log(threadMessages.data); } - + main(); response: | { @@ -3606,7 +3606,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + thread_message = client.beta.threads.messages.create( "thread_abc123", role="user", @@ -3615,18 +3615,18 @@ paths: print(thread_message) node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const threadMessages = await openai.beta.threads.messages.create( "thread_abc123", { role: "user", content: "How does AI work? Explain it in simple terms." } ); - + console.log(threadMessages); } - + main(); response: | { @@ -3691,7 +3691,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + message = client.beta.threads.messages.retrieve( message_id="msg_abc123", thread_id="thread_abc123", @@ -3699,18 +3699,18 @@ paths: print(message) node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const message = await openai.beta.threads.messages.retrieve( "thread_abc123", "msg_abc123" ); - + console.log(message); } - + main(); response: | { @@ -3785,7 +3785,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + message = client.beta.threads.messages.update( message_id="msg_abc12", thread_id="thread_abc123", @@ -3797,9 +3797,9 @@ paths: print(message) node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const message = await openai.beta.threads.messages.update( "thread_abc123", @@ -3875,7 +3875,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + deleted_message = client.beta.threads.messages.delete( message_id="msg_abc12", thread_id="thread_abc123", @@ -3883,15 +3883,15 @@ paths: print(deleted_message) node.js: |- import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const deletedMessage = await openai.beta.threads.messages.del( "thread_abc123", "msg_abc123" ); - + console.log(deletedMessage); } response: | @@ -3901,6 +3901,7 @@ paths: "deleted": true } + /threads/runs: post: operationId: createThreadAndRun @@ -3944,7 +3945,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + run = client.beta.threads.create_and_run( assistant_id="asst_abc123", thread={ @@ -3953,13 +3954,13 @@ paths: ] } ) - + print(run) node.js: | import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const run = await openai.beta.threads.createAndRun({ assistant_id: "asst_abc123", @@ -3969,10 +3970,10 @@ paths: ], }, }); - + console.log(run); } - + main(); response: | { @@ -4005,8 +4006,7 @@ paths: "incomplete_details": null, "usage": null, "response_format": "auto", - "tool_choice": "auto", - "parallel_tool_calls": true + "tool_choice": "auto" } - title: Streaming @@ -4028,7 +4028,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + stream = client.beta.threads.create_and_run( assistant_id="asst_123", thread={ @@ -4038,14 +4038,14 @@ paths: }, stream=True ) - + for event in stream: print(event) node.js: | import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const stream = await openai.beta.threads.createAndRun({ assistant_id: "asst_123", @@ -4056,58 +4056,58 @@ paths: }, stream: true }); - + for await (const event of stream) { console.log(event); } } - + main(); response: | event: thread.created data: {"id":"thread_123","object":"thread","created_at":1710348075,"metadata":{}} - + event: thread.run.created - data: {"id":"run_123","object":"thread.run","created_at":1710348075,"assistant_id":"asst_123","thread_id":"thread_123","status":"queued","started_at":null,"expires_at":1710348675,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[],"tool_resources":{},"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto","parallel_tool_calls":true} - + data: {"id":"run_123","object":"thread.run","created_at":1710348075,"assistant_id":"asst_123","thread_id":"thread_123","status":"queued","started_at":null,"expires_at":1710348675,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[],"tool_resources":{},"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto"} + event: thread.run.queued - data: {"id":"run_123","object":"thread.run","created_at":1710348075,"assistant_id":"asst_123","thread_id":"thread_123","status":"queued","started_at":null,"expires_at":1710348675,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[],"tool_resources":{},"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto","parallel_tool_calls":true} - + data: {"id":"run_123","object":"thread.run","created_at":1710348075,"assistant_id":"asst_123","thread_id":"thread_123","status":"queued","started_at":null,"expires_at":1710348675,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[],"tool_resources":{},"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto"} + event: thread.run.in_progress - data: {"id":"run_123","object":"thread.run","created_at":1710348075,"assistant_id":"asst_123","thread_id":"thread_123","status":"in_progress","started_at":null,"expires_at":1710348675,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[],"tool_resources":{},"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto","parallel_tool_calls":true} - + data: {"id":"run_123","object":"thread.run","created_at":1710348075,"assistant_id":"asst_123","thread_id":"thread_123","status":"in_progress","started_at":null,"expires_at":1710348675,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[],"tool_resources":{},"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto"} + event: thread.run.step.created data: {"id":"step_001","object":"thread.run.step","created_at":1710348076,"run_id":"run_123","assistant_id":"asst_123","thread_id":"thread_123","type":"message_creation","status":"in_progress","cancelled_at":null,"completed_at":null,"expires_at":1710348675,"failed_at":null,"last_error":null,"step_details":{"type":"message_creation","message_creation":{"message_id":"msg_001"}},"usage":null} - + event: thread.run.step.in_progress data: {"id":"step_001","object":"thread.run.step","created_at":1710348076,"run_id":"run_123","assistant_id":"asst_123","thread_id":"thread_123","type":"message_creation","status":"in_progress","cancelled_at":null,"completed_at":null,"expires_at":1710348675,"failed_at":null,"last_error":null,"step_details":{"type":"message_creation","message_creation":{"message_id":"msg_001"}},"usage":null} - + event: thread.message.created data: {"id":"msg_001","object":"thread.message","created_at":1710348076,"assistant_id":"asst_123","thread_id":"thread_123","run_id":"run_123","status":"in_progress","incomplete_details":null,"incomplete_at":null,"completed_at":null,"role":"assistant","content":[], "metadata":{}} - + event: thread.message.in_progress data: {"id":"msg_001","object":"thread.message","created_at":1710348076,"assistant_id":"asst_123","thread_id":"thread_123","run_id":"run_123","status":"in_progress","incomplete_details":null,"incomplete_at":null,"completed_at":null,"role":"assistant","content":[], "metadata":{}} - + event: thread.message.delta data: {"id":"msg_001","object":"thread.message.delta","delta":{"content":[{"index":0,"type":"text","text":{"value":"Hello","annotations":[]}}]}} - + ... - + event: thread.message.delta data: {"id":"msg_001","object":"thread.message.delta","delta":{"content":[{"index":0,"type":"text","text":{"value":" today"}}]}} - + event: thread.message.delta data: {"id":"msg_001","object":"thread.message.delta","delta":{"content":[{"index":0,"type":"text","text":{"value":"?"}}]}} - + event: thread.message.completed data: {"id":"msg_001","object":"thread.message","created_at":1710348076,"assistant_id":"asst_123","thread_id":"thread_123","run_id":"run_123","status":"completed","incomplete_details":null,"incomplete_at":null,"completed_at":1710348077,"role":"assistant","content":[{"type":"text","text":{"value":"Hello! How can I assist you today?","annotations":[]}}], "metadata":{}} - + event: thread.run.step.completed data: {"id":"step_001","object":"thread.run.step","created_at":1710348076,"run_id":"run_123","assistant_id":"asst_123","thread_id":"thread_123","type":"message_creation","status":"completed","cancelled_at":null,"completed_at":1710348077,"expires_at":1710348675,"failed_at":null,"last_error":null,"step_details":{"type":"message_creation","message_creation":{"message_id":"msg_001"}},"usage":{"prompt_tokens":20,"completion_tokens":11,"total_tokens":31}} - + event: thread.run.completed - {"id":"run_123","object":"thread.run","created_at":1710348076,"assistant_id":"asst_123","thread_id":"thread_123","status":"completed","started_at":1713226836,"expires_at":null,"cancelled_at":null,"failed_at":null,"completed_at":1713226837,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":{"prompt_tokens":345,"completion_tokens":11,"total_tokens":356},"response_format":"auto","tool_choice":"auto","parallel_tool_calls":true} - + {"id":"run_123","object":"thread.run","created_at":1710348076,"assistant_id":"asst_123","thread_id":"thread_123","status":"completed","started_at":1713226836,"expires_at":null,"cancelled_at":null,"failed_at":null,"completed_at":1713226837,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":{"prompt_tokens":345,"completion_tokens":11,"total_tokens":356},"response_format":"auto","tool_choice":"auto"} + event: done data: [DONE] @@ -4153,7 +4153,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + tools = [ { "type": "function", @@ -4174,7 +4174,7 @@ paths: } } ] - + stream = client.beta.threads.create_and_run( thread={ "messages": [ @@ -4185,14 +4185,14 @@ paths: tools=tools, stream=True ) - + for event in stream: print(event) node.js: | import OpenAI from "openai"; - + const openai = new OpenAI(); - + const tools = [ { "type": "function", @@ -4213,7 +4213,7 @@ paths: } } ]; - + async function main() { const stream = await openai.beta.threads.createAndRun({ assistant_id: "asst_123", @@ -4225,52 +4225,52 @@ paths: tools: tools, stream: true }); - + for await (const event of stream) { console.log(event); } } - + main(); response: | event: thread.created data: {"id":"thread_123","object":"thread","created_at":1710351818,"metadata":{}} - + event: thread.run.created - data: {"id":"run_123","object":"thread.run","created_at":1710351818,"assistant_id":"asst_123","thread_id":"thread_123","status":"queued","started_at":null,"expires_at":1710352418,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[{"type":"function","function":{"name":"get_current_weather","description":"Get the current weather in a given location","parameters":{"type":"object","properties":{"location":{"type":"string","description":"The city and state, e.g. San Francisco, CA"},"unit":{"type":"string","enum":["celsius","fahrenheit"]}},"required":["location"]}}}],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto","parallel_tool_calls":true}} - + data: {"id":"run_123","object":"thread.run","created_at":1710351818,"assistant_id":"asst_123","thread_id":"thread_123","status":"queued","started_at":null,"expires_at":1710352418,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[{"type":"function","function":{"name":"get_current_weather","description":"Get the current weather in a given location","parameters":{"type":"object","properties":{"location":{"type":"string","description":"The city and state, e.g. San Francisco, CA"},"unit":{"type":"string","enum":["celsius","fahrenheit"]}},"required":["location"]}}}],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto"}} + event: thread.run.queued - data: {"id":"run_123","object":"thread.run","created_at":1710351818,"assistant_id":"asst_123","thread_id":"thread_123","status":"queued","started_at":null,"expires_at":1710352418,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[{"type":"function","function":{"name":"get_current_weather","description":"Get the current weather in a given location","parameters":{"type":"object","properties":{"location":{"type":"string","description":"The city and state, e.g. San Francisco, CA"},"unit":{"type":"string","enum":["celsius","fahrenheit"]}},"required":["location"]}}}],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto","parallel_tool_calls":true}} - + data: {"id":"run_123","object":"thread.run","created_at":1710351818,"assistant_id":"asst_123","thread_id":"thread_123","status":"queued","started_at":null,"expires_at":1710352418,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[{"type":"function","function":{"name":"get_current_weather","description":"Get the current weather in a given location","parameters":{"type":"object","properties":{"location":{"type":"string","description":"The city and state, e.g. San Francisco, CA"},"unit":{"type":"string","enum":["celsius","fahrenheit"]}},"required":["location"]}}}],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto"}} + event: thread.run.in_progress - data: {"id":"run_123","object":"thread.run","created_at":1710351818,"assistant_id":"asst_123","thread_id":"thread_123","status":"in_progress","started_at":1710351818,"expires_at":1710352418,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[{"type":"function","function":{"name":"get_current_weather","description":"Get the current weather in a given location","parameters":{"type":"object","properties":{"location":{"type":"string","description":"The city and state, e.g. San Francisco, CA"},"unit":{"type":"string","enum":["celsius","fahrenheit"]}},"required":["location"]}}}],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto","parallel_tool_calls":true}} - + data: {"id":"run_123","object":"thread.run","created_at":1710351818,"assistant_id":"asst_123","thread_id":"thread_123","status":"in_progress","started_at":1710351818,"expires_at":1710352418,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[{"type":"function","function":{"name":"get_current_weather","description":"Get the current weather in a given location","parameters":{"type":"object","properties":{"location":{"type":"string","description":"The city and state, e.g. San Francisco, CA"},"unit":{"type":"string","enum":["celsius","fahrenheit"]}},"required":["location"]}}}],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto"}} + event: thread.run.step.created data: {"id":"step_001","object":"thread.run.step","created_at":1710351819,"run_id":"run_123","assistant_id":"asst_123","thread_id":"thread_123","type":"tool_calls","status":"in_progress","cancelled_at":null,"completed_at":null,"expires_at":1710352418,"failed_at":null,"last_error":null,"step_details":{"type":"tool_calls","tool_calls":[]},"usage":null} - + event: thread.run.step.in_progress data: {"id":"step_001","object":"thread.run.step","created_at":1710351819,"run_id":"run_123","assistant_id":"asst_123","thread_id":"thread_123","type":"tool_calls","status":"in_progress","cancelled_at":null,"completed_at":null,"expires_at":1710352418,"failed_at":null,"last_error":null,"step_details":{"type":"tool_calls","tool_calls":[]},"usage":null} - + event: thread.run.step.delta data: {"id":"step_001","object":"thread.run.step.delta","delta":{"step_details":{"type":"tool_calls","tool_calls":[{"index":0,"id":"call_XXNp8YGaFrjrSjgqxtC8JJ1B","type":"function","function":{"name":"get_current_weather","arguments":"","output":null}}]}}} - + event: thread.run.step.delta data: {"id":"step_001","object":"thread.run.step.delta","delta":{"step_details":{"type":"tool_calls","tool_calls":[{"index":0,"type":"function","function":{"arguments":"{\""}}]}}} - + event: thread.run.step.delta data: {"id":"step_001","object":"thread.run.step.delta","delta":{"step_details":{"type":"tool_calls","tool_calls":[{"index":0,"type":"function","function":{"arguments":"location"}}]}}} - + ... - + event: thread.run.step.delta data: {"id":"step_001","object":"thread.run.step.delta","delta":{"step_details":{"type":"tool_calls","tool_calls":[{"index":0,"type":"function","function":{"arguments":"ahrenheit"}}]}}} - + event: thread.run.step.delta data: {"id":"step_001","object":"thread.run.step.delta","delta":{"step_details":{"type":"tool_calls","tool_calls":[{"index":0,"type":"function","function":{"arguments":"\"}"}}]}}} - + event: thread.run.requires_action - data: {"id":"run_123","object":"thread.run","created_at":1710351818,"assistant_id":"asst_123","thread_id":"thread_123","status":"requires_action","started_at":1710351818,"expires_at":1710352418,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":{"type":"submit_tool_outputs","submit_tool_outputs":{"tool_calls":[{"id":"call_XXNp8YGaFrjrSjgqxtC8JJ1B","type":"function","function":{"name":"get_current_weather","arguments":"{\"location\":\"San Francisco, CA\",\"unit\":\"fahrenheit\"}"}}]}},"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[{"type":"function","function":{"name":"get_current_weather","description":"Get the current weather in a given location","parameters":{"type":"object","properties":{"location":{"type":"string","description":"The city and state, e.g. San Francisco, CA"},"unit":{"type":"string","enum":["celsius","fahrenheit"]}},"required":["location"]}}}],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":{"prompt_tokens":345,"completion_tokens":11,"total_tokens":356},"response_format":"auto","tool_choice":"auto","parallel_tool_calls":true}} - + data: {"id":"run_123","object":"thread.run","created_at":1710351818,"assistant_id":"asst_123","thread_id":"thread_123","status":"requires_action","started_at":1710351818,"expires_at":1710352418,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":{"type":"submit_tool_outputs","submit_tool_outputs":{"tool_calls":[{"id":"call_XXNp8YGaFrjrSjgqxtC8JJ1B","type":"function","function":{"name":"get_current_weather","arguments":"{\"location\":\"San Francisco, CA\",\"unit\":\"fahrenheit\"}"}}]}},"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[{"type":"function","function":{"name":"get_current_weather","description":"Get the current weather in a given location","parameters":{"type":"object","properties":{"location":{"type":"string","description":"The city and state, e.g. San Francisco, CA"},"unit":{"type":"string","enum":["celsius","fahrenheit"]}},"required":["location"]}}}],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":{"prompt_tokens":345,"completion_tokens":11,"total_tokens":356},"response_format":"auto","tool_choice":"auto"}} + event: done data: [DONE] @@ -4333,25 +4333,25 @@ paths: python: | from openai import OpenAI client = OpenAI() - + runs = client.beta.threads.runs.list( "thread_abc123" ) - + print(runs) node.js: | import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const runs = await openai.beta.threads.runs.list( "thread_abc123" ); - + console.log(runs); } - + main(); response: | { @@ -4401,8 +4401,7 @@ paths: "last_messages": null }, "response_format": "auto", - "tool_choice": "auto", - "parallel_tool_calls": true + "tool_choice": "auto" }, { "id": "run_abc456", @@ -4448,8 +4447,7 @@ paths: "last_messages": null }, "response_format": "auto", - "tool_choice": "auto", - "parallel_tool_calls": true + "tool_choice": "auto" } ], "first_id": "run_abc123", @@ -4500,27 +4498,27 @@ paths: python: | from openai import OpenAI client = OpenAI() - + run = client.beta.threads.runs.create( thread_id="thread_abc123", assistant_id="asst_abc123" ) - + print(run) node.js: | import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const run = await openai.beta.threads.runs.create( "thread_abc123", { assistant_id: "asst_abc123" } ); - + console.log(run); } - + main(); response: &run_object_example | { @@ -4555,8 +4553,7 @@ paths: "last_messages": null }, "response_format": "auto", - "tool_choice": "auto", - "parallel_tool_calls": true + "tool_choice": "auto" } - title: Streaming request: @@ -4572,74 +4569,74 @@ paths: python: | from openai import OpenAI client = OpenAI() - + stream = client.beta.threads.runs.create( thread_id="thread_123", assistant_id="asst_123", stream=True ) - + for event in stream: print(event) node.js: | import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const stream = await openai.beta.threads.runs.create( "thread_123", { assistant_id: "asst_123", stream: true } ); - + for await (const event of stream) { console.log(event); } } - + main(); response: | event: thread.run.created - data: {"id":"run_123","object":"thread.run","created_at":1710330640,"assistant_id":"asst_123","thread_id":"thread_123","status":"queued","started_at":null,"expires_at":1710331240,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto","parallel_tool_calls":true}} - + data: {"id":"run_123","object":"thread.run","created_at":1710330640,"assistant_id":"asst_123","thread_id":"thread_123","status":"queued","started_at":null,"expires_at":1710331240,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto"}} + event: thread.run.queued - data: {"id":"run_123","object":"thread.run","created_at":1710330640,"assistant_id":"asst_123","thread_id":"thread_123","status":"queued","started_at":null,"expires_at":1710331240,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto","parallel_tool_calls":true}} - + data: {"id":"run_123","object":"thread.run","created_at":1710330640,"assistant_id":"asst_123","thread_id":"thread_123","status":"queued","started_at":null,"expires_at":1710331240,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto"}} + event: thread.run.in_progress - data: {"id":"run_123","object":"thread.run","created_at":1710330640,"assistant_id":"asst_123","thread_id":"thread_123","status":"in_progress","started_at":1710330641,"expires_at":1710331240,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto","parallel_tool_calls":true}} - + data: {"id":"run_123","object":"thread.run","created_at":1710330640,"assistant_id":"asst_123","thread_id":"thread_123","status":"in_progress","started_at":1710330641,"expires_at":1710331240,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto"}} + event: thread.run.step.created data: {"id":"step_001","object":"thread.run.step","created_at":1710330641,"run_id":"run_123","assistant_id":"asst_123","thread_id":"thread_123","type":"message_creation","status":"in_progress","cancelled_at":null,"completed_at":null,"expires_at":1710331240,"failed_at":null,"last_error":null,"step_details":{"type":"message_creation","message_creation":{"message_id":"msg_001"}},"usage":null} - + event: thread.run.step.in_progress data: {"id":"step_001","object":"thread.run.step","created_at":1710330641,"run_id":"run_123","assistant_id":"asst_123","thread_id":"thread_123","type":"message_creation","status":"in_progress","cancelled_at":null,"completed_at":null,"expires_at":1710331240,"failed_at":null,"last_error":null,"step_details":{"type":"message_creation","message_creation":{"message_id":"msg_001"}},"usage":null} - + event: thread.message.created data: {"id":"msg_001","object":"thread.message","created_at":1710330641,"assistant_id":"asst_123","thread_id":"thread_123","run_id":"run_123","status":"in_progress","incomplete_details":null,"incomplete_at":null,"completed_at":null,"role":"assistant","content":[],"metadata":{}} - + event: thread.message.in_progress data: {"id":"msg_001","object":"thread.message","created_at":1710330641,"assistant_id":"asst_123","thread_id":"thread_123","run_id":"run_123","status":"in_progress","incomplete_details":null,"incomplete_at":null,"completed_at":null,"role":"assistant","content":[],"metadata":{}} - + event: thread.message.delta data: {"id":"msg_001","object":"thread.message.delta","delta":{"content":[{"index":0,"type":"text","text":{"value":"Hello","annotations":[]}}]}} - + ... - + event: thread.message.delta data: {"id":"msg_001","object":"thread.message.delta","delta":{"content":[{"index":0,"type":"text","text":{"value":" today"}}]}} - + event: thread.message.delta data: {"id":"msg_001","object":"thread.message.delta","delta":{"content":[{"index":0,"type":"text","text":{"value":"?"}}]}} - + event: thread.message.completed data: {"id":"msg_001","object":"thread.message","created_at":1710330641,"assistant_id":"asst_123","thread_id":"thread_123","run_id":"run_123","status":"completed","incomplete_details":null,"incomplete_at":null,"completed_at":1710330642,"role":"assistant","content":[{"type":"text","text":{"value":"Hello! How can I assist you today?","annotations":[]}}],"metadata":{}} - + event: thread.run.step.completed data: {"id":"step_001","object":"thread.run.step","created_at":1710330641,"run_id":"run_123","assistant_id":"asst_123","thread_id":"thread_123","type":"message_creation","status":"completed","cancelled_at":null,"completed_at":1710330642,"expires_at":1710331240,"failed_at":null,"last_error":null,"step_details":{"type":"message_creation","message_creation":{"message_id":"msg_001"}},"usage":{"prompt_tokens":20,"completion_tokens":11,"total_tokens":31}} - + event: thread.run.completed - data: {"id":"run_123","object":"thread.run","created_at":1710330640,"assistant_id":"asst_123","thread_id":"thread_123","status":"completed","started_at":1710330641,"expires_at":null,"cancelled_at":null,"failed_at":null,"completed_at":1710330642,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":{"prompt_tokens":20,"completion_tokens":11,"total_tokens":31},"response_format":"auto","tool_choice":"auto","parallel_tool_calls":true}} - + data: {"id":"run_123","object":"thread.run","created_at":1710330640,"assistant_id":"asst_123","thread_id":"thread_123","status":"completed","started_at":1710330641,"expires_at":null,"cancelled_at":null,"failed_at":null,"completed_at":1710330642,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":{"prompt_tokens":20,"completion_tokens":11,"total_tokens":31},"response_format":"auto","tool_choice":"auto"}} + event: done data: [DONE] @@ -4680,7 +4677,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + tools = [ { "type": "function", @@ -4701,21 +4698,21 @@ paths: } } ] - + stream = client.beta.threads.runs.create( thread_id="thread_abc123", assistant_id="asst_abc123", tools=tools, stream=True ) - + for event in stream: print(event) node.js: | import OpenAI from "openai"; - + const openai = new OpenAI(); - + const tools = [ { "type": "function", @@ -4736,7 +4733,7 @@ paths: } } ]; - + async function main() { const stream = await openai.beta.threads.runs.create( "thread_abc123", @@ -4746,55 +4743,55 @@ paths: stream: true } ); - + for await (const event of stream) { console.log(event); } } - + main(); response: | event: thread.run.created - data: {"id":"run_123","object":"thread.run","created_at":1710348075,"assistant_id":"asst_123","thread_id":"thread_123","status":"queued","started_at":null,"expires_at":1710348675,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto","parallel_tool_calls":true}} - + data: {"id":"run_123","object":"thread.run","created_at":1710348075,"assistant_id":"asst_123","thread_id":"thread_123","status":"queued","started_at":null,"expires_at":1710348675,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto"}} + event: thread.run.queued - data: {"id":"run_123","object":"thread.run","created_at":1710348075,"assistant_id":"asst_123","thread_id":"thread_123","status":"queued","started_at":null,"expires_at":1710348675,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto","parallel_tool_calls":true}} - + data: {"id":"run_123","object":"thread.run","created_at":1710348075,"assistant_id":"asst_123","thread_id":"thread_123","status":"queued","started_at":null,"expires_at":1710348675,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto"}} + event: thread.run.in_progress - data: {"id":"run_123","object":"thread.run","created_at":1710348075,"assistant_id":"asst_123","thread_id":"thread_123","status":"in_progress","started_at":1710348075,"expires_at":1710348675,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto","parallel_tool_calls":true}} - + data: {"id":"run_123","object":"thread.run","created_at":1710348075,"assistant_id":"asst_123","thread_id":"thread_123","status":"in_progress","started_at":1710348075,"expires_at":1710348675,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto"}} + event: thread.run.step.created data: {"id":"step_001","object":"thread.run.step","created_at":1710348076,"run_id":"run_123","assistant_id":"asst_123","thread_id":"thread_123","type":"message_creation","status":"in_progress","cancelled_at":null,"completed_at":null,"expires_at":1710348675,"failed_at":null,"last_error":null,"step_details":{"type":"message_creation","message_creation":{"message_id":"msg_001"}},"usage":null} - + event: thread.run.step.in_progress data: {"id":"step_001","object":"thread.run.step","created_at":1710348076,"run_id":"run_123","assistant_id":"asst_123","thread_id":"thread_123","type":"message_creation","status":"in_progress","cancelled_at":null,"completed_at":null,"expires_at":1710348675,"failed_at":null,"last_error":null,"step_details":{"type":"message_creation","message_creation":{"message_id":"msg_001"}},"usage":null} - + event: thread.message.created data: {"id":"msg_001","object":"thread.message","created_at":1710348076,"assistant_id":"asst_123","thread_id":"thread_123","run_id":"run_123","status":"in_progress","incomplete_details":null,"incomplete_at":null,"completed_at":null,"role":"assistant","content":[],"metadata":{}} - + event: thread.message.in_progress data: {"id":"msg_001","object":"thread.message","created_at":1710348076,"assistant_id":"asst_123","thread_id":"thread_123","run_id":"run_123","status":"in_progress","incomplete_details":null,"incomplete_at":null,"completed_at":null,"role":"assistant","content":[],"metadata":{}} - + event: thread.message.delta data: {"id":"msg_001","object":"thread.message.delta","delta":{"content":[{"index":0,"type":"text","text":{"value":"Hello","annotations":[]}}]}} - + ... - + event: thread.message.delta data: {"id":"msg_001","object":"thread.message.delta","delta":{"content":[{"index":0,"type":"text","text":{"value":" today"}}]}} - + event: thread.message.delta data: {"id":"msg_001","object":"thread.message.delta","delta":{"content":[{"index":0,"type":"text","text":{"value":"?"}}]}} - + event: thread.message.completed data: {"id":"msg_001","object":"thread.message","created_at":1710348076,"assistant_id":"asst_123","thread_id":"thread_123","run_id":"run_123","status":"completed","incomplete_details":null,"incomplete_at":null,"completed_at":1710348077,"role":"assistant","content":[{"type":"text","text":{"value":"Hello! How can I assist you today?","annotations":[]}}],"metadata":{}} - + event: thread.run.step.completed data: {"id":"step_001","object":"thread.run.step","created_at":1710348076,"run_id":"run_123","assistant_id":"asst_123","thread_id":"thread_123","type":"message_creation","status":"completed","cancelled_at":null,"completed_at":1710348077,"expires_at":1710348675,"failed_at":null,"last_error":null,"step_details":{"type":"message_creation","message_creation":{"message_id":"msg_001"}},"usage":{"prompt_tokens":20,"completion_tokens":11,"total_tokens":31}} - + event: thread.run.completed - data: {"id":"run_123","object":"thread.run","created_at":1710348075,"assistant_id":"asst_123","thread_id":"thread_123","status":"completed","started_at":1710348075,"expires_at":null,"cancelled_at":null,"failed_at":null,"completed_at":1710348077,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":{"prompt_tokens":20,"completion_tokens":11,"total_tokens":31},"response_format":"auto","tool_choice":"auto","parallel_tool_calls":true}} - + data: {"id":"run_123","object":"thread.run","created_at":1710348075,"assistant_id":"asst_123","thread_id":"thread_123","status":"completed","started_at":1710348075,"expires_at":null,"cancelled_at":null,"failed_at":null,"completed_at":1710348077,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":{"prompt_tokens":20,"completion_tokens":11,"total_tokens":31},"response_format":"auto","tool_choice":"auto"}} + event: done data: [DONE] @@ -4838,27 +4835,27 @@ paths: python: | from openai import OpenAI client = OpenAI() - + run = client.beta.threads.runs.retrieve( thread_id="thread_abc123", run_id="run_abc123" ) - + print(run) node.js: | import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const run = await openai.beta.threads.runs.retrieve( "thread_abc123", "run_abc123" ); - + console.log(run); } - + main(); response: | { @@ -4897,8 +4894,7 @@ paths: "last_messages": null }, "response_format": "auto", - "tool_choice": "auto", - "parallel_tool_calls": true + "tool_choice": "auto" } post: operationId: modifyRun @@ -4951,19 +4947,19 @@ paths: python: | from openai import OpenAI client = OpenAI() - + run = client.beta.threads.runs.update( thread_id="thread_abc123", run_id="run_abc123", metadata={"user_id": "user_abc123"}, ) - + print(run) node.js: | import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const run = await openai.beta.threads.runs.update( "thread_abc123", @@ -4974,10 +4970,10 @@ paths: }, } ); - + console.log(run); } - + main(); response: | { @@ -5026,8 +5022,7 @@ paths: "last_messages": null }, "response_format": "auto", - "tool_choice": "auto", - "parallel_tool_calls": true + "tool_choice": "auto" } /threads/{thread_id}/runs/{run_id}/submit_tool_outputs: @@ -5087,7 +5082,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + run = client.beta.threads.runs.submit_tool_outputs( thread_id="thread_123", run_id="run_123", @@ -5098,13 +5093,13 @@ paths: } ] ) - + print(run) node.js: | import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const run = await openai.beta.threads.runs.submitToolOutputs( "thread_123", @@ -5118,10 +5113,10 @@ paths: ], } ); - + console.log(run); } - + main(); response: | { @@ -5173,8 +5168,7 @@ paths: "last_messages": null }, "response_format": "auto", - "tool_choice": "auto", - "parallel_tool_calls": true + "tool_choice": "auto" } - title: Streaming @@ -5196,7 +5190,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + stream = client.beta.threads.runs.submit_tool_outputs( thread_id="thread_123", run_id="run_123", @@ -5208,14 +5202,14 @@ paths: ], stream=True ) - + for event in stream: print(event) node.js: | import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const stream = await openai.beta.threads.runs.submitToolOutputs( "thread_123", @@ -5229,61 +5223,61 @@ paths: ], } ); - + for await (const event of stream) { console.log(event); } } - + main(); response: | event: thread.run.step.completed data: {"id":"step_001","object":"thread.run.step","created_at":1710352449,"run_id":"run_123","assistant_id":"asst_123","thread_id":"thread_123","type":"tool_calls","status":"completed","cancelled_at":null,"completed_at":1710352475,"expires_at":1710353047,"failed_at":null,"last_error":null,"step_details":{"type":"tool_calls","tool_calls":[{"id":"call_iWr0kQ2EaYMaxNdl0v3KYkx7","type":"function","function":{"name":"get_current_weather","arguments":"{\"location\":\"San Francisco, CA\",\"unit\":\"fahrenheit\"}","output":"70 degrees and sunny."}}]},"usage":{"prompt_tokens":291,"completion_tokens":24,"total_tokens":315}} - + event: thread.run.queued - data: {"id":"run_123","object":"thread.run","created_at":1710352447,"assistant_id":"asst_123","thread_id":"thread_123","status":"queued","started_at":1710352448,"expires_at":1710353047,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[{"type":"function","function":{"name":"get_current_weather","description":"Get the current weather in a given location","parameters":{"type":"object","properties":{"location":{"type":"string","description":"The city and state, e.g. San Francisco, CA"},"unit":{"type":"string","enum":["celsius","fahrenheit"]}},"required":["location"]}}}],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto","parallel_tool_calls":true}} - + data: {"id":"run_123","object":"thread.run","created_at":1710352447,"assistant_id":"asst_123","thread_id":"thread_123","status":"queued","started_at":1710352448,"expires_at":1710353047,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[{"type":"function","function":{"name":"get_current_weather","description":"Get the current weather in a given location","parameters":{"type":"object","properties":{"location":{"type":"string","description":"The city and state, e.g. San Francisco, CA"},"unit":{"type":"string","enum":["celsius","fahrenheit"]}},"required":["location"]}}}],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto"}} + event: thread.run.in_progress - data: {"id":"run_123","object":"thread.run","created_at":1710352447,"assistant_id":"asst_123","thread_id":"thread_123","status":"in_progress","started_at":1710352475,"expires_at":1710353047,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[{"type":"function","function":{"name":"get_current_weather","description":"Get the current weather in a given location","parameters":{"type":"object","properties":{"location":{"type":"string","description":"The city and state, e.g. San Francisco, CA"},"unit":{"type":"string","enum":["celsius","fahrenheit"]}},"required":["location"]}}}],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto","parallel_tool_calls":true}} - + data: {"id":"run_123","object":"thread.run","created_at":1710352447,"assistant_id":"asst_123","thread_id":"thread_123","status":"in_progress","started_at":1710352475,"expires_at":1710353047,"cancelled_at":null,"failed_at":null,"completed_at":null,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[{"type":"function","function":{"name":"get_current_weather","description":"Get the current weather in a given location","parameters":{"type":"object","properties":{"location":{"type":"string","description":"The city and state, e.g. San Francisco, CA"},"unit":{"type":"string","enum":["celsius","fahrenheit"]}},"required":["location"]}}}],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":null,"response_format":"auto","tool_choice":"auto"}} + event: thread.run.step.created data: {"id":"step_002","object":"thread.run.step","created_at":1710352476,"run_id":"run_123","assistant_id":"asst_123","thread_id":"thread_123","type":"message_creation","status":"in_progress","cancelled_at":null,"completed_at":null,"expires_at":1710353047,"failed_at":null,"last_error":null,"step_details":{"type":"message_creation","message_creation":{"message_id":"msg_002"}},"usage":null} - + event: thread.run.step.in_progress data: {"id":"step_002","object":"thread.run.step","created_at":1710352476,"run_id":"run_123","assistant_id":"asst_123","thread_id":"thread_123","type":"message_creation","status":"in_progress","cancelled_at":null,"completed_at":null,"expires_at":1710353047,"failed_at":null,"last_error":null,"step_details":{"type":"message_creation","message_creation":{"message_id":"msg_002"}},"usage":null} - + event: thread.message.created data: {"id":"msg_002","object":"thread.message","created_at":1710352476,"assistant_id":"asst_123","thread_id":"thread_123","run_id":"run_123","status":"in_progress","incomplete_details":null,"incomplete_at":null,"completed_at":null,"role":"assistant","content":[],"metadata":{}} - + event: thread.message.in_progress data: {"id":"msg_002","object":"thread.message","created_at":1710352476,"assistant_id":"asst_123","thread_id":"thread_123","run_id":"run_123","status":"in_progress","incomplete_details":null,"incomplete_at":null,"completed_at":null,"role":"assistant","content":[],"metadata":{}} - + event: thread.message.delta data: {"id":"msg_002","object":"thread.message.delta","delta":{"content":[{"index":0,"type":"text","text":{"value":"The","annotations":[]}}]}} - + event: thread.message.delta data: {"id":"msg_002","object":"thread.message.delta","delta":{"content":[{"index":0,"type":"text","text":{"value":" current"}}]}} - + event: thread.message.delta data: {"id":"msg_002","object":"thread.message.delta","delta":{"content":[{"index":0,"type":"text","text":{"value":" weather"}}]}} - + ... - + event: thread.message.delta data: {"id":"msg_002","object":"thread.message.delta","delta":{"content":[{"index":0,"type":"text","text":{"value":" sunny"}}]}} - + event: thread.message.delta data: {"id":"msg_002","object":"thread.message.delta","delta":{"content":[{"index":0,"type":"text","text":{"value":"."}}]}} - + event: thread.message.completed data: {"id":"msg_002","object":"thread.message","created_at":1710352476,"assistant_id":"asst_123","thread_id":"thread_123","run_id":"run_123","status":"completed","incomplete_details":null,"incomplete_at":null,"completed_at":1710352477,"role":"assistant","content":[{"type":"text","text":{"value":"The current weather in San Francisco, CA is 70 degrees Fahrenheit and sunny.","annotations":[]}}],"metadata":{}} - + event: thread.run.step.completed data: {"id":"step_002","object":"thread.run.step","created_at":1710352476,"run_id":"run_123","assistant_id":"asst_123","thread_id":"thread_123","type":"message_creation","status":"completed","cancelled_at":null,"completed_at":1710352477,"expires_at":1710353047,"failed_at":null,"last_error":null,"step_details":{"type":"message_creation","message_creation":{"message_id":"msg_002"}},"usage":{"prompt_tokens":329,"completion_tokens":18,"total_tokens":347}} - + event: thread.run.completed - data: {"id":"run_123","object":"thread.run","created_at":1710352447,"assistant_id":"asst_123","thread_id":"thread_123","status":"completed","started_at":1710352475,"expires_at":null,"cancelled_at":null,"failed_at":null,"completed_at":1710352477,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[{"type":"function","function":{"name":"get_current_weather","description":"Get the current weather in a given location","parameters":{"type":"object","properties":{"location":{"type":"string","description":"The city and state, e.g. San Francisco, CA"},"unit":{"type":"string","enum":["celsius","fahrenheit"]}},"required":["location"]}}}],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":{"prompt_tokens":20,"completion_tokens":11,"total_tokens":31},"response_format":"auto","tool_choice":"auto","parallel_tool_calls":true}} - + data: {"id":"run_123","object":"thread.run","created_at":1710352447,"assistant_id":"asst_123","thread_id":"thread_123","status":"completed","started_at":1710352475,"expires_at":null,"cancelled_at":null,"failed_at":null,"completed_at":1710352477,"required_action":null,"last_error":null,"model":"gpt-4-turbo","instructions":null,"tools":[{"type":"function","function":{"name":"get_current_weather","description":"Get the current weather in a given location","parameters":{"type":"object","properties":{"location":{"type":"string","description":"The city and state, e.g. San Francisco, CA"},"unit":{"type":"string","enum":["celsius","fahrenheit"]}},"required":["location"]}}}],"metadata":{},"temperature":1.0,"top_p":1.0,"max_completion_tokens":null,"max_prompt_tokens":null,"truncation_strategy":{"type":"auto","last_messages":null},"incomplete_details":null,"usage":{"prompt_tokens":20,"completion_tokens":11,"total_tokens":31},"response_format":"auto","tool_choice":"auto"}} + event: done data: [DONE] @@ -5328,27 +5322,27 @@ paths: python: | from openai import OpenAI client = OpenAI() - + run = client.beta.threads.runs.cancel( thread_id="thread_abc123", run_id="run_abc123" ) - + print(run) node.js: | import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const run = await openai.beta.threads.runs.cancel( "thread_abc123", "run_abc123" ); - + console.log(run); } - + main(); response: | { @@ -5380,9 +5374,7 @@ paths: "usage": null, "temperature": 1.0, "top_p": 1.0, - "response_format": "auto", - "tool_choice": "auto", - "parallel_tool_calls": true + "response_format": "auto" } /threads/{thread_id}/runs/{run_id}/steps: @@ -5450,17 +5442,17 @@ paths: python: | from openai import OpenAI client = OpenAI() - + run_steps = client.beta.threads.runs.steps.list( thread_id="thread_abc123", run_id="run_abc123" ) - + print(run_steps) node.js: | import OpenAI from "openai"; const openai = new OpenAI(); - + async function main() { const runStep = await openai.beta.threads.runs.steps.list( "thread_abc123", @@ -5468,7 +5460,7 @@ paths: ); console.log(runStep); } - + main(); response: | { @@ -5553,18 +5545,18 @@ paths: python: | from openai import OpenAI client = OpenAI() - + run_step = client.beta.threads.runs.steps.retrieve( thread_id="thread_abc123", run_id="run_abc123", step_id="step_abc123" ) - + print(run_step) node.js: | import OpenAI from "openai"; const openai = new OpenAI(); - + async function main() { const runStep = await openai.beta.threads.runs.steps.retrieve( "thread_abc123", @@ -5573,7 +5565,7 @@ paths: ); console.log(runStep); } - + main(); response: &run_step_object_example | { @@ -5656,18 +5648,18 @@ paths: python: | from openai import OpenAI client = OpenAI() - + vector_stores = client.beta.vector_stores.list() print(vector_stores) node.js: | import OpenAI from "openai"; const openai = new OpenAI(); - + async function main() { const vectorStores = await openai.beta.vectorStores.list(); console.log(vectorStores); } - + main(); response: | { @@ -5742,7 +5734,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + vector_store = client.beta.vector_stores.create( name="Support FAQ" ) @@ -5750,14 +5742,14 @@ paths: node.js: | import OpenAI from "openai"; const openai = new OpenAI(); - + async function main() { const vectorStore = await openai.beta.vectorStores.create({ name: "Support FAQ" }); console.log(vectorStore); } - + main(); response: | { @@ -5810,7 +5802,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + vector_store = client.beta.vector_stores.retrieve( vector_store_id="vs_abc123" ) @@ -5818,14 +5810,14 @@ paths: node.js: | import OpenAI from "openai"; const openai = new OpenAI(); - + async function main() { const vectorStore = await openai.beta.vectorStores.retrieve( "vs_abc123" ); console.log(vectorStore); } - + main(); response: | { @@ -5876,7 +5868,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + vector_store = client.beta.vector_stores.update( vector_store_id="vs_abc123", name="Support FAQ" @@ -5885,7 +5877,7 @@ paths: node.js: | import OpenAI from "openai"; const openai = new OpenAI(); - + async function main() { const vectorStore = await openai.beta.vectorStores.update( "vs_abc123", @@ -5895,7 +5887,7 @@ paths: ); console.log(vectorStore); } - + main(); response: | { @@ -5948,7 +5940,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + deleted_vector_store = client.beta.vector_stores.delete( vector_store_id="vs_abc123" ) @@ -5956,14 +5948,14 @@ paths: node.js: | import OpenAI from "openai"; const openai = new OpenAI(); - + async function main() { const deletedVectorStore = await openai.beta.vectorStores.del( "vs_abc123" ); console.log(deletedVectorStore); } - + main(); response: | { @@ -6037,7 +6029,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + vector_store_files = client.beta.vector_stores.files.list( vector_store_id="vs_abc123" ) @@ -6045,14 +6037,14 @@ paths: node.js: | import OpenAI from "openai"; const openai = new OpenAI(); - + async function main() { const vectorStoreFiles = await openai.beta.vectorStores.files.list( "vs_abc123" ); console.log(vectorStoreFiles); } - + main(); response: | { @@ -6120,7 +6112,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + vector_store_file = client.beta.vector_stores.files.create( vector_store_id="vs_abc123", file_id="file-abc123" @@ -6129,7 +6121,7 @@ paths: node.js: | import OpenAI from "openai"; const openai = new OpenAI(); - + async function main() { const myVectorStoreFile = await openai.beta.vectorStores.files.create( "vs_abc123", @@ -6139,7 +6131,7 @@ paths: ); console.log(myVectorStoreFile); } - + main(); response: | { @@ -6195,7 +6187,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + vector_store_file = client.beta.vector_stores.files.retrieve( vector_store_id="vs_abc123", file_id="file-abc123" @@ -6204,7 +6196,7 @@ paths: node.js: | import OpenAI from "openai"; const openai = new OpenAI(); - + async function main() { const vectorStoreFile = await openai.beta.vectorStores.files.retrieve( "vs_abc123", @@ -6212,7 +6204,7 @@ paths: ); console.log(vectorStoreFile); } - + main(); response: | { @@ -6264,7 +6256,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + deleted_vector_store_file = client.beta.vector_stores.files.delete( vector_store_id="vs_abc123", file_id="file-abc123" @@ -6273,7 +6265,7 @@ paths: node.js: | import OpenAI from "openai"; const openai = new OpenAI(); - + async function main() { const deletedVectorStoreFile = await openai.beta.vectorStores.files.del( "vs_abc123", @@ -6281,7 +6273,7 @@ paths: ); console.log(deletedVectorStoreFile); } - + main(); response: | { @@ -6336,7 +6328,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + vector_store_file_batch = client.beta.vector_stores.file_batches.create( vector_store_id="vs_abc123", file_ids=["file-abc123", "file-abc456"] @@ -6345,7 +6337,7 @@ paths: node.js: | import OpenAI from "openai"; const openai = new OpenAI(); - + async function main() { const myVectorStoreFileBatch = await openai.beta.vectorStores.fileBatches.create( "vs_abc123", @@ -6355,7 +6347,7 @@ paths: ); console.log(myVectorStoreFileBatch); } - + main(); response: | { @@ -6416,7 +6408,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + vector_store_file_batch = client.beta.vector_stores.file_batches.retrieve( vector_store_id="vs_abc123", batch_id="vsfb_abc123" @@ -6425,7 +6417,7 @@ paths: node.js: | import OpenAI from "openai"; const openai = new OpenAI(); - + async function main() { const vectorStoreFileBatch = await openai.beta.vectorStores.fileBatches.retrieve( "vs_abc123", @@ -6433,7 +6425,7 @@ paths: ); console.log(vectorStoreFileBatch); } - + main(); response: | { @@ -6493,7 +6485,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + deleted_vector_store_file_batch = client.beta.vector_stores.file_batches.cancel( vector_store_id="vs_abc123", file_batch_id="vsfb_abc123" @@ -6502,7 +6494,7 @@ paths: node.js: | import OpenAI from "openai"; const openai = new OpenAI(); - + async function main() { const deletedVectorStoreFileBatch = await openai.vector_stores.fileBatches.cancel( "vs_abc123", @@ -6510,7 +6502,7 @@ paths: ); console.log(deletedVectorStoreFileBatch); } - + main(); response: | { @@ -6599,7 +6591,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + vector_store_files = client.beta.vector_stores.file_batches.list_files( vector_store_id="vs_abc123", batch_id="vsfb_abc123" @@ -6608,7 +6600,7 @@ paths: node.js: | import OpenAI from "openai"; const openai = new OpenAI(); - + async function main() { const vectorStoreFiles = await openai.beta.vectorStores.fileBatches.listFiles( "vs_abc123", @@ -6616,7 +6608,7 @@ paths: ); console.log(vectorStoreFiles); } - + main(); response: | { @@ -6661,18 +6653,13 @@ paths: type: string description: | The ID of an uploaded file that contains requests for the new batch. - + See [upload file](/docs/api-reference/files/create) for how to upload a file. - - Your input file must be formatted as a [JSONL file](/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 100 MB in size. + + Your input file must be formatted as a [JSONL file](/docs/api-reference/batch/requestInput), and must be uploaded with the purpose `batch`. The file can contain up to 50,000 requests, and can be up to 100 MB in size. endpoint: type: string - enum: - [ - "/v1/chat/completions", - "/v1/embeddings", - "/v1/completions", - ] + enum: ["/v1/chat/completions", "/v1/embeddings", "/v1/completions"] description: 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. completion_window: type: string @@ -6709,7 +6696,7 @@ paths: python: | from openai import OpenAI client = OpenAI() - + client.batches.create( input_file_id="file-abc123", endpoint="/v1/chat/completions", @@ -6717,19 +6704,19 @@ paths: ) node: | import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const batch = await openai.batches.create({ input_file_id: "file-abc123", endpoint: "/v1/chat/completions", completion_window: "24h" }); - + console.log(batch); } - + main(); response: | { @@ -6800,21 +6787,21 @@ paths: python: | from openai import OpenAI client = OpenAI() - + client.batches.list() node: | import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const list = await openai.batches.list(); - + for await (const batch of list) { console.log(batch); } } - + main(); response: | { @@ -6889,19 +6876,19 @@ paths: python: | from openai import OpenAI client = OpenAI() - + client.batches.retrieve("batch_abc123") node: | import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const batch = await openai.batches.retrieve("batch_abc123"); - + console.log(batch); } - + main(); response: &batch_object | { @@ -6939,7 +6926,7 @@ paths: operationId: cancelBatch tags: - Batch - summary: 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. + summary: Cancels an in-progress batch. parameters: - in: path name: batch_id @@ -6968,19 +6955,19 @@ paths: python: | from openai import OpenAI client = OpenAI() - + client.batches.cancel("batch_abc123") node: | import OpenAI from "openai"; - + const openai = new OpenAI(); - + async function main() { const batch = await openai.batches.cancel("batch_abc123"); - + console.log(batch); } - + main(); response: | { @@ -7089,7 +7076,7 @@ components: prompt: description: &completions_prompt_description | The prompt(s) to generate completions for, encoded as a string, array of strings, array of tokens, or array of token arrays. - + Note that <|endoftext|> is the document separator that the model sees during training, so if a prompt is not specified the model will generate as if from the beginning of a new document. default: "<|endoftext|>" nullable: true @@ -7123,9 +7110,9 @@ components: nullable: true description: &completions_best_of_description | Generates `best_of` completions server-side and returns the "best" (the one with the highest log probability per token). Results cannot be streamed. - + When used with `n`, `best_of` controls the number of candidate completions and `n` specifies how many to return – `best_of` must be greater than `n`. - + **Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. echo: type: boolean @@ -7141,7 +7128,7 @@ components: nullable: true description: &completions_frequency_penalty_description | Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim. - + [See more information about frequency and presence penalties.](/docs/guides/text-generation/parameter-details) logit_bias: &completions_logit_bias type: object @@ -7152,9 +7139,9 @@ components: type: integer description: &completions_logit_bias_description | Modify the likelihood of specified tokens appearing in the completion. - + Accepts a JSON object that maps tokens (specified by their token ID in the GPT tokenizer) to an associated bias value from -100 to 100. You can use this [tokenizer tool](/tokenizer?view=bpe) to convert text to token IDs. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token. - + As an example, you can pass `{"50256": -100}` to prevent the <|endoftext|> token from being generated. logprobs: &completions_logprobs_configuration type: integer @@ -7164,7 +7151,7 @@ components: nullable: true description: &completions_logprobs_description | Include the log probabilities on the `logprobs` most likely output tokens, as well the chosen tokens. For example, if `logprobs` is 5, the API will return a list of the 5 most likely tokens. The API will always return the `logprob` of the sampled token, so there may be up to `logprobs+1` elements in the response. - + The maximum value for `logprobs` is 5. max_tokens: type: integer @@ -7174,7 +7161,7 @@ components: nullable: true description: &completions_max_tokens_description | The maximum number of [tokens](/tokenizer) that can be generated in the completion. - + The token count of your prompt plus `max_tokens` cannot exceed the model's context length. [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) for counting tokens. n: type: integer @@ -7185,7 +7172,7 @@ components: nullable: true description: &completions_completions_description | How many completions to generate for each prompt. - + **Note:** Because this parameter generates many completions, it can quickly consume your token quota. Use carefully and ensure that you have reasonable settings for `max_tokens` and `stop`. presence_penalty: type: number @@ -7195,7 +7182,7 @@ components: nullable: true description: &completions_presence_penalty_description | Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics. - + [See more information about frequency and presence penalties.](/docs/guides/text-generation/parameter-details) seed: &completions_seed_param type: integer @@ -7204,7 +7191,7 @@ components: nullable: true description: | If specified, our system will make a best effort to sample deterministically, such that repeated requests with the same `seed` and parameters should return the same result. - + Determinism is not guaranteed, and you should refer to the `system_fingerprint` response parameter to monitor changes in the backend. stop: description: &completions_stop_description > @@ -7234,7 +7221,7 @@ components: suffix: description: | The suffix that comes after a completion of inserted text. - + This parameter is only supported for `gpt-3.5-turbo-instruct`. default: null nullable: true @@ -7249,7 +7236,7 @@ components: nullable: true description: &completions_temperature_description | What sampling temperature to use, between 0 and 2. Higher values like 0.8 will make the output more random, while lower values like 0.2 will make it more focused and deterministic. - + We generally recommend altering this or `top_p` but not both. top_p: type: number @@ -7260,7 +7247,7 @@ components: nullable: true description: &completions_top_p_description | An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. - + We generally recommend altering this or `temperature` but not both. user: &end_user_param_configuration type: string @@ -7333,7 +7320,7 @@ components: type: string description: | This fingerprint represents the backend configuration that the model runs with. - + Can be used in conjunction with the `seed` request parameter to understand when backend changes have been made that might impact determinism. object: type: string @@ -7496,7 +7483,6 @@ components: type: object deprecated: true description: "Deprecated and replaced by `tool_calls`. The name and arguments of a function that should be called, as generated by the model." - nullable: true properties: arguments: type: string @@ -7510,20 +7496,6 @@ components: required: - role - FineTuneChatCompletionRequestAssistantMessage: - allOf: - - type: object - title: Assistant message - deprecated: false - properties: - weight: - type: integer - enum: [0, 1] - description: "Controls whether the assistant message is trained against (0 or 1)" - - $ref: "#/components/schemas/ChatCompletionRequestAssistantMessage" - required: - - role - ChatCompletionRequestToolMessage: type: object title: Tool message @@ -7566,7 +7538,7 @@ components: FunctionParameters: type: object - description: "The parameters the functions accepts, described as a JSON Schema object. See the [guide](/docs/guides/function-calling) for examples, and the [JSON Schema reference](https://json-schema.org/understanding-json-schema/) for documentation about the format. \n\nOmitting `parameters` defines a function with an empty parameter list." + description: "The parameters the functions accepts, described as a JSON Schema object. See the [guide](/docs/guides/text-generation/function-calling) for examples, and the [JSON Schema reference](https://json-schema.org/understanding-json-schema/) for documentation about the format. \n\nOmitting `parameters` defines a function with an empty parameter list." additionalProperties: true ChatCompletionFunctions: @@ -7629,7 +7601,7 @@ components: `auto` 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. Specifying a particular tool via `{"type": "function", "function": {"name": "my_function"}}` forces the model to call that tool. - + `none` is the default when no tools are present. `auto` is the default if tools are present. oneOf: - type: string @@ -7661,11 +7633,6 @@ components: - type - function - ParallelToolCalls: - description: Whether to enable [parallel function calling](/docs/guides/function-calling/parallel-function-calling) during tool use. - type: boolean - default: true - ChatCompletionMessageToolCalls: type: array description: The tool calls generated by the model, such as function calls. @@ -7864,7 +7831,7 @@ components: type: integer description: | Modify the likelihood of specified tokens appearing in the completion. - + Accepts a JSON object that maps tokens (specified by their token ID in the tokenizer) to an associated bias value from -100 to 100. Mathematically, the bias is added to the logits generated by the model prior to sampling. The exact effect will vary per model, but values between -1 and 1 should decrease or increase likelihood of selection; values like -100 or 100 should result in a ban or exclusive selection of the relevant token. logprobs: description: Whether to return log probabilities of the output tokens or not. If true, returns the log probabilities of each output token returned in the `content` of `message`. @@ -7880,7 +7847,7 @@ components: max_tokens: description: | The maximum number of [tokens](/tokenizer) that can be generated in the chat completion. - + The total length of input tokens and generated tokens is limited by the model's context length. [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) for counting tokens. type: integer nullable: true @@ -7903,9 +7870,9 @@ components: type: object description: | An object specifying the format that the model must output. Compatible with [GPT-4 Turbo](/docs/models/gpt-4-and-gpt-4-turbo) and all GPT-3.5 Turbo models newer than `gpt-3.5-turbo-1106`. - + Setting to `{ "type": "json_object" }` enables JSON mode, which guarantees the message the model generates is valid JSON. - + **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length. properties: type: @@ -7925,17 +7892,6 @@ components: Determinism is not guaranteed, and you should refer to the `system_fingerprint` response parameter to monitor changes in the backend. x-oaiMeta: beta: true - service_tier: - description: | - Specifies the latency tier to use for processing the request. This parameter is relevant for customers subscribed to the scale tier service: - - If set to 'auto', the system will utilize scale tier credits until they are exhausted. - - If set to 'default', the request will be processed using the default service tier with a lower uptime SLA and no latency guarentee. - - When this parameter is set, the response body will include the `service_tier` utilized. - type: string - enum: ["auto", "default"] - nullable: true - default: null stop: description: | Up to 4 sequences where the API will stop generating further tokens. @@ -7982,19 +7938,17 @@ components: $ref: "#/components/schemas/ChatCompletionTool" tool_choice: $ref: "#/components/schemas/ChatCompletionToolChoiceOption" - parallel_tool_calls: - $ref: "#/components/schemas/ParallelToolCalls" user: *end_user_param_configuration function_call: deprecated: true description: | Deprecated in favor of `tool_choice`. - + Controls which (if any) function is called by the model. `none` means the model will not call a function and instead generates a message. `auto` means the model can pick between generating a message or calling a function. Specifying a particular function via `{"name": "my_function"}` forces the model to call that function. - + `none` is the default when no functions are present. `auto` is the default if functions are present. oneOf: - type: string @@ -8008,7 +7962,7 @@ components: deprecated: true description: | Deprecated in favor of `tools`. - + A list of functions the model may generate JSON inputs for. type: array minItems: 1 @@ -8077,17 +8031,11 @@ components: model: type: string description: The model used for the chat completion. - service_tier: - description: The service tier used for processing the request. This field is only included if the `service_tier` parameter is specified in the request. - type: string - enum: ["scale", "default"] - example: "scale" - nullable: true system_fingerprint: type: string description: | This fingerprint represents the backend configuration that the model runs with. - + Can be used in conjunction with the `seed` request parameter to understand when backend changes have been made that might impact determinism. object: type: string @@ -8129,8 +8077,7 @@ components: description: &chat_completion_function_finish_reason_description | The reason the model stopped generating tokens. This will be `stop` if the model hit a natural stop point or a provided stop sequence, `length` if the maximum number of tokens specified in the request was reached, `content_filter` if content was omitted due to a flag from our content filters, or `function_call` if the model called a function. - enum: - ["stop", "length", "function_call", "content_filter"] + enum: ["stop", "length", "function_call", "content_filter"] index: type: integer description: The index of the choice in the list of choices. @@ -8146,7 +8093,7 @@ components: type: string description: | This fingerprint represents the backend configuration that the model runs with. - + Can be used in conjunction with the `seed` request parameter to understand when backend changes have been made that might impact determinism. object: type: string @@ -8259,12 +8206,6 @@ components: model: type: string description: The model to generate the completion. - service_tier: - description: The service tier used for processing the request. This field is only included if the `service_tier` parameter is specified in the request. - type: string - enum: ["scale", "default"] - example: "scale" - nullable: true system_fingerprint: type: string description: | @@ -8488,7 +8429,7 @@ components: model: description: | Two content moderations models are available: `text-moderation-stable` and `text-moderation-latest`. - + The default is `text-moderation-latest` which will be automatically upgraded over time. This ensures you are always using our most accurate model. If you use `text-moderation-stable`, we will provide advanced notice before updating the model. Accuracy of `text-moderation-stable` may be slightly lower than for `text-moderation-latest`. nullable: false default: "text-moderation-latest" @@ -8656,10 +8597,10 @@ components: purpose: description: | The intended purpose of the uploaded file. - + Use "assistants" for [Assistants](/docs/api-reference/assistants) and [Message](/docs/api-reference/messages) files, "vision" for Assistants image file inputs, "batch" for [Batch API](/docs/guides/batch), and "fine-tune" for [Fine-tuning](/docs/api-reference/fine-tuning). type: string - enum: ["assistants", "batch", "fine-tune", "vision"] + enum: ["assistants", "batch", "fine-tune"] required: - file - purpose @@ -8695,13 +8636,11 @@ components: training_file: description: | The ID of an uploaded file that contains training data. - + See [upload file](/docs/api-reference/files/create) for how to upload a file. - + Your dataset must be formatted as a JSONL file. Additionally, you must upload your file with the purpose `fine-tune`. - - The contents of the file should differ depending on if the model uses the [chat](/docs/api-reference/fine-tuning/chat-input) or [completions](/docs/api-reference/fine-tuning/completions-input) format. - + See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. type: string example: "file-abc123" @@ -8745,7 +8684,7 @@ components: suffix: description: | A string of up to 18 characters that will be added to your fine-tuned model name. - + For example, a `suffix` of "custom-model-name" would produce a model name like `ft:gpt-3.5-turbo:openai:custom-model-name:7p4lURel`. type: string minLength: 1 @@ -8755,14 +8694,14 @@ components: validation_file: description: | The ID of an uploaded file that contains validation data. - + If you provide this file, the data is used to generate validation metrics periodically during fine-tuning. These metrics can be viewed in the fine-tuning results file. The same data should not be present in both train and validation files. - + Your dataset must be formatted as a JSONL file. You must upload your file with the purpose `fine-tune`. - + See the [fine-tuning guide](/docs/guides/fine-tuning) for more details. type: string nullable: true @@ -9041,7 +8980,7 @@ components: required: - text x-oaiMeta: - name: The transcription object (JSON) + name: The transcription object group: audio example: *basic_transcription_response_example @@ -9139,7 +9078,7 @@ components: $ref: "#/components/schemas/TranscriptionSegment" required: [language, duration, text] x-oaiMeta: - name: The transcription object (Verbose JSON) + name: The transcription object group: audio example: *verbose_transcription_response_example @@ -9301,7 +9240,7 @@ components: "batch_output", "fine-tune", "fine-tune-results", - "vision", + "vision" ] status: type: string @@ -9419,9 +9358,9 @@ components: maximum: 50 default: auto description: - The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset. - - "auto" decides the optimal number of epochs based on the size of the dataset. If setting the number manually, we support any number between 1 and 50 epochs. + The number of epochs to train the model for. An epoch refers to one full cycle through the training dataset. + + "auto" decides the optimal number of epochs based on the size of the dataset. If setting the number manually, we support any number between 1 and 50 epochs. required: - n_epochs model: @@ -9649,98 +9588,6 @@ components: "step_number": 88 } - FinetuneChatRequestInput: - type: object - description: The per-line training example of a fine-tuning input file for chat models - properties: - messages: - type: array - minItems: 1 - items: - oneOf: - - $ref: "#/components/schemas/ChatCompletionRequestSystemMessage" - - $ref: "#/components/schemas/ChatCompletionRequestUserMessage" - - $ref: "#/components/schemas/FineTuneChatCompletionRequestAssistantMessage" - - $ref: "#/components/schemas/ChatCompletionRequestToolMessage" - - $ref: "#/components/schemas/ChatCompletionRequestFunctionMessage" - x-oaiExpandable: true - tools: - type: array - description: A list of tools the model may generate JSON inputs for. - items: - $ref: "#/components/schemas/ChatCompletionTool" - parallel_tool_calls: - $ref: "#/components/schemas/ParallelToolCalls" - functions: - deprecated: true - description: - A list of functions the model may generate JSON inputs for. - type: array - minItems: 1 - maxItems: 128 - items: - $ref: "#/components/schemas/ChatCompletionFunctions" - x-oaiMeta: - name: Training format for chat models - example: | - { - "messages": [ - { "role": "user", "content": "What is the weather in San Francisco?" }, - { - "role": "assistant", - "tool_calls": [ - { - "id": "call_id", - "type": "function", - "function": { - "name": "get_current_weather", - "arguments": "{\"location\": \"San Francisco, USA\", \"format\": \"celsius\"}" - } - } - ] - } - ], - "parallel_tool_calls": false, - "tools": [ - { - "type": "function", - "function": { - "name": "get_current_weather", - "description": "Get the current weather", - "parameters": { - "type": "object", - "properties": { - "location": { - "type": "string", - "description": "The city and country, eg. San Francisco, USA" - }, - "format": { "type": "string", "enum": ["celsius", "fahrenheit"] } - }, - "required": ["location", "format"] - } - } - } - ] - } - - FinetuneCompletionRequestInput: - type: object - description: The per-line training example of a fine-tuning input file for completions models - properties: - prompt: - type: string - description: The input prompt for this training example. - completion: - type: string - description: The desired completion for this training example. - x-oaiMeta: - name: Training format for completions models - example: | - { - "prompt": "What is the answer to 2+2", - "completion": "4" - } - CompletionUsage: type: object description: Usage statistics for the completion request. @@ -9800,9 +9647,9 @@ components: AssistantsApiResponseFormatOption: description: | Specifies the format that the model must output. Compatible with [GPT-4o](/docs/models/gpt-4o), [GPT-4 Turbo](/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_object" }` enables JSON mode, which guarantees the message the model generates is valid JSON. - + **Important:** when using JSON mode, you **must** also instruct the model to produce JSON yourself via a system or user message. Without this, the model may generate an unending stream of whitespace until the generation reaches the token limit, resulting in a long-running and seemingly "stuck" request. Also note that the message content may be partially cut off if `finish_reason="length"`, which indicates the generation exceeded `max_tokens` or the conversation exceeded the max context length. oneOf: - type: string @@ -9923,7 +9770,7 @@ components: nullable: true description: &run_top_p_description | An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. - + We generally recommend altering this or temperature but not both. response_format: $ref: "#/components/schemas/AssistantsApiResponseFormatOption" @@ -10044,52 +9891,6 @@ components: maxItems: 10000 items: type: string - chunking_strategy: - # Ideally we'd reuse the chunking strategy schema here, but it doesn't expand properly - type: object - description: The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy. - oneOf: - - type: object - title: Auto Chunking Strategy - description: The default strategy. This strategy currently uses a `max_chunk_size_tokens` of `800` and `chunk_overlap_tokens` of `400`. - additionalProperties: false - properties: - type: - type: string - description: Always `auto`. - enum: ["auto"] - required: - - type - - type: object - title: Static Chunking Strategy - additionalProperties: false - properties: - type: - type: string - description: Always `static`. - enum: ["static"] - static: - type: object - additionalProperties: false - properties: - max_chunk_size_tokens: - type: integer - minimum: 100 - maximum: 4096 - description: The maximum number of tokens in each chunk. The default value is `800`. The minimum value is `100` and the maximum value is `4096`. - chunk_overlap_tokens: - type: integer - description: | - The number of tokens that overlap between chunks. The default value is `400`. - - Note that the overlap must not exceed half of `max_chunk_size_tokens`. - required: - - max_chunk_size_tokens - - chunk_overlap_tokens - required: - - type - - static - x-oaiExpandable: true metadata: type: object description: | @@ -10122,7 +9923,7 @@ components: nullable: true description: &run_top_p_description | An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. - + We generally recommend altering this or temperature but not both. response_format: $ref: "#/components/schemas/AssistantsApiResponseFormatOption" @@ -10213,7 +10014,7 @@ components: nullable: true description: &run_top_p_description | An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. - + We generally recommend altering this or temperature but not both. response_format: $ref: "#/components/schemas/AssistantsApiResponseFormatOption" @@ -10276,29 +10077,6 @@ components: - type AssistantToolsFileSearch: - type: object - title: FileSearch tool - properties: - type: - type: string - description: "The type of tool being defined: `file_search`" - enum: ["file_search"] - file_search: - type: object - description: Overrides for the file search tool. - properties: - max_num_results: - type: integer - minimum: 1 - maximum: 50 - description: | - The maximum number of results the file search tool should output. The default is 20 for gpt-4* models and 5 for gpt-3.5-turbo. This number should be between 1 and 50 inclusive. - - Note that the file search tool may output fewer than `max_num_results` results. See the [file search tool documentation](/docs/assistants/tools/file-search/number-of-chunks-returned) for more information. - required: - - type - - AssistantToolsFileSearchTypeOnly: type: object title: FileSearch tool properties: @@ -10444,8 +10222,7 @@ components: code: type: string description: One of `server_error`, `rate_limit_exceeded`, or `invalid_prompt`. - enum: - ["server_error", "rate_limit_exceeded", "invalid_prompt"] + enum: ["server_error", "rate_limit_exceeded", "invalid_prompt"] message: type: string description: A human-readable description of the error. @@ -10531,8 +10308,6 @@ components: tool_choice: $ref: "#/components/schemas/AssistantsApiToolChoiceOption" nullable: true - parallel_tool_calls: - $ref: "#/components/schemas/ParallelToolCalls" response_format: $ref: "#/components/schemas/AssistantsApiResponseFormatOption" nullable: true @@ -10560,7 +10335,6 @@ components: - max_completion_tokens - truncation_strategy - tool_choice - - parallel_tool_calls - response_format x-oaiMeta: name: The run object @@ -10598,8 +10372,7 @@ components: "last_messages": null }, "response_format": "auto", - "tool_choice": "auto", - "parallel_tool_calls": true + "tool_choice": "auto" } CreateRunRequest: type: object @@ -10686,7 +10459,7 @@ components: nullable: true description: &run_top_p_description | An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. - + We generally recommend altering this or temperature but not both. stream: type: boolean @@ -10711,8 +10484,6 @@ components: tool_choice: $ref: "#/components/schemas/AssistantsApiToolChoiceOption" nullable: true - parallel_tool_calls: - $ref: "#/components/schemas/ParallelToolCalls" response_format: $ref: "#/components/schemas/AssistantsApiResponseFormatOption" nullable: true @@ -10932,8 +10703,6 @@ components: tool_choice: $ref: "#/components/schemas/AssistantsApiToolChoiceOption" nullable: true - parallel_tool_calls: - $ref: "#/components/schemas/ParallelToolCalls" response_format: $ref: "#/components/schemas/AssistantsApiResponseFormatOption" nullable: true @@ -11055,58 +10824,11 @@ components: maxItems: 10000 items: type: string - chunking_strategy: - # Ideally we'd reuse the chunking strategy schema here, but it doesn't expand properly - type: object - description: The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy. - oneOf: - - type: object - title: Auto Chunking Strategy - description: The default strategy. This strategy currently uses a `max_chunk_size_tokens` of `800` and `chunk_overlap_tokens` of `400`. - additionalProperties: false - properties: - type: - type: string - description: Always `auto`. - enum: ["auto"] - required: - - type - - type: object - title: Static Chunking Strategy - additionalProperties: false - properties: - type: - type: string - description: Always `static`. - enum: ["static"] - static: - type: object - additionalProperties: false - properties: - max_chunk_size_tokens: - type: integer - minimum: 100 - maximum: 4096 - description: The maximum number of tokens in each chunk. The default value is `800`. The minimum value is `100` and the maximum value is `4096`. - chunk_overlap_tokens: - type: integer - description: | - The number of tokens that overlap between chunks. The default value is `400`. - - Note that the overlap must not exceed half of `max_chunk_size_tokens`. - required: - - max_chunk_size_tokens - - chunk_overlap_tokens - required: - - type - - static - x-oaiExpandable: true metadata: type: object description: | Set of 16 key-value pairs that can be attached to a vector store. This can be useful for storing additional information about the vector store in a structured format. Keys can be a maximum of 64 characters long and values can be a maxium of 512 characters long. x-oaiTypeLabel: map - x-oaiExpandable: true oneOf: - required: [vector_store_ids] - required: [vector_stores] @@ -11277,7 +10999,7 @@ components: items: oneOf: - $ref: "#/components/schemas/AssistantToolsCode" - - $ref: "#/components/schemas/AssistantToolsFileSearchTypeOnly" + - $ref: "#/components/schemas/AssistantToolsFileSearch" x-oaiExpandable: true description: A list of files attached to the message, and the tools they were added to. nullable: true @@ -11394,19 +11116,19 @@ components: - `assistant`: Indicates the message is generated by the assistant. Use this value to insert messages from the assistant into the conversation. content: oneOf: - - type: string - description: The text contents of the message. - title: Text content - - type: array - description: An array of content parts with a defined type, each can be of type `text` or images can be passed with `image_url` or `image_file`. Image types are only supported on [Vision-compatible models](/docs/models/overview). - title: Array of content parts - items: - oneOf: - - $ref: "#/components/schemas/MessageContentImageFileObject" - - $ref: "#/components/schemas/MessageContentImageUrlObject" - - $ref: "#/components/schemas/MessageRequestContentTextObject" - x-oaiExpandable: true - minItems: 1 + - type: string + description: The text contents of the message. + title: Text content + - type: array + description: An array of content parts with a defined type, each can be of type `text` or images can be passed with `image_url` or `image_file`. Image types are only supported on [Vision-compatible models](/docs/models/overview). + title: Array of content parts + items: + oneOf: + - $ref: "#/components/schemas/MessageContentImageFileObject" + - $ref: "#/components/schemas/MessageContentImageUrlObject" + - $ref: "#/components/schemas/MessageRequestContentTextObject" + x-oaiExpandable: true + minItems: 1 x-oaiExpandable: true attachments: type: array @@ -11422,7 +11144,7 @@ components: items: oneOf: - $ref: "#/components/schemas/AssistantToolsCode" - - $ref: "#/components/schemas/AssistantToolsFileSearchTypeOnly" + - $ref: "#/components/schemas/AssistantToolsFileSearch" x-oaiExpandable: true description: A list of files attached to the message, and the tools they should be added to. required: @@ -11655,8 +11377,12 @@ components: file_id: description: The ID of the specific File the citation is from. type: string + quote: + description: The specific quote in the file. + type: string required: - file_id + - quote start_index: type: integer minimum: 0 @@ -12442,13 +12168,6 @@ components: type: string expires_after: $ref: "#/components/schemas/VectorStoreExpirationAfter" - chunking_strategy: - type: object - description: 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. - oneOf: - - $ref: "#/components/schemas/AutoChunkingStrategyRequestParam" - - $ref: "#/components/schemas/StaticChunkingStrategyRequestParam" - x-oaiExpandable: true metadata: description: *metadata_description type: object @@ -12558,13 +12277,6 @@ components: required: - code - message - chunking_strategy: - type: object - description: The strategy used to chunk the file. - oneOf: - - $ref: "#/components/schemas/StaticChunkingStrategyResponseParam" - - $ref: "#/components/schemas/OtherChunkingStrategyResponseParam" - x-oaiExpandable: true required: - id - object @@ -12584,99 +12296,9 @@ components: "created_at": 1698107661, "vector_store_id": "vs_abc123", "status": "completed", - "last_error": null, - "chunking_strategy": { - "type": "static", - "static": { - "max_chunk_size_tokens": 800, - "chunk_overlap_tokens": 400 - } - } + "last_error": null } - OtherChunkingStrategyResponseParam: - type: object - title: Other Chunking Strategy - description: This is returned when the chunking strategy is unknown. Typically, this is because the file was indexed before the `chunking_strategy` concept was introduced in the API. - additionalProperties: false - properties: - type: - type: string - description: Always `other`. - enum: ["other"] - required: - - type - - StaticChunkingStrategyResponseParam: - type: object - title: Static Chunking Strategy - additionalProperties: false - properties: - type: - type: string - description: Always `static`. - enum: ["static"] - static: - $ref: "#/components/schemas/StaticChunkingStrategy" - required: - - type - - static - - StaticChunkingStrategy: - type: object - additionalProperties: false - properties: - max_chunk_size_tokens: - type: integer - minimum: 100 - maximum: 4096 - description: The maximum number of tokens in each chunk. The default value is `800`. The minimum value is `100` and the maximum value is `4096`. - chunk_overlap_tokens: - type: integer - description: | - The number of tokens that overlap between chunks. The default value is `400`. - - Note that the overlap must not exceed half of `max_chunk_size_tokens`. - required: - - max_chunk_size_tokens - - chunk_overlap_tokens - - AutoChunkingStrategyRequestParam: - type: object - title: Auto Chunking Strategy - description: The default strategy. This strategy currently uses a `max_chunk_size_tokens` of `800` and `chunk_overlap_tokens` of `400`. - additionalProperties: false - properties: - type: - type: string - description: Always `auto`. - enum: ["auto"] - required: - - type - - StaticChunkingStrategyRequestParam: - type: object - title: Static Chunking Strategy - additionalProperties: false - properties: - type: - type: string - description: Always `static`. - enum: ["static"] - static: - $ref: "#/components/schemas/StaticChunkingStrategy" - required: - - type - - static - - ChunkingStrategyRequestParam: - type: object - description: The chunking strategy used to chunk the file(s). If not set, will use the `auto` strategy. - oneOf: - - $ref: "#/components/schemas/AutoChunkingStrategyRequestParam" - - $ref: "#/components/schemas/StaticChunkingStrategyRequestParam" - x-oaiExpandable: true - CreateVectorStoreFileRequest: type: object additionalProperties: false @@ -12684,8 +12306,6 @@ components: file_id: description: A [File](/docs/api-reference/files) ID that the vector store should use. Useful for tools like `file_search` that can access files. type: string - chunking_strategy: - $ref: "#/components/schemas/ChunkingStrategyRequestParam" required: - file_id @@ -12812,29 +12432,27 @@ components: maxItems: 500 items: type: string - chunking_strategy: - $ref: "#/components/schemas/ChunkingStrategyRequestParam" required: - file_ids AssistantStreamEvent: description: | Represents an event emitted when streaming a Run. - + Each event in a server-sent events stream has an `event` and `data` property: - + ``` event: thread.created data: {"id": "thread_123", "object": "thread", ...} ``` - + We emit events whenever a new object is created, transitions to a new state, or is being streamed in parts (deltas). For example, we emit `thread.run.created` when a new run is created, `thread.run.completed` when a run completes, and so on. When an Assistant chooses to create a message during a run, we emit a `thread.message.created event`, a `thread.message.in_progress` event, many `thread.message.delta` events, and finally a `thread.message.completed` event. - + We may add additional events over time, so we recommend handling unknown events gracefully in your code. See the [Assistants API quickstart](/docs/assistants/overview) to learn how to integrate the Assistants API with streaming. @@ -12932,19 +12550,6 @@ components: description: Occurs when a [run](/docs/api-reference/runs/object) is completed. x-oaiMeta: dataDescription: "`data` is a [run](/docs/api-reference/runs/object)" - - type: object - properties: - event: - type: string - enum: [ "thread.run.incomplete" ] - data: - $ref: "#/components/schemas/RunObject" - required: - - event - - data - description: Occurs when a [run](/docs/api-reference/runs/object) ends with status `incomplete`. - x-oaiMeta: - dataDescription: "`data` is a [run](/docs/api-reference/runs/object)" - type: object properties: event: @@ -13432,7 +13037,7 @@ x-oaiMeta: title: Audio description: | Learn how to turn audio into text or text into audio. - + Related guide: [Speech to text](/docs/guides/speech-to-text) navigationGroup: endpoints sections: @@ -13455,7 +13060,7 @@ x-oaiMeta: title: Chat description: | Given a list of messages comprising a conversation, the model will return a response. - + Related guide: [Chat Completions](/docs/guides/text-generation) navigationGroup: endpoints sections: @@ -13472,7 +13077,7 @@ x-oaiMeta: title: Embeddings description: | Get a vector representation of a given input that can be easily consumed by machine learning models and algorithms. - + Related guide: [Embeddings](/docs/guides/embeddings) navigationGroup: endpoints sections: @@ -13486,7 +13091,7 @@ x-oaiMeta: title: Fine-tuning description: | Manage fine-tuning jobs to tailor a model to your specific training data. - + Related guide: [Fine-tune models](/docs/guides/fine-tuning) navigationGroup: endpoints sections: @@ -13508,12 +13113,6 @@ x-oaiMeta: - type: endpoint key: cancelFineTuningJob path: cancel - - type: object - key: FinetuneChatRequestInput - path: chat-input - - type: object - key: FinetuneCompletionRequestInput - path: completions-input - type: object key: FineTuningJob path: object @@ -13527,7 +13126,7 @@ x-oaiMeta: title: Batch description: | Create large batches of API requests for asynchronous processing. The Batch API returns completions within 24 hours for a 50% discount. - + Related guide: [Batch](/docs/guides/batch) navigationGroup: endpoints sections: @@ -13548,10 +13147,10 @@ x-oaiMeta: path: object - type: object key: BatchRequestInput - path: request-input + path: requestInput - type: object key: BatchRequestOutput - path: request-output + path: requestOutput - id: files title: Files description: | @@ -13580,7 +13179,7 @@ x-oaiMeta: title: Images description: | Given a prompt and/or an input image, the model will generate a new image. - + Related guide: [Image generation](/docs/guides/images) navigationGroup: endpoints sections: @@ -13618,7 +13217,7 @@ x-oaiMeta: title: Moderations description: | Given some input text, outputs if the model classifies it as potentially harmful across several categories. - + Related guide: [Moderations](/docs/guides/moderation) navigationGroup: endpoints sections: @@ -13633,7 +13232,7 @@ x-oaiMeta: beta: true description: | Build assistants that can call models and use tools to perform tasks. - + [Get started with the Assistants API](/docs/assistants) navigationGroup: assistants sections: @@ -13660,7 +13259,7 @@ x-oaiMeta: beta: true description: | Create threads that assistants can interact with. - + Related guide: [Assistants](/docs/assistants/overview) navigationGroup: assistants sections: @@ -13684,7 +13283,7 @@ x-oaiMeta: beta: true description: | Create messages within threads - + Related guide: [Assistants](/docs/assistants/overview) navigationGroup: assistants sections: @@ -13711,7 +13310,7 @@ x-oaiMeta: beta: true description: | Represents an execution run on a thread. - + Related guide: [Assistants](/docs/assistants/overview) navigationGroup: assistants sections: @@ -13744,7 +13343,7 @@ x-oaiMeta: beta: true description: | Represents the steps (model and tool calls) taken during the run. - + Related guide: [Assistants](/docs/assistants/overview) navigationGroup: assistants sections: @@ -13762,7 +13361,7 @@ x-oaiMeta: beta: true description: | Vector stores are used to store files for use by the `file_search` tool. - + Related guide: [File Search](/docs/assistants/tools/file-search) navigationGroup: assistants sections: @@ -13789,7 +13388,7 @@ x-oaiMeta: beta: true description: | Vector store files represent files inside a vector store. - + Related guide: [File Search](/docs/assistants/tools/file-search) navigationGroup: assistants sections: @@ -13813,7 +13412,7 @@ x-oaiMeta: beta: true description: | Vector store file batches represent operations to add multiple files to a vector store. - + Related guide: [File Search](/docs/assistants/tools/file-search) navigationGroup: assistants sections: @@ -13837,11 +13436,11 @@ x-oaiMeta: beta: true description: | Stream the result of executing a Run or resuming a Run after submitting tool outputs. - + You can stream events from the [Create Thread and Run](/docs/api-reference/runs/createThreadAndRun), [Create Run](/docs/api-reference/runs/createRun), and [Submit Tool Outputs](/docs/api-reference/runs/submitToolOutputs) endpoints by passing `"stream": true`. The response will be a [Server-Sent events](https://html.spec.whatwg.org/multipage/server-sent-events.html#server-sent-events) stream. - + Our Node and Python SDKs provide helpful utilities to make streaming easy. Reference the [Assistants API quickstart](/docs/assistants/overview) to learn more. navigationGroup: assistants @@ -13867,4 +13466,4 @@ x-oaiMeta: path: create - type: object key: CreateCompletionResponse - path: object \ No newline at end of file + path: object From 1070a9afec044bf9970b3c4151186ba24befd308 Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Wed, 3 Jul 2024 10:10:35 +0200 Subject: [PATCH 7/8] Update build, and Github Actions --- .github/workflows/create-version-tag.yml | 2 +- .github/workflows/publish-development-version.yml | 2 +- .github/workflows/publish.yml | 2 +- build.gradle.kts | 2 -- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/create-version-tag.yml b/.github/workflows/create-version-tag.yml index 8be17b4a3..630caef92 100644 --- a/.github/workflows/create-version-tag.yml +++ b/.github/workflows/create-version-tag.yml @@ -23,7 +23,7 @@ jobs: - name: Build uses: gradle/gradle-build-action@v3 with: - arguments: :xef-openai-client-generator:openaiClientGenerate build + arguments: build - name: Read version id: read-version diff --git a/.github/workflows/publish-development-version.yml b/.github/workflows/publish-development-version.yml index 1d0aa7895..7406faab7 100644 --- a/.github/workflows/publish-development-version.yml +++ b/.github/workflows/publish-development-version.yml @@ -34,7 +34,7 @@ jobs: - name: Assemble uses: gradle/gradle-build-action@v3 with: - arguments: :xef-openai-client-generator:openaiClientGenerate assemble + arguments: assemble - name: Upload reports if: failure() diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index b324b6eb4..9498adf8e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -32,7 +32,7 @@ jobs: - name: Assemble uses: gradle/gradle-build-action@v3 with: - arguments: :xef-openai-client-generator:openaiClientGenerate assemble + arguments: assemble - name: Upload reports if: failure() diff --git a/build.gradle.kts b/build.gradle.kts index 031f04b0a..594022ff9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -28,12 +28,10 @@ fun Project.configureBuildAndTestTask(taskName: String, moduleType: ModulePlatfo doLast { when (moduleType) { ModulePlatformType.SINGLE -> { - project.exec { commandLine(gradleCommand, ":xef-openai-client-generator:openaiClientGenerate") } val excludedModules = includeOrNotModulesToCommand(multiPlatformModules, platform, false) project.exec { commandLine(gradleCommand, "build", *excludedModules) } } ModulePlatformType.MULTI -> { - project.exec { commandLine(gradleCommand, ":xef-openai-client-generator:openaiClientGenerate") } val includedModules = includeOrNotModulesToCommand(multiPlatformModules, platform, true) project.exec { commandLine(gradleCommand, *includedModules) } } From 9847521ab0f8cd51d521e226ee9b08ce4b68961a Mon Sep 17 00:00:00 2001 From: Simon Vergauwen Date: Thu, 4 Jul 2024 10:57:42 +0200 Subject: [PATCH 8/8] Update 0.0.6, excludes certain fields as being required, and include response info in serialization errors. --- core/build.gradle.kts | 2 -- gradle/libs.versions.toml | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 595e18b53..d7580df54 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -73,8 +73,6 @@ kotlin { languageSettings.optIn("kotlin.ExperimentalStdlibApi") } val commonMain by getting { - kotlin.srcDir(project.file("build/generated/openapi/src/commonMain/kotlin")) - dependencies { api(libs.bundles.arrow) api(libs.kotlinx.serialization.json) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d39171a6b..12b6707de 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -39,7 +39,7 @@ progressbar = "0.10.0" jmf = "2.1.1e" mp3-wav-converter = "1.0.4" yamlkt="0.13.0" -openapi-kt="0.0.4" +openapi-kt="0.0.6" [libraries] arrow-core = { module = "io.arrow-kt:arrow-core", version.ref = "arrow" }