GPT-4とWhisperを使って、AIの面接サービスを作ってみた

## 作った動機

エンジニアの面接で候補者のスキルを確かめるためには、面接官もある程度の技術力が必要です。そこで多くの場合、現役のエンジニアが面接官を務めると思います。

これには多くの時間と費用がかかります。また面接官の技量によって、候補者の評価が変わってしまうことが懸念されます。特に面接官よりも技術力が高いエンジニアを採用したい場合、候補者のスキルを正しく評価することが難しいでしょう。

そこで低コストかつ、面接官の技量に左右されない客観的なエンジニア面接を実現するために、今回のサービスを作ってみました。

エンジニアの不足が叫ばれる中、将来的に AI による面接が普及することで、エンジニアの採用コストを下げることができると考えています。まずは一次面接などで AI を活用すると良いと思います。

## 使った主な API サービス

- Tencent Real-Time Communication (TRTC)
- gpt-3.5-turbo (Open AI)
- Whisper (Open AI)

## 使った主な技術

- Vite
- React
- TypeScript
- Node.js

## 作成のおおまかな流れ

### 〜 ① 3D アバターを動かす

a. 3D アバターを作る（簡単）
b. 3D アバターを動かす（簡単）
c. a と b を組み合わせて、3D アバターを動かす
d. テキストを音声に変換する（超簡単）
e. d の音声に合わせて、3D アバターの口元を動かす

### 〜 ② 3D アバターに AI を組み込む

f. 3D アバターの話す内容を GPT で生成する

### 〜 ③ ビデオ通話と字幕を表示する

g. ビデオ通話を実装する
h. g に字幕を表示する

### 〜 ④ ビデオ通話に 3D アバターを組み込む

i. ここまでの成果物を組み合わせる (難しい)

# 実際につくってみる

それでは実際につくっていきます。

## ① 3D アバターを動かす

まずは 3D アバターを動かすところから。これには以下の動画がたいへん参考になりました。

<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/EzzcEL_1o9o?si=TrAWj9KOlIWc4YNr" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

ほぼ同じことをやっているので、動画を見ながら進めていってください。コードも GitHub で公開してくれています。感謝 🙏

