🔞

【個人開発記録】指定単語を配列要素から除外する【GASで自作APIを作る】

2024/04/15に公開

はじめに

現在個人で開発中のアプリに関連する備忘録的なアウトプット記事です。
https://word-chain-image-generator.onrender.com/
今回は転用するにはもしかしたら少しニッチなトピックかもしれません。
GAS(Google Apps Script)で自作のAPIの作り方を知りたい方には若干需要あるかも?

記事の結論

  • GASをAPI化する(指定した単語を配列要素から除外するロジックをGASで実装しAPIとして呼び出せるようにする)
  • RailsからGASで自作したAPI呼び出す

という内容です。以前、類似記事も書いているのでそちらも参考にしつつ↓

https://zenn.dev/no215/articles/5f9d1bdfcfe869

抱えていた課題

  • 画像を生成するにあたり しりとりの単語をプロンプトとして画像生成APIに渡す のですが、たとえば暴力的な単語や卑猥なワードもプロンプトとして渡せてしまうので不適切な画像が生成されるリスクをはらんでいました。

検討した方法論

  • JavaScriptなどフロントエンド側で除外したい指定単語のリストを作成して、照合するロジック
  • データベースにあらかじめ除外したい単語を保存しておき、画像生成のタイミングでDBと照合するロジック
  • APIを通じて除外したい単語を照合するロジック

実装手順

GAS(Google Apps Script)でAPIを作成する

【手順】

  1. 自身のマイドライブ(Googleドライブ)へアクセス
  2. 右クリック ▶︎ Googleスプレッドシートファイルを作成しメニューから GASエディター を展開
手順図解

スプレッドシートを作成


拡張機能からApps Scriptをクリック

  1. 関数の作成
コード例
コード.gs
// GASをWebアプリケーションとして動作させるdoGet関数の定義
function doGet(e) {
  // スプレッドシートから指定のシートを取得
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("シート名");
  // シート上でA列2行目から最終行までのデータを取得する範囲を指定
  const range = sheet.getRange(2, 1, sheet.getLastRow() - 1);
  // 範囲から取得したデータを1次元の配列に変換する(rejectWordsに格納)
  const rejectWords = range.getValues().flat();
  // もしURLパラメータの"words"が指定されていない場合は、エラーメッセージを返す
  if (!e.parameter.words) {
    return ContentService.createTextOutput(JSON.stringify({
      error: "単語のパラメーターが存在しません"
    })).setMimeType(ContentService.MimeType.JSON);
  }

  // URLパラメータの"words"をカンマで分割し、inputWordsに格納
  const inputWords = e.parameter.words.split(",");
  // inputWordsからrejectWordsに含まれていない単語だけを抽出した配列を作成し、filteredWordsに格納
  const filteredWords = inputWords.filter(word => !rejectWords.includes(word.trim()));
  // フィルタリングされた単語の配列をJSON形式で出力(サーバーサイドへ返す)
  return ContentService.createTextOutput(JSON.stringify({ "filteredWords": filteredWords }))
    .setMimeType(ContentService.MimeType.JSON);
}

端的にいうと、APIの呼び出し元から送信されたパラメーターの中から、スプレッドシートのA2〜A最終行(文字列が入っている最終行)までの文字列と一致する要素をすべて排除する。
という処理をしています。

  1. APIとしてデプロイする
手順図解

①右上の[デプロイ][新しいデプロイ]をクリック


②アクセスできるユーザーで全員を選択


③ウェブアプリのURLをコピーする ← これをAPIのエンドポイントして扱う

スプレッドシートに除外したいワードリストを作成する

A列2行目以降に除外したい単語を入力します。
たとえば バカ という単語を配列から排除したいとします。

RailsでAPIを呼び込むサービスクラスを作成する

以下はRailsでの導入手順例です。

  1. GemfileHTTParty をインストールする
Gemfile
gem 'httparty'
ターミナル
bundle install
  1. APIの呼び出しに関するロジックをサービスクラスとして定義する
    app/sevices/word_filter_service.rb ファイルを作成
word_filter_service.rb
require 'httparty'

class WordFilterService
  def self.filter_words(words)
    uri = '(GASでコピーしたURLをペースト)https://...'
    query = { words: words.join(',') }
    response = HTTParty.get(uri, query: query, follow_redirects: true)

    if response.success?
      JSON.parse(response.body)["filteredWords"]
    else
      puts "HTTP Error: #{response.code} #{response.message}"
      words # エラーの場合は入力された単語リストをそのまま返す
    end
  rescue => e
    puts "Error filtering words: #{e.message}"
    words # 通信エラーの場合も入力された単語リストをそのまま返す
  end
end
  1. コントローラーでAPIを呼び出す
sample_controller.rb
〜省略〜
words = params[:words] # => "バカ", "カバ", "バスケットボール", "ルビー", "ビーム"
filtered_words = WordFilterService.filter_words(words)
〜省略〜

ターミナル

結果的に配列の要素から除外されています。

さいごに

他にも画像生成を行う上でネガティブプロンプト(指定の要素を含めないようにする指示文)を駆使したりして、生成される画像の安全性・信頼性を担保しています。
開発中のアプリケーションのペルソナが小学校低学年なもので、不適切な画像が表示されないようにする工夫でした。

現場からは以上です(^o^)/

脚注
  1. コンテナバインド:スプレッドシートに紐づく/スタンドアローン:スプレッドシートに紐づかない ↩︎

Discussion