Saltar al contenido

Cómo crear una aplicación GPT-3 con Nextjs, React y GitHub Copilot

25 de julio de 2023

A principios de año, comencé a entrenar con un entrenador que quería que comenzara a hacer un seguimiento de mis comidas, pero siempre he estado muy en contra de hacer un seguimiento de mis comidas porque simplemente no funciona para mí. Sin embargo, en lugar de hacer un seguimiento de mis comidas, decidí crear una aplicación que automáticamente me dice la información nutricional de cualquier receta. Pero para hacer eso, necesitaba algunas capacidades de análisis de lenguaje natural bastante complejas, así que pensé que esta sería una gran oportunidad para jugar con OpenAI y usar GitHub Copilot un poco más para ayudarme a construir la aplicación rápidamente.

GitHub Copilot es un excelente ejemplo de un producto que aprovecha los modelos de lenguaje grande (LLM) para resolver problemas para las personas y mejorar su productividad. En este blog, le explicaré cómo creé mi propia aplicación que encuentra la información nutricional de cualquier receta utilizando el modelo GPT-3.5-turbo de OpenAI, GitHub Copilot, Next.js, React y Material UI.

Vamos a profundizar en el tutorial.

1. Crear un repositorio e instalar dependencias

Para comenzar, creemos un nuevo repositorio a partir de la plantilla GitHub Codespaces Next.js para comenzar a funcionar rápidamente. Vaya a este repositorio y haga una copia. Para hacerlo, haga clic en el botón verde «Usar esta plantilla», luego seleccione «Crear un nuevo repositorio» y asigne el nombre que desee a su repositorio. Llamé al mío «mealmetrics-copilot».

Ahora, clone el repositorio en su máquina local y abra el repositorio en su editor de código preferido. Estoy usando el código VS.

Abre tu terminal y cd en el proyecto para que podamos instalar algunas dependencias necesarias. En tu terminal ejecuta el siguiente comando:

npm i express openai dotenv @material-ui/core @material-ui/icons

Luego, instala lo siguiente como una dependencia de desarrollo:

npm i --save-dev nodemon

Una vez que todo se instala correctamente, estamos listos para comenzar a construir el servidor, pero primero, tomemos nuestra clave de API de OpenAI.

2. Obtener su clave API de OpenAI

Vaya a la página de inicio de sesión para desarrolladores de OpenAI y cree una nueva cuenta o inicie sesión si ya tiene una. Una vez que haya iniciado sesión, haga clic en su nombre en la esquina superior derecha y seleccione «ver claves API». Haga clic en el botón «Crear una nueva clave secreta». Desde allí, puede nombrar su apikey, hacer clic en el botón verde para generar la clave y luego copiar la apikey y guardarla en una ubicación segura (como un administrador de contraseñas).

Guarde su apikey en un .env archivo en vscode en la raíz del proyecto y agregue .env hacia gitignore archivo.

3. Instalar la extensión GitHub Copilot

Usaremos GitHub Copilot como nuestro asistente para construir esta aplicación. Si no está familiarizado con GitHub Copilot, lea esta publicación de blog para obtener más información.

En el editor de código de su elección, vaya a su panel de extensiones y busque GitHub Copilot. Estoy usando VSCode y así es como se ve.

Haga clic en el botón de instalación y luego haga clic en el botón de inicio de sesión para autenticar su acceso. Una vez hecho esto, ¡estará listo para comenzar y seguir adelante!

4. Construyendo el servidor

Ahora que tenemos nuestra apikey, hemos instalado las dependencias y tenemos GitHub Copilot en nuestro editor de código, ¡profundicemos en la creación de la aplicación!

Lo primero que vamos a hacer es construir un servidor simple con Express.js (si prefieres usar Fastify, NestJS, Koa o algo más, ¡siéntete libre de usarlos!).

En el pages carpeta, cree una carpeta llamada api y luego un archivo llamado server.js. Aquí es donde agregaremos nuestra información de solicitud para GitHub Copilot. Agreguemos nuestro primer aviso como un comentario en el server.js archivo que dice lo siguiente:

