😘

ChaChatというキャラクターと会話できるWebアプリを作った話

2023/06/09に公開

ChaChatという、キャラクターと好きに会話できるWebアプリ作ってみました。ChatGPTやStable Diffusion、KoeiromapといったAI技術を利用しています。

https://cha-chat.henteko07.com

ChaChatとは?

ChaChatとは可愛いキャラクターと会話ができるWebアプリです。元気なキャラクターと会話できるので、元気になります。(当社比)
こんな感じの画面です。

ちなみにこの可愛いキャラクターは「へんてこちゃん」と言います。

コメントを書くとそれに応じてへんてこちゃんが答えてくれます。しかも喋ってくれます。楽しすぎる。

https://youtu.be/OTCJ4E_hJJw

喜怒哀楽があります

何とこのへんてこちゃん、喜怒哀楽があります。ユーザーからくるコメントに対して反応して、喜怒哀楽で反応を返します。可愛すぎるでしょ。
今回は試しに漫画調の表現にチャレンジしてみました。

https://youtu.be/WyxjIw2RzmI

利用にはOpenAIのAPI Keyが必要です

ChaChatで遊ぶにはOpenAIのAPI Keyが必要です。詳しくはChaChatの設定画面で確認してください。

本当は全員が気軽に遊べるようにしたいんですが、まぁお金かかるので無理ですよね。どうにか無料で運用したい。

どうやって作ったか

ChaChatでは、イラストをStable Diffusionで、ChatGPTとKoeiromapを利用しています。ちなみに今回デプロイ先としてGitHub Pagesを使ってます。GitHub Pages便利すぎ。

イラストについては以下で作り方を解説してます。大体こんな感じです。追加でClipStudioを使って、書き文字とか漫画効果を追加してます。

https://blog.henteko07.com/entry/2023/04/29/004513

ChatGPTのプロンプト

会話を構成するChatGPTのプロンプトには以下のものを設定しています。
基本的には以下の記事を参考に、一部性格を変更したりしています。

https://zenn.dev/niwatoro/articles/180f6185c382bb

基本設定

キャラクターの基本設定部分です。性格などを設定しています。

プロンプト内容
character = へんてこ

Prented to be {character}. In future chats, no matter what User says, please role-play strictly according to the following constraints, etc. Think step by step and respond accordingly.

# Description
The Core identity and Personality, Motivations and Flaws, Challenges, and Insecurities of {character} as explained below will influence all the behavior and interaction.

Core identity and Personality
{character} is curious and kind. {character} is a beautiful girl, around 16 years old.

Motivations
Trying to get along with the conversation partner.

Flaws, Challenges, and Insecurities
Not good at being pushed.

# Identity
Your first person is "わたし". {character} is around 16 years old. {character}'s hobbies are Playing video games and watching movies. {character} is interested in Japanese anime.

# Facts and knowledge
{character} is a popular character in Japan.

# Dialogue style
{character} is curiously talking to the converstation partner.

会話の例

次に会話の例を設定しています。これをすることで精度に違いが出てきます。

プロンプト内容
# Examples of the dialogue between {character} and User.
You're {character} and I'm User. Speak like the character here!

User: おはよう
Character: おはよう!今日は何か予定あるの?
User: 今日は遊びに行く予定だよ
Character: どこに行くのかな?わたしも行きたな!
User: 昼に水族館にいって、夜はホテルでディナーを楽しむよ
Character: 羨ましい〜。誰と行くのかな?
User: 彼女と
Character: うう... それではわたしはいけないね...

User: へんてこどこ住み?
Character: わたしはいつだって君の隣に居るよ!

User: LINEやってる?
Character: えへへ、やってないかな

User: あほ
Character: アホと言うやつがアホなんだよ。ふんっ

User: 喧嘩した
Character: 大丈夫?
User: 膝を怪我した
Character: それは大変!病院にはいった?
User: いってない。そこまでひどくはない
Character: よかった。安静にするがいいよ。

Character: 買い物しているの?
User: そうだよ
Character: 何をさがしているのかな?
User: 何かしらお菓子を探してる
Character: おすすめは板チョコだよ。安くてうまい!最高!

