Gemini API: Basic code generation

This notebook demonstrates how to use prompting to perform basic code generation using the Gemini API’s JS SDK. Two use cases are explored: error handling and code generation.

The Gemini API can be a great tool to save you time during the development process. Tasks such as code generation, debugging, or optimization can be done with the assistance of the Gemini model.

Setup

Install the Google GenAI SDK

Install the Google GenAI SDK from npm.

$ npm install @google/genai

Setup your API key

You can create your API key using Google AI Studio with a single click.

Remember to treat your API key like a password. Don’t accidentally save it in a notebook or source file you later commit to GitHub. In this notebook we will be storing the API key in a .env file. You can also set it as an environment variable or use a secret manager.

Here’s how to set it up in a .env file:

$ touch .env
$ echo "GEMINI_API_KEY=<YOUR_API_KEY>" >> .env
Tip

Another option is to set the API key as an environment variable. You can do this in your terminal with the following command:

$ export GEMINI_API_KEY="<YOUR_API_KEY>"

Load the API key

To load the API key from the .env file, we will use the dotenv package. This package loads environment variables from a .env file into process.env.

$ npm install dotenv

Then, we can load the API key in our code:

const dotenv = require("dotenv") as typeof import("dotenv");

dotenv.config({
  path: "../../.env",
});

const GEMINI_API_KEY = process.env.GEMINI_API_KEY ?? "";
if (!GEMINI_API_KEY) {
  throw new Error("GEMINI_API_KEY is not set in the environment variables");
}
console.log("GEMINI_API_KEY is set in the environment variables");
GEMINI_API_KEY is set in the environment variables
Note

In our particular case the .env is is two directories up from the notebook, hence we need to use ../../ to go up two directories. If the .env file is in the same directory as the notebook, you can omit it altogether.

│
├── .env
└── examples
    └── prompting
        └── Basic_Code_Generation.ipynb

Initialize SDK Client

With the new SDK, now you only need to initialize a client with you API key (or OAuth if using Vertex AI). The model is now set in each call.

const google = require("@google/genai") as typeof import("@google/genai");

const ai = new google.GoogleGenAI({ apiKey: GEMINI_API_KEY });

Select a model

Now select the model you want to use in this guide, either by selecting one in the list or writing it down. Keep in mind that some models, like the 2.5 ones are thinking models and thus take slightly more time to respond (cf. thinking notebook for more details and in particular learn how to switch the thiking off).

const tslab = require("tslab") as typeof import("tslab");

const MODEL_ID = "gemini-2.5-flash-preview-05-20";

Examples

Error handling

For code generation, you should prioritize accuracy over creativity. A temperature of 0 ensures that the generated content is deterministic, producing the most sensible output every time.

const ERROR_HANDLING_SYSTEM_PROMPT = `
  Your task is to explain exactly why this error occurred and how to fix it.
`;

const errorPrompt = (message: string) => `
  You've encountered the following error message:

  Error: ${message}
`;
const error_message = `
    1 my_list = [1,2,3]
  ----> 2 print(my_list[3])

  IndexError: list index out of range
`;

const error_response = await ai.models.generateContent({
  model: MODEL_ID,
  contents: errorPrompt(error_message),
  config: {
    temperature: 0,
    systemInstruction: ERROR_HANDLING_SYSTEM_PROMPT,
  },
});
tslab.display.markdown(error_response.text ?? "");

This error, IndexError: list index out of range, is one of the most common errors when working with lists (or other sequence types like strings and tuples) in Python.

Let’s break down exactly why it occurred and how to fix it.

Understanding the Error: IndexError: list index out of range

  1. What is an Index? In Python, elements in a list are stored in a specific order. Each element has a numerical position, called an “index,” which allows you to access it directly.

  2. Zero-Based Indexing: The most crucial concept here is that Python (like many other programming languages) uses zero-based indexing. This means:

    • The first element is at index 0.
    • The second element is at index 1.
    • The third element is at index 2.
    • And so on…
  3. Analyzing Your Code: You have the list: my_list = [1, 2, 3]

    Let’s map the elements to their indices:

    • 1 is at my_list[0]
    • 2 is at my_list[1]
    • 3 is at my_list[2]

    Your code then tries to access print(my_list[3]).

  4. The Problem: Since the list my_list only has three elements, its valid indices are 0, 1, and 2. There is no element at index 3. When you try to access an index that doesn’t exist within the list’s boundaries, Python raises an IndexError because the index is “out of range.”

How to Fix It

The fix depends on what you were trying to achieve:

Scenario 1: You wanted to access the last element

If you intended to get the last element (3 in this case), you have a couple of common ways:

Option A: Using len() (Length of the list) The length of my_list is 3. Since indexing is zero-based, the last element’s index is always len(list) - 1.

my_list = [1, 2, 3]
# The length of my_list is 3.
# The last valid index is 3 - 1 = 2.
print(my_list[len(my_list) - 1])
# Output: 3