Create a server with the following specifications:

1. import express and dotenv node modules
3. create the server with express and name it app
4. use port 8080 as default port
5. enable body parser to accept json data
6. state which port the server is listening to and log it to the console

Presione la tecla Intro y GitHub Copilot comenzará a generar sugerencias para construir el servidor. Para aceptar las sugerencias, presione la tecla de tabulación. Mire este video para ver cómo se aceptan sugerencias.

Podemos actualizar el archivo package.json para incluir el script devserver: "nodemon pages/api/server.js luego ejecute el comando en nuestra terminal usando npm run devserver. ¡Verás que el servidor se ha iniciado!

Después de construir el servidor simple, pasemos a hacer esto un poco más complejo al construir el controlador para nuestra aplicación.

Vamos a crear un nuevo archivo en el api carpeta llamada generateInfo.js y agregue el siguiente comentario en el archivo:

Create a controller with the following specifications:

1. import the Configuration class and the OpenAIApi class from the openai npm module
2. create a new configuration object that includes the api key and uses the Configuration class from the openai module
3. create a new instance of the OpenAIApi class and pass in the configuration object
4. create an async function called generateInfo that accepts a request and response object as parameters
5. use try to make a request to the OpenAI completetion api and return the response
6. use catch to catch any errors and return the error include a message to the user
7. export the generateInfo function as a module

Como notará, estoy siendo muy explícito en mis instrucciones para GitHub Copilot. Una cosa que siempre debe recordar cuando trabaje con LLM es que la magia está en el aviso: cuanto más claras sean sus instrucciones, mejores serán los resultados que obtendrá.

Golpear ingresar en tu teclado y luego presiona pestaña para aceptar las recomendaciones que proporciona GitHub Copilot. En la imagen a continuación, notará que las sugerencias de Copilot son grises.

Acepte la sugerencia pulsando pestaña en su teclado y hagamos un poco de limpieza.

Recuerde, GitHub Copilot es nuestro asistente, por lo que aún debemos asegurarnos de que las sugerencias que brinda cumplan con nuestros requisitos.

Como estamos construyendo una aplicación gpt-3, usaremos el completion API de OpenAI y la gpt-3.5-turbo model para generar información nutricional para nosotros.

Si observa la sugerencia anterior, se nos proporcionó el davinci motor y parámetros que no son necesarios para este proyecto, también necesitamos el messages parámetro para enviar solicitudes con el modelo 3.5-turbo.

También queremos agregar el mensaje de receta, crear una función llamada recipe que representa la receta que ingresa un usuario y también actualiza la completion object enviado a OpenAI. Las claves que usaremos son max_tokens, prompt, model, temperature y n. Obtenga más información sobre estos parámetros leyendo los documentos de API de OpenAI.

Actualicemos también el mensaje de error para incluir 401 en caso de que nuestra clave api no sea válida. Entonces, hagamos estas actualizaciones.

1. Agregar aviso de receta

Cree una nueva carpeta llamada datos en la raíz de su proyecto, luego cree un archivo llamado prompt.json. Esto contendrá una parte del aviso de la receta que enviaremos a OpenAI. Agregue el siguiente script al archivo prompt.json:

{
"recipePrompt": "I want you to act as a Nutrition Facts Generator. I will provide you with a recipe and your role is to generate nutrition facts for that recipe. You should use your knowledge of nutrition science, nutrition facts labels and other relevant information to generate nutritional information for the recipe. Add each nutrition fact to a new line. I want you to only reply with the nutrition fact. Do not provide any other information. My first request is: "
}

Luego importa el recipePrompt hacia generateInfo.js archivo y actualice la función principal para obtener la receta enviada por el usuario.

// add the prompt to the top of the file
const { recipePrompt } = require('../../data/recipe.json');

// update this function to include the recipe before the try
const generateInfo = async(req, res) => {
const { recipe } = req.body
}

2. Actualice la función de finalización y la respuesta.

Ahora, actualicemos el try parecerse un poco más a lo que queremos.

