Original article: How to Integrate ChatGPT with Google Sheets Using Google Apps Script

Bienvenido a este tutorial sobre cómo integrar ChatGPT con Google Spreadsheets usando la API de GPT y Google Apps Script.

Crearemos dos fórmulas personalizadas, GPT_SUMMARY y GPT_SIMPLIFY. Puedes usar GPT_SUMMARY para resumir un pasaje grande o un texto en viñetas para una fácil lectura. Y puedes usar GPT_SIMPLIFY para simplificar el Inglés (o Español) que sea fácil de leer.

También crearemos menús con acceso a funciones que realizan las mismas tareas que las fórmulas. Luego discutiremos los pros y contras de usar fórmulas versus menús.

Al final de este tutorial, entenderás cómo usar ChatGPT en Google Sheets con Google Apps Script. También serás capaz de modificar las fórmulas y menús para conseguir según tus propias necesidades, tales como crear CVs, publicaciones de redes sociales, o cartas de presentación.

Puedes encontrar el código fuente de este proyecto en este repo en Github.

Si quieres seguirlo con una versión en vídeo de este artículo, aquí lo tienes:

Pre-requisitos

Este tutorial no es para principiantes en Apps Script o JavaScript. No estaré explicando cada método o clase usada en el código. Esto tampoco es un tutorial sobre cómo usar y optimizar ChatGPT – sino que nos enfocaremos en cómo integrar ChatGPT en Google Sheets.

¿Para quién es este tutorial?

Este tutorial es para usuarios intermedios a avanzados quienes tienen un entendimiento básico de Apps Script y JavaScript. Si eres nuevo a cualquiera de estos lenguajes, te recomiendo que comiences con un tutorial de principiantes antes de intentar este tutorial.

Paso 1 – Obtén la clave de la API de ChatGPT

Get ChatGpt API Keys
Obtén la clave de la API de ChatGpt

Primero, si todavía no tienes una cuenta en OpenAI, necesitarás crear una. Una vez que tengas una cuenta, puedes crear un nueva clave API yendo a la sección de claves API en la pestaña User (Usuario).

Haz clic en el botón Crear nueva clave secreta y copia la clave después que haya sido creado. No serás capaz de ver esta clave API nuevamente, así que asegúrate de copiarlo a un lugar seguro.

Paso 2 – Obtén los datos de la API de ChatGpt con Apps Script

8586ac7a-9b41-41ef-9dcd-c4297436912d
Muestra de una Hoja de Cálculo

Le puse el nombre GPT_Integration a mi hoja de cálculo con tres columnas: Passage (Pasaje), Simplified Passage (Pasaje Simplificado), y Summarized Text (Texto Resumido).

How to Open Apps Script Code Editor From Spreadsheet

Abramos el app script para ésta hoja de cálculo, renómbralo a GPT_Integration, y también renombra el archivo existente a utils.gs. Crearemos una función llamada fetchData allí.

const CHAT_GPT_API_KEY = "pega tu clave API aquí"
const BASE_URL = "https://api.openai.com/v1/chat/completions";


function fetchData(systemContent, userContent) {
  try {
    const headers = {
      "Content-Type": "application/json",
      "Authorization": `Bearer ${CHAT_GPT_API_KEY}`
    };

    const options = {
      headers,
      method: "GET",
      muteHttpExceptions: true,
      payload: JSON.stringify({
        "model": "gpt-3.5-turbo",
        "messages": [{
          "role": "system",
          "content": systemContent,
        },
        {
          "role": "user",
          "content": userContent
        },
        ],
        "temperature": 0.7
      })
    };

    const response = JSON.parse(UrlFetchApp.fetch(BASE_URL, options));
    //console.log(response);
    //console.log(response.choices[0].message.content)
    return response.choices[0].message.content;
  } catch (e) {
    console.log(e)
    SpreadsheetApp.getActiveSpreadsheet().toast("Ocurrió algún error. Por favor verifica tu fórmula o intenta nuevamente más tarde.");
    return "Ocurrió algún error. Por favor verifica tu fórmula o intenta nuevamente más tarde.";
  }
}

