エムスリーテックブログ

エムスリー(m3)のエンジニア・開発メンバーによる技術ブログです

ノーコードツールの高度な処理をコードで実装!iOS・macOSのショートカットアプリで手軽に定形プロンプト

この記事はエムスリーAdvent Calendar 2023の23日目の記事です。

エンジニアの星川 (id:oboenikui) です。

突然ですが、弊社では毎日ダジャレが飛び交っています。

ダジャレが飛び交うことの良し悪しはさておき、こんな会社の中なら思わず唸ってしまうような上手いダジャレを日常的に投稿できれば、社内で尊敬の眼差しを向けられること間違いなしです。

そこで今回は、「ChatGPTに上手いダジャレを作らせて、チャットに即座に投稿できる機能」を作っていきたいと思います。

ChatGPTにダジャレを作らせる

ChatGPTを触ったことのある方なら、必ず一度は試したことがあるであろうダジャレ生成。「〜でダジャレを作って」のような質問をしてしても、ダジャレになっていない文章が生成された、という経験はないでしょうか。

私が手元で gpt-4-1106-preview モデルで試してみたところ、以下のようなレスポンスが返ってきました。

input >
採用 (読み:さいよう) を使って、ダジャレを5文作ってください

output >
1. 野菜が高いので「菜葉のサイヨウ」も困りますね。
2. サイを飼っている動物園は、「サイヨウ」の条件が厳しいみたいです。
3. 料理の腕が上がって、採用と味噌が合いました。「さいようみそ」合わせの才能ですね。
4. 「サイヨウ」面接でサイの着ぐるみを着ていったら、面接官も困惑していました。
5. 新しいポスターに才能ある画家を採用しようとしたら、「さい画う」なんて言われてしまいました。

1は菜葉(なっぱ?)を音読みにして、ダジャレとして成立しているような気もします。2, 4番のサイの文章もなんとか成立しているでしょうか。しかしダジャレのクオリティは何度か試しましたがあまり高くなく、そのまま使ったら気まずい空気になること間違いなしです。

そこで、ChatGPTへの指示を、普段私がダジャレを作成しているときの手順を基に具体化してみます。

input >
ダジャレとは、同じ読み方で別の意味の単語やフレーズを使った文のことです。
以下に良いダジャレと悪いダジャレの例を挙げます。

|ダジャレ|良し悪し|理由|
|------|-----|-----|
|布団が吹っ飛んだ|良い|「布団」と「吹っ飛ん」が似た読み方で別の意味であるため|
|ふとんな布団|悪い|「ふとんな」というフレーズは日本語として不適切|
|布団は布団|悪い|同じ意味の単語の繰り返し|

ダジャレを考える時のフローは以下の通りです。
1. まず対象の単語と読み方が完全に一致、もしくは同じ読みを含む、存在する単語やフレーズを10個まで探します。元と同じ単語は除外してください。
ない場合は、1字を同じ母音の別の文字に置き換えた単語やフレーズを探します。例えば「未完」、「ミラン」、「ミトン」の中で「蜜柑」と似ているのは、どちらも「みかん」と読む「未完」、次いで「か」を「ら」に置き換えた「ミラン」の2つです。
2. 対象の単語と、見つけた単語を組み合わせた文章を作成します。より意味が通っているほど好ましいです。
以上の情報に従って、「採用」を使ったダジャレを5文作成してください。

1, 2のそれぞれのプロセスで結果を出力してください。

> output
まず、ステップ1で「採用」という単語に関連したダジャレができそうな単語やフレーズを探します。読みが「さいよう」となる単語を探しますが、完全一致する単語の候補は限られているでしょう。一文字を母音で置き換えるか、類似の発音を探し出します。

「採用」に似た発音の単語・フレーズの例:
1. 西洋 (せいよう) - 「い」と「え」の母音が異なるが、似た音
2. サヨウナラ (さようなら) - 発音の一部が似ている
3. 細腰 (さいよう / ほそごし) - 読みが「さいよう」であるものの意味が違う
4. 最優 (さいゆう) - 発音が似ている
5. 再葉 (さいよう) - 読みが「さいよう」で同じだが意味が異なる
6. 西葉 (さいよう) - 地名等で存在する可能性があり、読みが「さいよう」で同じ

では、これらの単語を用いてダジャレを作成します。

ステップ2のダジャレ作成:
1. 新しいスーツを着たら、西洋アートに詳しくなったような採用面接だった。
   - 「西洋」と「採用」を掛け合わせています。
 
2. サヨウナラだけは言いたくないけれど、君を採用する時は必ずやってくる。
   - 別れを惜しむ気持ちと採用決定のシーンを結び付けています。

3. 細腰を強調したドレスに心惹かれたけれど、私が本当に欲しかったのは新しい仕事の採用通知だった。
   - 「細腰」と「採用」を掛け合わせています。

4. 最優秀賞を獲得した彼は、運も実力もあるから次の採用試験にもきっと合格するだろう。
   - 「最優」と「採用」が似た響きを持ちますが、文脈としては異なる使われ方をしています。

5. 春が来てもうすぐ草木が再葉するけど、うちの会社は年中無休で新しい人材を採用するよ。
   - 春と新しい出発、採用するという意味合いを繋げました。

この5つは採用をテーマにしたダジャレで、それぞれ文脈に合わせたワードプレイが施されています。

見違えるほどクオリティの高いダジャレが生成できました。ところどころ造語が生まれてしまっていますが、意味は通じるレベルの造語で個人的には許せる範囲です。

ただ、この長文をChatGPTに毎回送るのは面倒ですよね。そこで、次は入力文字列に対してダジャレを生成するショートカットを作ってみます。

