Publicado el martes 20 de febrero del 2024 por Lino Uruñuela
El otro día vimos cómo podíamos utilizar la API de Vertex para utilizar la tecnología de IA generativa de Google Gemini. Hoy quiero profundizar en la redacción de textos utilizando Gemini, y cómo resolver algunos de los problemas comunes que suelen ocurrir cuando generamos textos con este tipo de tecnología, ya sea Gemini, chatGPT o cualquier otro LLM (Modelo Grande de Lenguaje).
Cuando intentas generar con IA el contenido que requiere una mínima longitud, por ejemplo el contenido generado en base a determinadas características de productos, el contenido total de un artículo sobre algún tema, guías completas sobre ciertos temas, etc me he encontrado con dos problemas iniciales:
En primer lugar, debemos saber que lo que determina la longitud máxima de la respuesta depende de los límites de cada modelo, y por esa razón debemos informarnos sobre esta y otras características en la documentación del modelo concreto que estemos usando, en este caso Gemini pro. Esta cantidad de texto normalmente viene dado en tokens, que aproximadamente podemos decir que 100 tokens corresponden a casi 60 u 80 palabras.
En el caso de Google Gemini pro, a día de hoy , la cantidad máxima de tokens que se pueden generar en la respuesta es de 8192 tokens (juraría que la semana pasada solamente eran 2048! Esto quiere decir que va a ir mejorando, y esto siempre es una buena noticia :)), que son 4.915 palabras, una cantidad de palabras que a priori es más que suficiente para cualquier temática que queramos abordar.
Recordemos que en nuestro ejemplo base, que vimos en el artículo Cómo utilizar la API de Google Gemini, teníamos una función que procesaba el prompt, aquí el código de esta función
def genera_texto(ejecutaPrompt: str) -> str:
# Initialize Vertex AI
# Load the model
model = GenerativeModel("gemini-pro")
response = model.generate_content(
ejecutaPrompt,
generation_config={
"max_output_tokens": 8192,
"temperature": 0.9,
"top_p": 1
},
)
return response
En ella vemos un parámetro denominado "max_output_tokens" con un valor de 8192 que es dónde indicamos la cantidad máxima de tokens que puede tener la respuesta.
Tal como decíamos anteriormente, 8.192 tokens representan más o menos unas 4.915 palabras, y debería ser más que suficiente para el contenido de un artículo. Pero la realidad es que cuando ejecutas el modelo, aunque pongas explícitamente que el resultado debe tener un mínimo de X palabras, raramente hace caso explícito a esa orden y el resultado casi siempre es menor (mucho menor) al número de palabras que le has solicitado.
Siguiendo con nuestro ejemplo base, definimos nuestro prompt para generer un artículo sobre el juego 'Fortnite', dónde indicamos el mínimo de palabras de la respuesta
#DEFINE TU PROMPT PARA EJECUTAR SOBRE GOOGLE GEMINI
prompt='''
Eres un redactor de contenido experto en videojuegos,
redacta un artículo con diferentes seccciones sobre el juego 'Fortnite' que tenga como mínimo 2.000 palabras.
GENERA LA SALIDA EN FORMATO HTML
'''
genera_texto(prompt)
Al ejecutar este prompt, nos devuelve el siguiente HTML
<!DOCTYPE html>
<html>
<head>
<title>Fortnite: Una Guía Integral</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Un análisis en profundidad del popular videojuego Fortnite, que incluye jugabilidad, estrategia y consejos para principiantes y jugadores avanzados.">
<style>
body {
font-family: Arial, sans-serif;
line-height: 1.6;
}
h1, h2, h3 {
margin-bottom: 16px;
}
h2 {
font-size: 1.5em;
}
h3 {
font-size: 1.2em;
}
ul, ol {
padding-left: 1.5em;
margin-bottom: 16px;
}
li {
margin-bottom: 8px;
}
code {
font-family: monospace;
padding: 4px;
background-color: #eee;
}
</style>
</head>
<body>
<h1>Fortnite: Una Guía Integral</h1>
<h2>Introducción</h2>
<p>Fortnite es un videojuego multijugador en línea desarrollado por Epic Games y People Can Fly. Se lanzó por primera vez en 2017 y desde entonces se ha convertido en uno de los juegos más populares del mundo, con más de 350 millones de jugadores registrados.</p>
<p>Fortnite es un juego de disparos en tercera persona en el que los jugadores compiten en equipos o solos para ser el último jugador o equipo en pie. El juego cuenta con una gran variedad de armas, vehículos y elementos que los jugadores pueden usar para sobrevivir y derrotar a sus oponentes.</p>
<h2>Jugabilidad</h2>
<p>Fortnite tiene dos modos de juego principales: Battle Royale y Save the World.</p>
<h3>Battle Royale</h3>
<p>Battle Royale es el modo de juego más popular de Fortnite. En este modo, 100 jugadores se enfrentan en una isla cada vez más pequeña. Los jugadores deben recolectar armas y recursos, construir estructuras y luchar contra otros jugadores para ser el último jugador en pie.</p>
<h3>Save the World</h3>
<p>Save the World es un modo de juego cooperativo en el que los jugadores trabajan juntos para completar misiones y defenderse de las hordas de enemigos controladas por computadora.</p>
<h2>Estrategia</h2>
<p>Hay una serie de estrategias diferentes que los jugadores pueden utilizar para tener éxito en Fortnite. Algunos de los consejos más importantes incluyen:</p>
<ul>
<li>Aterrizar en un lugar apartado para evitar el combate inicial.</li>
<li>Recoger recursos y construir estructuras para protegerse de los enemigos.</li>
<li>Usar armas y vehículos de forma eficaz.</li>
<li>Trabajar en equipo con otros jugadores para aumentar tus posibilidades de ganar.</li>
</ul>
<h2>Consejos para principiantes</h2>
<p>Si eres nuevo en Fortnite, aquí tienes algunos consejos para ayudarte a empezar:</p>
<ul>
<li>Juega el tutorial para aprender los conceptos básicos del juego.</li>
<li>Salta a partidas de Battle Royale en solitario para practicar tus habilidades.</li>
<li>Experimenta con diferentes armas y vehículos para encontrar los que más te gustan.</li>
<li>No te desanimes si mueres al principio. ¡Todos los jugadores comienzan en algún lugar!</li>
</ul>
<h2>Consejos para jugadores avanzados</h2>
<p>Una vez que hayas dominado los conceptos básicos, aquí tienes algunos consejos para ayudarte a mejorar tu juego:</p>
<ul>
<li>Aprende a construir estructuras de forma rápida y eficiente.</li>
<li>Usa las coberturas y el terreno en tu beneficio.</li>
<li>Domina el uso de armas y vehículos avanzados.</li>
<li>Trabaja en equipo con otros jugadores para mejorar tus posibilidades de ganar.</li>
</ul>
<h2>Conclusión</h2>
<p>Fortnite es un juego complejo y emocionante que requiere habilidad, estrategia y trabajo en equipo. Ya seas un principiante o un jugador experimentado, siempre hay algo nuevo que aprender. Con estos consejos, puedes mejorar tu juego y divertirte más con Fortnite.</p>
</body>
</html>
Este resultado no está nada mal! (aquí está el resultado HTML) pero no es suficientemente largo para que sea el contenido completo de un artículo.
Una manera de generar un contenido más extenso es predefinir las secciones principales que tendrá cada artículo y realizar una llamada al modelo de lenguaje para que genere el texto de cada una de las secciones del artículo.
Tomamos como secciones del artículo las siguientes:
Y ejecutamos una petición para cada una de las secciones (ver ejemplo concreto en Colab).
TextoFinal = ""
prompt='''
Eres un redactor de contenido experto en videojuegos,
Redacta el contenido de la sección 'Historia y Desarrollo' que será parte de un artículo sobre el juego 'Fortnite'.
Escribe párrafos largos, descriptivos con un estilo narrativo. Genera diferentes párrafos por cada subsección, hasta un máximo de 4 párrafos. En algunos casos usar jerarquía de etiquetas <H3>,<H4>.
Genera la respuesta en código HTML, este HTML se añadirá a un HTML ya existente entre <div> y </div> por lo tanto no puede contener <body> ni <head> ni otros elementos que van fuera de <body>.
La respuesta debe comenzar con '<H2>Historia y Desarrollo</H2> \n .
'''
resultado = genera_texto(prompt)
TextoFinal = TextoFinal+resultado.text
prompt='''
Eres un redactor de contenido experto en videojuegos,
Redacta el contenido de la sección 'Mecánica de juego' que será parte de un artículo sobre el juego 'Fortnite'.
Escribe párrafos largos, descriptivos con un estilo narrativo. Genera diferentes párrafos por cada subsección, hasta un máximo de 4 párrafos. En algunos casos usar jerarquía de etiquetas <H3>,<H4>.
Genera la respuesta en código HTML, este HTML se añadirá a un HTML ya existente entre <div> y </div> por lo tanto no puede contener <body> ni <head> ni otros elementos que van fuera de <body>.
La respuesta debe comenzar con '<H2>Mecánica de juego</H2>'
'''
resultado = genera_texto(prompt)
TextoFinal = TextoFinal+resultado.text
prompt='''
Eres un redactor de contenido experto en videojuegos,
Redacta el contenido de la sección 'Modos de juego' que será parte de un artículo sobre el juego 'Fortnite'.
Escribe párrafos largos, descriptivos con un estilo narrativo. Genera diferentes párrafos por cada subsección, hasta un máximo de 4 párrafos. En algunos casos usar jerarquía de etiquetas <H3>,<H4>.
Genera la respuesta en código HTML, este HTML se añadirá a un HTML ya existente entre <div> y </div> por lo tanto no puede contener <body> ni <head> ni otros elementos que van fuera de <body>.
La respuesta debe comenzar con '<H2>Modos de juego</H2>'
'''
resultado = genera_texto(prompt)
TextoFinal = TextoFinal+resultado.text
prompt='''
Eres un redactor de contenido experto en videojuegos,
Redacta el contenido de la sección 'Personajes y cosméticos' que será parte de un artículo sobre el juego 'Fortnite'.
Escribe párrafos largos, descriptivos con un estilo narrativo. Genera diferentes párrafos por cada subsección, hasta un máximo de 4 párrafos. En algunos casos usar jerarquía de etiquetas <H3>,<H4>.
Genera la respuesta en código HTML, este HTML se añadirá a un HTML ya existente entre <div> y </div> por lo tanto no puede contener <body> ni <head> ni otros elementos que van fuera de <body>.
La respuesta debe comenzar con '<h2>Personajes y cosméticos</h2>
'''
resultado = genera_texto(prompt)
TextoFinal = TextoFinal+resultado.text
prompt='''
Eres un redactor de contenido experto en videojuegos,
Redacta el contenido de la sección 'Impacto cultural' que será parte de un artículo sobre el juego 'Fortnite'.
Escribe párrafos largos, descriptivos con un estilo narrativo. Genera diferentes párrafos por cada subsección, hasta un máximo de 4 párrafos. En algunos casos usar jerarquía de etiquetas <H3>,<H4>.
Genera la respuesta en código HTML, este HTML se añadirá a un HTML ya existente entre <div> y </div> por lo tanto no puede contener <body> ni <head> ni otros elementos que van fuera de <body>.
La respuesta debe comenzar con '<H2>Impacto cultural</H2>'
'''
resultado = genera_texto(prompt)
TextoFinal = TextoFinal+resultado.text
print(TextoFinal)
Esto nos da un resultado mucho más extenso que en el anterior ejemplo, aquí el resultado tras ejecutarlo y montar el HTML, y ahora sí podemos decir que cumple el requisito de un mínimo de contenido. Pero esto nos limita a tener que predefiir previamente las secciones del artículo y puede ser un problema cuando quieres generar contenido para una diversidad de temas diferentes ya que puede que no todos los temas responden a una misma estructura de contenido.
Podemos hacer que sea el propio Gemini quién nos defina las secciones principales para cada artículo y así no tener que predefinir cada sección en cada artículo.
Para este caso vamos a solicitar las secciones principales para la redacción de un artículo sobre el vídeo juego 'Fortnite', este término lo definimos en la variable tituloPost.
Ya en texto del propio prompt le indicamos en qué formato de salida exacto queremos los resultados (así luego recorrerlos fácilmente). Para que el resultado se ajuste a un formato concreto, hemos definido la variable 'ejemploEsquema', con el esquema del resultado que nos gustaría recibir. Y al final de nuestro prompt sustituiremos '<ejemploEsquema>' por el contenido de nuestra variable para obtener secciones de un artículo concreto en formato determinado.
Ver este ejemplo concreto en Colab
ejemploEsquema="""
{
"secciones": [
"Nombre Seccion 1",
"Nombre Seccion 2",
"Nombre Seccion 3",
"Nombre Seccion 4",
"Nombre Seccion 5"
]
}
"""
tituloPost = "Fortnite"
prompt='''
Eres un redactor de contenido experto en videojuegos.
Ddefine entre 4 y 6 secciones que serán parte de un artículo sobre <titulo>.
Es MUY IMPORTANTE que la lista no contenga secciones que pudiesen contener elementos muy parecidos que otra seccion de la lista.
Devuelve una unica lista en formato JSON con el título para cada seción, cada seciión tendrá como máximo 10 palabras.
El esquema del JSON debe ser exactamente como esté: <ejemploEsquema>
'''
promptProcesado=prompt.replace('<titulo>',tituloPost).replace('<ejemploEsquema>',ejemploEsquema)
ResultadoPrompt = genera_texto(promptProcesado)
print(ResultadoPrompt.text)
Esto nos da el siguiente resultado:
{
"secciones": [
"Fundamentos del juego y mecánicas",
"Modos de juego y objetivos",
"Sistema de construcción y edición",
"Personajes, armas y equipo",
"Estrategia y tácticas avanzadas"
]
}
Perfecto! De esta manera podremos recorrer cada una de las secciones propuestas y solicitar que genere el texto completo para cada una de ellas.
Para procesar correctamente la respuesta anterior vamos a importar alguna librería en python que trate los resultados JSON y los convierta a una lista de manera que la podamos recorrer fácilmente.
Siguiendo nuestro ejemplo anterior vamos a recorrer cada sección que hemos almacenado en ResultadoPrompt.text
import json
def convertir_JSON_a_lista(json_data):
def extraer_elementos(data, clave, items, max_items):
if clave in data and isinstance(data[clave], list):
items.extend(data[clave][:max_items])
items = []
clave_poco = None
# Obtener la primera clave
first_key = next(iter(json_data))
# Extraer 5 elementos de la primera clave
extraer_elementos(json_data, first_key, items, 5)
# Si se encontró una clave con 'poco', extraer 4 elementos de esa clave
if clave_poco:
extraer_elementos(json_data, clave_poco, items, 4)
return items
jsondata = json.loads(ResultadoPrompt.text.replace('```json','').replace('```','').replace('JSON',''))
secciones = convertir_JSON_a_lista(jsondata)
cabeceras=[]
miContexto = ""
elementos=0
texto_Articulo=f'<h1>Eejemplo de bienes muebles</h1> '
for seccion in secciones:
seccion_lower = seccion.lower()
print(seccion)
Esto nos da como resultado:
Fundamentos del juego y mecánicas
Modos de juego y objetivos
Sistema de construcción y edición
Personajes, armas y equipo
Estrategia y tácticas avanzadas
Ok, vemos que podemos recorrer cada una de las secciones, lo único que nos falta es crear el contenido adecuado en cada una de ellas. Aquí está el código específico en Google colab.
import json
def convertir_JSON_a_lista(json_data):
def extraer_elementos(data, clave, items, max_items):
if clave in data and isinstance(data[clave], list):
items.extend(data[clave][:max_items])
items = []
clave_poco = None
# Obtener la primera clave
first_key = next(iter(json_data))
# Extraer 5 elementos de la primera clave
extraer_elementos(json_data, first_key, items, 5)
# Si se encontró una clave con 'poco', extraer 4 elementos de esa clave
if clave_poco:
extraer_elementos(json_data, clave_poco, items, 4)
return items
jsondata = json.loads(ResultadoPrompt.text.replace('```json','').replace('```','').replace('JSON',''))
secciones = convertir_JSON_a_lista(jsondata)
cabeceras=[]
miContexto = ""
elementos=0
TextoFinal=f'<h1><titulo></h1> '.replace('<titulo>',tituloPost)
for seccion in secciones:
seccion_lower = seccion.lower()
prompt='''
Eres un redactor de contenido experto en videojuegos,
Redacta el contenido de la sección '<seccion>' que será parte de un artículo sobre el juego '<titulo>'.
Escribe párrafos largos, descriptivos con un estilo narrativo. Genera diferentes párrafos por cada subsección, con un máximo de 4 párrafos. En algunos casos usar jerarquía de etiquetas <H3>,<H4>.
Genera la salida en formato HTML pero no puede contener <body> ni <head> ni otros elementos que van fuera de <body> porque este HTML se añadirá a un HTML ya existente.
La salida debe comenzar con '<h2><seccion></h2>
'''
resultado = genera_texto(prompt.replace('<seccion>',seccion).replace('<titulo>',tituloPost))
TextoFinal = TextoFinal+resultado.text
print(TextoFinal)
El resultado completo puedes verlo en este enlace, creo que en cuanto a cantidad de contenido dado un tema concreto es suficiente, pero todavía nos quedan cosas importantes por mejorar, una de ellas es la repetitividad de cierto contenido.
En este ejemplo que acabamos de ver no ha ocurrido, pero mientras creaba este artículo tuve varios casos en los que había información repetida o redundante, por ejemplo, este es un resultado que generé previamente usando este mismo prompt, si nos fijamos en su contenido tenemos que dentro de las secciones 'Mecánica de juego' y 'Modos de juego' existen subsecciones que se repiten, por ejemplo 'Salvar el mundo' y 'Salvamento del Mundo' o 'Battle Royale', es decir, el contenido de una y otra sección se solapan / pisan / duplican.
Este tipo de repetitividad es mucho más común de lo que quisiéramos, por lo que una de las maneras que se me han ocurrido para evitar esta repetitividad ha sido la de indicar al modelo qué información ya hemos ido añadiendo al artículo cada vez que solicitamos el texto de una nueva sección.
Para conseguir esto he creado una variable que se llama 'cabeceras', dónde iré incluyendo cada Hx y cada <li> que haya en las respuestas anteriores. Esto lo conseguimos creando una función 'ExtraerCabeceras' que extrae determinados tags HTML com Hx, o <li> que suelen ser los puntos importantes de cada subsección, esta información se la pasaremos al modelo para indicarle que el texto que va a crear no puede contener información que haga referencia a alguno de estas cabeceras, digamos que le estamos proporcionando un contexto negativo, es decir, la información que no debe incluir en el contenido de la sección que esté tratando.
from bs4 import BeautifulSoup
def ExtraerCabeceras(html_text):
soup = BeautifulSoup(html_text, 'html.parser')
# Inicializar la variable de contenido
content = []
# Extraer encabezados
headers = [tag.text for tag in soup.find_all(['h1', 'h2', 'h3', 'h4', 'h5', 'h6'])]
content.extend(headers) # Agregar encabezados a la lista de contenido
# Extraer listas ordenadas
for ol in soup.find_all('ol'):
items = [li.text for li in ol.find_all('li')]
content.append('Ordered List:')
content.extend(items) # Agregar elementos de lista ordenada a la lista de contenido
# Extraer listas desordenadas
for ul in soup.find_all('ul'):
items = [li.text for li in ul.find_all('li')]
content.append('Unordered List:')
content.extend(items) # Agregar elementos de lista desordenada a la lista de contenido
return content
Haciendo zoom en la parte del código en la que usaremos esta variable cabecera, dónde por cada texto generado de cada sección añadimos a la variable 'cabeceras' las cabeceras (hx, li) con la información relevante de cada sección para no repetirla al generar el texto de las siguientes secciones.
Por cada sección creamos una variable llamada 'miContexto', que generará una frase, la cual añadiremos a nuestro prompt indicando que información NO debe añadir a la sección actual porque previamente ha sido añadida.
La frase que añadiremos al prompt en cada sección tiene la estructura siguiente
"No puedes añadir la siguiente información que ya está en el artículo y sería información redundante y duplicada: <INFORMACION YA GENERADA> por lo tanto redacta el contenido con información complementaria a la que ya tiene"
Dónde sustituiremos <INFORMACION YA GENERADA> por las cabeceras de cada sección previamente generada.
secciones = convertir_JSON_a_lista(jsondata)
cabeceras=[]
miContexto = ""
elementos=0
TextoFinal=f'<h1><titulo></h1> '.replace('<titulo>',tituloPost)
for seccion in secciones:
seccion_lower = seccion.lower()
if len(cabeceras) > 1:
miContexto = "No puedes añadir la siguiente información que ya está en el artículo y sería información redundante y duplicada: \"" + ',\n '.join(cabeceras)+' '
miContexto=miContexto+'" por lo tanto redacta el contenido con información complementaria a la que ya tiene.'
prompt='''
Eres un redactor de contenido experto en videojuegos,
Redacta el contenido de la sección '<seccion>' que será parte de un artículo sobre el juego '<titulo>'.
Escribe párrafos largos, descriptivos con un estilo narrativo. Genera diferentes párrafos por cada subsección, con un máximo de 4 párrafos. En algunos casos usar jerarquía de etiquetas <H3>,<H4>.
Genera la respuesta en HTML, este HTML se añadirá a un HTML ya existente entre <div> y </div> por lo tanto no puede contener <body> ni <head> ni otros elementos que van fuera de <body>.
La respuesta debe comenzar con '<H2><seccion></H2> \n .
<miContexto>
'''
print("Prompt para la Seccion:",seccion)
print(prompt.replace('<seccion>',seccion).replace('<titulo>',tituloPost).replace('<miContexto>',miContexto))
resultado = genera_texto(prompt.replace('<seccion>',seccion).replace('<titulo>',tituloPost).replace('<miContexto>',miContexto))
TextoFinal = TextoFinal+resultado.text
cabeceras.extend(ExtraerCabeceras(resultado.text))
print("HTML RESULTADO FINAL:")
print(TextoFinal)
Ejemplo de cómo se van formando los prompts concatenando las cabeceras de las secciones anteriores (podéis acceder a este código en concreto).
Prompt para la Seccion: Fundamentos del juego y mecánicas
Eres un redactor de contenido experto en videojuegos,
Redacta el contenido de la sección 'Fundamentos del juego y mecánicas' que será parte de un artículo sobre el juego 'Fortnite'.
Escribe párrafos largos, descriptivos con un estilo narrativo. Genera diferentes párrafos por cada subsección, con un máximo de 4 párrafos. En algunos casos usar jerarquía de etiquetas <H3>,<H4>.
Genera la respuesta en HTML, este HTML se añadirá a un HTML ya existente entre <div> y </div> por lo tanto no puede contener <body> ni <head> ni otros elementos que van fuera de <body>.
La respuesta debe comenzar con '<H2>Fundamentos del juego y mecánicas</H2>
.
Prompt para la Seccion: Modos de juego y objetivos
Eres un redactor de contenido experto en videojuegos,
Redacta el contenido de la sección 'Modos de juego y objetivos' que será parte de un artículo sobre el juego 'Fortnite'.
Escribe párrafos largos, descriptivos con un estilo narrativo. Genera diferentes párrafos por cada subsección, con un máximo de 4 párrafos. En algunos casos usar jerarquía de etiquetas <H3>,<H4>.
Genera la respuesta en HTML, este HTML se añadirá a un HTML ya existente entre <div> y </div> por lo tanto no puede contener <body> ni <head> ni otros elementos que van fuera de <body>.
La respuesta debe comenzar con '<H2>Modos de juego y objetivos</H2>
.
No puedes añadir la siguiente información que ya está en el artículo y sería información redundante y duplicada: "Fundamentos del juego y mecánicas,
El bucle de juego de Fortnite,
El sistema de construcción,
Combate y armas " por lo tanto redacta el contenido con información complementaria a la que ya tiene.
Prompt para la Seccion: Sistema de construcción y edición
Eres un redactor de contenido experto en videojuegos,
Redacta el contenido de la sección 'Sistema de construcción y edición' que será parte de un artículo sobre el juego 'Fortnite'.
Escribe párrafos largos, descriptivos con un estilo narrativo. Genera diferentes párrafos por cada subsección, con un máximo de 4 párrafos. En algunos casos usar jerarquía de etiquetas <H3>,<H4>.
Genera la respuesta en HTML, este HTML se añadirá a un HTML ya existente entre <div> y </div> por lo tanto no puede contener <body> ni <head> ni otros elementos que van fuera de <body>.
La respuesta debe comenzar con '<H2>Sistema de construcción y edición</H2>
.
No puedes añadir la siguiente información que ya está en el artículo y sería información redundante y duplicada: "Fundamentos del juego y mecánicas,
El bucle de juego de Fortnite,
El sistema de construcción,
Combate y armas,
Modos de juego y objetivos,
Battle Royale,
Salvar el mundo,
Cooperativo para 4 jugadores,
Creativo " por lo tanto redacta el contenido con información complementaria a la que ya tiene.
Prompt para la Seccion: Personajes, armas y equipo
Eres un redactor de contenido experto en videojuegos,
Redacta el contenido de la sección 'Personajes, armas y equipo' que será parte de un artículo sobre el juego 'Fortnite'.
Escribe párrafos largos, descriptivos con un estilo narrativo. Genera diferentes párrafos por cada subsección, con un máximo de 4 párrafos. En algunos casos usar jerarquía de etiquetas <H3>,<H4>.
Genera la respuesta en HTML, este HTML se añadirá a un HTML ya existente entre <div> y </div> por lo tanto no puede contener <body> ni <head> ni otros elementos que van fuera de <body>.
La respuesta debe comenzar con '<H2>Personajes, armas y equipo</H2>
.
No puedes añadir la siguiente información que ya está en el artículo y sería información redundante y duplicada: "Fundamentos del juego y mecánicas,
El bucle de juego de Fortnite,
El sistema de construcción,
Combate y armas,
Modos de juego y objetivos,
Battle Royale,
Salvar el mundo,
Cooperativo para 4 jugadores,
Creativo,
Sistema de construcción y edición,
Construyendo tu camino hacia la victoria,
Materiales versátiles,
Edición precisa y formas complejas,
Trabajo en equipo y colaboración " por lo tanto redacta el contenido con información complementaria a la que ya tiene.
Prompt para la Seccion: Estrategia y tácticas avanzadas
Eres un redactor de contenido experto en videojuegos,
Redacta el contenido de la sección 'Estrategia y tácticas avanzadas' que será parte de un artículo sobre el juego 'Fortnite'.
Escribe párrafos largos, descriptivos con un estilo narrativo. Genera diferentes párrafos por cada subsección, con un máximo de 4 párrafos. En algunos casos usar jerarquía de etiquetas <H3>,<H4>.
Genera la respuesta en HTML, este HTML se añadirá a un HTML ya existente entre <div> y </div> por lo tanto no puede contener <body> ni <head> ni otros elementos que van fuera de <body>.
La respuesta debe comenzar con '<H2>Estrategia y tácticas avanzadas</H2>
.
No puedes añadir la siguiente información que ya está en el artículo y sería información redundante y duplicada: "Fundamentos del juego y mecánicas,
El bucle de juego de Fortnite,
El sistema de construcción,
Combate y armas,
Modos de juego y objetivos,
Battle Royale,
Salvar el mundo,
Cooperativo para 4 jugadores,
Creativo,
Sistema de construcción y edición,
Construyendo tu camino hacia la victoria,
Materiales versátiles,
Edición precisa y formas complejas,
Trabajo en equipo y colaboración,
Personajes, armas y equipo,
Personajes,
Armas,
Equipo,
Otros artículos " por lo tanto redacta el contenido con información complementaria a la que ya tiene.
Estos serían los prompts ejecutados en cada sección, dónde podemos ver cómo le vamos dando los elementos generados en secciones anteriores para que no los repita, en este ejemplo vemos que:
El resultado final podemos verlo en esta URL , tiene un total de más de 1.300 palabras!
Con un resultado HTML mucho más extenso que realizándose todo de golpe y con unas mínimas posibilidades de que exista información redundante entre las diferentes secciones podríamos decir que este sistema genera contenido extenso, en formato HTML y con mínimas duplicidades.
Vamos a poner el código completo de este script
from google.colab import auth
auth.authenticate_user()
import vertexai
from vertexai.preview.generative_models import GenerativeModel, Part
import json
from bs4 import BeautifulSoup
IDPROYECTO="ID_PROYECTO"
ZONA_PROYECTO='us-central1'
tituloPost = "Mario Kart"
vertexai.init(project=IDPROYECTO, location=ZONA_PROYECTO)
def genera_texto(ejecutaPrompt: str) -> str:
# Initialize Vertex AI
# Load the model
model = GenerativeModel("gemini-pro")
response = model.generate_content(
ejecutaPrompt,
generation_config={
"max_output_tokens": 8192,
"temperature": 0.9,
"top_p": 1
},
)
return response
def ExtraerCabeceras(html_text):
soup = BeautifulSoup(html_text, 'html.parser')
# Inicializar la variable de contenido
content = []
# Extraer encabezados
headers = [tag.text for tag in soup.find_all(['h1', 'h2', 'h3', 'h4', 'h5', 'h6'])]
content.extend(headers) # Agregar encabezados a la lista de contenido
# Extraer listas ordenadas
for ol in soup.find_all('ol'):
items = [li.text for li in ol.find_all('li')]
content.append('Ordered List:')
content.extend(items) # Agregar elementos de lista ordenada a la lista de contenido
# Extraer listas desordenadas
for ul in soup.find_all('ul'):
items = [li.text for li in ul.find_all('li')]
content.append('Unordered List:')
content.extend(items) # Agregar elementos de lista desordenada a la lista de contenido
return content
def convertir_JSON_a_lista(json_data):
def extraer_elementos(data, clave, items, max_items):
if clave in data and isinstance(data[clave], list):
items.extend(data[clave][:max_items])
items = []
clave_poco = None
# Obtener la primera clave
first_key = next(iter(json_data))
# Extraer 5 elementos de la primera clave
extraer_elementos(json_data, first_key, items, 5)
# Si se encontró una clave con 'poco', extraer 4 elementos de esa clave
if clave_poco:
extraer_elementos(json_data, clave_poco, items, 4)
return items
ejemploEsquema="""
{
"secciones": [
"Nombre Seccion 1",
"Nombre Seccion 2",
"Nombre Seccion 3",
"Nombre Seccion 4",
"Nombre Seccion 5"
]
}
"""
prompt='''
Eres un redactor de contenido experto en videojuegos.
Ddefine entre 4 y 6 secciones que serán parte de un artículo sobre <titulo>.
Es MUY IMPORTANTE que la lista no contenga secciones que pudiesen contener elementos muy parecidos que otra seccion de la lista.
Devuelve una unica lista en formato JSON con el título para cada seción, cada seciión tendrá como máximo 10 palabras.
El esquema del JSON debe ser exactamente como esté: <ejemploEsquema>
'''
promptProcesado=prompt.replace('<titulo>',tituloPost).replace('<ejemploEsquema>',ejemploEsquema)
ResultadoPrompt = genera_texto(promptProcesado)
print(ResultadoPrompt.text)
jsondata = json.loads(ResultadoPrompt.text.replace('```json','').replace('```','').replace('JSON',''))
secciones = convertir_JSON_a_lista(jsondata)
cabeceras=[]
miContexto = ""
elementos=0
TextoFinal=f'<h1><titulo></h1> '.replace('<titulo>',tituloPost)
for seccion in secciones:
seccion_lower = seccion.lower()
if len(cabeceras) > 1:
miContexto = "No puedes añadir la siguiente información que ya está en el artículo y sería información redundante y duplicada: \"" + ',\n '.join(cabeceras)+' '
miContexto=miContexto+'" por lo tanto redacta el contenido con información complementaria a la que ya tiene.'
prompt='''
Eres un redactor de contenido experto en videojuegos,
Redacta el contenido de la sección '<seccion>' que será parte de un artículo sobre el juego '<titulo>'.
Escribe párrafos largos, descriptivos con un estilo narrativo. Genera diferentes párrafos por cada subsección, con un máximo de 4 párrafos. En algunos casos usar jerarquía de etiquetas <H3>,<H4>.
Genera la respuesta en HTML, este HTML se añadirá a un HTML ya existente entre <div> y </div> por lo tanto no puede contener <body> ni <head> ni otros elementos que van fuera de <body>.
La respuesta debe comenzar con '<H2><seccion></H2> \n .
<miContexto>
'''
print("Prompt para la Seccion:",seccion)
print(prompt.replace('<seccion>',seccion).replace('<titulo>',tituloPost).replace('<miContexto>',miContexto))
resultado = genera_texto(prompt.replace('<seccion>',seccion).replace('<titulo>',tituloPost).replace('<miContexto>',miContexto))
TextoFinal = TextoFinal+resultado.text
cabeceras.extend(ExtraerCabeceras(resultado.text))
print("HTML RESULTADO FINAL:")
print(TextoFinal)
Hay mucho que se puede mejorar en este prompt, pero en cuanto a los problemas que intenta resolver se puede mejorar: