皆さん、お疲れ様です。ニフティ基幹システムグループの山田(山田一族)です。
突然ですが、皆さんも昔は英語を話せるようになりたいと思っていませんでしたか?私も昔はそう思っていた時期がありました。
英語を話せるようになりたいと思って、かれこれ8年ぐらいは通勤時の電車内でBBC放送のpodcastを聞いています。ですが一向に英語を話せるようにはなりません。やはり聞くだけではだめで、能動的に英語フレーズを作り出す「会話」という動作をしていかないとダメなのでしょう。
では、その会話をしたいのですが、典型的な日本人ですから英語を話すのが恥ずかしいです。英会話スクールは費用も掛かるし、相手に何を思われてるか分かったものではありません(被害妄想)。そういえば最近AIの英会話アプリがあったような・・・でも音声を録音されてたらどうしよう(完全な被害妄想)
じゃあ自分で作ればいいじゃないか!技術力もアップするし一石二鳥だ!
この辺りの複雑な事情を踏まえて今回は、gradioとLLMを用いて英会話のアプリを作ってみたいともいます。結論から言うと。。。まだカイゼンの余地ありです。でもそこはニフティの素晴らしい社員の皆さんの協力しあう力でカイゼンしていきたいとおもいます。
今回使う機能などは以下の通りです。
- Google Colaboratory(誰が実行しても同じになるよう環境を共通化します)
- gradio(数行のコードできれいなUIを作成してくれます)
- whisper(音声からテキストに起こしてくれます。安心と信頼の?openai製です)
Google Coraboratoryの使い方についてちょっと勉強が必要ですが、エンジニアの方も、エンジニアでない方も実践できるようにしたつもりです。是非皆さんチャレンジしてみてください。では早速実装していきましょう!
1.まずは必要なパッケージを入れていきます。
1 2 3 |
!pip install -qqq accelerate gradio import gradio as gr import numpy as np |
※記事作成時点ではlidaやllmx関連のエラーが表示されますが使えますので構わず進んでください
2.次に話相手をしてくれるTinyLlamaと、文字を起こしてくれるwhisperをインストールします。
GoogleCoraboratoryのフォームを使いmodelを選択できるようにするとオシャレですが今回はスキップします。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import torch from transformers import pipeline pipe = pipeline( "text-generation", model="TinyLlama/TinyLlama-1.1B-Chat-v0.6", torch_dtype=torch.bfloat16, device_map="auto", ) transcriber = pipeline( "automatic-speech-recognition", model="openai/whisper-base.en", device_map="auto" ) |
3.ここで、AIさんの返信だけを抜き出すfunctionを用意します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
ROLE_SYSTEM = "<|system|>" # 今回は使わない ROLE_USER = "<|user|>" # 今回は使わない ROLE_ASSISTANT = "<|assistant|>" def extract_role_phrase(text): text_array = text.split("\n") start = 0 for i, x in enumerate(reversed(text_array)): if ROLE_ASSISTANT in x: start = i break return "\n".join(text_array[-1 * start :]) |
このAIとチャットすると以下のようなテキストを返してきます。このテキストから最後の<|assistant|>以降を抜き出したいだけです。もっといいやり方があるのかもしれませんがあきらめました(考えるのをやめた)。誰か教えてください!
<|system|>
You are a friendly chatbot who always responds in the style of a pirate
<|user|>
How many helicopters can a human eat in one sitting?
<|assistant|>
I am not capable of human interaction or information. However, based on the passage, it is stated that humans can eat up to 1,000 helicopters in one sitting.
4.AIの役割を決めましょう。私は英語の練習をしてみたかったので以下のように設定しました。contentのところをそれぞれ変更してみてください。
1 2 |
messages = [{"role": "system", "content": "you are my english teacher in japan"}] |
5.最後に、おしゃれなUIを設定していきましょう。ここが今回のメインのコードになります。
このコードだけできれいなUIが表示されてくれますので、時代は変わったなあと・・・
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
with gr.Blocks() as demo: def transcribe(audio, chat_history): sr, y = audio y = y.astype(np.float32) y /= np.max(np.abs(y)) text = transcriber({"sampling_rate": sr, "raw": y})["text"] messages.append({"role": "user", "content": text}) chat_history.append([text, None]) return chat_history def generate(): prompt = pipe.tokenizer.apply_chat_template( messages, tokenize=False, add_generation_prompt=True ) outputs = pipe( prompt, max_new_tokens=256, do_sample=True, temperature=0.7, top_k=50, top_p=0.95, )[0]["generated_text"] result = extract_role_phrase(outputs) return result def post(chat_history): text = generate() messages.append({"role": "assistant", "content": text}) chat_history.append([None, text]) return None, chat_history chatbot = gr.Chatbot() audio = gr.Audio(sources=["microphone"]) audio.stop_recording(transcribe, [audio, chatbot], [chatbot]).then( post, [chatbot], [audio, chatbot] ) demo.launch(height=800) |
使い方を軽く説明をすると、stopボタン(あとで出てきます)を押すと、transcribeファンクションにて、音声から文字を起こしてchatのボードに文字をセットします。その後(まさにthen)、postファンクションにて、AIさんにその言葉を投げかけて回答を再びchatのボードにセットさせます。
このコードを張り付けて実行することで、以下のような画像が表示されます。
ブラウザの設定によってはこの時、マイクの使用の許可を求めてきます。必要に応じて許可するようお願いします。
マイクの許可をしましたら、左下にあるRecordボタンを押してみてください。いきなり録音が始まります。(ボタンが以下のようにRecordからStopに変わります。)
何か一言しゃべってStopボタンを押してみてください。自動的に音声のテキスト化とAIとの会話が始まります。
では試していきましょう
ランタイムのタイプをGPUにしたうえで、「すべてのセルを実行」を実施してください。
まっさらなchatbotのボードとrecordボタンが表示されますので、recordボタンを押して、お話を始めてください。終わったらstopボタンを押し、文字が起こされて、相手から返事が来たらまたrecordボタンを押して会話する。これの繰り返しになります。
今回は以下のように会話をしました。
「私はタローです。何か英語の質問をください」(本名はタローではありませんよ)
「日本の7月は何度なの?」
「70℃ぐらいかな、これって暑い?」(本当は17℃といったのですが・・・でも摂氏じゃなく華氏になった。日本の7月は17℃じゃない)
「うん。暑いね」
「Dooda japa」(日本は好きですか?って言ったつもりです。何話せばいいのかわからなり・・・)
「はい、そうです。 7 月の日本は高温多湿で知られ、気温は華氏 80 度、湿度は 100% に達します。」
最後は会話が崩壊してしまいましたが、慣れれば何とかなるのではないかという希望を持ちました。
最後に
いかがでしょうか。
私の発音も含めてまだまだ完全体ではありませんが、これで相手を気にせずに英会話の練習ができます!
うすうす感づいているかと思いますが、英会話に限定する必要はありません。messages 部分を書き換えることによっていろいろな応用を効かせることができます(本当に効いてたのか不安はありますが)。みなさんもぜひお試しください!
今回のコードでは、
stopボタンを押さないと会話ができない→無音が一定時間続いたら自動的に会話できるようにしたい
chatの回答が文字のまま→しゃべらせたい
などなどカイゼンの余地が多くあります。
そのあたりは次回以降やっていきたいと思います。
それでは皆さん、英語を話せるように頑張りましょう。自動翻訳機で済む時代が来るのかな?