Simple Generative AI Tutorial: File Listing and Uploading


Welcome to my guide on harnessing the power of the Generative AI API to seamlessly manage your files for use within in your prompts! In order to use files within your prompts they must first be uploaded so that Gemini can access them. Whether you’re a seasoned developer or just dipping your toes into the world of Node.js and npm, this tutorial is your roadmap to effortlessly navigating file interactions. By the end, you’ll master the art of listing existing files and effortlessly uploading new ones, empowering you to leverage the full potential of Generative AI with confidence. Let’s embark on this transformative journey together!

Objectives

  • Set up your environment.
  • Install the client library.
  • Set up the sample.
  • Run the sample.

Prerequisites

To run this quick start, you need the following prerequisites:

  • Node.js & npm installed.
  • A Gemini API key

Set up your environment

Create an api key

Install the SDK package

npm install @google/generative-ai

Initialize the Generative Service:

In this section we examine the core elements of our file interaction system. Here’s a concise overview:

Library Imports: We start by importing crucial libraries like googleapis, fs, mime-types, path, and dotenv. These tools are essential for efficient API interaction, file system management, file type determination, path handling, and environment variable handling, respectively.

API Key Retrieval: We demonstrate how to securely retrieve the API key from environment variables, ensuring smooth integration with the API.

Creating the Service Function: We define the createService function, which plays a central role in our system. This function constructs the discovery URL, utilizes google.discoverAPI to dynamically fetch API information, and creates a service object for seamless API interaction.

Error Handling: We cover error handling techniques to gracefully manage any potential issues encountered during the discovery process, ensuring the stability and reliability of our application.

This section provides a foundational understanding of the key c

const { google } = require('googleapis');
const fs = require('fs');
const mime = require('mime-types');
const path = require('path');
require('dotenv').config();
const API_KEY = process.env.API_KEY; // Get the api key from env
async function createService(apiKey) {
  const discoveryUrl = `https://generativelanguage.googleapis.com/$discovery/rest?version=v1beta&key=${apiKey}`;
  try {
    const service = google.discoverAPI(discoveryUrl, { auth : apiKey});
    return service;
  } catch (error) {
    console.error('Error fetching discovery document:', error);
    throw error;
  }
}

List Files:

This segment introduces the listFiles function, which is pivotal in our file interaction system. Here’s a breakdown of its functionality:

We define the listFiles function, designed to efficiently handle file listing operations. This function accepts the service object as its input parameter, facilitating seamless integration with the Generative AI API.

We can then use the service.files.list method, our function initiates the retrieval process for a comprehensive list of files. Notably, we set a practical limit of 100 files per page to ensure optimal performance and resource management.

Once we have the data returned by the api we can then return it back to our calling function, ready for further processing or presentation.

By meticulously executing these steps, the listFiles function allows you to retrieve and manage file data, within your applications.


/**
 * Function to list all files using the Google Drive API.
 * @param {object} service - The authenticated Google Drive API service.
 */
async function listFiles(service) {
    // Retrieve a list of files from Google Drive
    const res = await service.files.list({
        pageSize: 100,
    });

    // Extract the files from the response
    return res.data.files;
}

Test List Files:

Now lets look at the process of listing files and logging relevant information. Here’s a concise overview:

By invoking the createService function, which sets up the service required for file interaction. Then using the initialized service, we call upon the listFiles function to retrieve the desired list of files.

Its a good idea to verify if any files were retrieved from the list. In the event of an empty list, a message is thoughtfully logged to signify the absence of files, ensuring clarity in the execution flow.

With the list of files at our disposal, we loop though each file, logging important information about the file. This includes the system name, display name, URL, and MIME type, providing us with the info we need to know about the file.

This method gives us a framework for efficiently listing files and extracting essential information, thereby facilitating informed decision-making and streamlined file management processes.


// list files usage
createService(API_KEY)
    .then(async service => {
        // You can use the service object here
        const files = await listFiles(service);
        // Check if there are no files
        if (!files || files.length === 0) {
            console.log('No files found.');
            return;
        }
        // Log information for each file
        console.log('Files:');
        files.map(async (file) => {
            console.log(`System Name: ${file.name} Display name: ${file.displayName} URL: ${file['uri']} MimeType: ${file['mimeType']}`);
        });

    })
    .catch(error => {
      console.error('Error creating service:', error);
    });

