Skip to content

Commit

Permalink
fix(chat): function call nullable name/arguments (#232)
Browse files Browse the repository at this point in the history
  • Loading branch information
aallam authored Aug 30, 2023
1 parent b876b1c commit 782d030
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,54 @@ import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject

/**
* The name and arguments of a function that should be called, as generated by the model.
* Represents a function invocation with its name and serialized arguments as generated by the model.
*
* In scenarios such as a streaming variant of the chat API, both [nameOrNull] and [argumentsOrNull] can be null.
*/
@Serializable
public data class FunctionCall(
/**
* The name of the function to call.
*/
@SerialName("name") val name: String,
@SerialName("name") val nameOrNull: String? = null,

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

/**
* The name of the function to call.
*/
public val name: String
get() = requireNotNull(nameOrNull)

/**
* The arguments to call the function with, as generated by the model in JSON format.
* Note that the model does not always generate valid JSON, and may hallucinate parameters
* not defined by your function schema.
* Validate the arguments in your code before calling your function.
*/
public val arguments: String
get() = requireNotNull(argumentsOrNull)

/**
* Decodes the [arguments] JSON string into a JsonObject.
* If [arguments] is null, the function will return null.
*
* @param json The Json object to be used for decoding, defaults to a default Json instance
*/
public fun argumentsAsJson(json: Json = Json): JsonObject = json.decodeFromString(arguments)

/**
* Decodes the [arguments] JSON string into a JsonObject.
* If [arguments] is null, the function will return null.
*
* @param json The Json object to be used for decoding, defaults to a default Json instance
*/
public fun argumentsAsJsonOrNull(json: Json = Json): JsonObject? = argumentsOrNull?.let { json.decodeFromString(it) }
}
10 changes: 3 additions & 7 deletions sample/jvm/src/main/kotlin/com/aallam/openai/sample/jvm/Chat.kt
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
package com.aallam.openai.sample.jvm

import com.aallam.openai.api.BetaOpenAI
import com.aallam.openai.api.chat.ChatCompletionRequest
import com.aallam.openai.api.chat.ChatMessage
import com.aallam.openai.api.chat.ChatRole
import com.aallam.openai.api.model.ModelId
import com.aallam.openai.client.OpenAI
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onEach

@OptIn(BetaOpenAI::class)
suspend fun CoroutineScope.chat(openAI: OpenAI) {
suspend fun chat(openAI: OpenAI) {
println("\n> Create chat completions...")
val chatCompletionRequest = ChatCompletionRequest(
model = ModelId("gpt-3.5-turbo"),
Expand All @@ -33,6 +30,5 @@ suspend fun CoroutineScope.chat(openAI: OpenAI) {
openAI.chatCompletions(chatCompletionRequest)
.onEach { print(it.choices.first().delta.content.orEmpty()) }
.onCompletion { println() }
.launchIn(this)
.join()
.collect()
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
package com.aallam.openai.sample.jvm

import com.aallam.openai.api.BetaOpenAI
import com.aallam.openai.api.chat.*
import com.aallam.openai.api.model.ModelId
import com.aallam.openai.client.OpenAI
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onEach
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.*

@OptIn(BetaOpenAI::class)
suspend fun CoroutineScope.chatFunctionCall(openAI: OpenAI) {
suspend fun chatFunctionCall(openAI: OpenAI) {
// *** Chat Completion with Function Call *** //

println("\n> Create Chat Completion function call...")
Expand Down Expand Up @@ -84,8 +81,7 @@ suspend fun CoroutineScope.chatFunctionCall(openAI: OpenAI) {
updateChatMessages(chatMessages, message, it, functionResponse)
}
}
.launchIn(this)
.join()
.collect()

openAI.chatCompletions(
ChatCompletionRequest(
Expand All @@ -95,8 +91,7 @@ suspend fun CoroutineScope.chatFunctionCall(openAI: OpenAI) {
)
.onEach { print(it.choices.first().delta.content.orEmpty()) }
.onCompletion { println() }
.launchIn(this)
.join()
.collect()
}

@Serializable
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.aallam.openai.sample.jvm

import com.aallam.openai.api.BetaOpenAI
import com.aallam.openai.api.audio.TranscriptionRequest
import com.aallam.openai.api.audio.TranslationRequest
import com.aallam.openai.api.file.FileSource
Expand All @@ -9,7 +8,6 @@ import com.aallam.openai.client.OpenAI
import okio.FileSystem
import okio.Path.Companion.toPath

@OptIn(BetaOpenAI::class)
suspend fun whisper(openAI: OpenAI) {
println("\n>️ Create transcription...")
val transcriptionRequest = TranscriptionRequest(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.aallam.openai.sample.jvm

import com.aallam.openai.api.BetaOpenAI
import com.aallam.openai.api.file.FileSource
import com.aallam.openai.api.image.ImageCreation
import com.aallam.openai.api.image.ImageEdit
Expand All @@ -9,7 +8,6 @@ import com.aallam.openai.client.OpenAI
import okio.FileSystem
import okio.Path.Companion.toPath

@OptIn(BetaOpenAI::class)
suspend fun images(openAI: OpenAI) {
println("\n> Create images...")
val images = openAI.imageURL(
Expand Down

0 comments on commit 782d030

Please sign in to comment.