Skip to content

Commit 2edbc52

Browse files
thatfiredevrlazo
andauthored
Add Vertex AI for Firebase quickstart (#1610)
* feat: add vertexai quickstart app * style: run ktlint * chore: add vertex ai to mock-google-services.json * add Vertex AI link to main README file * bump gradle to 8.6 * Remove properties not supported by java 17 (#1612) * Update model to 1.5-pro (#1611) --------- Co-authored-by: Rodrigo Lazo <[email protected]>
1 parent af96c6d commit 2edbc52

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+2873
-1
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ the sample you wish to run.
3535
- [ML Kit Translate](mlkit-translate/README.md)
3636
- [Performance Monitoring](perf/README.md)
3737
- [Storage](storage/README.md)
38+
- [Vertex AI](vertexai/README.md)
3839

3940
## How to make contributions?
4041
Please read and follow the steps in the [CONTRIBUTING.md](CONTRIBUTING.md)

copy_mock_google_services_json.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ cp mock-google-services.json inappmessaging/app/google-services.json
1919
cp mock-google-services.json perf/app/google-services.json
2020
cp mock-google-services.json messaging/app/google-services.json
2121
cp mock-google-services.json storage/app/google-services.json
22+
cp mock-google-services.json vertexai/app/google-services.json

mock-google-services.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -957,6 +957,25 @@
957957
"test_interstitial_ad_unit_id": "ca-app-pub-3940256099942544/1033173712"
958958
}
959959
}
960+
},
961+
{
962+
"client_info": {
963+
"mobilesdk_app_id": "1:474448463284:android:c76572afd2f0ba8d97e8e1",
964+
"android_client_info": {
965+
"package_name": "com.google.firebase.quickstart.vertexai"
966+
}
967+
},
968+
"oauth_client": [],
969+
"api_key": [
970+
{
971+
"current_key": "AIzaSyCPndbsEs_QWumL5_B0BpNLuMkvVSecvL0"
972+
}
973+
],
974+
"services": {
975+
"appinvite_service": {
976+
"other_platform_oauth_client": []
977+
}
978+
}
960979
}
961980
],
962981
"client_info": [],

settings.gradle.kts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,6 @@ include(":admob:app",
2222
":inappmessaging:app",
2323
":messaging:app",
2424
":perf:app",
25-
":storage:app"
25+
":storage:app",
26+
":vertexai:app"
2627
)