model: "gpt-3.5-turbo",
messages: [{ role: "user", content: `${recipePrompt}${recipe}` }],
max_tokens: 200,
temperature: 0,
n: 1,

Y también actualicemos el response que recibimos.

const response = completion.data.choices[0].message.content;

return res.status(200).json({
success: true,
data: response,
});

3. Actualice el mensaje de error

Finalmente, actualicemos el catch tener mensajes de error más explícitos.

catch (error) {
if (error.response.status === 401) {
return res.status(401).json({
error: "Please provide a valid API key.",
});
}
return res.status(500).json({
error:
"An error occurred while generating recipe information. Please try again later.",
});
}

Una vez que hayamos actualizado todo, nuestra función de controlador debería verse así:

const { Configuration, OpenAIApi } = require("openai");
const { recipePrompt } = require("../../data/recipe.json");

const config = new Configuration({
apiKey: process.env.OPENAI_API_KEY,
});

const openai = new OpenAIApi(config);

const generateInfo = async (req, res) => {
const { recipe } = req.body;

try {
const completion = await openai.createChatCompletion({
model: "gpt-3.5-turbo",
messages: [{ role: "user", content: `${recipePrompt}${recipe}` }],
max_tokens: 200,
temperature: 0,
n: 1,
});
const response = completion.data.choices[0].message.content;

return res.status(200).json({
success: true,
data: response,
});
} catch (error) {
console.log(error);
if (error.response.status === 401) {
return res.status(401).json({
error: "Please provide a valid API key.",
});
}
return res.status(500).json({
error:
"An error occurred while generating recipe information. Please try again later.",
});
}
};

module.exports = { generateInfo };

Ahora, vamos a crear el enrutador y probarlo en Postman. Crear un nuevo archivo llamado router.js y comience a escribir para permitir que GitHub Copilot lo ayude mientras escribe.

Como puede ver, GitHub Copilot ofreció sugerencias mientras escribía y presioné el botón de tabulación para aceptar las sugerencias. Agregue el enrutador recién creado al server.js archivar y probar la ruta en cartero. Agregue lo siguiente a su server.js archivo.

app.use('/openai', require('./router'));

Ahora, probemos la ruta en cartero con una solicitud POST: ¡asegúrese de que su servidor aún se está ejecutando!

Vaya a la URL a continuación y agregue cualquier receta al cuerpo de la solicitud:

URL: http://localhost:8080/openai/generateinfo

RECIPE:
{
"recipe": "1 cup of all purpose flour, sifted 1 1/2 teaspoon baking powder 1/4 teaspoon salt 2 Tablespoon granulated sugar 1/2 Tablespoon unsalted butter, room temperature Approximately 1/3 cup water"
}

Debería recibir una respuesta exitosa que se vea así:

{
"success": true,
"data": "nnCalories: 112 nTotal Fat: 2.3g nSaturated Fat: 1.3g nTrans Fat: 0g nCholesterol: 5.4mg nSodium: 175.8mg nTotal Carbohydrates: 21.6g nDietary Fiber: 0.8g nSugars: 6.5g nProtein: 2.6g"
}

Aquí están los datos que enviamos a OpenAI que generaron esa respuesta exitosa:

data: '{"model":"text-davinci-003","prompt":"I want you to act as a Nutrition Facts Generator. I will provide you with a recipe and your role is to generate nutrition facts for that recipe. You should use your knowledge of nutrition science, nutrition facts labels and other relevant information to generate nutritional information for the recipe. Add each nutrition fact to a new line. I want you to only reply with the nutrition fact. Do not provide any other information. My first request is: 1 cup of all purpose flour, sifted 1 1/2 teaspoon baking powder 1/4 teaspoon salt 2 Tablespoon granulated sugar 1/2 Tablespoon unsalted butter, room temperature Approximately 1/3 cup water","max_tokens":200,"temperature":0.5,"n":1}',

Como puede ver, tanto la secuencia de comandos como la receta ingresadas en el cuerpo de la solicitud se enviaron a OpenAI, que generó los datos nutricionales para esta receta de bola de masa frita jamaicana.

