Skip to content

Commit 0f74341

Browse files
committed
Merge branch 'main' into code_execution_support
2 parents b9e991b + be8f480 commit 0f74341

File tree

33 files changed

+767
-169
lines changed

33 files changed

+767
-169
lines changed

.github/workflows/ai-nightlies.yml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
name: Firebase AI Nightlies
2+
3+
on:
4+
schedule:
5+
- cron: 2 7 * * * # Runs automatically once a day
6+
workflow_dispatch: # Allow triggering the workflow manually
7+
8+
jobs:
9+
nightlies:
10+
name: "Nightlies"
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
15+
with:
16+
fetch-depth: 2
17+
submodules: true
18+
19+
- name: Enable KVM
20+
run: |
21+
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
22+
sudo udevadm control --reload-rules
23+
sudo udevadm trigger --name-match=kvm
24+
25+
- name: Set up JDK 17
26+
uses: actions/setup-java@3a4f6e1af504cf6a31855fa899c6aa5355ba6c12 # v4.7.0
27+
with:
28+
java-version: 17
29+
distribution: temurin
30+
cache: gradle
31+
32+
- name: Add google-services.json
33+
env:
34+
INTEG_TESTS_GOOGLE_SERVICES: ${{ secrets.INTEG_TESTS_GOOGLE_SERVICES }}
35+
run: |
36+
echo $INTEG_TESTS_GOOGLE_SERVICES | base64 -d > google-services.json
37+
- uses: google-github-actions/auth@71f986410dfbc7added4569d411d040a91dc6935 # v2.1.8
38+
with:
39+
credentials_json: ${{ secrets.GCP_SERVICE_ACCOUNT }}
40+
41+
- uses: google-github-actions/setup-gcloud@77e7a554d41e2ee56fc945c52dfd3f33d12def9a # v2.1.4
42+
43+
- name: Run tests
44+
uses: reactivecircus/android-emulator-runner@62dbb605bba737720e10b196cb4220d374026a6d #v2.33.0
45+
env:
46+
FIREBASE_CI: 1
47+
FTL_RESULTS_BUCKET: android-ci
48+
FTL_RESULTS_DIR: ${{ format('logs/{0}/{1}_{2}/artifacts/', github.workflow, github.run_id, github.run_attempt) }}
49+
FIREBASE_APP_CHECK_DEBUG_SECRET: ${{ secrets.FIREBASE_APP_CHECK_DEBUG_SECRET }}
50+
with:
51+
api-level: 31
52+
arch: x86_64
53+
ram-size: 4096M
54+
heap-size: 4096M
55+
script: |
56+
adb logcat -v time > logcat.txt &
57+
./gradlew firebase-ai:connectedCheck withErrorProne -PtargetBackend="prod"
58+
59+
- name: Upload logs
60+
if: failure()
61+
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
62+
with:
63+
name: logcat.txt
64+
path: logcat.txt
65+
retention-days: 7
66+
if-no-files-found: ignore

firebase-ai/CHANGELOG.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
# Unreleased
2-
* [feature] added support for Imagen Editing, including inpainting, outpainting, control, style
2+
* [feature] Added support for returning thought summaries, which are synthesized
3+
versions of a model's internal reasoning process.
4+
* [fixed] Fixed an issue causing the accessor methods in `GenerateContentResponse` to throw an exception
5+
when the response contained no candidates.
6+
* [changed] Added better description for requests which fail due to the Gemini API not being
7+
configured.
8+
* [changed] Added a `dilation` parameter to `ImagenMaskReference.generateMaskAndPadForOutpainting`
9+
(#7260)
10+
11+
# 17.1.0
12+
=======
13+
* [feature] added support for Imagen Editing, including inpainting, outpainting, control, style
314
transfer, and subject references (#7075)
15+
* [feature] **Preview:** Added support for bidirectional streaming in Gemini Developer Api
416

517
# 17.0.0
618
* [feature] Added support for configuring the "thinking" budget when using Gemini
@@ -43,4 +55,3 @@
4355

4456
Note: This feature is in Public Preview, which means that it is not subject to any SLA or
4557
deprecation policy and could change in backwards-incompatible ways.
46-

firebase-ai/api.txt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@ package com.google.firebase.ai.java {
157157

158158
package com.google.firebase.ai.type {
159159

160+
public final class APINotConfiguredException extends com.google.firebase.ai.type.FirebaseAIException {
161+
}
162+
160163
public final class AudioRecordInitializationFailedException extends com.google.firebase.ai.type.FirebaseAIException {
161164
ctor public AudioRecordInitializationFailedException(String message);
162165
}
@@ -214,6 +217,8 @@ package com.google.firebase.ai.type {
214217
ctor public CodeExecutionResultPart(String outcome, String output);
215218
method public String getOutcome();
216219
method public String getOutput();
220+
method public boolean isThought();
221+
property public boolean isThought;
217222
property public final String outcome;
218223
property public final String output;
219224
}
@@ -289,14 +294,18 @@ package com.google.firebase.ai.type {
289294
ctor public ExecutableCodePart(String language, String code);
290295
method public String getCode();
291296
method public String getLanguage();
297+
method public boolean isThought();
292298
property public final String code;
299+
property public boolean isThought;
293300
property public final String language;
294301
}
295302

296303
public final class FileDataPart implements com.google.firebase.ai.type.Part {
297304
ctor public FileDataPart(String uri, String mimeType);
298305
method public String getMimeType();
299306
method public String getUri();
307+
method public boolean isThought();
308+
property public boolean isThought;
300309
property public final String mimeType;
301310
property public final String uri;
302311
}
@@ -331,8 +340,10 @@ package com.google.firebase.ai.type {
331340
method public java.util.Map<java.lang.String,kotlinx.serialization.json.JsonElement> getArgs();
332341
method public String? getId();
333342
method public String getName();
343+
method public boolean isThought();
334344
property public final java.util.Map<java.lang.String,kotlinx.serialization.json.JsonElement> args;
335345
property public final String? id;
346+
property public boolean isThought;
336347
property public final String name;
337348
}
338349

@@ -361,7 +372,9 @@ package com.google.firebase.ai.type {
361372
method public String? getId();
362373
method public String getName();
363374
method public kotlinx.serialization.json.JsonObject getResponse();
375+
method public boolean isThought();
364376
property public final String? id;
377+
property public boolean isThought;
365378
property public final String name;
366379
property public final kotlinx.serialization.json.JsonObject response;
367380
}
@@ -375,6 +388,7 @@ package com.google.firebase.ai.type {
375388
method public java.util.List<com.google.firebase.ai.type.InlineDataPart> getInlineDataParts();
376389
method public com.google.firebase.ai.type.PromptFeedback? getPromptFeedback();
377390
method public String? getText();
391+
method public String? getThoughtSummary();
378392
method public com.google.firebase.ai.type.UsageMetadata? getUsageMetadata();
379393
property public final java.util.List<com.google.firebase.ai.type.Candidate> candidates;
380394
property public final java.util.List<com.google.firebase.ai.type.CodeExecutionResultPart> codeExecutionResults;
@@ -383,6 +397,7 @@ package com.google.firebase.ai.type {
383397
property public final java.util.List<com.google.firebase.ai.type.InlineDataPart> inlineDataParts;
384398
property public final com.google.firebase.ai.type.PromptFeedback? promptFeedback;
385399
property public final String? text;
400+
property public final String? thoughtSummary;
386401
property public final com.google.firebase.ai.type.UsageMetadata? usageMetadata;
387402
}
388403

@@ -553,7 +568,9 @@ package com.google.firebase.ai.type {
553568
public final class ImagePart implements com.google.firebase.ai.type.Part {
554569
ctor public ImagePart(android.graphics.Bitmap image);
555570
method public android.graphics.Bitmap getImage();
571+
method public boolean isThought();
556572
property public final android.graphics.Bitmap image;
573+
property public boolean isThought;
557574
}
558575

559576
@com.google.firebase.ai.type.PublicPreviewAPI public final class ImagenAspectRatio {
@@ -702,12 +719,14 @@ package com.google.firebase.ai.type {
702719
@com.google.firebase.ai.type.PublicPreviewAPI public abstract class ImagenMaskReference extends com.google.firebase.ai.type.ImagenReferenceImage {
703720
method public static final java.util.List<com.google.firebase.ai.type.ImagenReferenceImage> generateMaskAndPadForOutpainting(com.google.firebase.ai.type.ImagenInlineImage image, com.google.firebase.ai.type.Dimensions newDimensions);
704721
method public static final java.util.List<com.google.firebase.ai.type.ImagenReferenceImage> generateMaskAndPadForOutpainting(com.google.firebase.ai.type.ImagenInlineImage image, com.google.firebase.ai.type.Dimensions newDimensions, com.google.firebase.ai.type.ImagenImagePlacement newPosition = com.google.firebase.ai.type.ImagenImagePlacement.CENTER);
722+
method public static final java.util.List<com.google.firebase.ai.type.ImagenReferenceImage> generateMaskAndPadForOutpainting(com.google.firebase.ai.type.ImagenInlineImage image, com.google.firebase.ai.type.Dimensions newDimensions, com.google.firebase.ai.type.ImagenImagePlacement newPosition = com.google.firebase.ai.type.ImagenImagePlacement.CENTER, double dilation = 0.01);
705723
field public static final com.google.firebase.ai.type.ImagenMaskReference.Companion Companion;
706724
}
707725

708726
public static final class ImagenMaskReference.Companion {
709727
method public java.util.List<com.google.firebase.ai.type.ImagenReferenceImage> generateMaskAndPadForOutpainting(com.google.firebase.ai.type.ImagenInlineImage image, com.google.firebase.ai.type.Dimensions newDimensions);
710728
method public java.util.List<com.google.firebase.ai.type.ImagenReferenceImage> generateMaskAndPadForOutpainting(com.google.firebase.ai.type.ImagenInlineImage image, com.google.firebase.ai.type.Dimensions newDimensions, com.google.firebase.ai.type.ImagenImagePlacement newPosition = com.google.firebase.ai.type.ImagenImagePlacement.CENTER);
729+
method public java.util.List<com.google.firebase.ai.type.ImagenReferenceImage> generateMaskAndPadForOutpainting(com.google.firebase.ai.type.ImagenInlineImage image, com.google.firebase.ai.type.Dimensions newDimensions, com.google.firebase.ai.type.ImagenImagePlacement newPosition = com.google.firebase.ai.type.ImagenImagePlacement.CENTER, double dilation = 0.01);
711730
}
712731

713732
@com.google.firebase.ai.type.PublicPreviewAPI public final class ImagenPersonFilterLevel {
@@ -776,7 +795,9 @@ package com.google.firebase.ai.type {
776795
ctor public InlineDataPart(byte[] inlineData, String mimeType);
777796
method public byte[] getInlineData();
778797
method public String getMimeType();
798+
method public boolean isThought();
779799
property public final byte[] inlineData;
800+
property public boolean isThought;
780801
property public final String mimeType;
781802
}
782803

@@ -885,6 +906,8 @@ package com.google.firebase.ai.type {
885906
}
886907

887908
public interface Part {
909+
method public boolean isThought();
910+
property public abstract boolean isThought;
888911
}
889912

890913
public final class PartKt {
@@ -1145,6 +1168,8 @@ package com.google.firebase.ai.type {
11451168
public final class TextPart implements com.google.firebase.ai.type.Part {
11461169
ctor public TextPart(String text);
11471170
method public String getText();
1171+
method public boolean isThought();
1172+
property public boolean isThought;
11481173
property public final String text;
11491174
}
11501175

@@ -1154,6 +1179,7 @@ package com.google.firebase.ai.type {
11541179
public static final class ThinkingConfig.Builder {
11551180
ctor public ThinkingConfig.Builder();
11561181
method public com.google.firebase.ai.type.ThinkingConfig build();
1182+
method public com.google.firebase.ai.type.ThinkingConfig.Builder setIncludeThoughts(boolean includeThoughts);
11571183
method public com.google.firebase.ai.type.ThinkingConfig.Builder setThinkingBudget(int thinkingBudget);
11581184
}
11591185

firebase-ai/firebase-ai.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
2121
plugins {
2222
id("firebase-library")
2323
id("kotlin-android")
24+
id("copy-google-services")
2425
alias(libs.plugins.kotlinx.serialization)
2526
}
2627

firebase-ai/gradle.properties

Lines changed: 2 additions & 2 deletions
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.1.0
16-
latestReleasedVersion=17.0.0
15+
version=17.2.0
16+
latestReleasedVersion=17.1.0

firebase-ai/src/androidTest/kotlin/com/google/firebase/ai/AIModels.kt

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ package com.google.firebase.ai
1717

1818
import androidx.test.platform.app.InstrumentationRegistry
1919
import com.google.firebase.FirebaseApp
20-
import com.google.firebase.FirebaseOptions
2120
import com.google.firebase.ai.type.GenerativeBackend
2221

2322
class AIModels {
@@ -48,15 +47,7 @@ class AIModels {
4847

4948
fun setup() {
5049
val context = InstrumentationRegistry.getInstrumentation().context
51-
app =
52-
FirebaseApp.initializeApp(
53-
context,
54-
FirebaseOptions.Builder()
55-
.setApiKey(API_KEY)
56-
.setApplicationId(APP_ID)
57-
.setProjectId(PROJECT_ID)
58-
.build()
59-
)
50+
app = FirebaseApp.initializeApp(context)
6051
flash2Model =
6152
FirebaseAI.getInstance(app!!, GenerativeBackend.vertexAI())
6253
.generativeModel(

firebase-ai/src/androidTest/kotlin/com/google/firebase/ai/ImagenTests.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,13 @@ import com.google.firebase.ai.type.ImagenEditingConfig
2222
import com.google.firebase.ai.type.ImagenRawImage
2323
import com.google.firebase.ai.type.PublicPreviewAPI
2424
import kotlinx.coroutines.runBlocking
25+
import org.junit.Ignore
2526
import org.junit.Test
2627

2728
@OptIn(PublicPreviewAPI::class)
2829
class ImagenTests {
30+
31+
@Ignore("Currently not supported by backend model")
2932
@Test
3033
fun testGenerateAndEditImage() {
3134
val imageGenerationModel = FirebaseAI.getInstance(app()).imagenModel("imagen-3.0-generate-002")

firebase-ai/src/main/kotlin/com/google/firebase/ai/common/APIController.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,9 @@ private suspend fun validateResponse(response: HttpResponse) {
334334
if (message.contains("The prompt could not be submitted")) {
335335
throw PromptBlockedException(message)
336336
}
337+
if (message.contains("genai config not found")) {
338+
throw APINotConfiguredException()
339+
}
337340
getServiceDisabledErrorDetailsOrNull(error)?.let {
338341
val errorMessage =
339342
if (it.metadata?.get("service") == "firebasevertexai.googleapis.com") {

firebase-ai/src/main/kotlin/com/google/firebase/ai/common/Exceptions.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,16 @@ internal constructor(
8989
internal class UnsupportedUserLocationException(cause: Throwable? = null) :
9090
FirebaseCommonAIException("User location is not supported for the API use.", cause)
9191

92+
/**
93+
* The user's project does not have the Gemini Developer API enabled in the Firebase Console.
94+
*
95+
* See the Firebase documentation for the
96+
* [steps](https://firebase.google.com/docs/ai-logic/faq-and-troubleshooting?api=dev#error-genai-config-not-found)
97+
* to enable the Gemini Developer API.
98+
*/
99+
internal class APINotConfiguredException(cause: Throwable? = null) :
100+
FirebaseCommonAIException("Gemini Developer API not enabled in Firebase console.", cause)
101+
92102
/**
93103
* Some form of state occurred that shouldn't have.
94104
*

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ internal constructor(message: String, cause: Throwable? = null) : RuntimeExcepti
6161
ContentBlockedException(cause.message ?: "", cause.cause)
6262
is com.google.firebase.ai.common.QuotaExceededException ->
6363
QuotaExceededException(cause.message ?: "", cause.cause)
64+
is com.google.firebase.ai.common.APINotConfiguredException ->
65+
APINotConfiguredException(cause.cause)
6466
else -> UnknownException(cause.message ?: "", cause)
6567
}
6668
is TimeoutCancellationException ->
@@ -149,6 +151,16 @@ internal constructor(message: String, cause: Throwable? = null) :
149151
public class UnsupportedUserLocationException internal constructor(cause: Throwable? = null) :
150152
FirebaseAIException("User location is not supported for the API use.", cause)
151153

154+
/**
155+
* The user's project does not have the Gemini Developer API enabled in the Firebase Console.
156+
*
157+
* See the Firebase documentation for the
158+
* [steps](https://firebase.google.com/docs/ai-logic/faq-and-troubleshooting?api=dev#error-genai-config-not-found)
159+
* to enable the Gemini Developer API.
160+
*/
161+
public class APINotConfiguredException internal constructor(cause: Throwable? = null) :
162+
FirebaseAIException("Gemini Developer API not enabled in Firebase console.", cause)
163+
152164
/**
153165
* Some form of state occurred that shouldn't have.
154166
*

0 commit comments

Comments
 (0)