Letzte Woche hatte ich die Ehre, eines auf TheJam.dev vorzustellen. Dies war meine erste Präsentation über generative KI und ich konnte einen meiner Meinung nach interessanten Anwendungsfall vorstellen – die Unterstützung beim Schreibprozess.
Um es klarzustellen: Ich meine nicht, GenAI zum Schreiben von Blogbeiträgen zu verwenden, das wäre eine schreckliche Idee. (Meiner Meinung nach!) Stattdessen habe ich mir angesehen, wie es bei einigen Prozessen helfen könnte. Lassen Sie mich etwas zurückhalten und einige Hintergrundinformationen geben.
Ich bin schon seit vielen Jahren ein Fan von John Birmingham . Er ist ein Autor, der im Genre Militär/Science-Fiction usw. schreibt und einige ziemlich faszinierende Ideen hat. Ich habe ihn zunächst über seine „Achse der Zeit“-Trilogie entdeckt, in der es um die Idee einer modernen internationalen Marine geht, die in die Zeit von 1942 zurückgeschickt wird.
Das ist an sich schon cool, aber ich fand es toll, dass er sich nicht nur auf den militärischen Aspekt konzentrierte, sondern viel Zeit damit verbrachte, über den Kulturkonflikt zwischen den „Uptimern“ (Menschen aus der Zukunft) und den Zeitgenossen zu sprechen.
Ich nehme an, man könnte sagen, es war ein bisschen wie Tom Clancy, aber der Fokus lag nicht nur auf der Action. Ich würde so ziemlich jedes seiner Bücher empfehlen, und wenn Sie ihn bereits gelesen haben, lassen Sie es mich unten in einem Kommentar wissen.
Als Anhänger seiner Arbeit habe ich seinen Patreon abonniert und es war wirklich interessant. Er teilt Entwürfe von Kapiteln aus kommenden Werken, aber was noch wichtiger ist, er spricht auch ziemlich viel über seinen Prozess. Da ich selbst Autor bin, finde ich das wirklich faszinierend.
Kürzlich sprach er über seinen eigenen Einsatz von GenAI und erörterte, wie er es eher aus einer „Framework“-Perspektive nutzt. Das heißt, wie man das Motiv einer Figur zum richtigen Zeitpunkt einbringt und wie man Handlungspunkte festlegt. Das ist immer noch „kreative“ Arbeit, aber mehr ... ich weiß es nicht. Leitung der Arbeit?
Aber wie gesagt, ich fand es wirklich interessant und hat mich zum Nachdenken gebracht. Wie könnte ich GenAI in meinem Blog nutzen, um den Schreibprozess zu unterstützen? Hier ist, was ich mir ausgedacht habe.
Kurz nebenbei: Alles, was ich unten bespreche, nutzt die Gemini-API von Google und Eleventy , wäre aber sicherlich auch anderswo nützlich.
Die erste Demo, die ich erstellt habe, bestand darin, mir bei der Entwicklung von Titeln für Blogbeiträge zu helfen. Normalerweise habe ich damit keine Probleme, aber ich war neugierig, ob GenAI vielleicht Alternativen für bessere Titel vorschlagen könnte.
Ich begann damit, eine Eingabeaufforderung auszuprobieren:
gemi
Teilen Sie angesichts des folgenden Titels für einen Blogbeitrag drei Vorschläge mit, die den Titel verbessern und den Traffic für den Beitrag steigern können: „EINIGE TITEL“. Präsentieren Sie Ihre Antwort im JSON-Format. Der Schlüssel der obersten Ebene des JSON-Ergebnisses sollte „Vorschläge“ lauten und jeder Vorschlag sollte den Schlüssel „title“ für den vorgeschlagenen Titel und „reasoning“ für die Begründung verwenden.
Sie werden feststellen, dass ich ausdrücklich um drei Vorschläge bitte und sage, dass ich dazu beitragen möchte, mehr Traffic zu generieren. Nun, ich bin ehrlich. Das fühlt sich etwas eklig und spammig an. Ich möchte nicht unbedingt Clickbait-Titel. Davon abgesehen wollte ich noch ein paar andere Ideen für meine Titel sehen.
Diese Eingabeaufforderung schien bei einigen Tests in AI Studio gut zu funktionieren, also sprang ich in den Code ein. Ich habe den von Google exportierten Code genommen und dann ein wenig Code geschrieben:
Hier ist das gesamte Skript:
#!/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('------------------------------------------------------------------------'); }); })();
Und wie funktioniert es? Dieser Blogbeitrag trägt den Titel: „Verwenden Sie generative KI als Ihren Inhaltsassistenten“
Folgendes hat Gemini vorgeschlagen:
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.
Ja... ich finde das ziemlich cool. Allerdings fühlt sich hier nichts davon wirklich wie „meine“ Stimme an. Ich sehe in den Vorschlägen auf jeden Fall einen gewissen Wert und es gibt mir Anlass zum Nachdenken, aber natürlich habe ich den Originaltitel unverändert gelassen.
Für meine nächste Demo habe ich einen Teil meines Schreibprozesses untersucht, der mir wirklich keinen Spaß macht, nämlich das Schreiben der description
mit einem Satz, die in meiner Titelseite verwendet wird. Diese Zeichenfolge landet schließlich in meinem <meta name="description">
-Tag und wird nirgendwo anders verwendet.
Ich dachte, dass dies eine hervorragende Nutzung der Zusammenfassungsfunktion von GenAI wäre. Ich begann mit einer Aufforderung wie dieser:
Schreiben Sie anhand des folgenden Blogbeitrags eine Zusammenfassung in einem Satz, die Sie als Beschreibung verwenden können
Und dann überlegte ich, welche Inhalte ich senden würde. Meine Blog-Beiträge enthalten normalerweise viele Codebeispiele, und ich ging davon aus, dass das am Ende nur Rauschen sein würde. So wurde meine Logik:
Das meiste davon ist nur eine modifizierte Version des ersten Beispiels, aber werfen wir einen Blick auf den Bereinigungsaspekt:
function cleanup(str) { str = str.replace(/```(.*?)```/sg, ''); str = str.replace(/---(.*?)---/sg, ''); str = str.replace(/\n{3,}/g, '\n'); return str.trim(); }
Dabei handelt es sich um den gesamten Inhalt des Blog-Beitrags, daher habe ich den Titel und die Codebeispiele entfernt. Ich habe dann auch mehrere Leerzeilen ersetzt. Hier ist das gesamte Skript:
#!/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); })();
Und hier ist, was es für einen Beitrag von vor ein paar Tagen zeigt : „Using Generative AI to Improve Image Filenames“ :
This post explores how Generative AI can be used to enhance image filenames, making them more descriptive, accurate, and consistent.
Ich muss sagen, das ist genau richtig! Und ich mache mir keine großen Sorgen um die „Stimme“ dafür. Ich habe es für diesen Beitrag verwendet (nachdem ich fertig war) und bekam (und verwendete) – Folgendes:
Verbessern Sie Ihren Content-Erstellungsprozess, indem Sie generative KI als Ihren virtuellen Schreibassistenten nutzen.
Wenn Sie das interessiert, Sie aber gerne zusehen würden, wie ich beim Betrachten eines LEGO-Todessterns weiterschweife, können Sie sich die folgende Präsentation ansehen:
Meine beiden oben gezeigten Skripte befinden sich in meinem Repo und können im Skriptverzeichnis hier gefunden werden: https://github.com/cfjedimaster/raymondcamden2023/tree/main/scripts
Teilen Sie mir unten in einem Kommentar Ihre Meinung mit!