Upload Files:

Lets look at the process of uploading files. Here’s a structured breakdown:

The uploadFile function, a cornerstone in our file uploading process. This function was created with the intent to handle the uploading of files, requiring essential inputs such as the service object, file path, and display name.

Prior to proceeding with the upload, a check is conducted to verify the existence of the specified file. If the file is not found, an error message is promptly returned, ensuring data integrity and smooth execution flow.

Using the ‘mime-types’ library, the function determines the MIME type of the file, which is required for uploading the file data.

With file existence confirmed and MIME type identified, the function proceeds to construct the request body, containing the metadata such as the display name.

The function then prepares the media object, encapsulating the file’s MIME type and path in readiness for the upload process.

Finally we can then call the service.media.upload method, initiating the file upload process. With prepared metadata and media, the file is seamlessly uploaded to its designated destination.

Upon successful upload, the function returns the uploaded file object, ensuring developers have access to crucial information regarding the uploaded file. Alternatively, in the event of failure, an informative error message is returned, facilitating swift troubleshooting and resolution.

By following these steps, the “Upload Files” section allows you to integrate file uploading functionality into your applications, ensuring robust performance and data integrity throughout the process.

/**
 * Uploads a file to the GenAI File API.
 * @param {Object} service - The authenticated Google API service object.
 * @param {string} filePath - The path to the file to be uploaded.
 * @param {string} fileDisplayName - The display name of the file.
 * @returns {Object} - The uploaded file object.
 */
async function uploadFile(service, filePath, fileDisplayName) {
    try {
        // Check if the file exists
        if (!fs.existsSync(filePath)) {
            console.log(`File '${filePath}' does not exist`);
            return { error: `File '${filePath}' does not exist` };
        }

        // Determine the MIME type of the file
        const mimeType = mime.lookup(filePath) || 'application/octet-stream';

        // Prepare the metadata for the file
        const body = {
            file: {
                displayName: fileDisplayName
            }
        };

        // Prepare the media object for uploading
        const media = {
            mimeType: mimeType,
            body: filePath
        };

        // Upload the file
        const createFileResponse = await service.media.upload({
            media: media,
            requestBody: body
        });

        // Return the uploaded file object
        return createFileResponse.data.file;
    } catch (error) {
        console.error('Error uploading file:', error.message);
        return { error: 'Error uploading file' };
    }
}

Test Upload Files:

Lets test the upload method. Here’s a structured breakdown:

Similar to the process of testing list files, this segment begins by initializing the service and promptly calling the uploadFile function. Essential parameters such as the file path and display name are provided to facilitate the upload process seamlessly.

Following the upload operation, pertinent information about the successfully uploaded file is diligently logged. This ensures developers are informed of the upload status, facilitating transparency and aiding in tracking file upload activities.

By following these steps outlined, you can seamlessly integrate file uploading functionality into your applications, ensuring efficient handling of file data.

// upload file usage
createService(API_KEY)
    .then(async service => {
        // You can use the service object here
        const file = await uploadFile(service,'test_data/test.txt','test.txt',);
        console.log(`File Uploaded: System Name: ${file.name} Display name: ${file.displayName} URL: ${file['uri']} MimeType: ${file['mimeType']}`);
    })
    .catch(error => {
        console.error('Error creating service:', error);
    });

Conclusion

This tutorial equipped you with the knowledge and tools to interact with files using the Generative AI API. You learned how to set up your environment, install the necessary libraries, and utilize the API to list existing files and upload new ones.

By mastering these techniques, you open doors to various possibilities within the Generative AI ecosystem. You can now seamlessly use files within your prompts.

Remember, this is just the beginning of your journey. As you explore the Generative AI API further, you’ll discover even more ways to incorporate file management into your projects and unlock the full potential of AI-powered applications.


About Linda Lawton

My name is Linda Lawton I have more than 20 years experience working as an application developer and a database expert. I have also been working with Google APIs since 2012 and I have been contributing to the Google .Net client library since 2013. In 2013 I became a a Google Developer Experts for Google Analytics.

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.