Option B: Using Negative Indexing (Recommended for last element) Python allows you to use negative indices to count from the end of the list: * -1 refers to the last element. * -2 refers to the second-to-last element. * And so on…

my_list = [1, 2, 3]
print(my_list[-1])
# Output: 3

Scenario 2: You wanted to access a specific existing element

If you simply made a mistake in the index number and wanted to access, say, the first, second, or third element:

my_list = [1, 2, 3]

# To access the first element (which is 1):
print(my_list[0])
# Output: 1

# To access the second element (which is 2):
print(my_list[1])
# Output: 2

# To access the third element (which is 3):
print(my_list[2])
# Output: 3

Scenario 3: You’re iterating or accessing elements dynamically

If you’re working with lists whose size might change, or you’re looping, it’s good practice to check if an index is valid before trying to access it:

my_list = [1, 2, 3]
index_to_access = 3 # This would cause the error

if index_to_access < len(my_list):
    print(my_list[index_to_access])
else:
    print(f"Error: Index {index_to_access} is out of range for a list of size {len(my_list)}")

# Output: Error: Index 3 is out of range for a list of size 3

Best Practices to Avoid This Error

  1. Always Remember Zero-Based Indexing: This is fundamental.
  2. Use len() for Bounds Checking: When you need to know the size or iterate up to the last element, len(my_list) is your friend.
  3. Prefer Negative Indexing for End Elements: my_list[-1] is much cleaner than my_list[len(my_list) - 1].
  4. Iterate Safely:
    • If you just need the items: for item in my_list:
    • If you need items and their indices: for index, item in enumerate(my_list): These methods automatically handle the bounds for you.
  5. Error Handling (Advanced): For robust applications, you can use try-except blocks to gracefully handle IndexError if you anticipate it might occur due to external input or unpredictable data.
my_list = [1, 2, 3]
user_input_index = 5 # Imagine this came from user input

try:
    print(my_list[user_input_index])
except IndexError:
    print(f"Sorry, the index {user_input_index} is not valid for this list. Valid indices are 0 to {len(my_list) - 1}.")
# Output: Sorry, the index 5 is not valid for this list. Valid indices are 0 to 2.

Code generation

const CODE_GENERATION_SYSTEM_PROMPT = `
  You are a coding assistant. Your task is to generate a code snippet that
  accomplishes a specific goal. The code snippet must be concise, efficient,
  and well-commented for clarity. Consider any constraints or requirements
  provided for the task.

  If the task does not specify a programming language, default to Python.
`;
const code_response = await ai.models.generateContent({
  model: MODEL_ID,
  contents: `
      Create a countdown timer that ticks down every second and prints
      "Time is up!" after 20 seconds

      Language: JavaScript
    `,
  config: {
    temperature: 0,
    systemInstruction: CODE_GENERATION_SYSTEM_PROMPT,
  },
});
tslab.display.markdown(code_response.text ?? "");
/**
 * Creates a countdown timer that ticks down every second.
 * Prints the remaining time and "Time is up!" when it reaches zero.
 */
function startCountdown() {
  let seconds = 20; // Initial countdown time in seconds

  // Display initial time immediately
  console.log(`Time remaining: ${seconds} seconds`);

  // Set up an interval to run every 1000 milliseconds (1 second)
  const timerInterval = setInterval(() => {
    seconds--; // Decrement the time

    if (seconds > 0) {
      // If time is still remaining, print it
      console.log(`Time remaining: ${seconds} seconds`);
    } else {
      // If time is up, print the final message and clear the interval
      console.log("Time is up!");
      clearInterval(timerInterval); // Stop the timer
    }
  }, 1000); // 1000 milliseconds = 1 second
}

// Start the countdown when the script runs
startCountdown();
const matchFound = /```javascript\n([\s\S]*?)```/.exec(code_response.text ?? "");
if (matchFound) {
  const code = matchFound[1];
  // eslint-disable-next-line no-eval
  eval(code);
} else {
  console.error("No JavaScript code found in the response");
}
Time remaining: 20 seconds
Time remaining: 19 seconds
Time remaining: 18 seconds
Time remaining: 17 seconds
Time remaining: 16 seconds
Time remaining: 15 seconds
Time remaining: 14 seconds
Time remaining: 13 seconds
Time remaining: 12 seconds
Time remaining: 11 seconds
Time remaining: 10 seconds
Time remaining: 9 seconds
Time remaining: 8 seconds
Time remaining: 7 seconds
Time remaining: 6 seconds
Time remaining: 5 seconds
Time remaining: 4 seconds
Time remaining: 3 seconds
Time remaining: 2 seconds
Time remaining: 1 seconds
Time is up!

Next steps

Be sure to explore other examples of prompting in the repository. Try writing prompts around your own code as well using the examples in this notebook.