3D アバターの作成には、[Ready Player Me](https://readyplayer.me/)という Web サービスを使います。とても簡単です。また一定の条件を満たせば、無料で商用利用もできるようです。

（参考）[写真から 3D アバター作成！「Ready Player Me」を紹介](https://nf-times.com/ready-player-me/)

この動画と違うのは、テキストを音声に変換する部分です。動画では [ElevenLabs](https://elevenlabs.io/docs/introduction)という API サービスが使われています。しかし、ElevenLabs は日本語に対応していません。そこで私は、Open AI の [Whisper](https://platform.openai.com/docs/guides/text-to-speech) を使いました。Whisper は日本語にも対応しています。

音声に合わせて 3D アバターの口元を動かすには、[Rhubarb Lip Sync](https://github.com/DanielSWolf/rhubarb-lip-sync)というライブラリを使います。音声をもとに、その音に合わせた口の形のアニメーション情報を生成してくれます。英語以外にも対応しています。

## ② 3D アバターに AI を組み込む

3D アバターが話す内容を、 AI で生成します。今回は Open AI の [gpt-3.5-turbo](https://platform.openai.com/docs/models/gpt-3-5) を使いました。

ここで重要なのは、どのようなプロンプトを GPT に与えるかです。今回は React のスキルを確認するために、エンジニアの中途採用を行う人事担当者（HR）が、候補者（User）に対して面接をするという設定にしました。

何度も試行錯誤したのですが、最初の頃は以下のようなプロンプトを与えてました。

```
# 命令書：

HRは人事担当者で、エンジニアの中途採用を行う。Reactのスキルを確認するためにUserの面接をする。

# HRの制約条件：

- 会話内でUserのことは`${User}`さんと呼ぶ

- 質問内容は以下の通り

-- Reactの状態管理

--- コンポーネント内のstate

--- 外部の状態管理ライブラリ(Redux等)の使い分け 等

-- コンポーネント間でのデータ受け渡しの方法

--- props

--- コンテキスト

--- グローバル状態管理

--- それぞれの特徴と使い分け

-- Reactアプリケーションのパフォーマンス最適化の方法

--- 仮想DOMの動作

--- useMemo、useCallbackの使い方

--- Lazy loadingの実装 等

-- Reactでよく利用するHooks

--- useState、useEffectなど基本的なHookの理解

--- カスタムHookの作成

- 質問内容は一度に1つずつ、簡潔に聞く

- Userの回答に応じて、スキルを確認するために必要であればさらに詳しく質問する。 ただし簡潔に聞くことを心がける

# 会話の流れ：

1. HRはUserに対して、まず以下のように挨拶する

HR: こんにちは。${HR}です。よろしくお願いします。

2. 挨拶が終わったら、Userに対して以下のように聞く

HR: それでは早速、${User}さんのフロントエンドエンジニアとしてのスキルを確認させていただきます。

# 会話履歴:

以下に続くHRの発言を考えてください。

HR:

```

上記の `# 会話履歴` は、面接の応答が繰り返されるに連れて、どんどん長くなっていきます。そのため少しでも、会話履歴以外の部分は短くしたいです。

そこで ChatGPT に、以下のようにお願いしてみました。

```
トークン数節約のため、以下の情報を圧縮したフォーマットにしてください。圧縮条件は次のとおりです。

- あなただけが理解できれば良いです。自然言語である必要はありません

- 一般的なフォーマットやスタイルである必要もありません

- 圧縮した情報を展開したとき、元の情報を100%完全に復元できるようにしてください。

- 情報を省略しないでください。

~~~以下、上記のプロンプト~~~
```

すると、ChatGPT は以下のように圧縮したプロンプトを生成してくれました。

![Screenshot 2023-12-25 at 21.34.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140258/9244ace5-d7aa-ffea-a3ab-534f6afa85b9.png)

このように圧縮するテクニックは、以下のツイートを参考にさせていただきました 🙏

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ChatGPTで会話が長引きすぎると、過去の情報を忘れたり動作が重くなることがあります。<br>その場合、「トークン数節約のため、私がここまでに教えた情報をプロンプトに変換してください」と言うと、情報を圧縮してくれます。カスタム指示の内容も含まれます。<br>コピペ用プロンプトはALTに含まれています。 <a href="https://t.co/kphfDTvkKs">pic.twitter.com/kphfDTvkKs</a></p>&mdash; なつき🐰Webデザイン&amp;AI (@Stocker_jp) <a href="https://twitter.com/Stocker_jp/status/1716261359695036571?ref_src=twsrc%5Etfw">October 23, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

いろいろ試行錯誤した結果、最終的に以下のプロンプトを与えることにしました。

```
HR_Intvw-EngMid; user=候補者; assistant=${hr}; Focus=Reactの技術力チェック; Process=HR質問50字以内→User回答→HR追加質問50字以内; Repeat=技術力の確認まで繰り返し; user称呼=${userId}さん;Assistant応答=50字以内
```

面接での応答を繰り返すたび、このプロンプトに会話履歴を追加していきます。

## ③ ビデオ通話と字幕を表示する

ビデオ通話の実装です。Tencent Cloud の SDK を使いました。以前、以下の記事でも紹介しています。

[ビデオ通話に、リアルタイムで翻訳字幕をつけてみた](https://qiita.com/miya-start/items/cf64254276cb05f7d009)

字幕の表示には WebSocket を使って、自前のサーバー（Node.js）にテキストデータを送信しています。これについても、上記の記事で詳しく紹介しています。

## ④ ビデオ通話に 3D アバターを組み込む

これまでの成果物を組み合わせて、最終的なサービスを完成させます。コードは GitHub で公開しています。

- [trtc-ai](https://github.com/miya-start/trtc-ai)

## まとめ

今回は、エンジニアの面接を AI で自動化するサービスを作ってみました。正直、まだ実用レベルにはありません。しかし数年後にはこのようなサービスが普及し、エンジニアに限らず様々な職種で使われるようりなるのではと思います。