Skip to content

Commit 782d030

Browse files
authored
fix(chat): function call nullable name/arguments (#232)
1 parent b876b1c commit 782d030

File tree

5 files changed

+35
-23
lines changed

5 files changed

+35
-23
lines changed

openai-core/src/commonMain/kotlin/com.aallam.openai.api/chat/FunctionCall.kt

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,54 @@ import kotlinx.serialization.json.Json
66
import kotlinx.serialization.json.JsonObject
77

88
/**
9-
* The name and arguments of a function that should be called, as generated by the model.
9+
* Represents a function invocation with its name and serialized arguments as generated by the model.
10+
*
11+
* In scenarios such as a streaming variant of the chat API, both [nameOrNull] and [argumentsOrNull] can be null.
1012
*/
1113
@Serializable
1214
public data class FunctionCall(
1315
/**
1416
* The name of the function to call.
1517
*/
16-
@SerialName("name") val name: String,
18+
@SerialName("name") val nameOrNull: String? = null,
1719

1820
/**
1921
* The arguments to call the function with, as generated by the model in JSON format.
2022
* Note that the model does not always generate valid JSON, and may hallucinate parameters
2123
* not defined by your function schema.
2224
* Validate the arguments in your code before calling your function.
2325
*/
24-
@SerialName("arguments") val arguments: String,
26+
@SerialName("arguments") val argumentsOrNull: String? = null,
2527
) {
2628

29+
/**
30+
* The name of the function to call.
31+
*/
32+
public val name: String
33+
get() = requireNotNull(nameOrNull)
34+
35+
/**
36+
* The arguments to call the function with, as generated by the model in JSON format.
37+
* Note that the model does not always generate valid JSON, and may hallucinate parameters
38+
* not defined by your function schema.
39+
* Validate the arguments in your code before calling your function.
40+
*/
41+
public val arguments: String
42+
get() = requireNotNull(argumentsOrNull)
43+
2744
/**
2845
* Decodes the [arguments] JSON string into a JsonObject.
2946
* If [arguments] is null, the function will return null.
3047
*
3148
* @param json The Json object to be used for decoding, defaults to a default Json instance
3249
*/
3350
public fun argumentsAsJson(json: Json = Json): JsonObject = json.decodeFromString(arguments)
51+
52+
/**
53+
* Decodes the [arguments] JSON string into a JsonObject.
54+
* If [arguments] is null, the function will return null.
55+
*
56+
* @param json The Json object to be used for decoding, defaults to a default Json instance
57+
*/
58+
public fun argumentsAsJsonOrNull(json: Json = Json): JsonObject? = argumentsOrNull?.let { json.decodeFromString(it) }
3459
}

sample/jvm/src/main/kotlin/com/aallam/openai/sample/jvm/Chat.kt

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
package com.aallam.openai.sample.jvm
22

3-
import com.aallam.openai.api.BetaOpenAI
43
import com.aallam.openai.api.chat.ChatCompletionRequest
54
import com.aallam.openai.api.chat.ChatMessage
65
import com.aallam.openai.api.chat.ChatRole
76
import com.aallam.openai.api.model.ModelId
87
import com.aallam.openai.client.OpenAI
9-
import kotlinx.coroutines.CoroutineScope
10-
import kotlinx.coroutines.flow.launchIn
8+
import kotlinx.coroutines.flow.collect
119
import kotlinx.coroutines.flow.onCompletion
1210
import kotlinx.coroutines.flow.onEach
1311

14-
@OptIn(BetaOpenAI::class)
15-
suspend fun CoroutineScope.chat(openAI: OpenAI) {
12+
suspend fun chat(openAI: OpenAI) {
1613
println("\n> Create chat completions...")
1714
val chatCompletionRequest = ChatCompletionRequest(
1815
model = ModelId("gpt-3.5-turbo"),
@@ -33,6 +30,5 @@ suspend fun CoroutineScope.chat(openAI: OpenAI) {
3330
openAI.chatCompletions(chatCompletionRequest)
3431
.onEach { print(it.choices.first().delta.content.orEmpty()) }
3532
.onCompletion { println() }
36-
.launchIn(this)
37-
.join()
33+
.collect()
3834
}

sample/jvm/src/main/kotlin/com/aallam/openai/sample/jvm/ChatFunctionCall.kt

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
11
package com.aallam.openai.sample.jvm
22

3-
import com.aallam.openai.api.BetaOpenAI
43
import com.aallam.openai.api.chat.*
54
import com.aallam.openai.api.model.ModelId
65
import com.aallam.openai.client.OpenAI
7-
import kotlinx.coroutines.CoroutineScope
8-
import kotlinx.coroutines.flow.launchIn
6+
import kotlinx.coroutines.flow.collect
97
import kotlinx.coroutines.flow.onCompletion
108
import kotlinx.coroutines.flow.onEach
119
import kotlinx.serialization.Serializable
1210
import kotlinx.serialization.encodeToString
1311
import kotlinx.serialization.json.*
1412

15-
@OptIn(BetaOpenAI::class)
16-
suspend fun CoroutineScope.chatFunctionCall(openAI: OpenAI) {
13+
suspend fun chatFunctionCall(openAI: OpenAI) {
1714
// *** Chat Completion with Function Call *** //
1815

1916
println("\n> Create Chat Completion function call...")
@@ -84,8 +81,7 @@ suspend fun CoroutineScope.chatFunctionCall(openAI: OpenAI) {
8481
updateChatMessages(chatMessages, message, it, functionResponse)
8582
}
8683
}
87-
.launchIn(this)
88-
.join()
84+
.collect()
8985

9086
openAI.chatCompletions(
9187
ChatCompletionRequest(
@@ -95,8 +91,7 @@ suspend fun CoroutineScope.chatFunctionCall(openAI: OpenAI) {
9591
)
9692
.onEach { print(it.choices.first().delta.content.orEmpty()) }
9793
.onCompletion { println() }
98-
.launchIn(this)
99-
.join()
94+
.collect()
10095
}
10196

10297
@Serializable

sample/jvm/src/main/kotlin/com/aallam/openai/sample/jvm/Whisper.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.aallam.openai.sample.jvm
22

3-
import com.aallam.openai.api.BetaOpenAI
43
import com.aallam.openai.api.audio.TranscriptionRequest
54
import com.aallam.openai.api.audio.TranslationRequest
65
import com.aallam.openai.api.file.FileSource
@@ -9,7 +8,6 @@ import com.aallam.openai.client.OpenAI
98
import okio.FileSystem
109
import okio.Path.Companion.toPath
1110

12-
@OptIn(BetaOpenAI::class)
1311
suspend fun whisper(openAI: OpenAI) {
1412
println("\n>️ Create transcription...")
1513
val transcriptionRequest = TranscriptionRequest(

sample/jvm/src/main/kotlin/com/aallam/openai/sample/jvm/images.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.aallam.openai.sample.jvm
22

3-
import com.aallam.openai.api.BetaOpenAI
43
import com.aallam.openai.api.file.FileSource
54
import com.aallam.openai.api.image.ImageCreation
65
import com.aallam.openai.api.image.ImageEdit
@@ -9,7 +8,6 @@ import com.aallam.openai.client.OpenAI
98
import okio.FileSystem
109
import okio.Path.Companion.toPath
1110

12-
@OptIn(BetaOpenAI::class)
1311
suspend fun images(openAI: OpenAI) {
1412
println("\n> Create images...")
1513
val images = openAI.imageURL(

0 commit comments

Comments
 (0)