Ahora, creemos la interfaz de la aplicación para mostrar la información en la web.

5. Construyendo la aplicación frontend

Usaremos React para la interfaz. Eliminar todo el código en el index.js archivo que existe actualmente en el proyecto. Luego, en un comentario, indique a GitHub Copilot que cree un área de texto simple.

Create a text area with the following specifications:
1. a H1 with the text "Find Nutrition Facts for any recipe"
2. a text area for users to upload recipe
3. a button for users to submit the entered recipe
4. a section at the bottom to display nutrition facts
5. Get the data from this link: http://localhost:8080/openai/generateinfo
6. Name the component RecipeInfo

GitHub Copilot generó rápidamente el código para nosotros.

vamos a golpear pestaña para aceptar la sugerencia y ejecutar npm run dev en tu terminal para ver la app en la web. Cuando vas a localhost:3000verá lo siguiente en la web.

Es cierto que no es lo más hermoso, pero pudimos darle vueltas muy rápidamente.

En menos de un minuto completamos un mvp de interfaz funcional de nuestra aplicación con GitHub Copilot.

Ingresemos la receta que tenemos en el cuadro de texto y veamos la respuesta que obtenemos.

Y tenemos nuestro primer error, lo cual no es sorprendente ya que no validamos el código que se proporcionó. Echemos un vistazo a la consola y veamos si tenemos algún detalle adicional.

Parece que es un problema de CORS: clásico. Preguntemos a GitHub Copilot cómo resolver esto.

Agregue las siguientes preguntas como comentario en cualquier parte de su archivo:

q: how do I resolve the CORS error?
q: how do I add Access-Control-Allow-Origin to the header?

La pregunta y la respuesta deberían verse así:

También podemos preguntarle a GitHub Copilot Chat cómo resolver los errores de CORS y nos da una respuesta perfecta.

Instalamos el cors middleware y agréguelo al server.js archivo.

const cors = require("cors");

// Allow cross-origin requests (CORS)
app.use(cors());

Luego, actualicemos nuestro archivo router.js.

router.options("/generateInfo", (req, res) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Headers", "*");
res.setHeader("Access-Control-Allow-Methods", "*");
res.sendStatus(200);
});

Ahora, intentemos obtener datos nutricionales nuevamente y veamos qué sucede.

Y tenemos otro error. ¡Progreso!

Esta vez no es necesario depurar con GitHub Copilot ya que se nos dice que los datos que se devuelven son un objeto con las claves success y data. Cambiemos el nombre de la función de respuesta a recipeInfo y actualizar el estado nutricional para recibir recipeInfo.data.

const recipeInfo = await response.json();
setNutrition(recipeInfo.data);

Intentemos enviar la receta nuevamente y esperemos una respuesta exitosa.

¡Éxito!

Acabamos de crear una aplicación GPT-3 en un tiempo récord con GitHub Copilot, React, Next.js y OpenAI. Ahora que tenemos los datos que necesitamos, hagamos que la aplicación sea más hermosa con Material UI.

6. Diseñar la aplicación con Material UI

En esta sección, usaremos una característica de GitHub Copilot X en vista previa técnica para individuos y en versión beta pública para organizaciones, Copilot Chat, para mejorar la apariencia de nuestra aplicación. Debe tener acceso a GitHub Copilot para estar en la lista de espera de Copilot Chat que está abierta actualmente. ¡Regístrese hoy si aún no lo ha hecho!

Preguntemos al chat de GitHub Copilot cómo podemos implementar material-ui en la aplicación:

Avancemos e implementemos las sugerencias y veamos qué sucede, y también pidamos al chat de GitHub Copilot que implemente un encabezado para nosotros.

Después de implementar el encabezado, la nueva área de texto y centrar el contenido, así es como se ve la aplicación.

Bien, estamos llegando a alguna parte.

Hagamos algunas actualizaciones más con la ayuda de GitHub Copilot Chat. He incluido el mensaje / preguntas que hice:

  • Haga el área de texto más grande e implemente Material UI