iOS, macOSのショートカットアプリ

iOSユーザーであれば知ってる方も多いと思いますが、iOSやmacOSには「ショートカット」というノーコードツールがプリインストールされています。

support.apple.com

このツール、名前からは想像し難いですが、かなり多彩な機能を備えています。例えば、プログラミング寄りの機能だと指定したURLに指定したヘッダー付きでHTTPリクエストを送ったり、WebページでJSを実行したりできますし、アプリケーション寄りの機能だと文字列からQRコードを生成したり他の対応するアプリケーションを呼び出したりといったことが可能です。もちろんif文やfor文に相当する機能もあります。

しかし、これらの設定はすべてGUIでポチポチ触りながら構築する必要があり、コードに慣れているエンジニアからするとまどろっこしい作業になります。文字列を加工したり、HTTPリクエストを送ってJSONをパースしたりといった処理をGUIで書いていくのは、かなり心が折れる作業になります。

特に、そこまで高度な操作を実装することが想定されていないためか、多くの操作を追加していくとエディタがもっさりしてしまいます。

そこで「ショートカット」を生成するプログラミング言語やライブラリがないか探し、いくつか候補を見つけました。

github.com

github.com

github.com

このうち、Cherri以外はメンテナンスされていないようでしたので、今回はCherriを使うことにしました。

Cherriを使ってショートカットを実装

CherriはGoで実装されている.shortcutファイルを生成するコンパイラです。VSCode向けにSyntax Highlightingの拡張機能も提供されています。

以下、公式のサンプルコードです。

/* Hello, Cherri! */

#define glyph smiley
#define color yellow

@message = "Hello!"
alert("Message: {message}", "Alert")

サンプルコードからもわかるように、他の主流なプログラミング言語を扱っている人なら違和感なく書ける文法となっています。

実際に実装してみると、まだ開発途上でバグや使いづらい部分もあることがわかりましたが、GUIでポチポチやるよりは楽ですので、ぜひみなさんも試してみてください。

それでは、実装していきましょう。

下準備

ダジャレ生成プロンプトを、自動化用に書き換えます。また今回は入力を文章にして、そこからダジャレに使用する単語もChatGPTに選択してもらうようにします。

以下のようにプロンプトを書き換え、JSONが出力されるようにしました。*1

ダジャレとは、同じ読み方で別の意味の単語やフレーズを使った文のことです。
以下に良いダジャレと悪いダジャレの例を挙げます。

|ダジャレ|良し悪し|理由|
|------|-----|-----|
|布団が吹っ飛んだ|良い|「布団」と「吹っ飛ん」が似た読み方で別の意味であるため|
|ふとんな布団|悪い|「ふとんな」というフレーズは日本語として不適切|

|布団は布団|悪い|同じ意味の単語の繰り返し|ダジャレを考える時のフローは以下の通りです。
1. 【入力】文の中から特徴的な単語を1個抽出します。
2. 抽出した単語語と読み方が完全に一致、もしくは同じ読みを含む、実在する単語やフレーズを10個まで探します。元と同じ単語は除外してください。
例えば、「蜜柑」と同じ読みを含む単語として、「未刊」や「未完成」、「アルミ缶」を得られます。
3. 見つけた単語を使って【入力】への返信として適切な文章を作成します。より意味が通っているほど好ましいです。
以上の情報に従って、ダジャレの返信文を5文作成してください。

出力は、以下のJSON形式で行います。JSON以外は出力しないでください。
{ "result": [{ "text": "作成した文", "keyword": "作成した文で使用した単語" }, ...] }

【入力】「{input}」

処理の流れ

以下の流れでダジャレを生成します。

  1. ダジャレを作るベースの文を取得する。共有メニューから起動した場合、その入力を採用する。そうでなければ、テキスト入力、音声入力、クリップボードから選択して入力する。
  2. ダジャレ解説プロンプトに、1で取得したベースの文を埋め込む。
  3. ChatGPT APIに、2のプロンプトを投げる。
  4. レスポンスのJSONをパースし、生成されたダジャレ文のリストを得る
  5. 4のリストを表示してユーザーに選択させる。
  6. 選択したダジャレ文をクリップボードにコピーして終了。

そしてこの流れを実装したのがこちらのコードです。実際に使用する場合は、OpenAIのAPIトークンが必要ですので、外部に漏洩してしまわないようお気をつけください。

CherriでSiriショートカットを実装 · GitHub

ショートカットに変換すると、約80個の命令ブロックで構成されたとても大きなショートカットになっています。

Cherriのコードでも構造化されたJSONのデータを取得するのが少し煩雑ですが、GUIで設定するよりは遥かに楽でした。

それでは早速、実際に返信で使ってみましょう。なお、iPhone 15 Proからアクションボタンを使ってショートカットを呼び出せるようになったので、もちろんいつでも瞬時に呼び出せるように設定しています。


www.youtube.com

クソリプ 素晴らしいダジャレが生成されましたね! なおこちらのショートカットで生成された文章を使用したことによる損害について、弊社および星川は一切の責任を負いません。

文章を入力にしたことでダジャレの品質が激落ちしてしまったので、今後の改善点とします。

We are hiring!

エムスリーでは、エンジニアを絶賛募集中です! ダジャレの経験年数は不問ですので、ご興味ある方は是非カジュアル面談等ご応募ください。

jobs.m3.com

*1:gpt-4-1106-preview および gpt-3.5-turbo-1106 では確実にJSONで出力させるオプションが追加されました。 https://platform.openai.com/docs/api-reference/chat/create#chat-create-response_format