La semana pasada tuve el honor de presentar uno en TheJam.dev . Esta fue mi primera presentación sobre IA generativa y pude compartir lo que pensé que era un caso de uso interesante: ayudar con el proceso de escritura.
Ahora, para ser claros, no me refiero a usar GenAI para escribir publicaciones de blog, sería una idea horrible. (¡En mi opinión!) En cambio, miré cómo podría ayudar con parte del proceso. Permítanme retroceder un poco y brindarles algunos antecedentes.
Soy fan de John Birmingham desde hace muchos años. Es un autor que escribe en el género militar/ciencia ficción/etc. y tiene algunas ideas bastante fascinantes. Inicialmente lo descubrí a través de su trilogía "Axis of Time", que trataba sobre la idea de una flota naval internacional moderna enviada al pasado, hasta 1942.
Ahora, eso por sí solo es genial, sin embargo, me encantó que no se centrara solo en el aspecto militar sino que pasara mucho tiempo hablando sobre el choque cultural entre los "uptimers" (gente del futuro) y los contemporáneos.
Supongo que se podría decir que era un poco como Tom Clancy pero no sólo centrado en la acción. Recomendaría cualquiera de sus libros y, si ya lo has leído, házmelo saber en un comentario a continuación.
Como seguidor de su trabajo, me suscribí a su Patreon y ha sido realmente interesante. Comparte borradores de capítulos de próximos trabajos, pero lo más importante es que también habla bastante sobre su proceso. Como escritor, esto me parece realmente fascinante.
Recientemente, habló sobre su propio uso de GenAI y discutió cómo lo está usando desde una perspectiva más de "marco". Es decir, cómo introducir el motivo de un personaje en el momento adecuado y cómo establecer los puntos de la trama. Esto sigue siendo un trabajo 'creativo', pero más... no lo sé. ¿Gestión de la obra?
Sin embargo, como dije, pensé que era realmente interesante y me hizo pensar. ¿Cómo podría utilizar GenAI en mi blog como una forma de ayudar con el proceso de escritura? Esto es lo que se me ocurrió.
Como comentario breve, todo lo que analizo a continuación utiliza la API Gemini y Eleventy de Google, pero sin duda sería útil en otros lugares.
La primera demostración que construí implicó ayudarme a crear títulos para publicaciones de blog. Normalmente no tengo problemas con esto, pero tenía curiosidad por saber si GenAI podría sugerir alternativas para mejores títulos.
Comencé probando un mensaje:
gemi
Dado el siguiente título para una publicación de blog, comparta tres sugerencias que puedan mejorar el título y generar tráfico a la publicación: "ALGÚN TÍTULO". Presente su respuesta en formato JSON. La clave de nivel superior del resultado JSON debe ser "sugerencias" y cada sugerencia debe usar la clave "título" para el título sugerido y "razonamiento" para el razonamiento.
Notarás que pido específicamente tres sugerencias y digo que quiero ayudar a generar más tráfico. Ahora, seré honesto. Eso parece un poco asqueroso y spam. No necesariamente quiero títulos clickbait. Dicho esto, quería ver otras ideas para mis títulos.
Ese mensaje pareció funcionar bien con algunas pruebas en AI Studio , así que salté al código. Tomé el código que Google exportó y luego escribí un poco de código para:
Aquí está el guión completo:
#!/usr/bin/env node /* Given an input MD file, grab the title, and ask Google's AI APIs to offer suggestions. */ const fs = require('fs'); const fm = require('front-matter'); require('dotenv').config({path:__dirname + '/.env'}); const { GoogleGenerativeAI, HarmCategory, HarmBlockThreshold, } = require("@google/generative-ai"); const MODEL_NAME = "gemini-pro"; const API_KEY = process.env.GOOGLE_AI_KEY; async function runGenerate(title) { const genAI = new GoogleGenerativeAI(API_KEY); const model = genAI.getGenerativeModel({ model: MODEL_NAME }); const generationConfig = { temperature: 0.9, topK: 1, topP: 1, maxOutputTokens: 2048, }; const safetySettings = [ { category: HarmCategory.HARM_CATEGORY_HARASSMENT, threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE, }, { category: HarmCategory.HARM_CATEGORY_HATE_SPEECH, threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE, }, { category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT, threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE, }, { category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE, }, ]; const parts = [ {text: `Given the following title for a blog post, share three suggestions that may improve the title and drive traffic to the post: \"${title}\". Present your answer in JSON form. The top level key of the JSON result should be "suggestions" and each suggestion should use the key "title" for the suggested title and "reasoning" for the reasoning. The returned JSON should look like the following sample: [ { title: "First suggested title", reasoning: "This is the reason for the suggestion." } ] `}, ]; const result = await model.generateContent({ contents: [{ role: "user", parts }], generationConfig, safetySettings, }); const response = result.response; // remove backticks and parse. I'm seeing ```json sometimes too // console.log('DEBUG', response.text()); return JSON.parse(response.text().replace(/```/mg, '').replace(/```json/mg,'')); } (async () => { if(process.argv.length === 2) { console.log('Usage: titlesuggestions.js <<path to md>>'); process.exit(1); } const mdPath = process.argv[2]; if(!fs.existsSync(mdPath)) { console.log(`Unable to find ${mdPath}.`); process.exit(1); } const contents = fs.readFileSync(mdPath,'utf-8'); let title = fm(contents).attributes.title; console.log(`\nGenerating suggestions for: ${title}`); console.log('------------------------------------------------------------------------'); let suggestions = (await runGenerate(title)).suggestions; //console.log(suggestions); suggestions.forEach(s => { console.log(`Suggested Title: ${s['title']}\n\nReasoning: ${s['reasoning']}\n`); console.log('------------------------------------------------------------------------'); }); })();
Y, ¿cómo funciona? Esta publicación de blog se titula: "Uso de IA generativa como asistente de contenido"
Esto es lo que sugirió Géminis:
Suggested Title: The Power of Generative AI: Your New Content Assistant Reasoning: This title emphasizes the strength and potential of generative AI as a content creation tool, capturing the reader's attention and making them curious about the possibilities it offers. ------------------------------------------------------------------------ Suggested Title: Unlock Your Content Creation Potential with Generative AI Reasoning: This title suggests that generative AI can unlock new levels of productivity and creativity in content creation, attracting readers who are looking for ways to enhance their content strategy. ------------------------------------------------------------------------ Suggested Title: Revolutionize Your Content Creation: Meet Your Generative AI Assistant Reasoning: This title highlights the transformative potential of generative AI in content creation, appealing to readers who are eager to adopt cutting-edge technologies to streamline their workflow.
Sí... creo que eso es genial. Sin embargo, ninguno de estos realmente se siente como "mi" voz aquí. Veo absolutamente algún mérito en las sugerencias y me dan algo en qué pensar, pero obviamente dejé el título original como está.
Para mi siguiente demostración, analicé una parte de mi proceso de escritura que realmente no disfruto: escribir el valor description
de una oración utilizado en mi presentación. Esta cadena termina en mi etiqueta <meta name="description">
y no se usa en ningún otro lugar.
Pensé que este sería un uso excelente de la función de resumen de GenAI. Comencé con un mensaje como este:
Dada la siguiente publicación de blog, escriba un resumen de una oración para usarlo como descripción.
Y luego pensé en qué contenido enviaría. Las publicaciones de mi blog suelen tener muchos ejemplos de código y pensé que eso terminaría siendo ruido. Entonces mi lógica se convirtió en:
La mayor parte de esto es sólo una versión modificada del primer ejemplo, pero echemos un vistazo al aspecto de limpieza:
function cleanup(str) { str = str.replace(/```(.*?)```/sg, ''); str = str.replace(/---(.*?)---/sg, ''); str = str.replace(/\n{3,}/g, '\n'); return str.trim(); }
Esto incluye todo el contenido de la publicación del blog, por lo que eliminé la portada y los ejemplos de código. Luego también reemplacé varias líneas en blanco. Aquí está el guión completo:
#!/usr/bin/env node /* Given an input MD file, grab the text, scrub code, and ask for a summary. */ const fs = require('fs'); const fm = require('front-matter'); require('dotenv').config({path:__dirname + '/.env'}); const { GoogleGenerativeAI, HarmCategory, HarmBlockThreshold, } = require("@google/generative-ai"); const MODEL_NAME = "gemini-pro"; const API_KEY = process.env.GOOGLE_AI_KEY; async function runGenerate(text) { const genAI = new GoogleGenerativeAI(API_KEY); const model = genAI.getGenerativeModel({ model: MODEL_NAME }); const generationConfig = { temperature: 0.9, topK: 1, topP: 1, maxOutputTokens: 2048, }; const safetySettings = [ { category: HarmCategory.HARM_CATEGORY_HARASSMENT, threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE, }, { category: HarmCategory.HARM_CATEGORY_HATE_SPEECH, threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE, }, { category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT, threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE, }, { category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE, }, ]; const parts = [ {text: `Given the following blog post, write a one sentence summary to use as the description:\n${text} `}, ]; const result = await model.generateContent({ contents: [{ role: "user", parts }], generationConfig, safetySettings, }); return result.response.candidates[0].content.parts[0].text; } /* I'm responsible for 'cleaning' up the text before sending to Google. For now, I'll just remove code blocks, but in the future I may remove images too. Also remove double blank lines. Oh, also remove FM. */ function cleanup(str) { str = str.replace(/```(.*?)```/sg, ''); str = str.replace(/---(.*?)---/sg, ''); str = str.replace(/\n{3,}/g, '\n'); return str.trim(); } (async () => { if(process.argv.length === 2) { console.log('Usage: summarysuggestions.j <<path to md>>'); process.exit(1); } const mdPath = process.argv[2]; if(!fs.existsSync(mdPath)) { console.log(`Unable to find ${mdPath}.`); process.exit(1); } let contents = fs.readFileSync(mdPath,'utf-8'); let title = fm(contents).attributes.title; // Make it nicer! contents = cleanup(contents); console.log(`\nGenerating summary suggestion for: ${title}`); console.log('------------------------------------------------------------------------'); let suggestion = (await runGenerate(title)); console.log(suggestion); })();
Y esto es lo que muestra una publicación de hace unos días, "Uso de IA generativa para mejorar los nombres de archivos de imágenes" :
This post explores how Generative AI can be used to enhance image filenames, making them more descriptive, accurate, and consistent.
¡Tengo que decir que es bastante acertado! Y no me preocupa tanto la 'voz' por eso. Seguí adelante y lo usé para esta publicación (después de terminar), y obtuve (y usé) esto:
Mejore su proceso de creación de contenido utilizando IA generativa como su asistente de escritura virtual.
Si esto te interesa pero te encantaría verme divagar mientras miro una Estrella de la Muerte LEGO, puedes ver la presentación a continuación:
Los dos scripts que se muestran arriba están en mi repositorio y se pueden encontrar en el directorio de scripts aquí: https://github.com/cfjedimaster/raymondcamden2023/tree/main/scripts
¡Déjame saber lo que piensas en un comentario a continuación!