Skip to content

feat(firebase-ai-logic-basics): add image generation and on-device hybrid inference guides - #214

Open
AustinBenoit wants to merge 1 commit into
ai-logic/4-structured-and-toolsfrom
ai-logic/5-image-and-hybrid
Open

AustinBenoit wants to merge 1 commit into
ai-logic/4-structured-and-toolsfrom
ai-logic/5-image-and-hybrid

Conversation

@AustinBenoit

@AustinBenoit AustinBenoit commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

Summary (Stack 4/5)

Extracts the remaining Web-only usage sections from web_setup.md into dedicated capability guides (image_generation.md and on_device_hybrid.md), completing the SKILL.md routing table and trimming web_setup.md to its final setup-only state.

Changes

  • Adds image_generation.md (Nano Banana responseModalities: [TEXT, IMAGE] across all 4 platforms; Imagen deprecation notice).
  • Adds on_device_hybrid.md (Web Chrome mode: InferenceMode.PREFER_ON_DEVICE + inCloudParams / onDeviceParams + mobile platform stubs).
  • Finalizes web_setup.md and SKILL.md.

@AustinBenoit
AustinBenoit added this pull request to stack #216 October 9, 2026 14:39

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request reorganizes the Firebase AI Logic documentation by extracting web-only patterns into dedicated capability guides for "Image Generation (Nano Banana)" and "On-Device Hybrid Inference (Web)", updating the capability table in SKILL.md and cleaning up web_setup.md. The review feedback identifies critical improvements for the code examples in the new guides, specifically recommending the use of safe calls in Kotlin to prevent runtime crashes when handling empty or blocked model responses, and adding an error handler to the JavaScript FileReader promise to avoid hanging indefinitely on file read failures.

Comment on lines +83 to +85
val generatedImageAsBitmap: Bitmap? = model.generateContent(prompt)
// Handle the generated image
.candidates.first().content.parts.filterIsInstance<ImagePart>().firstOrNull()?.image

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

In Kotlin, candidates can be empty, and content within a Candidate can be null (for example, if the response was blocked by safety filters). Calling .first() on an empty list throws a NoSuchElementException, and accessing .content directly can lead to a NullPointerException or compilation error.

Using safe calls (firstOrNull() and ?.) is highly recommended to prevent crashes.

Suggested change
val generatedImageAsBitmap: Bitmap? = model.generateContent(prompt)
// Handle the generated image
.candidates.first().content.parts.filterIsInstance<ImagePart>().firstOrNull()?.image
val generatedImageAsBitmap: Bitmap? = model.generateContent(prompt)
// Handle the generated image
.candidates.firstOrNull()?.content?.parts?.filterIsInstance<ImagePart>()?.firstOrNull()?.image

Comment on lines +107 to +109
val generatedImageAsBitmap = model.generateContent(prompt)
// Handle the generated image
.candidates.first().content.parts.filterIsInstance<ImagePart>().firstOrNull()?.image

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similarly to the generation example above, candidates can be empty and content can be null if the model's response is blocked or fails. Use safe navigation to avoid potential runtime exceptions.

Suggested change
val generatedImageAsBitmap = model.generateContent(prompt)
// Handle the generated image
.candidates.first().content.parts.filterIsInstance<ImagePart>().firstOrNull()?.image
val generatedImageAsBitmap = model.generateContent(prompt)
// Handle the generated image
.candidates.firstOrNull()?.content?.parts?.filterIsInstance<ImagePart>()?.firstOrNull()?.image

Comment on lines +275 to +285
async function fileToGenerativePart(file) {
const base64EncodedDataPromise = new Promise((resolve) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result.split(',')[1]);
reader.readAsDataURL(file);
});
return {
type: "inlineData",
inlineData: { data: await base64EncodedDataPromise, mimeType: file.type },
};
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

In the fileToGenerativePart helper function, the FileReader promise does not handle the onerror event. If reading the file fails (e.g., due to permission issues or file corruption), the promise will remain pending indefinitely, which can hang the application flow. Adding an onerror handler to reject the promise ensures robust error handling.

Suggested change
async function fileToGenerativePart(file) {
const base64EncodedDataPromise = new Promise((resolve) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result.split(',')[1]);
reader.readAsDataURL(file);
});
return {
type: "inlineData",
inlineData: { data: await base64EncodedDataPromise, mimeType: file.type },
};
}
async function fileToGenerativePart(file) {
const base64EncodedDataPromise = new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result.split(',')[1]);
reader.onerror = reject;
reader.readAsDataURL(file);
});
return {
type: "inlineData",
inlineData: { data: await base64EncodedDataPromise, mimeType: file.type },
};
}

@AustinBenoit
AustinBenoit removed this pull request from stack #216 October 9, 2026 14:48
@AustinBenoit
AustinBenoit force-pushed the ai-logic/5-image-and-hybrid branch from 90d3c93 to f77234d Compare October 9, 2026 14:48
@AustinBenoit
AustinBenoit added this pull request to stack #218 October 9, 2026 14:48
@AustinBenoit
AustinBenoit force-pushed the ai-logic/5-image-and-hybrid branch 2 times, most recently from 1c00c95 to 45b041e Compare October 9, 2026 15:49
@AustinBenoit
AustinBenoit force-pushed the ai-logic/5-image-and-hybrid branch from 45b041e to 9ad4c50 Compare October 9, 2026 16:13
…brid inference guides

### Summary (Stack 5/6)
Extracts the remaining Web-only usage sections from `web_setup.md` into dedicated capability guides (`image_generation.md` and `on_device_hybrid.md`), completing the `SKILL.md` routing table and trimming `web_setup.md` to its final setup-only state.

### Changes
- Adds `image_generation.md` (Nano Banana `responseModalities: [TEXT, IMAGE]` across all 4 platforms; Imagen deprecation notice).
- Adds `on_device_hybrid.md` (Web Chrome `mode: InferenceMode.PREFER_ON_DEVICE` + `inCloudParams` / `onDeviceParams` + mobile platform stubs).
- Finalizes `web_setup.md` and `SKILL.md`.
@AustinBenoit
AustinBenoit force-pushed the ai-logic/5-image-and-hybrid branch from 9ad4c50 to 8212b72 Compare October 9, 2026 16:51
@AustinBenoit
AustinBenoit removed this pull request from stack #218 October 9, 2026 16:53
@AustinBenoit
AustinBenoit added this pull request to stack #223 October 9, 2026 16:53

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant