Skip to content

Feat/ai samples multimodal - #1073

Draft
sedanah-m wants to merge 9 commits into
feat/ai-samplesfrom
feat/ai-samples-multimodal
Draft

Feat/ai samples multimodal#1073
sedanah-m wants to merge 9 commits into
feat/ai-samplesfrom
feat/ai-samples-multimodal

Conversation

@sedanah-m

@sedanah-m sedanah-m commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

-Multimodal sample:The user should be able to upload a pdf file/image and enter a prompt to receive a response in plain text.

@sedanah-m
sedanah-m changed the base branch from master to feat/ai-samples July 21, 2026 22:42

@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 introduces a new set of Firebase AI samples demonstrating capabilities like text generation, multi-turn chat, and multimodal input. Key feedback focuses on fixing critical issues, including replacing the non-existent model name 'gemini-3.5-flash' with 'gemini-1.5-flash' across multiple services, and resolving a security vulnerability where the App Check debug token was hardcoded to true. Additionally, recommendations were made to uncomment and correctly export the local Firebase configuration, use ReCaptchaV3Provider to align with the documentation, improve type safety in file parsing, and wrap React handlers in useCallback to satisfy hook dependency rules.

I am having trouble creating individual review comments. Click here to see my feedback.

ai/ai-samples/src/config/firebase-config.ts (1-7)

high

Uncomment and export the firebaseConfig object so that it can be imported and used by firebaseAIService.ts. This aligns the code with the setup instructions in the README.

export const firebaseConfig = {
  apiKey: "YOUR_API_KEY",
  authDomain: "YOUR_AUTH_DOMAIN",
  projectId: "YOUR_PROJECT_ID",
  storageBucket: "YOUR_STORAGE_BUCKET",
  messagingSenderId: "YOUR_MESSAGING_SENDER_ID",
  appId: "YOUR_APP_ID"
};

ai/ai-samples/src/services/firebaseAIService.ts (1-4)

high

Import ReCaptchaV3Provider instead of ReCaptchaEnterpriseProvider to match the README instructions (which specify reCAPTCHA v3). Also, import firebaseConfig from the configuration file to support local configuration.

import { initializeApp } from 'firebase/app';
import { getAI, getGenerativeModel } from 'firebase/ai';
import { initializeAppCheck, ReCaptchaV3Provider } from 'firebase/app-check';
import { firebaseConfig as localConfig } from '../config/firebase-config';

ai/ai-samples/src/services/firebaseAIService.ts (6-15)

high

Use the imported localConfig as the fallback when VITE_FIREBASE_CONFIG is not set. This ensures that the configuration changes made by users in src/config/firebase-config.ts (as instructed by the README) are actually used by the application.

const firebaseConfig = import.meta.env.VITE_FIREBASE_CONFIG 
  ? JSON.parse(import.meta.env.VITE_FIREBASE_CONFIG) 
  : localConfig;

ai/ai-samples/src/services/firebaseAIService.ts (19-30)

security-high high

Only enable the App Check debug token if VITE_APPCHECK_DEBUG_TOKEN is explicitly set to 'true' in the environment. Hardcoding it to true exposes production environments to App Check bypasses. Also, use ReCaptchaV3Provider to match the README instructions.

// initialize app check with debug token 
if (typeof window !== 'undefined') {
  if (import.meta.env.VITE_APPCHECK_DEBUG_TOKEN === 'true') {
    (window as any).FIREBASE_APPCHECK_DEBUG_TOKEN = true;
  }

  initializeAppCheck(app, {
  // The string here doesn't matter in this specific case, as setting 
  // FIREBASE_APPCHECK_DEBUG_TOKEN above means it will be ignored. 
  // However, in production, this MUST be a valid reCAPTCHA site key.
    provider: new ReCaptchaV3Provider('YOUR_RECAPTCHA_SITE_KEY'),
    isTokenAutoRefreshEnabled: true
  });
}

ai/ai-samples/src/services/firebaseAIService.ts (34)

high

