From ffdff5f42656f6a1a562e206eb00bcb5ef8b3b64 Mon Sep 17 00:00:00 2001 From: Emily Ploszaj Date: Wed, 20 May 2026 06:12:59 -0500 Subject: [PATCH] Add missing construction to TemplateTool that is present in Tool --- ai-logic/firebase-ai/CHANGELOG.md | 1 + ai-logic/firebase-ai/api.txt | 17 +++- ai-logic/firebase-ai/gradle.properties | 2 +- .../firebase/ai/TemplateIntegrationTests.kt | 31 +++++++ .../google/firebase/ai/type/TemplateTool.kt | 81 +++++++++++++++++-- .../com/google/firebase/ai/type/Tool.kt | 4 +- 6 files changed, 126 insertions(+), 10 deletions(-) diff --git a/ai-logic/firebase-ai/CHANGELOG.md b/ai-logic/firebase-ai/CHANGELOG.md index b82058ce8e6..14d8c925401 100644 --- a/ai-logic/firebase-ai/CHANGELOG.md +++ b/ai-logic/firebase-ai/CHANGELOG.md @@ -1,5 +1,6 @@ # Unreleased +- [feature] Added the `retrievalConfig` argument to `TemplateToolConfig` (#8107) - [fixed] Fixed citation indices to be native UTF-16 instead of UTF-8. (#8056) # 17.12.0 diff --git a/ai-logic/firebase-ai/api.txt b/ai-logic/firebase-ai/api.txt index 4468325c4f6..26448f58eb7 100644 --- a/ai-logic/firebase-ai/api.txt +++ b/ai-logic/firebase-ai/api.txt @@ -213,8 +213,8 @@ package com.google.firebase.ai { method @com.google.firebase.ai.type.PublicPreviewAPI public com.google.firebase.ai.TemplateChat startChat(String templateId, java.util.Map inputs, java.util.List history = emptyList()); } - @com.google.firebase.ai.type.PublicPreviewAPI public final class TemplateImagenModel { - method public suspend Object? generateImages(String templateId, java.util.Map inputs, kotlin.coroutines.Continuation>); + @Deprecated @com.google.firebase.ai.type.PublicPreviewAPI public final class TemplateImagenModel { + method @Deprecated public suspend Object? generateImages(String templateId, java.util.Map inputs, kotlin.coroutines.Continuation>); } } @@ -1839,15 +1839,28 @@ package com.google.firebase.ai.type { public final class TemplateTool { method public static com.google.firebase.ai.type.TemplateTool functionDeclarations(java.util.List functionDeclarations, java.util.List>? autoFunctionDeclarations = null); + method public static com.google.firebase.ai.type.TemplateTool googleMaps(); + method public static com.google.firebase.ai.type.TemplateTool googleMaps(com.google.firebase.ai.type.GoogleMaps googleMaps = com.google.firebase.ai.type.GoogleMaps()); + method public static com.google.firebase.ai.type.TemplateTool googleSearch(); + method public static com.google.firebase.ai.type.TemplateTool googleSearch(com.google.firebase.ai.type.GoogleSearch googleSearch = com.google.firebase.ai.type.GoogleSearch()); + method public static com.google.firebase.ai.type.TemplateTool urlContext(); + method public static com.google.firebase.ai.type.TemplateTool urlContext(com.google.firebase.ai.type.UrlContext urlContext = com.google.firebase.ai.type.UrlContext()); field public static final com.google.firebase.ai.type.TemplateTool.Companion Companion; } public static final class TemplateTool.Companion { method public com.google.firebase.ai.type.TemplateTool functionDeclarations(java.util.List functionDeclarations, java.util.List>? autoFunctionDeclarations = null); + method public com.google.firebase.ai.type.TemplateTool googleMaps(); + method public com.google.firebase.ai.type.TemplateTool googleMaps(com.google.firebase.ai.type.GoogleMaps googleMaps = com.google.firebase.ai.type.GoogleMaps()); + method public com.google.firebase.ai.type.TemplateTool googleSearch(); + method public com.google.firebase.ai.type.TemplateTool googleSearch(com.google.firebase.ai.type.GoogleSearch googleSearch = com.google.firebase.ai.type.GoogleSearch()); + method public com.google.firebase.ai.type.TemplateTool urlContext(); + method public com.google.firebase.ai.type.TemplateTool urlContext(com.google.firebase.ai.type.UrlContext urlContext = com.google.firebase.ai.type.UrlContext()); } public final class TemplateToolConfig { ctor public TemplateToolConfig(); + ctor public TemplateToolConfig(com.google.firebase.ai.type.RetrievalConfig? retrievalConfig); } public final class TextPart implements com.google.firebase.ai.type.Part { diff --git a/ai-logic/firebase-ai/gradle.properties b/ai-logic/firebase-ai/gradle.properties index a55522883fa..f7487d81d6c 100644 --- a/ai-logic/firebase-ai/gradle.properties +++ b/ai-logic/firebase-ai/gradle.properties @@ -12,5 +12,5 @@ # See the License for the specific language governing permissions and # limitations under the License. -version=17.12.1 +version=17.13.0 latestReleasedVersion=17.12.0 diff --git a/ai-logic/firebase-ai/src/androidTest/kotlin/com/google/firebase/ai/TemplateIntegrationTests.kt b/ai-logic/firebase-ai/src/androidTest/kotlin/com/google/firebase/ai/TemplateIntegrationTests.kt index f4a2939ba17..914686b3268 100644 --- a/ai-logic/firebase-ai/src/androidTest/kotlin/com/google/firebase/ai/TemplateIntegrationTests.kt +++ b/ai-logic/firebase-ai/src/androidTest/kotlin/com/google/firebase/ai/TemplateIntegrationTests.kt @@ -16,7 +16,12 @@ package com.google.firebase.ai +import com.google.firebase.ai.type.GenerativeBackend +import com.google.firebase.ai.type.LatLng import com.google.firebase.ai.type.PublicPreviewAPI +import com.google.firebase.ai.type.RetrievalConfig +import com.google.firebase.ai.type.TemplateTool +import com.google.firebase.ai.type.TemplateToolConfig import io.kotest.matchers.collections.shouldNotBeEmpty import io.kotest.matchers.string.shouldContainIgnoringCase import kotlinx.coroutines.flow.toList @@ -102,4 +107,30 @@ class TemplateIntegrationTests { it shouldContainIgnoringCase topic } } + + @Test + fun testTemplateGroundingCity_googleAI(): Unit = runBlocking { + val model = + FirebaseAI.getInstance(AIModels.app(), GenerativeBackend.googleAI()) + .templateGenerativeModel( + tools = listOf(TemplateTool.googleMaps()), + toolConfig = + TemplateToolConfig( + RetrievalConfig( + latLng = LatLng(latitude = 30.2672, longitude = -97.7431), + languageCode = "en_US", + ) + ) + ) + val responses = + model + .generateContentStream("maps-test-template-google-ai", mapOf("landmark" to "city")) + .toList() + responses + .joinToString { it.text ?: "" } + .lowercase() + .replace(",", "") + .replace(" ", " ") // Model sometimes doubles spacing + .let { it shouldContainIgnoringCase "new york" } + } } diff --git a/ai-logic/firebase-ai/src/main/kotlin/com/google/firebase/ai/type/TemplateTool.kt b/ai-logic/firebase-ai/src/main/kotlin/com/google/firebase/ai/type/TemplateTool.kt index 6e1553dde5d..b6bb7c94e2e 100644 --- a/ai-logic/firebase-ai/src/main/kotlin/com/google/firebase/ai/type/TemplateTool.kt +++ b/ai-logic/firebase-ai/src/main/kotlin/com/google/firebase/ai/type/TemplateTool.kt @@ -16,6 +16,7 @@ package com.google.firebase.ai.type +import kotlinx.serialization.InternalSerializationApi import kotlinx.serialization.Serializable /** @@ -23,10 +24,13 @@ import kotlinx.serialization.Serializable * to. */ public class TemplateTool -@OptIn(PublicPreviewAPI::class) +@OptIn(PublicPreviewAPI::class, InternalSerializationApi::class) internal constructor( internal val functionDeclarations: List?, internal val autoFunctionDeclarations: List>? = null, + internal val urlContext: UrlContext?, + internal val googleSearch: GoogleSearch?, + internal val googleMaps: GoogleMaps?, ) { @OptIn(PublicPreviewAPI::class) @@ -36,11 +40,17 @@ internal constructor( functionDeclarations?.let { addAll(it.map { it.toInternal() }) } autoFunctionDeclarations?.let { addAll(it.map { it.toInternal() }) } }, + urlContext?.toInternal(), + googleSearch?.toInternal(), + googleMaps?.toInternal(), ) @Serializable internal data class Internal( val templateFunctions: List? = null, + val urlContext: UrlContext.Internal? = null, + val googleSearch: GoogleSearch.Internal? = null, + val googleMaps: GoogleMaps.Internal? = null, ) public companion object { @@ -56,7 +66,63 @@ internal constructor( functionDeclarations: List, autoFunctionDeclarations: List>? = null, ): TemplateTool { - return TemplateTool(functionDeclarations, autoFunctionDeclarations) + return TemplateTool(functionDeclarations, autoFunctionDeclarations, null, null, null) + } + + /** + * Creates a [TemplateTool] instance that allows you to provide additional context to the models + * in the form of public web URLs. By including URLs in your request, the Gemini model will + * access the content from those pages to inform and enhance its response. + * + * @param urlContext Specifies the URL context configuration. + * @return A [TemplateTool] configured for URL context. + */ + @JvmStatic + @JvmOverloads + public fun urlContext(urlContext: UrlContext = UrlContext()): TemplateTool { + return TemplateTool(null, null, urlContext, null, null) + } + + /** + * Creates a [TemplateTool] instance that allows the model to use grounding with Google Search. + * + * Grounding with Google Search can be used to allow the model to connect to Google Search to + * access and incorporate up-to-date information from the web into its responses. + * + * When using this feature, you are required to comply with the "grounding with Google Search" + * usage requirements for your chosen API provider: + * [Gemini Developer API](https://ai.google.dev/gemini-api/terms#grounding-with-google-search) + * or Vertex AI Gemini API (see [Service Terms](https://cloud.google.com/terms/service-terms) + * section within the Service Specific Terms). + * + * @param googleSearch An empty [GoogleSearch] object. The presence of this object in the list + * of tools enables the model to use Google Search. + * @return A [TemplateTool] configured for Google Search. + */ + @JvmStatic + @JvmOverloads + public fun googleSearch(googleSearch: GoogleSearch = GoogleSearch()): TemplateTool { + return TemplateTool(null, null, null, googleSearch, null) + } + + /** + * Creates a [TemplateTool] instance that allows the model to use grounding with Google Maps. + * + * Grounding with Google Maps can be used to allow the model to connect to Google Maps to + * incorporate location-based information into its responses. + * + * When using this feature, you are required to comply with the "Grounding with Google Maps" + * usage requirements for your chosen API provider: + * [Gemini Developer API](https://ai.google.dev/gemini-api/terms#grounding-with-google-maps) or + * Vertex AI Gemini API (see [Service Terms](https://cloud.google.com/terms/service-terms) + * section within the Service Specific Terms). + * + * @return A [TemplateTool] configured for Google Maps. + */ + @JvmStatic + @JvmOverloads + public fun googleMaps(googleMaps: GoogleMaps = GoogleMaps()): TemplateTool { + return TemplateTool(null, null, null, null, googleMaps) } } } @@ -127,8 +193,13 @@ internal constructor( } /** Config for template tools to use with server prompts. */ -public class TemplateToolConfig { - internal fun toInternal(): ToolConfig.Internal? { - return null // Empty config payload as defined in flutter API +public class TemplateToolConfig public constructor(private val retrievalConfig: RetrievalConfig?) { + + public constructor() : this(null) + internal fun toInternal(): ToolConfig.Internal { + return ToolConfig.Internal( + functionCallingConfig = null, + retrievalConfig = retrievalConfig?.toInternal() + ) } } diff --git a/ai-logic/firebase-ai/src/main/kotlin/com/google/firebase/ai/type/Tool.kt b/ai-logic/firebase-ai/src/main/kotlin/com/google/firebase/ai/type/Tool.kt index 582b6aef676..a610aecea6d 100644 --- a/ai-logic/firebase-ai/src/main/kotlin/com/google/firebase/ai/type/Tool.kt +++ b/ai-logic/firebase-ai/src/main/kotlin/com/google/firebase/ai/type/Tool.kt @@ -61,7 +61,7 @@ internal constructor( public companion object { @OptIn(PublicPreviewAPI::class) - private val codeExecutionInstance by lazy { + internal val codeExecutionInstance by lazy { Tool(null, null, null, JsonObject(emptyMap()), null, null) } @@ -118,7 +118,7 @@ internal constructor( * Creates a [Tool] instance that allows the model to use grounding with Google Search. * * Grounding with Google Search can be used to allow the model to connect to Google Search to - * access and incorporate up-to-date information from the web into it's responses. + * access and incorporate up-to-date information from the web into its responses. * * When using this feature, you are required to comply with the "grounding with Google Search" * usage requirements for your chosen API provider: