Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 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
2 changes: 2 additions & 0 deletions firebase-ai/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# Unreleased
* [feature] Added support for returning thought summaries, which are synthesized
versions of a model's internal reasoning process.
* [fixed] Fixed an issue causing the accessor methods in `GenerateContentResponse` to throw an exception
when the response contained no candidates.
* [changed] Added better description for requests which fail due to the Gemini API not being
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,42 +34,64 @@ public class GenerateContentResponse(
/**
* Convenience field representing all the text parts in the response as a single string.
*
* The value is null if the response contains no [candidates].
* The value is null if the response contains no valid text [candidates].
*
* Any part that's marked as a thought will be ignored. Learn more about
* [thinking](https://firebase.google.com/docs/ai-logic/thinking?api=dev).
*/
public val text: String? by lazy {
candidates.firstOrNull()?.content?.parts?.filterIsInstance<TextPart>()?.joinToString(" ") {
it.text
}
val parts = candidates.firstOrNull()?.nonThoughtParts()?.filterIsInstance<TextPart>()
if (parts.isNullOrEmpty()) return@lazy null
parts.joinToString(" ") { it.text }
}

/**
* Convenience field to list all the [FunctionCallPart]s in the response.
*
* The value is an empty list if the response contains no [candidates].
*
* Any part that's marked as a thought will be ignored. Learn more about
* [thinking](https://firebase.google.com/docs/ai-logic/thinking?api=dev).
*/
public val functionCalls: List<FunctionCallPart> by lazy {
candidates.firstOrNull()?.content?.parts?.filterIsInstance<FunctionCallPart>().orEmpty()
}

/**
* Convenience field representing all the [InlineDataPart]s in the first candidate, if they exist.
* Convenience field representing all the text parts in the response that are marked as thoughts
* as a single string, if they exists.
*
* Learn more about [thinking](https://firebase.google.com/docs/ai-logic/thinking?api=dev).
*/
public val thoughtSummary: String? by lazy {
candidates.firstOrNull()?.thoughtParts()?.filterIsInstance<TextPart>()?.joinToString(" ")
}

/**
* Convenience field representing all the [InlineDataPart]s in the first candidate.
*
* This also includes any [ImagePart], but they will be represented as [InlineDataPart] instead.
*
* The value is an empty list if the response contains no [candidates].
*
* Any part that's marked as a thought will be ignored. Learn more about
* [thinking](https://firebase.google.com/docs/ai-logic/thinking?api=dev).
*/
public val inlineDataParts: List<InlineDataPart> by lazy {
candidates
.firstOrNull()
?.content
?.parts
?.nonThoughtParts()
?.let { parts ->
parts.filterIsInstance<ImagePart>().map { it.toInlineDataPart() } +
parts.filterIsInstance<InlineDataPart>()
}
.orEmpty()
}

private fun Candidate.thoughtParts(): List<Part> = content.parts.filter { it.isThought }

private fun Candidate.nonThoughtParts(): List<Part> = content.parts.filter { !it.isThought }

@Serializable
internal data class Internal(
val candidates: List<Candidate.Internal>? = null,
Expand Down
Loading
Loading