The model name 'gemini-3.5-flash' does not exist. Change the default model to 'gemini-1.5-flash' to prevent API errors when running the samples.

export const getAiModel = (modelName: string = 'gemini-1.5-flash', additionalConfig: Record<string, any> = {}) => {

ai/ai-samples/src/features/chat/service.ts (11)

high

Change the model name from 'gemini-3.5-flash' to 'gemini-1.5-flash' as 'gemini-3.5-flash' is not a valid model name and will cause API errors.

  const model = getAiModel('gemini-1.5-flash');

ai/ai-samples/src/features/multimodal/service.ts (41)

high

Change the model name from 'gemini-3.5-flash' to 'gemini-1.5-flash' as 'gemini-3.5-flash' is not a valid model name and will cause API errors.

        const model = getAiModel('gemini-1.5-flash');

ai/ai-samples/src/features/text-generation/service.ts (10)

high

Change the model name from 'gemini-3.5-flash' to 'gemini-1.5-flash' as 'gemini-3.5-flash' is not a valid model name and will cause API errors.

    const model = getAiModel('gemini-1.5-flash');

ai/ai-samples/src/features/text-generation/service.ts (27)

high

Change the model name from 'gemini-3.5-flash' to 'gemini-1.5-flash' as 'gemini-3.5-flash' is not a valid model name and will cause API errors.

    const model = getAiModel('gemini-1.5-flash');

ai/ai-samples/src/features/text-generation/service.ts (50)

high

Change the model name from 'gemini-3.5-flash' to 'gemini-1.5-flash' as 'gemini-3.5-flash' is not a valid model name and will cause API errors.

    const model = getAiModel('gemini-1.5-flash', { systemInstruction });

ai/ai-samples/src/features/multimodal/service.ts (10-30)

medium

Improve type safety and error handling in fileToGenerativePart. Checking if reader.result is a string and safely splitting it prevents potential runtime TypeErrors if the file reading fails or returns unexpected results.

export async function fileToGenerativePart(file: File): Promise<Part> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();

    reader.onloadend = () => {
      const result = reader.result;
      if (typeof result === 'string') {
        const splitResult = result.split(',');
        if (splitResult.length > 1) {
          resolve({
            inlineData: {
              data: splitResult[1],
              mimeType: file.type
            }
          });
          return;
        }
      }
      reject(new Error('Failed to parse file data as Base64.'));
    };

    reader.onerror = () => reject(reader.error || new Error('Error reading file.'));

    // Trigger the file read
    reader.readAsDataURL(file);
  });
}

ai/ai-samples/src/features/chat/index.tsx (1)

medium

Import useCallback from 'react' to wrap the handleResetChat function and avoid React hook dependency warnings/unnecessary recreations.

import React, { useState, useRef, useEffect, useCallback } from 'react';

ai/ai-samples/src/features/chat/index.tsx (21-34)

medium

Wrap handleResetChat in useCallback and add it to the dependency array of useEffect. This prevents the function from being recreated on every render and satisfies the React hooks dependency rules.

  const handleResetChat = useCallback(() => {
    try {
      chatSessionRef.current = startNewChat();
      setError(null);
    } catch (err: any) { 
      setError(err.message || 'Failed to initialize chat session. Please check your Firebase configuration.');
    }
    setMessages([]);
    setInput('');
  }, []);

  // Initialize the chat when the component mounts
  useEffect(() => {
    handleResetChat();
  }, [handleResetChat]);

Comment thread ai/ai-samples/src/features/multimodal/index.tsx Outdated
Comment thread ai/ai-samples/src/features/multimodal/index.tsx Outdated
Comment thread ai/ai-samples/src/features/multimodal/index.tsx Outdated
Comment thread ai/ai-samples/src/features/multimodal/service.ts Outdated
Comment thread ai/ai-samples/src/features/multimodal/service.ts Outdated
Comment thread ai/ai-samples/src/features/multimodal/index.tsx Outdated
Comment thread ai/ai-samples/src/features/multimodal/index.tsx Outdated
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.

2 participants