Build with AI

How do you call the GPT-3 API from a spreadsheet?

· By Robert Scales · 3 min read

Short answer

In Google Sheets you can write a small custom function in Apps Script that sends a cell's text to the OpenAI API and returns GPT-3's reply into the cell. With an API key, about twenty lines of code and a spending limit set in your OpenAI account, a column of product notes can become a column of draft descriptions.

A spreadsheet is a natural home for GPT-3 experiments. Many small businesses already keep their product lists, email subjects or survey answers in rows, and the jobs they want help with are row-shaped too: write a description for each product, tag each comment, shorten each title. Instead of copying text back and forth to the Playground, you can call the model straight from a formula.

Google Sheets makes this possible through Apps Script, a JavaScript-based language built into Google's apps. You write a function once, and then use it in any cell, just as you would use SUM or VLOOKUP.

What you need before you start

  • An OpenAI API key. It is the secret string, starting with sk-, shown on your account's API keys page at beta.openai.com. Treat it like a password.
  • A Google Sheet with some input text, for example product notes in column A.
  • A model choice. text-davinci-002 gives the best results; Curie is much cheaper and handles many simpler tasks.

The custom function, step by step

Open your sheet and choose Extensions > Apps Script. First, store your key so it is not typed into the formula itself. Paste this function, put your key between the quotes, run it once with the Run button, then delete the key from the code:

function saveKey() {
  PropertiesService.getScriptProperties().setProperty('OPENAI_API_KEY', 'sk-...');
}

Now add the function that does the work:

/**
 * Drafts a short product description with GPT-3.
 * @param {string} notes Notes about the product.
 * @customfunction
 */
function DESCRIBE(notes) {
  if (!notes) return '';
  var key = PropertiesService.getScriptProperties().getProperty('OPENAI_API_KEY');
  var prompt = 'Write a two-sentence product description for an online shop. ' +
    'Be concrete and friendly. Do not invent features.\n\nProduct notes: ' + notes + '\n\nDescription:';
  var response = UrlFetchApp.fetch(
    'https://api.openai.com/v1/engines/text-davinci-002/completions', {
      method: 'post',
      contentType: 'application/json',
      headers: { Authorization: 'Bearer ' + key },
      payload: JSON.stringify({ prompt: prompt, max_tokens: 80, temperature: 0.7 })
    });
  var data = JSON.parse(response.getContentText());
  return data.choices[0].text.trim();
}

Save, return to the sheet, and type =DESCRIBE(A2) in cell B2. A moment later, a draft description appears.

Here is what each part does:

PieceJob
@customfunctionMakes DESCRIBE appear in the sheet's formula suggestions
UrlFetchApp.fetchSends the request over the web; custom functions are allowed to use it
The URLOpenAI's completions endpoint for the chosen engine, the same address the official Python library uses
Authorization: BearerProves the request comes from your account
max_tokens: 80Caps the length of each reply, and therefore its cost
choices[0].textThe text GPT-3 wrote

Two limits are worth knowing. Google stops any custom function that takes longer than 30 seconds, which a short completion rarely does. And a custom function cannot ask for extra permissions, so it is restricted to services such as URL Fetch that do not touch your personal data.

If the cell shows an error instead of text, check three things in order: that saveKey ran successfully, that the engine name in the URL is spelled exactly, and that your account still has credit or quota left. Hovering over the error cell usually shows the start of the reply OpenAI sent back, which tends to name the problem in plain words.

Try it: Put notes for five real or invented products in column A, run =DESCRIBE(A2) down column B, and read the drafts. Then add one sentence about your shop's tone to the prompt and compare the second batch with the first.

How do you avoid surprise costs?

Start by knowing the price. OpenAI charges per 1,000 tokens, counting both the prompt you send and the text it returns; 1,000 tokens is about 750 words. Davinci costs $0.06 per 1,000 tokens and Curie $0.006. The prompt above plus a product note runs to roughly 60 tokens, and the reply is capped at 80, so each cell uses at most about 140 tokens: under one cent with Davinci. A sheet of 500 products would cost a few dollars. New accounts also get $18 of free credit for their first three months.

Then set a ceiling. In your OpenAI billing settings you can set a hard limit, after which the API stops answering, and a soft limit that emails you when spending passes a threshold. Set both before you share the sheet with anyone. Playground use counts toward the same total.

A few spreadsheet habits keep the bill predictable:

  • Test on five rows before filling a column of thousands.
  • Freeze results you like. A custom function runs again when its input cell or the formula changes. Copy finished descriptions and use Paste special > Values only, so later edits don't trigger new paid calls.
  • Keep max_tokens low and the prompt short; both are billed.
  • Try Curie first for simple jobs. OpenAI says it can do many Davinci tasks at a tenth of the cost.
  • Mind who can edit. Anyone with edit access to the sheet can open its script, so share the file carefully and never paste the key into a cell.

Sources

  1. Custom Functions in Google Sheets — Google for Developers
  2. OpenAI Python library (README and source, commit of 14 April 2022) — OpenAI (GitHub), April 14, 2022
  3. Pricing (OpenAI API) — OpenAI, April 5, 2022

Get the free Guide to Artificial Intelligence

Sign up for the weekly newsletter and receive the free guide: what changed in AI this week, one lesson, one prompt to try. Unsubscribe in one click.

How we handle your address

Back to top

Display

Your choices are saved in this browser only. No data is sent.

Text size
100%
Colours
Reading
More settings
Accessibility statement