Help

Re: Connect Airtable to OpenAI's text-davinci-003 with our new extension!

160 1
cancel
Showing results for 
Search instead for 
Did you mean: 
Lom_Labs
7 - App Architect
7 - App Architect

Want to use ChatGPT in your Airtable? Integrate your Airtable data with OpenAI's powerful text-davinci-003 model using our new Airtable extension! 

GPT Script Extension.gif

Please note that you need to use your own OpenAI key

Our new Airtable extension connects your Airtable data to OpenAI's text-davinci-003, a powerful language model that can generate human-like text, answer questions, and even write code with incredible accuracy and fluency. 

In future versions, we're planning to add even more features, including the ability to choose which OpenAI model to use and the ability to select data from multiple records at once.

Imagine being able to select a column containing multiple submissions of customer feedback and instantly gaining insights and sentiment analysis. Or selecting a view that contains your previous content ideas and asking OpenAI to generate new, relevant ideas for you. Maybe even submitting an image and asking for alt text!

Please also contact us directly if you have any ideas and would want us to build it with this form!

Installation instructions:
1. Click "Extension" at the top right
2. Click "Add Extension"
3. Click the "Scripting" extension
4. Click "Add Extension"
5. Paste the code below in!

Installation.gif

 

const {
    table,
    promptField,
    outputField,
    openaiApiKey,
    maxTokens,
} = input.config({
    title: "Connector to OpenAI API - Using text-davinci-003",
    description: "",
    items: [
        input.config.table("table", {
            label: "Table",
            description: "Where your fields are"
        }),
        input.config.field("promptField", {
            parentTable: "table",
            label: "Prompt Field",
            description: "Text you want a response to"
        }),
        input.config.field("outputField", {
            parentTable: "table",
            label: "Output Field",
            description: ""
        }),
        input.config.text("openaiApiKey", {
            label: "OpenAI API Key",
            description: "Get it from https://platform.openai.com/account/api-keys"
        }),
        input.config.number("maxTokens", {
            label: "Max Tokens",
            description: "Max: 4,097 tokens. A helpful rule of thumb is that one token generally corresponds to ~4 characters of text for common English text. This translates to roughly ¾ of a word (so 100 tokens ~= 75 words)."
        })
    ]
});

if(outputField.type != "singleLineText" && outputField.type != "multilineText"){
    throw "Output field must be a single line text or long text field"
}

const record = await input.recordAsync("Pick a record", table);

const userInput = record?.getCellValueAsString(promptField);

if (!userInput) {
    throw "Error: Prompt is empty"
}

let response;
try {
    response = await getGPTResponse(userInput);
} catch (error) {
    console.error(error);
    throw "Error: Failed to get GPT response"
}

output.markdown(`Received Prompt: **${userInput}**`);
output.markdown(`Response: **${response}**`);

const updates = [{
    id: record?.id,
    fields: {
        [outputField.name]: response
    }
}];

while (updates.length > 0) {
    await table.updateRecordsAsync(updates.slice(0, 50));
    updates.splice(0, 50);
}

async function getGPTResponse(userInput) {
  const prompt = `The following is a conversation with an AI assistant. The assistant is helpful, creative, clever, and very friendly.\n\nUser: ${userInput}\nAI:`;
  const response = await fetch('https://api.openai.com/v1/completions', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${openaiApiKey}`,
    },
    body: JSON.stringify(
      {
          "model": "text-davinci-003",
          "prompt": prompt,
          "max_tokens": maxTokens,
          "temperature": 0
      }
    ),
  });

  if (!response.ok) {
    console.error(getHTTPStatusHelpText(response.status))
    throw new Error(`HTTP error! status: ${response.status} - ${response.statusText}`);
  }

  const responseData = await response.json();
  return responseData.choices[0].text.trim();
}

function getHTTPStatusHelpText(statusCode) {
  switch (statusCode) {
    case 400:
      return "Bad Request: The server cannot understand the request due to invalid syntax.";
    case 401:
      return "Unauthorized: Authentication is required and has failed or has not yet been provided.\n\nPlease double check your API key";
    case 402:
      return "Payment Required: The request cannot be processed until a payment is made.";
    case 403:
      return "Forbidden: The server understood the request, but is refusing to fulfill it.";
    case 404:
      return "Not Found: The requested resource could not be found but may be available in the future.";
    case 429:
      return "Too Many Requests: The user has sent too many requests in a given amount of time.\n\nDo you still have credits in your account?";
    case 500:
      return "Internal Server Error: The server has encountered a situation it doesn't know how to handle.";
    case 502:
      return "Bad Gateway: The server was acting as a gateway or proxy and received an invalid response from the upstream server.";
    case 503:
      return "Service Unavailable: The server is currently unable to handle the request due to a temporary overload or maintenance.";
    default:
      return "Unknown HTTP status code.";
  }
}

 

11 Replies 11

@ARC_Gonza  Have you ever been trying to build an automation like you mentioned?

Yes, I got it!
I leave the code here to insert it as a script in an automation. I hope to be helpful.
Greetings:

 

// Initialization and configuration
let inputConfig = input.config();
let recordId = inputConfig.recordId; // Ensure you pass the record ID from the previous configuration of the automation

let table = base.getTable("YourTableName"); // Replace "YourTableName" with the actual name of your table
let record = await table.selectRecordAsync(recordId);
let userInput = record.getCellValue("PromptFieldName"); // Replace "PromptFieldName" with the actual field name for the prompt

if (userInput) { // Ensures there is a prompt to process
let response = await getOpenAIResponse(userInput);

// Update the response field in the same record
await table.updateRecordAsync(recordId, {
"ResponseFieldName": response // Replace "ResponseFieldName" with the actual field name for the response
});
}
else {
console.error("No prompt provided in the record.");
}

// Function to interact with OpenAI API
async function getOpenAIResponse(promptText) {
const model = "ModelName"; // Replace "ModelName" with the actual model name you intend to use
const apiKey = "YourOpenAIAPIKey"; // Replace "YourOpenAIAPIKey" with your actual OpenAI API key

const response = await fetch("https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${apiKey}`
},
body: JSON.stringify({
"model": model,
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": promptText}
]
}),
});

if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}

const responseData = await response.json();
return responseData.choices[0].message.content.trim();
}