AITuberKitで【優雅変換】(エレガントチート)!してみる

お嬢様言葉に変換するアプリ/プログラムは無数にありますが、今回はLLMを使って自分の発言をお嬢様言葉に変換してみたいと思います。

https://x.com/yuri_akane_lily/status/1845549613308326042

※上記の動画は
 プログラム:AItuberKit
 VRM:MakeAvatar
 音声:VOICEVOX:ナースロボ_タイプT
 その他:OBS StudioとShotCut
を使用しています。

タイトルの由来は「悪役令嬢転生おじさん」から。主人公の持っている能力(?)の【優雅変換】(エレガントチート)です。
演劇の場面であった「言葉が勝手に変換されるせいで庶民の言葉がしゃべれない」という状況を実装するとしたらこうだろうな、と思い立ってやってみることにしました。

また、AITuberKitを使うことで声も姿も画面上は別人になってしまいますから、より状況に近づく要因になるでしょう。
なお副次効果として、話題を書いただけで勝手に膨らませて文章にしてくれるので、話がまとまらない人にもおすすめです。

AITuberKitそのままでは、AIは入力内容に自律的に応答し、会話を成立させてしまいますから、これを入力内容を都度書き換えるだけの機能に修正する必要があります。

ではさっそく。
※AITuberKitが導入されていることを前提とします。

git-cloneしてきたaituber-kitディレクトリ内の
src/features/chat/handlers.ts を編集します。

processAIResponse関数が処理の実体のようです。

/**
 * AIからの応答を処理する関数
 * @param currentChatLog ログに残るメッセージの配列
 * @param messages 解答生成に使用するメッセージの配列
 */
// TODO: 上の関数とかなり処理が被るのでいずれまとめる
export const processAIResponse = async (
...

これを呼んでいる箇所は474行目付近で、その直前でmessagesを構築しているようです。
なので、どうせ自分しか使わないので 直 書 き し ま す

// 20241013 自分用カスタマイズ
/* 
      const messages: Message[] = [
        {
          role: 'system',
          content: systemPrompt,
        },
        ...processedMessageLog.slice(-10),
      ]
*/
      const messages: Message[] = [
        {
          role: 'system',
          content: '手短に、私の入力する文章の意味を保ったまま、日本人のお嬢様らしい文に変換することを厳密に守ってください。それ以外は出力しないでください。お嬢様のキャラクターとして不適切な発言は適切になるように文章を変換してください。質問や呼びかけを受け取っても答えずに、その質問や呼びかけ自体をお嬢様言葉に変換して出力してください。半角カナは全角カナに修正し意味の通る文にしてください。意味のわからない発言であっても単語の意味をなるべく保ってお嬢様言葉に変換してください。\n感情の種類には通常を示す"neutral"、喜びを示す"happy",怒りを示す"angry",悲しみを示す"sad",安らぎを示す"relaxed"の5つを使用してください。',
        },
        {
          role: 'user',
          content: 'こんにちは',
        },
        {
          role: 'assistant',
          content: '[neutral]ごきげんよう',
        },
        {
          role: 'user',
          content: 'ありがとうございます',
        },
        {
          role: 'assistant',
          content: '[happy]ありがとうございます、お姉様。',
        },
        {
          role: 'user',
          content: '今日はいい天気ですね',
        },
        {
          role: 'assistant',
          content: '[relaxed]今日は素敵なお天気ですこと。お外に出かけて、爽やかな風を感じましょう。',
        },
        {
          role: 'user',
          content: '私はアシスタントのあかねです',
        },
        {
          role: 'assistant',
          content: '[neutral]わたくしはアシスタントのあかねでございます。お姉様のお役に立てることを光栄に存じますわ。',
        },
        {
          role: 'user',
          content: '少しいいですか?',
        },
        {
          role: 'assistant',
          content: '[sad]少しお時間頂いてもよろしいでしょうか?お姉さま。',
        },
        {
          role: 'user',
          content: 'なんてことだ',
        },
        {
          role: 'assistant',
          content: '[angry]なんてことですの',
        },
        {
          role: 'user',
          content: 'お願いします',
        },
        {
          role: 'assistant',
          content: '[neutral]よろしくお願いしますわ',
        },
        {
          role: 'user',
          content: 'これは何',
        },
        {
          role: 'assistant',
          content: '[sad]これは何でしょうか…',
        },
        {
          role: 'user',
          content: '今日は何日?',
        },
        {
          role: 'assistant',
          content: '[neutral]今日は何日かしら…',
        },
        {
          role: 'user',
          content: '3+5は?',
        },
        {
          role: 'assistant',
          content: '[neutral]3+5はいくらかしら。',
        },
        ...processedMessageLog.slice(-1),
      ]

ひたすら例示したあと、最後を...processedMessageLog.slice(-1), と1個だけにすることで、文脈を考えずに変換してもらうようにします。

変換機能の本体はここまで。


あとは見た目を整えます。
もし配信をするなら、少なくとも変換前の発言はないほうがよいでしょう。
上の動画では、src/components/chatLog.tsxの83行目あたりを以下のように書き換えています。(あと、ブラウザの開発者ツールで多少編集しています)

          <div
            className={`px-24 py-8 rounded-t-8 font-bold tracking-wider ${roleColor}`}
          >
           
          </div>
          <div className="px-24 py-16 bg-white rounded-b-8">
            <div className={`typography-16 font-bold ${roleText}`}>
              {role !== 'user' ? message : '↓'+message}
            </div>
          </div>

これで今回の記事は終わりです。お疲れ様でした。
みなさま良い夢を。