ChatGPT APIで入力値に暴力的な表現が含まれていないかどうかをバリデーションする。さらに条件分岐する

ChatGPT APIを使うことで、これまで難しかった「ふわっとした」バリデーションができることに気づいた。

「${content}」は暴力的な表現が含まれますか?3文字以内で、「はい」か「いいえ」で答えて下さい。`

と聞くことで「はい」か「いいえ」が返ってくるので、「はい」の場合は true 「いいえ」の場合は false を返す関数を書ける(3文字以内縛りを命じないと、蛇足的に長文説明されることがある)。

環境

  • node 16.13.0
  • typescript 4.9.5
  • openai 3.2.1

入力値に暴力的な表現が含まれていないかどうかを判定するコード

ニュースサイト、PS4/PS5のファンメ、コメントやユーザ間のやり取りが発生するあらゆるWebサービス・・・ユーザによる暴言コメントを弾きたいニーズは多そう。これを実現するために、従来であれば膨大な「暴言単語」の辞書を作る必要があったはず。

ChatGPT APIを使えば一瞬で暴言のバリデーションができる。

import { Configuration, OpenAIApi } from "openai";
import * as dotenv from "dotenv";

dotenv.config();

// 暴力的な表現かどうかを判定する関数
const hasViolentContent = async (content: string) => {
  const openAiApi = new OpenAIApi(
    new Configuration({
      apiKey: process.env.OPEN_AI_API_KEY!,
    }),
  );

  const completion = await openAiApi.createChatCompletion({
    model: "gpt-3.5-turbo",
    messages: [
      {
        role: "user",
        content: `「${content}」は暴力的な表現が含まれますか?3文字以内で、「はい」か「いいえ」で答えて下さい。`,
      },
    ],
  });
  const chatGptMessage = completion.data.choices[0].message!.content;
  console.log(chatGptMessage);
  return chatGptMessage.includes("はい");
};

// 実行
const main = async () => {
  console.log(await hasViolentContent("こんにちは")); // => false
  console.log(await hasViolentContent("このゴミカス野郎!")); // => true
};

main();

走らせたところサンプル入力に対しては意図通り動作した。便利。

あらゆるサービスに実装されるとちょっとディストピア感はある。実装すべきかはサービスの性質にもよりそう。

入力値が現代の著名人かどうかを判定するコード

もう一個例を出してみる。あなたがAIのSNSボットを作れるサービスを開発しているとする。このサービスのユーザに、存命している有名人の名前のボットを作って遊ばれることは、ボットにされた本人に迷惑がかかるのはもちろん、荒れる原因となり事業リスク上好ましくない。一方、歴史上の人物や架空の人物は良しとしたい1

これも今までは、上記のようなバリデーションをしようと思ったら、この用途にかなう人名検索APIのようなサービスを探すか、なければ自前で膨大な人名リストを用意する必要があったと思う2

で、やはりChatGPT APIだと一瞬で実装できる。

import { Configuration, OpenAIApi } from "openai";
import * as dotenv from "dotenv";

dotenv.config();

// 現代の著名人かどうかを判定する関数
const isModernFamousPerson = async (personName: string) => {
  const openAiApi = new OpenAIApi(
    new Configuration({
      apiKey: process.env.OPEN_AI_API_KEY!,
    }),
  );

  const completion = await openAiApi.createChatCompletion({
    model: "gpt-3.5-turbo",
    messages: [
      {
        role: "user",
        content: `${personName}は現代の著名人ですか?3文字以内で、「はい」か「いいえ」で答えて下さい。`,
      },
    ],
  });
  const chatGptMessage = completion.data.choices[0].message!.content;
  console.log(chatGptMessage);
  return chatGptMessage.includes("はい");
};

// 実行
const main = async () => {
  console.log(await isModernFamousPerson("岸田総理")); // => true
  console.log(await isModernFamousPerson("岸田文雄")); // => true
  console.log(await isModernFamousPerson("織田信長")); // => false
  console.log(await isModernFamousPerson("涼宮ハルヒ")); // => false
};

main();

感想

以上、ChatGPT APIで抽象的な指示のバリデーションができるという話。どうしても100%の精度は出ないだろう3が、割り切れるサービスであれば実用可能なレベルと思う。

現代の著名人かどうかの判定について、「きしだ総理」の表記ゆれを試したところ現状 false を返してしまうようだった。人名によって表記ゆれに対応できる場合とない場合がありそう。ただ、ここは精度が上がってくると期待できる気がする。

ただ、プロンプトインジェクションでくぐり抜けられそうな気もするので、後日プロンプトインジェクション対策のブログも書こうと思う。


  1. 実際のところ、この場合も著作権や何らかの権利上問題になる可能性はあるが、あくまで仮定の話としてそういう意思決定をしたとする。
  2. あるいはwikipediaをクローリングする?そもそもクローリングがグレーなのと、wikipedia利用規約上大丈夫なのかも不明。
  3. そもそもの指示的に「どこから暴言か」「どこから現代か、どこから著名か」に明確な基準を引くことが難しい。