diff --git a/CHANGELOG.md b/CHANGELOG.md index 7970a3b8d..9015f064f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,9 @@ This list is not intended to be all-encompassing - it will document major and breaking API changes with their rationale when appropriate. Given version `A.B.C.D`, breaking changes are to be expected in version number increments where changes in the `A` or `B` sections: -### v5.20.1.0 (uncut) +### v5.21.0.0 (uncut) - **http4k-connect-*** - Upgrade dependencies including Kotlin to 2.0.10 + - **http4k-connect-ai-openai-**** - [Breaking] Model ResponseFormat as a sealed class hierarchy. Removed ResponseFormatType as now inherent in the JSON marshalling. Alpha support for `json_schema` response format, but it's just a map right now with no class structure. ### v5.20.0.0 - **http4k-connect-*** - Upgrade dependencies, including Kotshi to 3.0.0. Version bump to highlight that this could be a breaking change if you are using the Kotshi annotation processor. diff --git a/ai/openai/client/src/main/kotlin/org/http4k/connect/openai/OpenAIMoshi.kt b/ai/openai/client/src/main/kotlin/org/http4k/connect/openai/OpenAIMoshi.kt index 51dda78e7..f30bdc51b 100644 --- a/ai/openai/client/src/main/kotlin/org/http4k/connect/openai/OpenAIMoshi.kt +++ b/ai/openai/client/src/main/kotlin/org/http4k/connect/openai/OpenAIMoshi.kt @@ -29,7 +29,6 @@ object OpenAIMoshi : ConfigurableMoshi( .value(Timestamp) .value(TokenId) .value(User) - .value(ResponseFormatType) .done() ) diff --git a/ai/openai/client/src/main/kotlin/org/http4k/connect/openai/action/ChatCompletion.kt b/ai/openai/client/src/main/kotlin/org/http4k/connect/openai/action/ChatCompletion.kt index e571824da..dded1654e 100644 --- a/ai/openai/client/src/main/kotlin/org/http4k/connect/openai/action/ChatCompletion.kt +++ b/ai/openai/client/src/main/kotlin/org/http4k/connect/openai/action/ChatCompletion.kt @@ -8,12 +8,14 @@ import org.http4k.connect.Http4kConnectAction import org.http4k.connect.asRemoteFailure import org.http4k.connect.model.ModelName import org.http4k.connect.openai.CompletionId +import org.http4k.connect.openai.GPT3_5 import org.http4k.connect.openai.ObjectType import org.http4k.connect.openai.OpenAIAction import org.http4k.connect.openai.OpenAIMoshi import org.http4k.connect.openai.OpenAIMoshi.autoBody -import org.http4k.connect.openai.ResponseFormatType import org.http4k.connect.openai.Role +import org.http4k.connect.openai.Role.Companion.System +import org.http4k.connect.openai.Role.Companion.User import org.http4k.connect.openai.Timestamp import org.http4k.connect.openai.TokenId import org.http4k.connect.openai.User @@ -28,6 +30,8 @@ import org.http4k.lens.Header.CONTENT_TYPE import se.ansman.kotshi.ExperimentalKotshiApi import se.ansman.kotshi.JsonProperty import se.ansman.kotshi.JsonSerializable +import se.ansman.kotshi.Polymorphic +import se.ansman.kotshi.PolymorphicLabel import java.io.BufferedReader import java.io.InputStreamReader import kotlin.text.Charsets.UTF_8 @@ -103,10 +107,23 @@ data class ChatCompletion( } } + @JsonSerializable -data class ResponseFormat( - val type: ResponseFormatType -) +@Polymorphic("type") +sealed class ResponseFormat { + @JsonSerializable + @PolymorphicLabel("json_object") + data object Json : ResponseFormat() + + @JsonSerializable + @PolymorphicLabel("url") + data object Url : ResponseFormat() + + @JsonSerializable + @PolymorphicLabel("json_schema") + data class JsonSchema(val strict: Boolean, val json_schema: Map) : ResponseFormat() +} + @JsonSerializable data class Message( diff --git a/ai/openai/client/src/main/kotlin/org/http4k/connect/openai/model.kt b/ai/openai/client/src/main/kotlin/org/http4k/connect/openai/model.kt index 9966ff5c1..e9c2bfa55 100644 --- a/ai/openai/client/src/main/kotlin/org/http4k/connect/openai/model.kt +++ b/ai/openai/client/src/main/kotlin/org/http4k/connect/openai/model.kt @@ -57,13 +57,6 @@ val ModelName.Companion.GPT4_TURBO_PREVIEW get() = ModelName.of("gpt-4-turbo-pre val ModelName.Companion.GPT3_5 get() = ModelName.of("gpt-3.5-turbo") val ModelName.Companion.TEXT_EMBEDDING_ADA_002 get() = ModelName.of("text-embedding-ada-002") -class ResponseFormatType private constructor(value: String) : StringValue(value) { - companion object : NonBlankStringValueFactory(::ResponseFormatType) { - val JsonObject = ResponseFormatType.of("json_object") - val url = ResponseFormatType.of("url") - } -} - class Role private constructor(value: String) : StringValue(value) { companion object : NonBlankStringValueFactory(::Role) { val System = Role.of("system") diff --git a/ai/openai/client/src/test/kotlin/org/http4k/connect/openai/RealOpenAITest.kt b/ai/openai/client/src/test/kotlin/org/http4k/connect/openai/RealOpenAITest.kt index 182535348..a23ed5a35 100644 --- a/ai/openai/client/src/test/kotlin/org/http4k/connect/openai/RealOpenAITest.kt +++ b/ai/openai/client/src/test/kotlin/org/http4k/connect/openai/RealOpenAITest.kt @@ -16,7 +16,7 @@ class RealOpenAITest : OpenAIContract { override val openAi = OpenAI.Http( apiKey(ENV)!!, - JavaHttpClient().debug(debugStream = true), + JavaHttpClient().debug(), OpenAIOrg.of("org-Ydjc9eGanqJtCP70yPUwZsvs") ) }