Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(chat): function call nullable name/arguments #232

Merged
merged 2 commits into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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