Aquí hay algunos puntos claves a observar en el código de arriba:

  1. Pega la clave API que creaste anteriormente dentro de las comillas.
  2. Estaremos usando la API de Chat Completions. Puedes encontrar más detalles aquí.
  3. Los modelos de ChatGPT tienen diferentes roles, tales como sistema, usuario, y asistente.
  4. El parámetro systemContent es donde provees un juego de roles para el sistema de GPT. Por ejemplo, podrías decir: "Eres un profesor experto en álgebra" o "Eres un escritor experto en CV".
  5. El parámetro userContent es donde provees tareas a realizar para el modelo. En nuestro caso, proveeremos pasajes largos desde la hoja de cálculo para resumir y simplificar.
  6. Estaremos usando el modelo turbo GPT 3.5.
  7. Estamos silenciando las HTTPExceptions así podemos usar nuestro propio mensaje de error en el bloque catch.
  8. La cadena de error es útil cuando afrontamos errores tales como Rate Limit Exceed.

Estamos devolviendo el contenido del objeto response de GPT que luego será manejado por nuestras fórmulas.

El objeto response de ChatGPT tiene la siguiente estructura:

{
  "id": "chatcmpl-123",
  "object": "chat.completion",
  "created": 1677652288,
  "choices": [{
    "index": 0,
    "message": {
      "role": "assistant",
      "content": "\n\nHola! ¿en qué te puedo ayudar hoy?",
    },
    "finish_reason": "stop"
  }],
  "usage": {
    "prompt_tokens": 9,
    "completion_tokens": 12,
    "total_tokens": 21
  }
}

Lee más sobre cómo usar la URLFetchApp desde aquí.

Paso 3 – Integrar ChatGpt como una fórmula de sheets

Fórmula GPT SIMPLIFY

Nuevamente, para la fórmula personalizada, crearemos un nuevo archivo llamado formula y luego crearemos una función llamada GPT_SIMPLIFY.

/**
 * Simplifica el párrafo dado en el término de layman.
 * @param {String} input El valor a simplificar.
 * @return Texto Simplificado.
 * @customfunction
 */
function GPT_SIMPLIFY(input) {
  console.log(input)
  const systemContent = "Simplificar el texto dado en términos de layman. Recuerda que el lector/a no es un experto en español.";
  return Array.isArray(input) ?
    input.flat().map(text => fetchData(systemContent, text)) :
    fetchData(systemContent, input);

}
  1. La fórmula GPT_SIMPLIFY simplifica cualquier texto que se provea como entrada. La entrada a esta función son datos que vienen de la hoja de cálculos. Cuando seleccionas un rango, una celda, o múltiples celdas, los datos en el rango serán proveídos automáticamente por la hoja de cálculo a esta fórmula.
  2. El systemContent se define para que se pase como el primer parámetro a la función fetchData(systemContent,userContent).
  3. Estamos verificando si la entrada es un Arreglo porque los datos que se pasan a esta función puede ser un arreglo anidado o sólo una cadena si seleccionamos múltiples celdas o una sola, respectivamente, en la hoja de cálculos.

Puedes leer más sobre funciones personalizadas en esta página.

Ahora, adelante y aplica esta fórmula en tu hoja de cálculo. Copié algo de texto de un libro que estoy leyendo en la primer columna y apliqué la fórmula en la segunda columna llamada "Simplify Passage", así =GPT_SIMPLIFY(A2) para la segunda celda.

gpt_simplify_formula
Aplicación de la Fórmula GPT_SIMPLIFY

Nota: Asegúrate de refrescar la hoja de cálculo antes de que apliques la fórmula para sincronizar con los últimos cambios en el script.

GPT SUMMARY

Para resumir la fórmula, copiaremos la función simplify y algunas otras cosas, como puedes ver en el código de abajo.

/**
 * Resume el párrafo dado. Provee viñetas de 3 a 5
 *
 * @param {String} input El valor a resumir.
 * @return Texto Resumido.
 * @customfunction
 */
function GPT_SUMMARY(input) {
  console.log(input)
  const systemContent = "Resume el texto dado. Provee al menos entre 3 y casi 5 viñetas.";
  return Array.isArray(input) ?
    input.flat().map(text => fetchData(systemContent, text)) :
    fetchData(systemContent, input);

}

Lo principal a notar aquí es el contenido distinto del sistema.

Nota: Ya que esto no es un tutorial sobre cómo usar ChatGpt de forma óptima, proveí instrucciones como el contenido de sistema en vez de un juego de roles, y luego proveí los datos en el contenido de usuario. Puedo improvisar al suministrar roles en el contenido de sistema, y tareas así también como datos como dos roles de usuarios distintos en nuestra función FetchData().