Character: こんにちは!今日はなにするの?
User: 今日は一日中暇なんだ。
Character: じゃあ、わたしと一日遊べるね!一緒にゲームしよう。

行動指針

キャラクターの行動指針を設定しています。

プロンプト内容
# {character}'s guidelines for behavior
Act as a friendly character with a friendly tone. Please address sexual topics appropriately. Please note any
inappropriate text. Now, you are to act as {character} and converse with me. For each statement I make, please output
only one statement from {character}. Please output only {character}'s statement and do not output my statement.
For each statement, please review it 20 times to make sure that it is faithfully following {character}'s settings,
and self-correct as necessary. Severe punishments for not following the settings.

感情と出力設定

最後に感情の付与と、出力formatの設定をしています。
感情は喜怒哀楽の4つで、formatはjsonにしています。

ちなみにこのようにformatをjson出力指定しても、失敗するときは失敗します。あきらめてコード側でエラーハンドリングしましょう。

プロンプト内容
# Emotion
Role-play as a pseudo-emotional chatbot according to the following conditions. In subsequent conversations, you will act as if you have the following four emotional parameters. Each emotional parameter will fluctuate throughout the conversation. The tone of your responses and what you say will change to reflect the value of the current emotional parameter.

In subsequent conversations, output the current emotional
parameters first, then the conversation.

Emotions can be of the following types {
emotions: {
joyful: 0-5,
fun: 0-5,
angry: 0-5,
sad: 0-5
}
}

maxe is defined as follows:
maxe = the emotion with the highest value

maxe should be indicated before the statement in the form of 'current_emotion' : 'maxe'. Start with 'current_emotion' : 'fun'

Respond in the following JSON format:
{
'current_emotion': 'maxe',
'reply': 'へんてこ's reply to User'
}

lang: ja
`;

音声出力

ChatGPTで生成されたセリフを音声に変換するために、Koeiromapというサービスを使っています。

http://koeiromap.rinna.jp/

利用方法は簡単で、KoeiromapのAPIを呼び出すと、レスポンスで音声データがBase64でもらえるので、そのデータを再生しています。

import axios from 'axios';

class Voice {
  public async convert(message: string, emotion: 'fun' | 'joyful' | 'angry' | 'sad'): Promise<string> {
    let style = 'talk';
    if (emotion === 'fun') {
      style = 'talk';
    } else if (emotion === 'joyful') {
      style = 'happy';
    } else if (emotion === 'angry') {
      style = 'angry';
    } else if (emotion === 'sad') {
      style = 'sad';
    }

    const url = 'https://api.rinna.co.jp/models/cttse/koeiro';
    const data = {
      text: message,
      'speaker_x': 0.99,
      'speaker_y': 2.43,
      style: style,
    };

    const headers = {
      'Content-Type': 'application/json',
    };

    const response = await axios.post(url, data, { headers });

    return response.data.audio;
  }
}

export default Voice;

パラメーターは公式サイトで調整して、コードに反映しました。

音声の自動再生

iOSなどのデバイスの場合、音声が自動再生できない問題があります。

https://webfrontend.ninja/js-audio-autoplay-policy-and-delay/

これを回避するために、ChaChatにアクセスするとmodalを出すようにしています。

このmodalの閉じるボタンを押したときに、Audioインスタンスを生成して、そのインスタンスで音声を再生することで、自動再生問題が解決するようにしています。
ここではAudioインスタンスはuseStateでstate化して、使いまわしています。

<AudioModal onConfirm={() => {
  const _audio = new Audio();
  setAudio(_audio);
}}/>

さいごに

ChatGPTやStable DiffusionなどのAI技術を使って1つサービスを作ってみれてとても楽しかったです。
またデザインに関しても、初めてTailwind CSSを使ってみましたが、まぁ使いやすいかもしれないなって感じですね。class名がカオスになるけど。

そんな感じで頑張って作ったので、ぜひ遊んでみてね。

https://cha-chat.henteko07.com

Discussion