Skip to content

Commit 1ac16c8

Browse files
authored
Add missing construction to TemplateTool that is present in Tool (#8188)
`TemplateTool` is separate from `Tool` for some reason and was missing various features that are supported on `Tool` and work correctly with templates. This adds them to `TemplateTool` and adds testing to validate the maps grounding behavior on Google AI. Vertex does not respond correctly to our grounding query at the moment so has not been included.
1 parent b61c8cf commit 1ac16c8

6 files changed

Lines changed: 97 additions & 10 deletions

File tree

ai-logic/firebase-ai/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Unreleased
22

3+
- [feature] Added the `retrievalConfig` argument to `TemplateToolConfig` (#8107)
34
- [fixed] Fixed citation indices to be native UTF-16 instead of UTF-8. (#8056)
45

56
# 17.12.0

ai-logic/firebase-ai/api.txt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,8 @@ package com.google.firebase.ai {
213213
method @com.google.firebase.ai.type.PublicPreviewAPI public com.google.firebase.ai.TemplateChat startChat(String templateId, java.util.Map<java.lang.String,?> inputs, java.util.List<com.google.firebase.ai.type.Content> history = emptyList());
214214
}
215215

216-
@com.google.firebase.ai.type.PublicPreviewAPI public final class TemplateImagenModel {
217-
method public suspend Object? generateImages(String templateId, java.util.Map<java.lang.String,?> inputs, kotlin.coroutines.Continuation<? super com.google.firebase.ai.type.ImagenGenerationResponse<com.google.firebase.ai.type.ImagenInlineImage>>);
216+
@Deprecated @com.google.firebase.ai.type.PublicPreviewAPI public final class TemplateImagenModel {
217+
method @Deprecated public suspend Object? generateImages(String templateId, java.util.Map<java.lang.String,?> inputs, kotlin.coroutines.Continuation<? super com.google.firebase.ai.type.ImagenGenerationResponse<com.google.firebase.ai.type.ImagenInlineImage>>);
218218
}
219219

220220
}
@@ -1839,15 +1839,20 @@ package com.google.firebase.ai.type {
18391839

18401840
public final class TemplateTool {
18411841
method public static com.google.firebase.ai.type.TemplateTool functionDeclarations(java.util.List<? extends com.google.firebase.ai.type.TemplateFunctionDeclaration> functionDeclarations, java.util.List<? extends com.google.firebase.ai.type.TemplateAutoFunctionDeclaration<? extends java.lang.Object?,? extends java.lang.Object?>>? autoFunctionDeclarations = null);
1842+
method public static com.google.firebase.ai.type.TemplateTool googleMaps();
1843+
method public static com.google.firebase.ai.type.TemplateTool googleMaps(com.google.firebase.ai.type.GoogleMaps googleMaps = com.google.firebase.ai.type.GoogleMaps());
18421844
field public static final com.google.firebase.ai.type.TemplateTool.Companion Companion;
18431845
}
18441846

18451847
public static final class TemplateTool.Companion {
18461848
method public com.google.firebase.ai.type.TemplateTool functionDeclarations(java.util.List<? extends com.google.firebase.ai.type.TemplateFunctionDeclaration> functionDeclarations, java.util.List<? extends com.google.firebase.ai.type.TemplateAutoFunctionDeclaration<? extends java.lang.Object?,? extends java.lang.Object?>>? autoFunctionDeclarations = null);
1849+
method public com.google.firebase.ai.type.TemplateTool googleMaps();
1850+
method public com.google.firebase.ai.type.TemplateTool googleMaps(com.google.firebase.ai.type.GoogleMaps googleMaps = com.google.firebase.ai.type.GoogleMaps());
18471851
}
18481852

18491853
public final class TemplateToolConfig {
18501854
ctor public TemplateToolConfig();
1855+
ctor public TemplateToolConfig(com.google.firebase.ai.type.RetrievalConfig? retrievalConfig);
18511856
}
18521857

18531858
public final class TextPart implements com.google.firebase.ai.type.Part {

ai-logic/firebase-ai/gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
version=17.12.1
15+
version=17.13.0
1616
latestReleasedVersion=17.12.0

ai-logic/firebase-ai/src/androidTest/kotlin/com/google/firebase/ai/TemplateIntegrationTests.kt

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,16 @@
1616

1717
package com.google.firebase.ai
1818

19+
import com.google.firebase.ai.type.GenerativeBackend
20+
import com.google.firebase.ai.type.LatLng
1921
import com.google.firebase.ai.type.PublicPreviewAPI
22+
import com.google.firebase.ai.type.RetrievalConfig
23+
import com.google.firebase.ai.type.TemplateTool
24+
import com.google.firebase.ai.type.TemplateToolConfig
2025
import io.kotest.matchers.collections.shouldNotBeEmpty
26+
import io.kotest.matchers.string.shouldContain
2127
import io.kotest.matchers.string.shouldContainIgnoringCase
28+
import io.kotest.matchers.string.shouldNotContain
2229
import kotlinx.coroutines.flow.toList
2330
import kotlinx.coroutines.runBlocking
2431
import org.junit.Before
@@ -102,4 +109,49 @@ class TemplateIntegrationTests {
102109
it shouldContainIgnoringCase topic
103110
}
104111
}
112+
113+
@Test
114+
fun testTemplateGroundingCity_googleAI(): Unit = runBlocking {
115+
val model =
116+
FirebaseAI.getInstance(AIModels.app(), GenerativeBackend.googleAI())
117+
.templateGenerativeModel(
118+
tools = listOf(TemplateTool.googleMaps()),
119+
toolConfig =
120+
TemplateToolConfig(
121+
RetrievalConfig(
122+
latLng = LatLng(latitude = 30.2672, longitude = -97.7431),
123+
languageCode = "en_US",
124+
)
125+
)
126+
)
127+
val responses =
128+
model
129+
.generateContentStream("maps-test-template-google-ai", mapOf("landmark" to "city"))
130+
.toList()
131+
responses
132+
.joinToString { it.text ?: "" }
133+
.lowercase()
134+
.replace(",", "")
135+
.replace(" ", " ") // Model sometimes doubles spacing
136+
.let { it shouldContainIgnoringCase "new york" }
137+
}
138+
139+
@Test
140+
fun testTemplateToolsUrlContext_googleAI(): Unit = runBlocking {
141+
val model =
142+
FirebaseAI.getInstance(AIModels.app(), GenerativeBackend.googleAI())
143+
.templateGenerativeModel(
144+
tools = listOf(), // URLContext not provided, still can read links
145+
)
146+
val response =
147+
model.generateContent(
148+
"url-context-test-template-google-ai",
149+
mapOf(
150+
"url" to "https://en.wikipedia.org/wiki/Kasane_Teto",
151+
"question" to "What is the given name of the linked individual?",
152+
)
153+
)
154+
response.text?.lowercase() shouldContain "teto"
155+
response.text?.lowercase() shouldNotContain "kasane"
156+
}
105157
}

ai-logic/firebase-ai/src/main/kotlin/com/google/firebase/ai/type/TemplateTool.kt

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,19 @@
1616

1717
package com.google.firebase.ai.type
1818

19+
import kotlinx.serialization.InternalSerializationApi
1920
import kotlinx.serialization.Serializable
2021

2122
/**
2223
* Contains a set of tools (like function declarations) that the server template model has access
2324
* to.
2425
*/
2526
public class TemplateTool
26-
@OptIn(PublicPreviewAPI::class)
27+
@OptIn(PublicPreviewAPI::class, InternalSerializationApi::class)
2728
internal constructor(
2829
internal val functionDeclarations: List<TemplateFunctionDeclaration>?,
2930
internal val autoFunctionDeclarations: List<TemplateAutoFunctionDeclaration<*, *>>? = null,
31+
internal val googleMaps: GoogleMaps?,
3032
) {
3133

3234
@OptIn(PublicPreviewAPI::class)
@@ -36,11 +38,13 @@ internal constructor(
3638
functionDeclarations?.let { addAll(it.map { it.toInternal() }) }
3739
autoFunctionDeclarations?.let { addAll(it.map { it.toInternal() }) }
3840
},
41+
googleMaps?.toInternal(),
3942
)
4043

4144
@Serializable
4245
internal data class Internal(
4346
val templateFunctions: List<TemplateFunctionDeclaration.Internal>? = null,
47+
val googleMaps: GoogleMaps.Internal? = null,
4448
)
4549

4650
public companion object {
@@ -56,7 +60,27 @@ internal constructor(
5660
functionDeclarations: List<TemplateFunctionDeclaration>,
5761
autoFunctionDeclarations: List<TemplateAutoFunctionDeclaration<*, *>>? = null,
5862
): TemplateTool {
59-
return TemplateTool(functionDeclarations, autoFunctionDeclarations)
63+
return TemplateTool(functionDeclarations, autoFunctionDeclarations, null)
64+
}
65+
66+
/**
67+
* Creates a [TemplateTool] instance that allows the model to use grounding with Google Maps.
68+
*
69+
* Grounding with Google Maps can be used to allow the model to connect to Google Maps to
70+
* incorporate location-based information into its responses.
71+
*
72+
* When using this feature, you are required to comply with the "Grounding with Google Maps"
73+
* usage requirements for your chosen API provider:
74+
* [Gemini Developer API](https://ai.google.dev/gemini-api/terms#grounding-with-google-maps) or
75+
* Vertex AI Gemini API (see [Service Terms](https://cloud.google.com/terms/service-terms)
76+
* section within the Service Specific Terms).
77+
*
78+
* @return A [TemplateTool] configured for Google Maps.
79+
*/
80+
@JvmStatic
81+
@JvmOverloads
82+
public fun googleMaps(googleMaps: GoogleMaps = GoogleMaps()): TemplateTool {
83+
return TemplateTool(null, null, googleMaps)
6084
}
6185
}
6286
}
@@ -127,8 +151,13 @@ internal constructor(
127151
}
128152

129153
/** Config for template tools to use with server prompts. */
130-
public class TemplateToolConfig {
131-
internal fun toInternal(): ToolConfig.Internal? {
132-
return null // Empty config payload as defined in flutter API
154+
public class TemplateToolConfig public constructor(private val retrievalConfig: RetrievalConfig?) {
155+
156+
public constructor() : this(null)
157+
internal fun toInternal(): ToolConfig.Internal {
158+
return ToolConfig.Internal(
159+
functionCallingConfig = null,
160+
retrievalConfig = retrievalConfig?.toInternal()
161+
)
133162
}
134163
}

ai-logic/firebase-ai/src/main/kotlin/com/google/firebase/ai/type/Tool.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ internal constructor(
6161
public companion object {
6262

6363
@OptIn(PublicPreviewAPI::class)
64-
private val codeExecutionInstance by lazy {
64+
internal val codeExecutionInstance by lazy {
6565
Tool(null, null, null, JsonObject(emptyMap()), null, null)
6666
}
6767

@@ -118,7 +118,7 @@ internal constructor(
118118
* Creates a [Tool] instance that allows the model to use grounding with Google Search.
119119
*
120120
* Grounding with Google Search can be used to allow the model to connect to Google Search to
121-
* access and incorporate up-to-date information from the web into it's responses.
121+
* access and incorporate up-to-date information from the web into its responses.
122122
*
123123
* When using this feature, you are required to comply with the "grounding with Google Search"
124124
* usage requirements for your chosen API provider:

0 commit comments

Comments
 (0)