Error de límite de velocidad de GPT

Para usuarios gratuitos, el límite de velocidad para usar la API es de 3 minutos. Como tal, cuando aplicas estas fórmulas en más de tres celdas, encontrarás el error. Afortunadamente, la ejecución no se detendrá porque estamos ejecutando una cadena de error desde los datos de petición, el cual se guardarán en esas celdas.

GPT Rate Limit Error
API rate limit error

Auto refresco y error

Además, la característica de auto-refresco de la fórmula puede forzar la re-aplicación de la fórmula en celdas que ya tienen valores satisfactorios cuando sea que las celdas fuentes se actualicen, en nuestro caso las celdas en la columna "A".

Cuando agregamos un límite de velocidad por encima del auto-refresco, puede causar una adivinanza. Técnicamente puedes hacer cambios en funciones personalizadas para acomodar tales circunstancias, pero, me gusta mantener las fórmulas livianas y eficientes. Así que, recomiendo que creemos menús personalizados y apliquemos estas funciones manualmente.

Paso 4 – Integrar la API Chat de GPT en funciones de menú de hoja de estilo

GPT Simplify Menu

Primero, creemos otro archivo llamado menu. Luego, crearemos la función gptSimplifyMenu el cual será una alternativa a la fórmula GPT_SIMPLIFY.


/**
 * Simplifica el párrafo dado en términos de layman.
 * @customfunction
 */
function gptSimplifyMenu() {
  try {
    // obtiene hojas y datos
    const ss = SpreadsheetApp.getActiveSheet();
    const data = ss.getDataRange().getValues();
    const lastRow = data.length;
    const lastCol = data[0].length;

    // define el role play de gpt
    const systemContent = "Simplificar el texto dado en términos de layman. Recuerda que el lector no es un experto en inglés.";


    for (let i = 1; i < data.length; i++) {
      // solamente simplifica si todavía no está simplificado o si un error ocurrió previamente
      if (data[i][1] === "" || data[i][1] === "Ocurrió Algún Error. Por favor verifica tu fórmula o intenta nuevamente más tarde.") {
        data[i][1] = fetchData(systemContent, data[i][0]);
        console.log(data[i][1]);

      }
    }

    ss.getRange(1, 1, lastRow, lastCol).setValues(data);
  } catch (e) {
    console.log(e)
    SpreadsheetApp.getActiveSpreadsheet().toast("Ocurrió algún error. Por favor verifica tu fórmula o intenta nuevamente más tarde.");

  }
}

Puntos claves que son distintos de entender en este código son:

  1. Estamos codificando a mano las fuentes de los datos, tales como data[i][1], el cual se refiere a la segunda columna (es decir "Simplified Passage") como se muestra en la hoja de cálculo en la imagen de arriba. Esto significa que si estás usando algunas otras columnas para guardar los datos de ChatGPT, entones tendrás que hacer cambios según la columna.
  2. Solamente solicitamos los datos cuando la celda target esté vacía o contiene un mensaje de error. Esto ayuda en evitar llamadas a la API innecesariamente.

Agregar una función personalizada como un menú de la hoja de cálculo

La función está lista para ser probada, pero todavía no aparecerá en la hoja de cálculo. Para hacerlo, necesitaremos proveer las siguientes instrucciones.


/**
 * Menu crea la UI del menu en la hoja de cálculo.
 */
function createCustomMenu() {
   // define el ui del menú 
  let menu = SpreadsheetApp.getUi().createMenu("GPT Functions");
   // agrega la función al menú
   menu.addItem("GPT SIMPLIFY", "gptSimplifyMenu");
   // agrega el menú a la ui de la hoja de cálculo
  menu.addToUi();
}

/**
 * Disparador OnOpen que crea el menú
 * @param {Dictionary} e
 */
function onOpen(e) {
  createCustomMenu();
}

En createCustomMenu():

  1. Definimos menu con SpreadsheetApp.getUi().createMenu("GPT Functions") como Funciones de GPT, el título que aparece en la pestaña de la hoja de cálculo.
  2. Agregamos una función al menú con menu.addItem("GPT SIMPLIFY", "gptSimplifyMenu"), donde el primer parámetro es el título para mostrar y el segundo es la función a llamarse cuando se presione.
  3. Agrega el menú a la UI con menu.addToUi().

