Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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 @@ -36,12 +36,14 @@ public class GenerateContentResponse(
* exists.
*/
public val text: String? by lazy {
candidates.first().content.parts.filterIsInstance<TextPart>().joinToString(" ") { it.text }
candidates.firstOrNull()?.content?.parts?.filterIsInstance<TextPart>()?.joinToString(" ") {
it.text
}
}

/** Convenience field to list all the [FunctionCallPart]s in the response, if they exist. */
public val functionCalls: List<FunctionCallPart> by lazy {
candidates.first().content.parts.filterIsInstance<FunctionCallPart>()
candidates.firstOrNull()?.content?.parts?.filterIsInstance<FunctionCallPart>().orEmpty()
}

/**
Expand All @@ -50,10 +52,15 @@ public class GenerateContentResponse(
* This also includes any [ImagePart], but they will be represented as [InlineDataPart] instead.
*/
public val inlineDataParts: List<InlineDataPart> by lazy {
candidates.first().content.parts.let { parts ->
parts.filterIsInstance<ImagePart>().map { it.toInlineDataPart() } +
parts.filterIsInstance<InlineDataPart>()
}
candidates
.firstOrNull()
?.content
?.parts
?.let { parts ->
parts.filterIsInstance<ImagePart>().map { it.toInlineDataPart() } +
parts.filterIsInstance<InlineDataPart>()
}
.orEmpty()
}

@Serializable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ import com.google.firebase.ai.type.ResponseStoppedException
import com.google.firebase.ai.type.ServerException
import com.google.firebase.ai.util.goldenDevAPIUnaryFile
import io.kotest.assertions.throwables.shouldThrow
import io.kotest.matchers.collections.shouldBeEmpty
import io.kotest.matchers.collections.shouldNotBeEmpty
import io.kotest.matchers.nulls.shouldBeNull
import io.kotest.matchers.nulls.shouldNotBeNull
import io.kotest.matchers.should
import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
import io.ktor.http.HttpStatusCode
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.withTimeout
Expand All @@ -42,9 +42,24 @@ internal class DevAPIUnarySnapshotTests {
withTimeout(testTimeout) {
val response = model.generateContent("prompt")

response.candidates.isEmpty() shouldBe false
response.candidates.shouldNotBeEmpty()
response.candidates.first().finishReason shouldBe FinishReason.STOP
response.candidates.first().content.parts.isEmpty() shouldBe false
response.candidates.first().content.parts.shouldNotBeEmpty()
}
}

@Test
fun `only prompt feedback reply`() =
goldenDevAPIUnaryFile("unary-failure-only-prompt-feedback.json") {
withTimeout(testTimeout) {
val response = model.generateContent("prompt")

response.candidates.shouldBeEmpty()

// Check response from accessors
response.text.shouldBeNull()
response.functionCalls.shouldBeEmpty()
response.inlineDataParts.shouldBeEmpty()
}
}

Expand All @@ -54,9 +69,9 @@ internal class DevAPIUnarySnapshotTests {
withTimeout(testTimeout) {
val response = model.generateContent("prompt")

response.candidates.isEmpty() shouldBe false
response.candidates.shouldNotBeEmpty()
response.candidates.first().finishReason shouldBe FinishReason.STOP
response.candidates.first().content.parts.isEmpty() shouldBe false
response.candidates.first().content.parts.shouldNotBeEmpty()
}
}

Expand All @@ -66,11 +81,11 @@ internal class DevAPIUnarySnapshotTests {
withTimeout(testTimeout) {
val response = model.generateContent("prompt")

response.candidates.isEmpty() shouldBe false
response.candidates.shouldNotBeEmpty()
response.candidates.first().citationMetadata?.citations?.size shouldBe 4
response.candidates.first().citationMetadata?.citations?.forEach {
it.startIndex shouldNotBe null
it.endIndex shouldNotBe null
it.startIndex.shouldNotBeNull()
it.endIndex.shouldNotBeNull()
}
}
}
Expand Down
Loading