openai-kotlin
openai-kotlin copied to clipboard
submitStreamingToolOutput fails to send the body
Description
submitStreamingToolOutput throws an exception even before sending the message to openai API
Reason why is that submitStreamingToolOutput is setting the body as a mapOf("tool_outputs" to output, "stream" to true))
https://github.com/aallam/openai-kotlin/blob/f70d2f99fcf2d12e8b2c78b5e3b3c45fafb50c05/openai-client/src/commonMain/kotlin/com.aallam.openai.client/internal/api/RunsApi.kt#L117-L126
Problem is that mapOf() returns a LinkedHashMap, a Java class, not a Kotlin class, so it isn not annotated with @Serializable, nor is it automatically registered in Kotlinx Serialization’s standard module.
As a result, when you try to submit tool outputs using streaming, you get the following exception:
Serializer for subclass 'LinkedHashMap' is not found in the polymorphic scope of 'Map'.
Check if class with serial name 'LinkedHashMap' exists and serializer is registered in a corresponding SerializersModule.
To be registered automatically, class 'LinkedHashMap' has to be '@Serializable', and the base class 'Map' has to be sealed and '@Serializable'
Full stack trace:
Original Stack Trace:
at com.aallam.openai.client.internal.http.HttpTransport.handleException(HttpTransport.kt:76)
at com.aallam.openai.client.internal.http.HttpTransport.performSse(HttpTransport.kt:58)
at com.aallam.openai.client.internal.http.HttpTransport$performSse$1.invokeSuspend(HttpTransport.kt)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:231)
at kotlinx.coroutines.DispatchedTaskKt.resumeUnconfined(DispatchedTask.kt:187)
at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:159)
at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:466)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:500)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default(CancellableContinuationImpl.kt:489)
at kotlinx.coroutines.CancellableContinuationImpl.resumeWith(CancellableContinuationImpl.kt:364)
at kotlinx.coroutines.ResumeAwaitOnCompletion.invoke(JobSupport.kt:1409)
at kotlinx.coroutines.JobSupport.notifyCompletion(JobSupport.kt:1502)
at kotlinx.coroutines.JobSupport.completeStateFinalization(JobSupport.kt:322)
at kotlinx.coroutines.JobSupport.finalizeFinishingState(JobSupport.kt:239)
at kotlinx.coroutines.JobSupport.tryMakeCompletingSlowPath(JobSupport.kt:917)
at kotlinx.coroutines.JobSupport.tryMakeCompleting(JobSupport.kt:874)
at kotlinx.coroutines.JobSupport.makeCompleting$kotlinx_coroutines_core(JobSupport.kt:817)
at kotlinx.coroutines.CompletableDeferredImpl.completeExceptionally(CompletableDeferred.kt:89)
at io.ktor.client.plugins.sse.BuildersKt$serverSentEventsSession$2.invokeSuspend(builders.kt:58)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:111)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:99)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:811)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:715)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:702)
Caused by: io.ktor.client.plugins.sse.SSEClientException: Serializer for subclass 'LinkedHashMap' is not found in the polymorphic scope of 'Map'.
Check if class with serial name 'LinkedHashMap' exists and serializer is registered in a corresponding SerializersModule.
To be registered automatically, class 'LinkedHashMap' has to be '@Serializable', and the base class 'Map' has to be sealed and '@Serializable'.
at io.ktor.client.plugins.sse.BuildersKt.mapToSSEException(builders.kt:251)
at io.ktor.client.plugins.sse.BuildersKt.access$mapToSSEException(builders.kt:1)
at io.ktor.client.plugins.sse.BuildersKt$serverSentEventsSession$2.invokeSuspend(builders.kt:58)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:111)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:99)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:811)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:715)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:702)
Caused by: kotlinx.serialization.SerializationException: Serializer for subclass 'LinkedHashMap' is not found in the polymorphic scope of 'Map'.
Check if class with serial name 'LinkedHashMap' exists and serializer is registered in a corresponding SerializersModule.
To be registered automatically, class 'LinkedHashMap' has to be '@Serializable', and the base class 'Map' has to be sealed and '@Serializable'.
at kotlinx.serialization.internal.AbstractPolymorphicSerializerKt.throwSubtypeNotRegistered(AbstractPolymorphicSerializer.kt:102)
at kotlinx.serialization.internal.AbstractPolymorphicSerializerKt.throwSubtypeNotRegistered(AbstractPolymorphicSerializer.kt:114)
at kotlinx.serialization.PolymorphicSerializerKt.findPolymorphicSerializer(PolymorphicSerializer.kt:109)
at kotlinx.serialization.json.internal.StreamingJsonEncoder.encodeSerializableValue(StreamingJsonEncoder.kt:242)
at kotlinx.serialization.json.internal.JsonStreamsKt.encodeByWriter(JsonStreams.kt:31)
at kotlinx.serialization.json.Json.encodeToString(Json.kt:81)
at io.ktor.serialization.kotlinx.KotlinxSerializationConverter.serializeContent(KotlinxSerializationConverter.kt:91)
at io.ktor.serialization.kotlinx.KotlinxSerializationConverter.serialize(KotlinxSerializationConverter.kt:55)
at io.ktor.client.plugins.contentnegotiation.ContentNegotiationKt.ContentNegotiation$lambda$13$convertRequest(ContentNegotiation.kt:184)
at io.ktor.client.plugins.contentnegotiation.ContentNegotiationKt.access$ContentNegotiation$lambda$13$convertRequest(ContentNegotiation.kt:1)
at io.ktor.client.plugins.contentnegotiation.ContentNegotiationKt$ContentNegotiation$2$1.invokeSuspend(ContentNegotiation.kt:242)
at io.ktor.client.plugins.contentnegotiation.ContentNegotiationKt$ContentNegotiation$2$1.invoke(ContentNegotiation.kt)
at io.ktor.client.plugins.contentnegotiation.ContentNegotiationKt$ContentNegotiation$2$1.invoke(ContentNegotiation.kt)
at io.ktor.client.plugins.api.TransformRequestBodyHook$install$1.invokeSuspend(KtorCallContexts.kt:78)
at io.ktor.client.plugins.api.TransformRequestBodyHook$install$1.invoke(KtorCallContexts.kt)
at io.ktor.client.plugins.api.TransformRequestBodyHook$install$1.invoke(KtorCallContexts.kt)
at io.ktor.util.pipeline.DebugPipelineContext.proceedLoop(DebugPipelineContext.kt:79)
at io.ktor.util.pipeline.DebugPipelineContext.proceed(DebugPipelineContext.kt:57)
at io.ktor.client.plugins.RequestError$install$1.invokeSuspend(HttpCallValidator.kt:134)
at io.ktor.client.plugins.RequestError$install$1.invoke(HttpCallValidator.kt)
at io.ktor.client.plugins.RequestError$install$1.invoke(HttpCallValidator.kt)
at io.ktor.util.pipeline.DebugPipelineContext.proceedLoop(DebugPipelineContext.kt:79)
at io.ktor.util.pipeline.DebugPipelineContext.proceed(DebugPipelineContext.kt:57)
at io.ktor.client.plugins.SetupRequestContext$install$1.invokeSuspend$proceed(HttpRequestLifecycle.kt:40)
at io.ktor.client.plugins.SetupRequestContext$install$1.access$invokeSuspend$proceed(HttpRequestLifecycle.kt)
at io.ktor.client.plugins.SetupRequestContext$install$1$1.invoke(HttpRequestLifecycle.kt:40)
at io.ktor.client.plugins.SetupRequestContext$install$1$1.invoke(HttpRequestLifecycle.kt:40)
at io.ktor.client.plugins.HttpRequestLifecycleKt$HttpRequestLifecycle$1$1.invokeSuspend(HttpRequestLifecycle.kt:27)
at io.ktor.client.plugins.HttpRequestLifecycleKt$HttpRequestLifecycle$1$1.invoke(HttpRequestLifecycle.kt)
at io.ktor.client.plugins.HttpRequestLifecycleKt$HttpRequestLifecycle$1$1.invoke(HttpRequestLifecycle.kt)
at io.ktor.client.plugins.SetupRequestContext$install$1.invokeSuspend(HttpRequestLifecycle.kt:40)
at io.ktor.client.plugins.SetupRequestContext$install$1.invoke(HttpRequestLifecycle.kt)
at io.ktor.client.plugins.SetupRequestContext$install$1.invoke(HttpRequestLifecycle.kt)
at io.ktor.util.pipeline.DebugPipelineContext.proceedLoop(DebugPipelineContext.kt:79)
at io.ktor.util.pipeline.DebugPipelineContext.proceed(DebugPipelineContext.kt:57)
at io.ktor.util.pipeline.DebugPipelineContext.execute$ktor_utils(DebugPipelineContext.kt:63)
at io.ktor.util.pipeline.Pipeline.execute(Pipeline.kt:86)
at io.ktor.client.HttpClient.execute$ktor_client_core(HttpClient.kt:1329)
at io.ktor.client.statement.HttpStatement.fetchStreamingResponse(HttpStatement.kt:102)
at io.ktor.client.plugins.sse.BuildersKt$serverSentEventsSession$2.invokeSuspend(builders.kt:258)
... 8 more
Steps to Reproduce
- Try to submit a streaming tool output using
submitStreamingToolOutput
Environment
- openai-kotlin version: 4.0.1
- Kotlin version: 2.1.0
- OS: macOs