El disparador onOpen se ejecuta automáticamente cuando sea que el documento adjunto al script se recargue y como tal agregará un menú a la hoja de cálculo como se muestra en la imagen de abajo.

GPT Function Menu

Adelante e intenta la fórmula – se aplicará solamente si la celda está vacía o pre-cargada con un mensaje de error.

Menú de resumen de GPT

Haremos algunos cambios menores después de copiar la función simplify como se muestra abajo:

/**
 * Resume el párrafo dado. Provee de 3 a 5 viñetas
 * @customfunction
 */
function gptSummaryMenu() {
  try {
    // obtiene las hojas y los datos
    const ss = SpreadsheetApp.getActiveSheet();
    const data = ss.getDataRange().getValues();
    const lastRow = data.length;
    const lastCol = data[0].length;

    // define el rol de juego de gpt
    const systemContent = "Resume el texto dado. Provee al menos 3 y máximo 5 viñetas.";


    for (let i = 0; i < data.length; i++) {
      console.log(`Inside gptSummaryMenu() for loop`)

      if (i == 0) continue;
      // solamente resume si no está resumida todavía o un error ocurrió previamente
      if (data[i][2] === "" || data[i][2] === "Ocurrió Algún Error. Por favor verifica tu fórmula o intenta nuevamente más tade.") {
        data[i][2] = fetchData(systemContent, data[i][0]);
        console.log(data[i][2]);
      }
    }

    ss.getRange(1, 1, lastRow, lastCol).setValues(data);
  } catch (e) {
    console.log(e)
    SpreadsheetApp.getActiveSpreadsheet().toast("Ocurrió algún error. Por favor verifica tu fórmula o intenta nuevamente más tarde.");
  }
}
  1. El rol de sistema ha sido modificado para que abarque instrucciones de resumen.
  2. La columna target para guardar datos es ahora la columna tercera.
  3. La cadena doc ha sido modificada también.

En cuanto para agregar esta función al menú, te lo dejaré a ti.

Consejos para modificar el código

Todo lo que necesitas hacer para tu propia fórmula como =GPT_COVER_LETTER_CREATOR() son las siguientes modificaciones:

Para solicitar datos

Puedes cambiar la Descripción del Contenido del Sistema debería para cumplir tus requisitos, como "You write an expert cover letter for software developers".

Agrega una función más en el arreglo de mensajes:

// de esto 
[{
          "role": "system",
          "content": systemContent,
        },
        {
          "role": "user",
          "content": userContent
        },
        ], 

// a
[{
          "role": "system",
          "content": "Escribes una carta de presentación  experta para desarrolladores de software",
        },
        {
          "role": "user",
          "content": "Escríbeme una carta de presentación para este anuncio de trabajo"
        },
        {
          "role": "user",
          "content": userContent // este es el anuncio de trabajo desde la hoja de cálculo
        },
        ],

También puedes agregar otro ítem de lista para incluir tus habilidades y experiencias.

Otras funciones

Asegúrate que tu celdas/columnas fuentes y celdas/columnas target estén indexados correctamente (por ejemplo, si no estás usando la primera columna como la celda fuente y el segundo para guardar los datos).

Resumen

En este tutorial, aprendiste cómo usar el Apps Script de Google para solicitar respuestas de ChatGPT desde la API y guardarlos en hojas de cálculo usando fórmulas personalizadas y menús personalizados.

Comenzamos creando un nuevo proyecto de Apps Script de Google y agregando la API de ChatGPT. Luego, escribimos un script que solicitaría una respuesta de ChatGPT para una ventana dada. Guardamos la respuesta usando una fórmula personalizada en una celda de hoja de cálculo.

También creamos un ítem de menú personalizado que nos permitiría solicitar una respuesta de ChatGPT desde cualquier celda en la hoja de cálculo. Este ítem de menú abriría un botón para solicitar la respuesta.

El paso final era compartir la hoja de cálculo con los demás, de esa forma podrían usar las fórmulas personalizadas y menús para solicitar respuestas de ChatGPT.

Espero que hayas disfrutado de este artículo y lo hayas encontrado útil. Si tienes alguna pregunta, házmelo saber.

Soy Nibesh Khadka, Freelancer con especialización en automatizar productos de Google con Apps Script. Contáctame si necesitas mis servicios en me@nibeshkhadka.com.