Skip to content

Commit

Permalink
make FunctionCall.args nullable (google-gemini#207)
Browse files Browse the repository at this point in the history
  • Loading branch information
tanzimfh authored and PatilShreyas committed Sep 21, 2024
1 parent 09d60bb commit a345232
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 6 deletions.
1 change: 1 addition & 0 deletions .changes/common/coach-cap-control-dinosaurs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"type":"MINOR","changes":["make FunctionCall.args nullable"]}
1 change: 1 addition & 0 deletions .changes/generativeai/board-burn-cushion-calculator.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"type":"MAJOR","changes":["make FunctionCallPart.args nullable"]}
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ data class CodeExecutionResultPart(val codeExecutionResult: CodeExecutionResult)

@Serializable data class FunctionResponse(val name: String, val response: JsonObject)

@Serializable data class FunctionCall(val name: String, val args: Map<String, String?>)
@Serializable data class FunctionCall(val name: String, val args: Map<String, String?>? = null)

@Serializable data class FileDataPart(@SerialName("file_data") val fileData: FileData) : Part

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,8 @@ internal class UnarySnapshotTests {
val response = apiController.generateContent(textGenerateContentRequest("prompt"))
val callPart = (response.candidates!!.first().content!!.parts.first() as FunctionCallPart)

callPart.functionCall.args["season"] shouldBe null
callPart.functionCall.args shouldNotBe null
callPart.functionCall.args?.get("season") shouldBe null
}
}

Expand All @@ -333,7 +334,22 @@ internal class UnarySnapshotTests {
it.parts.first().shouldBeInstanceOf<FunctionCallPart>()
}

callPart.functionCall.args["current"] shouldBe "true"
callPart.functionCall.args shouldNotBe null
callPart.functionCall.args?.get("current") shouldBe "true"
}
}

@Test
fun `function call has no arguments field`() =
goldenUnaryFile("success-function-call-empty-arguments.json") {
withTimeout(testTimeout) {
val response = apiController.generateContent(textGenerateContentRequest("prompt"))
val content = response.candidates.shouldNotBeNullOrEmpty().first().content
content.shouldNotBeNull()
val callPart = content.parts.shouldNotBeNullOrEmpty().first() as FunctionCallPart

callPart.functionCall.name shouldBe "current_time"
callPart.functionCall.args shouldBe null
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"candidates": [
{
"content": {
"parts": [
{
"functionCall": {
"name": "current_time"
}
}
],
"role": "model"
},
"finishReason": "STOP",
"index": 0
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class FileDataPart(val uri: String, val mimeType: String) : Part
fun Part.asFileDataPartOrNull(): FileDataPart? = this as? FileDataPart

/** Represents function call name and params received from requests. */
class FunctionCallPart(val name: String, val args: Map<String, String?>) : Part
class FunctionCallPart(val name: String, val args: Map<String, String?>?) : Part

/** Represents function call output to be returned to the model when it requests a function call */
class FunctionResponsePart(val name: String, val response: JsonObject) : Part
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,9 @@ internal class GenerativeModelTests {
response.functionCalls.firstOrNull()?.let {
it.shouldNotBeNull()
it.name shouldBe "getExchangeRate"
it.args shouldContain ("currencyFrom" to "USD")
it.args shouldContain ("currencyTo" to "EUR")
it.args.shouldNotBeNull()
it.args?.shouldContain("currencyFrom" to "USD")
it.args?.shouldContain("currencyTo" to "EUR")
}

coEvery { mockApiController.generateContent(any()) } returns
Expand Down

0 comments on commit a345232

Please sign in to comment.