見出し画像

【自動日記ツール】Googleでアップスクリプトの作成:後編


年末に今年一年を振り返るために、毎日の出来事が自動的に日記として生成されていてほしいのだ。

そんな欲望をもとに考えた一連の仕組みがあるので、今日は、それを紹介します。

本記事だけを読んでも意味がわからないと思いますが、もし、興味のある方は、一連の流れを以下の記事にしていますので、こちらをご参照ください。


今回は、「Googleでアップスクリプトの作成」の以下記事に続く、後編です

いよいよ、「AIでイラストを作成する」という最新技術(でももうなくなってきてますけども)の導入になります。

※以降は、前編と「同じノリ」です

DALL-Eへ送るpromptを生成するためのGAS


上記キャプチャの前半部分です。
DALL-Eには、「どのようなイラストを描いてほしいか」を連絡する必要がありますが、日記の内容をただ送っただけでは、うまくありません。
「今日はご飯を食べて、仕事をして、映画を見に行った」と言われても、絵は描けないです。
そのため、日記の内容をもとに、「今日のイラストはどのようなイラストにしようか」と、一度GPTに揉んでもらうことにしました。

くわしくは、以下のnoteで書いていますので、参考にされてください(宣伝)
https://note.com/kamicup/n/nb51d66b5ccdb

本コードでは、「prompt」シートのセルC2と、先に作成した日記の内容をあわせてGPTに送ることで、上記のとおり、揉んでくれるようになっています。
また、著作権などの関係からか、めちゃくちゃ平和な内容でもコンテンツモデレーションにひっかかることがあるので、3回試行するように設定しています。



function extractEventFromDiary(apiUrl, headers, diaryContent) {
  // promptシートのC2から参照した内容を取得
  const promptSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('prompt');
  const additionalContent = promptSheet.getRange('C2').getValue();

  // C2の内容とdiaryContentを結合
  const combinedContent = additionalContent + diaryContent;

  const messagesForEventExtraction = [{
    'role': 'system',
    'content': combinedContent
  }];

  let jsonResponse = null;
  const optionsForEventExtraction = {
    'muteHttpExceptions': true,
    'headers': headers,
    'method': 'POST',
    'payload': JSON.stringify({
      'model': 'gpt-4-turbo-preview',
      'max_tokens': 1500,
      'temperature': 0.9,
      'messages': messagesForEventExtraction
    })
  };

  // 最大3回まで再試行する
  for (let attempt = 0; attempt < 3; attempt++) {
    const response = UrlFetchApp.fetch(apiUrl, optionsForEventExtraction);
    jsonResponse = JSON.parse(response.getContentText());

    if (jsonResponse.choices && jsonResponse.choices.length > 0) {
      // 成功した場合は結果を返す
      return jsonResponse.choices[0].message.content;
    } else {
      // 失敗した場合はログを出力し、再試行する
      console.log(`試行 ${attempt + 1}: 特徴的な出来事の抽出に失敗しました。`);
    }
  }

  // 3回試行しても成功しなかった場合
  console.log('特徴的な出来事の抽出に3回試行しても失敗しました。');
  return null;
}


DALL-Eへのイラストの指示をだすGAS


全工程の最後になる、イラストの作成〜保存部分です。

DALL-Eには、「どのようなイラストを描いてほしいか」を連絡する必要がありますが、情景の指示をただ送っただけでは、うまくありません。
「黒い猫が、窓辺で日向ぼっこをしている。太陽の光は暖かく、眠っている様子だ」と言われても、どのような画材を使うのかわからないと求められる絵は描けないです。

いや、DALL-Eは、描けます。
描けるんですけど、「そのときどきで、選ぶ画風が異なる」ので、統一したいっていう話です。

そのため、先ほど揉んでもらった内容に更にプラスして、「どのような画風で書いてほしいのか」を固定で指示するpromptを足すことにしました。

いまどきのアニメ風イラストになるpromptは、以下のnoteで書いていますので、参考にされてください(宣伝)
https://note.com/kamicup/n/nee587dc9450f

本コードでは、「prompt」シートのセルD2と、先に生成したpromptの内容をあわせてGPTに送ることで、上記のとおり、画風の指定もできるようになっています。

また、著作権などの関係からか、めちゃくちゃ平和な内容でもコンテンツモデレーションにひっかかることがあるので、3回試行するように設定しています。

加えて、作成されたイラストが、「前編」で作成されたドキュメントに添付され、サイズをドキュメントのサイズに調整するようにしています。

これで、完全自動の絵日記ツールが完成です。


function createIllustrationPrompt(eventContent) {
  // promptシートのD2から参照した内容を取得
  const promptSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('prompt');
  const cellD5Content = promptSheet.getRange('D2').getValue();

  // セルD2の内容とeventContentを結合してプロンプトを作成
  return `${cellD5Content} ${eventContent}`;
}

function requestIllustration(apiUrl, options, docId) {
  let attempts = 0;
  let success = false;

  while (attempts < 3 && !success) {
    attempts++;
    const responseText = UrlFetchApp.fetch(apiUrl, options).getContentText();
    const response = JSON.parse(responseText);
    
    if (response && response.data && response.data.length > 0) {
      const imageUrl = response.data[0].url;
      const imageResponse = UrlFetchApp.fetch(imageUrl);
      const imageBlob = imageResponse.getBlob();
      const doc = DocumentApp.openById(docId);
      const body = doc.getBody();
      
      const image = body.insertImage(0, imageBlob);
      const desiredWidth = 600;
      const imageWidth = image.getWidth();
      const imageHeight = image.getHeight();
      const aspectRatio = imageHeight / imageWidth;
      image.setWidth(desiredWidth);
      image.setHeight(desiredWidth * aspectRatio);
      
      console.log('イラストをドキュメントに挿入し、サイズを調整しました。');
      success = true; // 成功した場合はループを抜けます
    } else {
      console.log('再試行します。試行回数: ' + attempts);
      if (attempts >= 3) {
        console.log('イラストの生成に3回失敗しました。');
      }
    }
  }
}


function buildImageRequestOptions(illustrationPrompt) {
  const apiKey = ScriptProperties.getProperty('OpenAI_key');
  return {
    'muteHttpExceptions': true,
    'headers': {
      'Authorization': 'Bearer ' + apiKey,
      'Content-Type': 'application/json',
      'X-Slack-No-Retry': 1
    },
    'method': 'POST',
    'payload': JSON.stringify({
      'model': 'dall-e-3',
      'quality': 'standard',
      'style': 'vivid',
      'n': 1,
      'size': '1792x1024',
      'prompt': illustrationPrompt
    })
  };
}

テストで実行してみる

ここまでできたら、一度、テストしてみます。
「diary.gs」を開いて、「選択した関数を実行」を押してみます。

今回で、すべてのコードが完成していますので、うまくいけばエラーにならずに、ドキュメントの保存がされ、メールが届くはずです。

届かなかったときは、以下の設定に何らかの異常が発生していると要因が考えられます。
1: スクリプトプロパティの設定
2: GASコードの記載
3: APIkeyの取得
4: openAIとの契約(課金)
5: スクリプト実行権限

エラーコードをもとに、GPTに聞いてみることをおすすめします。(わたしは絶対わからないです)


テスト結果を確認する

うまくいけば、Googleドキュメントファイルが作成され、また、設定したメールアドレスあてにメールがとどいているはずです。


この記事が気に入ったらサポートをしてみませんか?