update the component to use material ui with the content centered and the buttoned positioned below the text area. use Grid from material ui and any other components needed.

  • Agregue el componente de papel de Material UI para mejorar la apariencia de la aplicación

add the Paper component from material ui to the text area highlighted

  • Agregue un segundo botón que borre el área de texto + datos después de enviar una receta

add a button to the app to clear the text in the textarea

  • Agregue un cargador mientras espera que se carguen los datos

add a loader to the highlighted code that checks if the data is loading. If the data is loading, then display the text "Nutrition Facts" and loader, if there is an error, display the error message otherwise, display nothing

  • Agregue un tema con colores primarios y secundarios personalizados

how do I create a custom theme with material ui and where do I create the custom theme?

  • Evite que el área de texto pase por encima del componente de papel de Material UI

in the highlihghted code how do I prevent the text area line from going over the paper component?

  • Agregar un nuevo componente: pie de página

Create a footer component with the following specifications:
1. The footer must be fixed at the bottom of the page
2. Use the Paper component from Material UI
3. Use the Typography component from Material UI
3. The text must say "Made with ❤️ by LadyKerr & GitHub Copilot" and "Powered by OpenAI"
4. The text "GitHub Copilot" must be a link to https://copilot.github.com/ that opens in a new tab with alt text " GitHub Copilot"
5. The text "OpenAI" must be a link to https://openai.com/ that opens in a new tab with alt text "openai api"

Pídale al chat de GitHub Copilot que realice los cambios anteriores y, una vez que haya terminado, su aplicación debería verse y funcionar así:

Ahora, creemos un nuevo componente que divida cada información nutricional en una nueva línea. Crear un nuevo archivo llamado NutritionFacts.js en la carpeta de componentes y escriba lo siguiente como comentario para que GitHub Copilot pueda ponerse a trabajar.

Create a component with the following specifications:
1. the component must split the received string data at /n/n or /n and return a Typography component for each string
2. the component must set a unique key for each Typography component
3. the component must return a div with the Typography components
4. the component must return null if the data is not a string
5. Name the component NutritionFacts
6. Use the Paper Component from Material UI
7. Add text above the data that says "Here are the nutrition facts for your recipe:"

A partir de este indicador, GitHub Copilot generó el siguiente código.

import React from "react";
import { Typography, Paper } from "@material-ui/core";

const NutritionFacts = ({ data }) => {
if (typeof data !== "string") {
return null;
}
const nutritionFacts = data.split(/nn|n/);
return (

Here are the nutrition facts for your recipe:

{nutritionFacts.map((fact, index) => (
{fact}
))}
);
};

export default NutritionFacts;

¡Brillante! Importemos este componente a nuestro principal index.js archivar y probar la aplicación para ver si cada hecho se dividió en una nueva línea como se esperaba.

Y lo hizo. Nuestra aplicación funciona como se esperaba.

Ahora, vamos a mover el código del encabezado a un nuevo archivo en la carpeta de componentes llamado Header.js. Una vez que todo está actualizado, la aplicación final se ve así y devuelve los datos nutricionales de cualquier receta.

¡Así que ahí lo tenemos!

Acabamos de crear una aplicación con GitHub Copilot, OpenAI, React, Next.js y GitHub Copilot Chat. El siguiente paso sería implementar la aplicación en GitHub Pages e implementar su servidor en un servicio como Azure.

Puede ver el código completo aquí. Siéntase libre de clonar o bifurcar el proyecto y personalizarlo. ¡Este fue un pequeño proyecto divertido de construir y espero que hayas aprendido algo nuevo y te sientas inspirado para crear tu propia aplicación GPT-3!

Obtenga más información sobre las solicitudes de GitHub Copilot leyendo Cómo usar GitHub Copilot: solicitudes, consejos y casos de uso y una guía para desarrolladores sobre ingeniería de solicitudes y LLM.

Hasta la próxima, ¡feliz codificación!

Recomendado:  Se necesita un cuerpo para entender el mundo: por qué ChatGPT, otras IA no saben lo que están diciendo