Exploramos Github Copilot en la web creando una …
Los asistentes de programación por IA están en boca de todos. Actualmente ya están alterando el …
leer másCasi todo el mundo se hace propósitos de año nuevo al empezar o terminar uno, o, cuánto menos, nos replanteamos metas y objetivos. Para este artículo, teniendo en cuenta las fechas en las que estamos, vamos a hacer algo “diferente”, algo sencillo pero práctico. Vamos a crear una pequeña aplicación que nos permita generar nuestros propósitos para el año que viene, utilizando Inteligenica Artificial.
Haremos uso de ChatGPT de OpenAI para, enviando una petición a su API, recibir como respuesta un número determinado de propósitos para este nuevo año, lo importante de este artículo, más allá de su utilidad y funcionalidad, es el uso de ChatGPT a través de su API y cómo utilizar los prompts del sistema para obtener respuestas personalizadas y estructuradas para luego consumir en la parte del cliente.
La idea es simple, una página web que conste de una caja de texto y un botón, la caja de texto permitirá ingresar al usuario una o varias palabras sobre el tema del que le gustaría obtener propósitos, por ejemplo, “Desarrollo de Software”, “Deporte”, “Salud”, “Ocio y Entretenimiento”, etc. Al presionar el botón, se enviará una petición a la API de ChatGPT con el texto ingresado y se mostrarán los propósitos generados.
Para ello, necesitaremos una cuenta en OpenAI, la cual nos permitirá obtener una clave para poder hacer uso de la a API de ChatGPT. Una vez tengamos la API Key, ya podremos enviar solicitudes a la API de ChatGPT para generar nuestros propósitos. Utilizaremos HTML, CSS, Javascript y Docker para crear y arrancar la aplicación. En el repositorio de Github encontrarás el código fuente completo de la aplicación. Aquí te muestro el archivo HTML con la estructura de nuestra página:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Generador de Propósitos 2025</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header>
<h1>🎉 Propósitos para 2025 🎉</h1>
<p>Genera metas motivadoras para el Año Nuevo</p>
</header>
<main>
<div class="form-container">
<div class="input-container">
<input type="text" id="topic" placeholder="Escribe un tema (ej. Tecnología, Salud)"/>
<button onclick="generateGoals()">Generar Propósitos</button>
</div>
<div id="output" class="results"></div>
</div>
</main>
<footer>
<p>💡 Inspiración para el Año Nuevo 💡</p>
<p><a href="https://betazeta.dev" target="_blank" class="beta-link">Por BetaZetaDev</a></p>
</footer>
<script src="script.js"></script>
</body>
</html>
El método generateGoals()
se encuentra en el fichero Javascript del cliente, dentro de la carpeta frontend
y se encarga
de realizar la petición al servidor (backend
) entre otras cosas:
const response = await fetch("http://localhost:3000/generate", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ topic }),
});
Gracias al CSS que lo acompaña aplicamos un diseño sencillo utilizando tarjetas que simulan ser notas escritas a mano
para darle una apariencia más acorde al contexto de nuestra aplicación. Además, almacenamos la clave de la API de OpenAI
en un
fichero .env
y utilizamos dos ficheros JavaScript, uno para manejar la lógica de la aplicación y otro para la parte
del
servidor:
require("dotenv").config();
const express = require("express");
const cors = require("cors");
const bodyParser = require("body-parser");
const axios = require("axios");
const app = express();
const port = 3000;
app.use(cors());
app.use(bodyParser.json());
const OPENAI_API_KEY = process.env.OPENAI_API_KEY;
app.post("/generate", async (req, res) => {
const {topic} = req.body;
if (!topic) {
return res.status(400).send({error: "El tema es obligatorio"});
}
try {
const response = await axios.post(
"https://api.openai.com/v1/chat/completions",
{
model: "gpt-4o",
messages: [
{
role: "system",
content: `You are an assistant that must always return valid JSON data. The responses must be written in Spanish. Generate exactly 5 resolutions for the given topic. Follow this strict JSON format:
{
"goals": [
"Resolution 1",
"Resolution 2",
"Resolution 3",
"Resolution 4",
"Resolution 5"
]
}
Do not include any additional text, comments, or explanations. Only return valid JSON.`
},
{
role: "user",
content: `Genera resoluciones para el tema: ${topic}`
}
],
temperature: 0.7,
},
{
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${OPENAI_API_KEY}`,
},
}
);
// Obtener el contenido de la respuesta
let content = response.data.choices[0].message.content.trim();
// Eliminar delimitadores de bloques de código (```json y ```)
if (content.startsWith("```json")) {
content = content.slice(7).trim(); // Quitar "```json"
}
if (content.endsWith("```")) {
content = content.slice(0, -3).trim(); // Quitar "```"
}
// Intentar parsear el contenido como JSON
try {
const parsed = JSON.parse(content);
if (!parsed.goals || !Array.isArray(parsed.goals) || parsed.goals.length !== 5) {
throw new Error("El JSON no contiene el formato esperado.");
}
// Formatear y enviar la respuesta
res.send({
title: `Propósitos de Año Nuevo para ${topic}`,
goals: parsed.goals,
});
} catch (parseError) {
console.error("Error al parsear JSON:", parseError.message, content);
res.status(500).send({error: "La respuesta no es un JSON válido."});
}
} catch (error) {
console.error("Error al llamar a la API de OpenAI:", error.response?.data || error.message);
res.status(500).send({error: "Hubo un problema al generar los propósitos."});
}
});
app.listen(port, () => {
console.log(`Servidor corriendo en http://localhost:${port}`);
});
La parte crucial de nuestra aplicación, se ejecuta en el servidor y se encarga de gestionar las peticiones contra
ChatGPT, petición que, como decíamos antes para la hace uso del prompt de sistema. Éste le indica a ChatGPT los
requisitos que deben cumplir su respuesta y lo aprovechamos también para indicarle la estructura del JSON que esperamos
recibir para poder parsear
correctamente la respuesta una vez recibida y mostrar los propósitos en la página. Hay que
tener en cuenta que en una de las actualizaciones de la API de ChatGPT se añadieron lo que
llaman Structured Outputs. El problema de hacerlo
de la forma de nuestro ejemplo es que puede pasar que ChatGPT no sea totalmente estricto con los requisitos indicados en
el prompt del sistema y devuelva una respuesta con un formato diferente al indicado, por lo que es importante tener en
cuenta este detalle. Para cerciorarnos de que la respuesta es correcta y tiene el formato esperado sin sorpresas
tendríamos que utilizar los Structured Outputs
.
Otro detalle a tener en cuenta es que, para poder gestionar de forma segura las claves de las API en general y no
exponerlas en el código fuente, lo ideal es utilizar un servidor backend
que se encargue de hacer las peticiones y
devolver los resultados. Esto es bastante común, ya que permite separar la lógica de negocio del frontend
y mantener las
claves de las API seguras para que no puedan ser accedidas y utilizadas por terceros.
La estructura del proyecto quedaría de la siguiente manera:
.
├── `backend`
│ ├── .env
│ ├── package.json
│ └── server.js
├── docker-compose.yml
├── Dockerfile.`backend`
├── Dockerfile.`frontend`
└── `frontend`
├── index.html
├── script.js
└── styles.css
Para poder ejecutar la aplicación haremos uso de Docker, preparado ya para levantar un contenedor para el frontend
y
otro para el backend
. Utilizaremos un archivo docker-compose.yml
, además de dos ficheros Dockerfile. En el
repositorio puedes ver todos los ficheros y su contenido.
Una vez tengamos todos los archivos necesarios, podremos construir y ejecutar la aplicación con el siguiente comando:
docker compose up --build -d
Esto lanzará ambos contenedores Docker en segundo plano, frontend
y backend
, los cuales se comunicarán entre sí, las
peticiones del frontend
se envían al backend
que se encarga de realizar la solicitud y gestionar la respuesta
devolviéndola al cliente. Una vez los contenedores estén en ejecución, podremos acceder a la aplicación desde nuestro
navegador web en la dirección http://localhost:8080 y empezar a generar nuestros propósitos para el año nuevo.
Ha sido un ejemplo sencillo pero práctico, en el que observamos cómo utilizar la inteligencia artificial en aplicaciones
web de forma sencilla y el uso del prompt del sistema para obtener respuestas personalizadas al utilizar ChatGPT.
También podemos comprobar cómo separar la lógica de negocio del frontend
utilizando un servidor backend
de forma
sencilla, sin necesidad de frameworks complejos ni librerías adicionales, más allá de las estrictamente necesarias. Cabe
mencionar que, en realidad, la parte del frontend
en Docker no es necesaria ya que la aplicación puede ejecutarse directamente
desde el navegador abriendo el archivo index.html
, pero utilizamos Docker para practicar el uso de contenedores.
Por nuestra parte simplemente desearte un muy feliz año nuevo, que los propósitos que te marques se cumplan y mucho éxito en todos tus proyectos y metas, tanto personales como profesionales.
¡Feliz año nuevo y Happy Coding!
Quizá te puedan interesar
Los asistentes de programación por IA están en boca de todos. Actualmente ya están alterando el …
leer másEn el artículo de hoy vamos a hablar sobre Github Copilot, un asistente de programación por …
leer másEl origen del debugging El término debugging o depuración de errores, tan familiar en el mundo del …
leer másDe concepto a realidad