vertexai/README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Firebase Vertex AI Sample for Android (Kotlin)
2+
3+
This Android sample app demonstrates how to use state-of-the-art
4+
generative AI models (like Gemini) to build AI-powered features and applications.
5+
6+
To try out this sample app, you need to use latest stable version of Android Studio.
7+
However, if you want to latest lint checks and AI productivity features in Android
8+
Studio use the latest preview version of [Android Studio](https://developer.android.com/studio/preview).
9+
10+
You can clone this repository or import the project from Android Studio following the steps
11+
[here](https://developer.android.com/jetpack/compose/setup#sample).
12+
13+
## Screenshots
14+
15+
<img src="screenshots/screenshots.png" alt="Screenshot">
16+
17+
## Requirements
18+
19+
TODO
20+
21+
## Features
22+
23+
This sample showcases the following API capablilites:
24+
* Generate Text - demonstrates the Text feature from the SDK
25+
* Photo Reasoning - demonstrates the MultiModal feature from the SDK
26+
* Chat - demonstrates the Multi-turn Conversations feature from the SDK
27+
28+
## Documentation
29+
30+
TODO

vertexai/app/build.gradle.kts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright 2023 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
plugins {
18+
id("com.android.application")
19+
id("org.jetbrains.kotlin.android")
20+
id("com.google.gms.google-services")
21+
}
22+
23+
android {
24+
namespace = "com.google.firebase.quickstart.vertexai"
25+
compileSdk = 34
26+
27+
defaultConfig {
28+
applicationId = "com.google.firebase.quickstart.vertexai"
29+
minSdk = 26
30+
targetSdk = 34
31+
versionCode = 1
32+
versionName = "1.0"
33+
34+
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
35+
vectorDrawables {
36+
useSupportLibrary = true
37+
}
38+
}
39+
40+
compileOptions {
41+
sourceCompatibility = JavaVersion.VERSION_17
42+
targetCompatibility = JavaVersion.VERSION_17
43+
}
44+
kotlinOptions {
45+
jvmTarget = "17"
46+
}
47+
buildFeatures {
48+
compose = true
49+
}
50+
composeOptions {
51+
kotlinCompilerExtensionVersion = "1.5.13"
52+
}
53+
}
54+
55+
dependencies {
56+
implementation("androidx.core:core-ktx:1.9.0")
57+
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
58+
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2")
59+
implementation("androidx.activity:activity-compose:1.8.1")
60+
implementation("androidx.navigation:navigation-compose:2.7.5")
61+
62+
implementation(platform("androidx.compose:compose-bom:2023.10.01"))
63+
implementation("androidx.compose.ui:ui")
64+
implementation("androidx.compose.ui:ui-graphics")
65+
implementation("androidx.compose.ui:ui-tooling-preview")
66+
implementation("androidx.compose.material3:material3")
67+
68+
implementation("io.coil-kt:coil-compose:2.5.0")
69+
implementation("com.google.firebase:firebase-analytics:21.6.1")
70+
implementation("com.google.firebase:firebase-vertexai:16.0.0-alpha03")
71+
72+
testImplementation("junit:junit:4.13.2")
73+
androidTestImplementation("androidx.test.ext:junit:1.1.5")
74+
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
75+
androidTestImplementation(platform("androidx.compose:compose-bom:2023.03.00"))
76+
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
77+
debugImplementation("androidx.compose.ui:ui-tooling")
78+
debugImplementation("androidx.compose.ui:ui-test-manifest")
79+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!-- Copyright 2023 Google LLC
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
16+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
17+
xmlns:tools="http://schemas.android.com/tools">
18+
19+
<application
20+
android:allowBackup="true"
21+
android:dataExtractionRules="@xml/data_extraction_rules"
22+
android:fullBackupContent="@xml/backup_rules"
23+
android:icon="@mipmap/ic_launcher"
24+
android:label="@string/app_name"
25+
android:roundIcon="@mipmap/ic_launcher_round"
26+
android:supportsRtl="true"
27+
tools:targetApi="31">
28+
<activity
29+
android:name=".MainActivity"
30+
android:exported="true"
31+
android:label="@string/app_name">
32+
<intent-filter>
33+
<action android:name="android.intent.action.MAIN" />
34+
35+
<category android:name="android.intent.category.LAUNCHER" />
36+
</intent-filter>
37+
</activity>
38+
</application>
39+
40+
</manifest>
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* Copyright 2023 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.firebase.quickstart.vertexai
18+
19+
import androidx.lifecycle.ViewModel
20+
import androidx.lifecycle.ViewModelProvider
21+
import androidx.lifecycle.viewmodel.CreationExtras
22+
import com.google.firebase.Firebase
23+
import com.google.firebase.quickstart.vertexai.feature.chat.ChatViewModel
24+
import com.google.firebase.quickstart.vertexai.feature.functioncalling.FunctionsChatViewModel
25+
import com.google.firebase.quickstart.vertexai.feature.multimodal.PhotoReasoningViewModel
26+
import com.google.firebase.quickstart.vertexai.feature.text.SummarizeViewModel
27+
import com.google.firebase.vertexai.type.Schema
28+
import com.google.firebase.vertexai.type.Tool
29+
import com.google.firebase.vertexai.type.defineFunction
30+
import com.google.firebase.vertexai.type.generationConfig
31+
import com.google.firebase.vertexai.vertexAI
32+
import org.json.JSONObject
33+
34+
val GenerativeViewModelFactory = object : ViewModelProvider.Factory {
35+
override fun <T : ViewModel> create(
36+
viewModelClass: Class<T>,
37+
extras: CreationExtras
38+
): T {
39+
val config = generationConfig {
40+
temperature = 0.7f
41+
}
42+
43+
return with(viewModelClass) {
44+
when {
45+
isAssignableFrom(SummarizeViewModel::class.java) -> {
46+
// Initialize a GenerativeModel with the `gemini-pro` AI model
47+
// for text generation
48+
val generativeModel = Firebase.vertexAI.generativeModel(
49+
modelName = "gemini-1.5-pro-preview-0409",
50+
generationConfig = config
51+
)
52+
SummarizeViewModel(generativeModel)
53+
}
54+
55+
isAssignableFrom(PhotoReasoningViewModel::class.java) -> {
56+
// Initialize a GenerativeModel with the `gemini-pro` AI model
57+
// for multimodal text generation
58+
val generativeModel = Firebase.vertexAI.generativeModel(
59+
modelName = "gemini-1.5-pro-preview-0409",
60+
generationConfig = config
61+
)
62+
PhotoReasoningViewModel(generativeModel)
63+
}
64+
65+
isAssignableFrom(ChatViewModel::class.java) -> {
66+
// Initialize a GenerativeModel with the `gemini-pro` AI model for chat
67+
val generativeModel = Firebase.vertexAI.generativeModel(
68+
modelName = "gemini-1.5-pro-preview-0409",
69+
generationConfig = config
70+
)
71+
ChatViewModel(generativeModel)
72+
}
73+
74+
isAssignableFrom(FunctionsChatViewModel::class.java) -> {
75+
// Declare the functions you want to make available to the model
76+
val tools = listOf(
77+
Tool(
78+
listOf(
79+
defineFunction(
80+
"upperCase",
81+
"Returns the upper case version of the input string",
82+
Schema.str("input", "Text to transform")
83+
) { input ->
84+
JSONObject("{\"response\": \"${input.uppercase()}\"}")
85+
}
86+
)
87+
)
88+
)
89+
90+
// Initialize a GenerativeModel with the `gemini-pro` AI model for function calling chat
91+
val generativeModel = Firebase.vertexAI.generativeModel(
92+
modelName = "gemini-1.5-pro-preview-0409",
93+
generationConfig = config,
94+
tools = tools
95+
)
96+
FunctionsChatViewModel(generativeModel)
97+
}
98+
99+
else ->
100+
throw IllegalArgumentException("Unknown ViewModel class: ${viewModelClass.name}")
101+
}
102+
} as T
103+
}
104+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
* Copyright 2023 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.firebase.quickstart.vertexai
18+
19+
import android.os.Bundle
20+
import androidx.activity.ComponentActivity
21+
import androidx.activity.compose.setContent
22+
import androidx.compose.foundation.layout.fillMaxSize
23+
import androidx.compose.material3.MaterialTheme
24+
import androidx.compose.material3.Surface
25+
import androidx.compose.ui.Modifier
26+
import androidx.navigation.compose.NavHost
27+
import androidx.navigation.compose.composable
28+
import androidx.navigation.compose.rememberNavController
29+
import com.google.firebase.quickstart.vertexai.feature.chat.ChatRoute
30+
import com.google.firebase.quickstart.vertexai.feature.functioncalling.FunctionsChatRoute
31+
import com.google.firebase.quickstart.vertexai.feature.multimodal.PhotoReasoningRoute
32+
import com.google.firebase.quickstart.vertexai.feature.text.SummarizeRoute
33+
import com.google.firebase.quickstart.vertexai.ui.theme.GenerativeAISample
34+
35+
class MainActivity : ComponentActivity() {
36+
37+
override fun onCreate(savedInstanceState: Bundle?) {
38+
super.onCreate(savedInstanceState)
39+
40+
setContent {
41+
GenerativeAISample {
42+
// A surface container using the 'background' color from the theme
43+
Surface(
44+
modifier = Modifier.fillMaxSize(),
45+
color = MaterialTheme.colorScheme.background
46+
) {
47+
val navController = rememberNavController()
48+
49+
NavHost(navController = navController, startDestination = "menu") {
50+
composable("menu") {
51+
MenuScreen(onItemClicked = { routeId ->
52+
navController.navigate(routeId)
53+
})
54+
}
55+
composable("summarize") {
56+
SummarizeRoute()
57+
}
58+
composable("photo_reasoning") {
59+
PhotoReasoningRoute()
60+
}
61+
composable("chat") {
62+
ChatRoute()
63+
}
64+
composable("functions_chat") {
65+
FunctionsChatRoute()
66+
}
67+
}
68+
}
69+
}
70+
}
71+
}
72+
}

0 commit comments

Comments
 (0)