🎤

chatGPT API + Whisper API +NLP(MeCab)で音声レコメンド機能を作ってみる

2023/06/19に公開

はじめに

こんにちは!5月から株式会社Voicyにエンジニアとして入社しました!うおくんです!
VoicyではWebフロント、バックエンド、iOS、Androidなどなんでもするマンとして日々勉強しています!(現在メインはWebフロント)

そんななんでもしたいマンの自分ですが、AIの領域ではChatGPTの表面的なことしか勉強していなかったので、今回は音声の会社に入社したということもあり

質問から対応する音声データをおすすめしてくれるレコメンド機能

を実装してみたいと思います!

準備

まず実装をするにあたって音声データが必要なので色々と作ってみようと思います
ネットに転がっている音声データを使えばいいのですが、せっかくなので内容はchatGPTくんを使って作っていこうかなと思います

<質問>
最近の音声業界について一人称の話し方で話してください

<ChatGPT>
わかりました、音声技術業界についての私の視点をお伝えします。

最近、私は音声技術業界について深く考える機会がありました。多くの分野がデジタル化の波に乗る中で、音声技術はそれ自体が進化を遂げています。私が認識している最も重要なトレンドの一つは、人工知能(AI)と音声認識の組み合わせです。

音声認識技術はもともと... 省略

音声技術の未来は非常に興奮するものです。私はその一部となり、この興奮する未来の形成に貢献できることを、非常にうれしく思っています。今後も引き続き、音声技術の進化とその影響に注目していきたいと思います。

これでまずテキストが作成されましたね
次はこれを音声に変換していきます

Text-to-SpeechのAPIは色々ありますが、今回の音声生成は準備段階なのでツールを使っちゃいます
それがこちら!!CoeFont!!(合成音声 aiみたいに検索したらヒットしたやつ)
https://coefont.cloud/coefonts

なんかすごそうですね。。。(語彙力)
自分の声も音声にしてくれるみたいです
そんな中サイトを見ていると

無料で使用できるものがありました!※1 ひろゆきいいな。。。

ひろゆきで試してみたかったので先ほどのchatGPTのテキストを少し変更します

<質問>
上記の内容についてひろゆき風にですますを使用して出力してください

<chatGPT>
音声技術の話となりますと、本当にその進歩には驚かされますよね。今の時代、AIと音声認識が組み合わさって、前までは想像もつかなかったようなことが可能になっているわけですから。

そもそも音声認識と言いますと、...省略

このように、音声技術の未来はとても興奮するものです。これからどういった進化が起こるのか、それが私たちの生活や社会にどのような影響を及ぼすのか、想像するだけでもワクワクしますよね。

内容をひろゆき風にして、とりあえずCoeFontでひろゆきを選び出力された内容を入れてみます

左が文章、右がアクセントや読みを修正する部分ですね、最初からほぼ修正するところなく出来上がってました。。。すごい

そして完成したのがこちら!
https://firebasestorage.googleapis.com/v0/b/voice-tech-57a10.appspot.com/o/ひろゆき.mp3?alt=media&token=8344d6de-80a5-46fd-8a1c-ff526d4028f4&_gl=1

もうひろゆきですね。ひろゆきが音声業界について語ってくれてます

そんな感じであと二つ作成しました

・猫の素晴らしさについて語るDaiGo

https://firebasestorage.googleapis.com/v0/b/voice-tech-57a10.appspot.com/o/DaiGo.mp3?alt=media&token=f8813654-c55a-40fe-b96c-6b6974a1d869

・トトロの話(おそらく全部嘘)を喋る岡田斗司夫

https://firebasestorage.googleapis.com/v0/b/voice-tech-57a10.appspot.com/o/嘘しか言わない岡田斗司夫.mp3?alt=media&token=14e2ce9b-ebae-44ae-b8cd-6cd7e8d98d18

CoeFontを使えばとても簡単に音声を作れます!
また有料になるとAPIも使用できるようなのでまた使ってみたいなと思います!
https://docs.coefont.cloud/#section/認証方式

※1) 人物名は敬称略で記載しています

本題

ちょっと寄り道しちゃいましたがテストの音声ファイルを作れたのでここからは本題のレコメンド機能を作っていきましょう!!

1. WhisperAPIで音声ファイルからテキストを取得する

まずは音声ファイルからテキストを出力します
OpenAIではchatGPTの他にspeech-to-textとしてWhisperという音声認識モデルがあります。
このWhisperもchatGPTと同様にAPIを提供していますので今回はこのWhisperAPIを使用してみます!

WhisperAPIについて

https://openai.com/research/whisper

WhisperAPIのドキュメント

https://platform.openai.com/docs/guides/speech-to-text

まずはOpenAIのAPIを使用できるようにopenaiをインストールします

brew install openai

インストールできたら使い方は簡単!指定した音声ファイルをOpenAIのAudio.transcribeに渡すだけです!

(ドキュメント参照)
import openai
audio_file= open("/path/to/file/audio.mp3", "rb")
transcript = openai.Audio.transcribe("whisper-1", audio_file)

たった3行で終了です。シンプルですね〜

またwhisperAPIには

file(指定ファイル)

テキストにしたい音声ファイルを指定します

model(使用するWhisperモデル)

現在はlarge-v2が最新バージョンですがwhisper-1と性能はあまり変わらないみたい

response_format(レスポンスのフォーマット)

デフォルトではjsonになっています

language(設定言語)

ここは特に設定せずとも日本語の音声を入れると日本語返ってきました

temperature(温度)

回答のランダム性を指定するもの、今回は一度だけの出力なので特に指定してないです。0から1まで指定できて1に近づくほど回答のランダム性が上がっていくみたいです

上記の5点を指定してリクエストを飛ばすことができます

それでは実際に書いてみます!!

今回は音声が三つあるのでそれぞれの音声を1.mp3 2.mp3 3.mp3としています(ファイル名は最後に再度変更します)

python

import openai

openai.api_key = "登録したopenAIのAPIKey"

for i in range(3):
    audio_file=open(f"usr/path/{i + 1}.mp3", "rb")
    encoded_transcript = openai.Audio.transcribe("whisper-1", audio_file)
    print(f"printでの出力\n---------\n{encoded_transcript['text']}\n---------")

繰り返し処理を書いてその中にWhisperAPIを使用して音声をテキストに処理をする方法を書いています
今回は単純に3回の繰り返しだけだったので素直にapiを3回叩いています

ちなみにWhisperAPiは1分音声の翻訳で大体¥1行かないぐらいです!良心的価格!!
自分は今回の記事で何十回かapiを叩きましたがそれでも100円もいってなかったです!

とりあえずファイルを実行してみます。

printでの出力
---------
音声技術の話となりますと本当にその進歩には驚かされますよね 今の時代AIと音声認識が組み合わさって 前までは想像もつかなかったようなことが可能になっているわけですから そもそも音声認識と言いますと以前はた...以下省略

おー!すごい!!音声からテキストに変換することができました!やったね!

確認してみると精度がすごいですね。。。
特にひろゆきの音声の1:26ぐらいからの

新たな可能性を開くでしょう 顧客サービス マーケティング 製品開発など 音声技術...

ここの部分のマーケティングが音声ではどう聞いても「マーテティング」と言っているのにも関わらず、WhisperAPIが出力したテキストではちゃんと「マーケティング」と書かれています
確認したところspeech-to-textの精度はほぼ100%でした
AIすごい。。。

以下が出力したテキストになります

ひろゆきモデルのspeech-to-text

音声技術の話となりますと本当にその進歩には驚かされますよね 今の時代AIと音声認識が組み合わさって 前までは想像もつかなかったようなことが可能になっているわけですから そもそも音声認識と言いますと以前はただ音声をテキストに変換するという機能だけだったんですよね でも今ではSiriやAlexaといった音声アシスタントがあり 様々な質問に答えてくれたり日々のタスクを管理してくれたり これだけを見てもどれだけ音声技術が進歩したかがわかると思います それだけではないんですよ 音声技術の進歩は近年音声合成技術が飛躍的に発展しているんです 人間のような音声を作り出すことが可能になったんですから これからはパーソナライズされた音声アシスタントを作ったり オーディオブックを朗読したり 映画やゲームのキャラクターの声を作ったりするので使われることになるでしょう つまり音声技術の進化によって 私たちの生活は劇的に変わろうとしているんです 考えてみてください 音声を使った対話が増えれば 私たちの生活もそれに合わせて変わるでしょう 音声技術による革新は 私たちが技術との関わり方を最低位し 生活の思想向上させる可能性を秘めているわけです それから音声技術はビジネスの視点からも 新たな可能性を開くでしょう 顧客サービス マーケティング 製品開発など 音声技術の利用が進むと 企業はこの新たなチャンネルを活用して 顧客とのエンゲージメントを深め ビジネスの効率化を図ることが可能になるわけです ただ音声技術もまだまだ発展途上なわけで いくつかの課題を抱えています プライバシーの保護 誤解を生む可能性 アクセシビリティの確保など まだ解決しなければならない問題があります これらの課題に対する解決策を見つけることが 音声技術のさらなる発展の鍵となるでしょう このように音声技術の未来は とても興奮するものです これからどういった進化が起こるのか それが私たちの生活や社会に どのような影響を及ぼすのか 想像するだけでもワクワクしますよね

DaiGoモデルのspeech-to-text

僕が猫を深く愛している理由っていうのは その独特な魅力と独立性に尽きるんですね それぞれの猫が持つ個性や行動パターンは まるで自己主張をしているかのようで 僕にとってそれはとても興味深いんです 心理学の視点から言うと 人間は社会的な生き物で 他人とのコミュニケーションや共感能力が大切なんです しかし猫はそれとはちょっと違うんですよ 猫は自分で時間を楽しむ 自分で問題を解決するという 自己効力感を強く持つ生き物なので それがまさに自己主張と 自立を体現しているんだと思います さらに猫のコミュニケーション方法も 興味深いんです 人間の言葉を使う一方で 猫は体の動きや音で感情や意図を表現します これは非言語コミュニケーションと呼ばれるもので 猫の気持ちを理解するには 彼らの行動をじっくり観察し その背後にある意味を読み解く能力が必要なんです そして猫の美しさには心を奪われます 滑らかな毛並み 鮮やかな瞳 優雅な動き それぞれの猫が異なる模様や色を持ち それが一つに組み合わさることで 個々の猫は独自の美しさを放つんです この美しさも僕が猫を愛する理由の一つです 心理学的に言うと 美しさは人間に安心感や喜びを与えるんですよ それは美術品を鑑賞している感情と同じなんです また猫の鳴き声の音色は 心地よくリラクゼーション効果があるとされています つまり猫の鳴き声を聞くことで 自分のストレスの軽減に役立つんですよ これらの魅力が一つに組み合わさって 猫はただ存在するだけで 僕たちの心を満たし日常生活を豊かにしてくれる それはまさに猫が持つ魅力と 僕たちがそれを受け入れる力が結びついた結果なんだと思います

岡田斗司夫モデルのspeech-to-text

さて私の愛する映画、『隣のトトロ』についての興味深い小ネタをお話ししましょう。 これらの情報を頭に入れてですね、映画を見直すと、まるで新しい視点から物語を楽しむことができるんですよね。 はじめにあなたはこの映画の舞台がどこかご存知ですか? それはですね、宮崎駿監督の故郷である東京都の多摩地域なんです。 多摩丘陵の自然豊かな風景や、暖かみのある地域の建物や風情が物語のバックグラウンドになっているんですよ。 この地域の風景をじっくり観察しながら映画を見てみると、まるで物語に自分自身が入り込んだかのような感覚を味わえます。 次に、この映画が当初は、興業的なリスクがあるとされていたことをご存知でしょうか? その理由として、物語が子供たちの日常の冒険を描いている点が挙げられます。 戦争や大きな対立といったドラマチックな要素やクライマックスが欠けていたんですね。 しかし、ホタルの墓と同時上映されることでそのリスクは払拭され、全世界に隣のトトロの魅力が広がりました。 実はこのサプライズが、隣のトトロが生み出すノスタルジックでユニークな魅力の一部を形成しているんですよ。 また、トトロという名前ですが、一体どこから来たのかご存知でしょうか? 実はこれは、主人公の妹名がトロルを言いたかったのですが、それをトトロと間違えて発音してしまったからなんです。 名の無邪気な言い間違いが、今や全世界に愛されるキャラクタートトロを生み出したんですね。 これはまさに子供たちの無邪気さと想像力の力を象徴しています。 最後に、サツキがトトロの吹き出す息を、カムカムと表現するシーンを覚えていますか? これは宮崎監督が作り出した造語なんです。 一見意味はないように思いますが、子供たちの直感的で独創的な世界観を表しているんじゃないかと私は考えています。 これらの小ネタを知ることで、隣のトトロの世界がさらに深く豊かに感じられるはずです。 次にこの映画を見るときには、これらの点を思い出してみてくださいね。 それがきっと新たな視点を提供してくれるでしょう。

たった数行のコードで音声がテキストになって返ってくるって改めてすごいですね。。。
そして次はこのテキストにNLPという自然言語処理を使用していきます!!

2. MeCab(NLP)を使用して特徴的な単語を抽出する

次にNLPという自然言語処理を使用して先ほど取得したテキストの特徴的な単語や言葉を抜き出していきます
今回のように短いテキストならそのままchatGPTに渡せばいいですが、今回はchatGPTとWhisper以外にも色々と使ってみたかったのでNLPの技術を使って色々と単語を抜き出していきます!

MeCab

MeCab(めかぶ)とは、「形態素解析」というものを用いて文章から単語を抽出するオープンソースの解析エンジンです
日本語の解析ツールでAIなどが日本語などの言語(自然言語)を機械的に処理するために用いられるらしいですね

https://taku910.github.io/mecab/

例えば
こんにちは、私の名前はうおくんです。最近Voicyに入社しました。好きなお寿司はサーモンです。

という文章があった場合に日本人なら
こんにちは\、\私\の\名前\は\うおくん\です\。\最近\Voicy\に\入社\し\まし\た\。\好き\な\お\寿司\は\サーモン\です\。\

みたいな感じで単語をそれぞれ分割できると思います
簡単に言えばこういった同じような分割をMeCabを使えばできるよ!というものです

まずMeCabを使用するにはMeCab本体と使用する辞書をインストールする必要があります
辞書も色々とありますが推奨されているものがあるのでそちらを使用します

  1. MeCabで使用する辞書をインストール(MeCabをインストールする前にこちらをインストールしてください)
brew install mecab-ipadic
  1. MeCabのインストール
brew install mecab

では試しに先ほどのサーモンの例をMeCabに入れてみます

mecab = MeCab.Tagger("-d /usr/local/lib/mecab/dic/ipadic")
print_text = mecab.parse('こんにちは、私の名前はうおくんです。最近Voicyに入社しました。好きなお寿司はサーモンです。')
print(print_text)

実行してみると。。。

こんにちは	感動詞,*,*,*,*,*,こんにちは,コンニチハ,コンニチワ
、	記号,読点,*,*,*,*,、,、,、
私	名詞,代名詞,一般,*,*,*,私,ワタシ,ワタシ
の	助詞,連体化,*,*,*,*,の,ノ,ノ
名前	名詞,一般,*,*,*,*,名前,ナマエ,ナマエ
はう	動詞,自立,*,*,五段・ワ行促音便,基本形,はう,ハウ,ハウ
おく	動詞,非自立,*,*,五段・カ行イ音便,基本形,おく,オク,オク
ん	名詞,非自立,一般,*,*,*,ん,ン,ン
です	助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
。	記号,句点,*,*,*,*,。,。,。
最近	名詞,副詞可能,*,*,*,*,最近,サイキン,サイキン
Voicy	名詞,一般,*,*,*,*,*
に	助詞,格助詞,一般,*,*,*,に,ニ,ニ
入社	名詞,サ変接続,*,*,*,*,入社,ニュウシャ,ニューシャ
し	動詞,自立,*,*,サ変・スル,連用形,する,シ,シ
まし	助動詞,*,*,*,特殊・マス,連用形,ます,マシ,マシ
た	助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
。	記号,句点,*,*,*,*,。,。,。
好き	名詞,形容動詞語幹,*,*,*,*,好き,スキ,スキ
な	助動詞,*,*,*,特殊・ダ,体言接続,だ,ナ,ナ
お	接頭詞,名詞接続,*,*,*,*,お,オ,オ
寿司	名詞,一般,*,*,*,*,寿司,スシ,スシ
は	助詞,係助詞,*,*,*,*,は,ハ,ワ
サーモン	名詞,一般,*,*,*,*,サーモン,サーモン,サーモン
です	助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
。	記号,句点,*,*,*,*,。,。,。
EOS

単語ごとに分かれましたね!!(うおくんが名詞として認識してくれてませんが、、、)

テキストから単語を分割できたのでWhisperAPIで変換したテキストをMeCabを使って単語ごとに分けていきます!!

色々と変更し最終的に以下のような感じになりました

def extract_word_info(text):
    mecab = MeCab.Tagger("-d /usr/local/lib/mecab/dic/ipadic")
    node = mecab.parseToNode(text)

    word_info = []
    while node:
        if node.feature.split(",")[0] != "BOS/EOS" and node.feature.split(",")[0] == "名詞" and node.feature.split(",")[1] != "代名詞" and node.feature.split(",")[1] != "非自立":
            current_word_info = {
                'surface': node.surface,
            }

            is_duplicate = False
            for word in word_info:
                if word['surface'] == current_word_info['surface']:
                    is_duplicate = True
                    word['count'] += 1
                    break

            if not is_duplicate:
                current_word_info['count'] = 1
                word_info.append(current_word_info)

        node = node.next

    return word_info

基本的にはサーモンの例とやっていることは同じなのですが、少し追加しています

まず先ほどのサーモンの例で言うと

Mecabを使用して「こんにちは、私の名前はうおくんです。最近Voicyに入社しました。好きなお寿司はサーモンです。」から単語を抽出した結果
こんにちは	感動詞,*,*,*,*,*,こんにちは,コンニチハ,コンニチワ
、	記号,読点,*,*,*,*,、,、,、
私	名詞,代名詞,一般,*,*,*,私,ワタシ,ワタシ
の	助詞,連体化,*,*,*,*,の,ノ,ノ
名前	名詞,一般,*,*,*,*,名前,ナマエ,ナマエ
はう	動詞,自立,*,*,五段・ワ行促音便,基本形,はう,ハウ,ハウ
おく	動詞,非自立,*,*,五段・カ行イ音便,基本形,おく,オク,オク
ん	名詞,非自立,一般,*,*,*,ん,ン,ン
です	助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
。	記号,句点,*,*,*,*,。,。,。
最近	名詞,副詞可能,*,*,*,*,最近,サイキン,サイキン
Voicy	名詞,一般,*,*,*,*,*
に	助詞,格助詞,一般,*,*,*,に,ニ,ニ
入社	名詞,サ変接続,*,*,*,*,入社,ニュウシャ,ニューシャ
し	動詞,自立,*,*,サ変・スル,連用形,する,シ,シ
まし	助動詞,*,*,*,特殊・マス,連用形,ます,マシ,マシ
た	助動詞,*,*,*,特殊・タ,基本形,た,タ,タ
。	記号,句点,*,*,*,*,。,。,。
好き	名詞,形容動詞語幹,*,*,*,*,好き,スキ,スキ
な	助動詞,*,*,*,特殊・ダ,体言接続,だ,ナ,ナ
お	接頭詞,名詞接続,*,*,*,*,お,オ,オ
寿司	名詞,一般,*,*,*,*,寿司,スシ,スシ
は	助詞,係助詞,*,*,*,*,は,ハ,ワ
サーモン	名詞,一般,*,*,*,*,サーモン,サーモン,サーモン
です	助動詞,*,*,*,特殊・デス,基本形,です,デス,デス
。	記号,句点,*,*,*,*,。,。,。
EOS

文章から全ての要素を分類して出力するのはかなり見にくくなりますし、例えば「です」や「た」などはそれ単体で意味を持たないのでレコメンドには必要ないです
なのでここから必要な単語だけを抽出したいと思います

色々と品詞を見ていくとレコメンドで必要になってきそうな品詞は「名詞」や「代名詞」あたりかなと思います
さらに「名詞」や「代名詞」の中でも第二分類が「非自立」なものに関してはそれ単体では意味を持たないので排除します
といった感じで色々と排除すると以下のようなコードになりました!

if node.feature.split(",")[0] != "BOS/EOS" and node.feature.split(",")[0] == "名詞" and node.feature.split(",")[1] != "代名詞" and node.feature.split(",")[1] != "非自立":
    current_word_info = {
	'surface': node.surface,
    }

そして抽出した単語に対して同じものに関しては一つにまとめ、出てきた数によってcountを追加していきます

is_duplicate = False
for word in word_info:
        if word['surface'] == current_word_info['surface']:
	is_duplicate = True
	word['count'] += 1
	break

        if not is_duplicate:
	current_word_info['count'] = 1
	word_info.append(current_word_info)

といった感じでここではMeCabを使用して

テキストから意味のあるような単語の情報と出てきた回数をまとめる

という処理をしています

この処理をひろゆきモデルから生成したテキストに対して実行すると

ひろゆきモデルのテキストから抽出した意味のありそうな単語たち
[
{'surface': '音声', 'count': 18},
{'surface': '技術', 'count': 12},
{'surface': '話', 'count': 1}, 
{'surface': '進歩', 'count': 3},
{'surface': '今', 'count': 2},
{'surface': '時代', 'count': 1},
{'surface': 'AI', 'count': 1}, 
{'surface': '認識', 'count': 2},
{'surface': '組み', 'count': 1},
{'surface': '前', 'count': 1}, 
...以下省略
]

うまい具合に音声の内容の特徴にあった単語が抽出されてまとまりましたね!

3. 単語の重要度を算出する

次に各単語の出現した回数からその単語の重要度を10段階評価でスコアとしてだします
ここの重要度の出し方はchatGPTくんに全任せしてみました!
それがこちら

def calculate_importance_score(word_info):
    importance_scores = {}
    max_count = max(word['count'] for word in word_info)
    min_count = min(word['count'] for word in word_info)
    range_count = max_count - min_count if max_count != min_count else 1

    for word in word_info:
        count = word['count']
        importance_score = 1 + 9 * (count - min_count) / range_count
        importance_scores[word['surface']] = importance_score

    return importance_scores

・まずリストからcountの最大値を最小値を出します
・その次にcountの範囲を計算します
・次に各単語に対して以下のような計算を行います

単語の出現回数(count)から最小出現回数を引き、それを範囲で割る。この値は0から1の範囲になる(ただし最大値と最小値が同じ場合は0になる)。

上記の値に9を掛けて1を足す。これにより、重要度スコアは1から10の範囲になる。出現回数が最小の単語は1のスコアを、最大の単語は10のスコアを得る。

といった感じで出力してもらいました
上記のスコアリングは自然言語処理における頻度分析でよく用いられる方法だそうです

コードを実行してみると

{'音声': 10.0, '技術': 6.823529411764706, '話': 1.0, '進歩': 2.0588235294117645, '今': 1.5294117647058822, '時代': 1.0, 'AI': 1.0, '認識': 1.5294117647058822, '組み': 1.0, '前': 1.0, '想像': 1.5294117647058822, '可能': 3.6470588235294117,

こんな感じで頻出単語は10点満点で重要度が点数で出力されるようになりました!
chatGPTくんありがとう。。。

4. chatGPTにレコメンドしてもらう

遠回りしましたがようやくchatGPTの出番です
最初からこいつを使っていればすぐに済むのですが、今回はWhisperとNLPのお勉強ということで最後までスタンバってもらいました

chatGPTの役割について

chatGPTは役割を設定するとその役割に沿った特徴的な回答をします
どんな役割があるのか、chatGPTくんに聞いてみました

chatGPTの役割にはどのような種類があるのですか?

ChatGPT
ChatGPTの役割は非常に多岐にわたり、それはあなたがどのような情報を得たいか、またはどのような視点からのレコメンドが欲しいかによります。以下に、ChatGPTに設定できる一部の役割の例を示します:

1. エキスパート/アドバイザー: これはChatGPTに特定の領域の専門家やアドバイザーとして振る舞うように指示する役割です。これは、法律、医学、科学、テクノロジーなど、特定の主題について詳しい情報を得たいときに役立ちます。

2. リサーチャー: この役割では、ChatGPTはリサーチャーとして行動し、あなたの質問や主題について広範な情報を探し出します。

3. フレンド: この役割では、ChatGPTは友人として振る舞い、よりカジュアルで親しみやすい会話を提供します。

4. カウンセラー: この役割では、ChatGPTはカウンセラーとして振る舞い、ユーザーの感情に対応したアドバイスやガイダンスを提供します。

5. コーチ: この役割では、ChatGPTはコーチとして振る舞い、ユーザーが目標を達成するための戦略やアドバイスを提供します。

6. 教師: この役割では、ChatGPTは教師として振る舞い、特定の主題について教育的な情報を提供します。

7. ストーリーテラー: この役割では、ChatGPTはストーリーテラーとして振る舞い、ユーザーが指定したテーマやパラメータに基づいて物語を作成します。

これらはあくまで例であり、あなたが具体的に何を求めているかによって、ChatGPTにさまざまな役割を設定することが可能です。また、システムメッセージを利用してChatGPTの行動をより具体的に指導することも可能です。

。。。まあ、色々とあるということですね!!
今回はレコメンドということでとりあえずリサーチャーを使用してみます

まずはchatGPTがレコメンドしやすいようにWhisperAPIを叩いている部分のデータと音声ファイル名を整えます

Before

for i in range(3):
    audio_file=open(f"usr/path/{i + 1}.mp3", "rb")
    encoded_transcript = openai.Audio.transcribe("whisper-1", audio_file)
    print(f"printでの出力\n---------\n{encoded_transcript['text']}\n---------")

After

recommend_words_list = []
audio_list = ['ひろゆきモデル', 'DaiGoモデル', '岡田斗司夫モデル']
for audio in audio_list:
    audio_file=open(f"usr/path/{i + 1}.mp3", "rb")
    encoded_transcript = openai.Audio.transcribe("whisper-1", audio_file)
    
    word = extract_word_info(encoded_transcript['text'])    # MeCabで頻出単語を抽出する処理
    result = calculate_importance_score(word)   # 単語からスコアリングを算出する処理
    recommend_words_list.append({'file_name': f"{audio}.mp3", 'words': result})

最後にchatGPTに質問する情報recommend_words_listが作成できたのでchatGPTに投げてみます

import sys

res = openai.ChatCompletion.create(
    model="gpt-3.5-turbo",
    messages=[
        {"role": "system", "content": "あなたはリサーチャーです"},
        {"role": "user", "content": f"{recommend_words_list}\nfile_nameは元ファイルの名前、
        contentはそのファイルにある頻出の単語とその単語の重要度を10段階評価で表したものになります。
        この時「{sys.argv[1]}」とリクエストがきた時に一番おすすめできるfile_nameとその理由を50文字以内で教えてください。
        またどれもおすすめできない場合は「おすすめできる投稿はありません」と出力してください"
        }              
    ],
    temperature=0
)

print(res["choices"][0]["message"]["content"])

ちょっと雑なmessageですがこれでどうでしょうか?

試しに質問を投げてみます

[質問]

音声業界の今後について知りたいです。おすすめの投稿はありますか?

[chatGPTの回答]

「ひろゆきモデル.mp3」がおすすめです。AIの進歩により、音声技術が劇的に進化し、生活においても活用されるようになっています。ビジネス視点からも注目されており、今後の方向性を知る上で参考になるでしょう。

[質問]

猫と犬はどちらがいい?

[chatGPTの回答]

「DaiGoモデル.mp3」がおすすめです。猫の独特な魅力や個性、コミュニケーション能力などを深く掘り下げており、猫好きには必見の内容となっています。

[質問]

ジブリについて解説しているものはありますか?

[chatGPTの回答]

「岡田斗司夫モデル.mp3」がおすすめです。映画「トトロ」について解説しており、トトロや宮崎駿監督についての情報が豊富に含まれています。

うまくリクエストされてますね!!
これで質問を元にレコメンドしてくれるシステムができました!!やったー!!!

ただChatGPTは単語の羅列から内容を想定して返信を返しているので、レコメンドした理由の部分は完全に正しいといった感じではないっぽいです。やはり内容をしっかりと鑑みてレコメンドをするにはテキスト全文をchatGPTに投げるしかないようです!

しかし単語とスコアリングのみでレコメンドができるようになれば、ファイル数が大きくなっても比較的スケールしやすいのではと思っています!どちらの方法も一長一短ですね。

こちらがコード全文になります
python

import openai
import MeCab
import sys

openai.api_key = "OpenAIのAPIKey"

def extract_word_info(text):
    mecab = MeCab.Tagger("-d /usr/local/lib/mecab/dic/ipadic")
    node = mecab.parseToNode(text)

    word_info = []
    while node:
        if node.feature.split(",")[0] != "BOS/EOS" and node.feature.split(",")[0] == "名詞" and node.feature.split(",")[1] != "代名詞" and node.feature.split(",")[1] != "非自立":
            current_word_info = {
                'surface': node.surface,
            }

            is_duplicate = False
            for word in word_info:
                if word['surface'] == current_word_info['surface']:
                    is_duplicate = True
                    word['count'] += 1
                    break

            if not is_duplicate:
                current_word_info['count'] = 1
                word_info.append(current_word_info)

        node = node.next

    return word_info

def calculate_importance_score(word_info):
    importance_scores = {}
    max_count = max(word['count'] for word in word_info)
    min_count = min(word['count'] for word in word_info)
    range_count = max_count - min_count if max_count != min_count else 1

    for word in word_info:
        count = word['count']
        importance_score = 1 + 9 * (count - min_count) / range_count
        importance_scores[word['surface']] = importance_score

    return importance_scores


recommend_words_list = []
audio_list = ['ひろゆきモデル', 'DaiGoモデル', '岡田斗司夫モデル']
for audio in audio_list:
   
    audio_file=open(f"usr/path/{audio}.mp3", "rb")
    encoded_transcript = openai.Audio.transcribe("whisper-1", audio_file)
    
    word = extract_word_info(encoded_transcript['text'])    # MeCabで頻出単語を抽出する処理
    result = calculate_importance_score(word)   # 単語からスコアリングを算出する処理
    recommend_words_list.append({'file_name': f"{audio}.mp3", 'words': result})



res = openai.ChatCompletion.create(
    model="gpt-3.5-turbo",
    messages=[
        {"role": "system", "content": "あなたはリサーチャーです"},
        {"role": "user", "content": f"{recommend_words_list}\nfile_nameは元ファイルの名前、contentはそのファイルにある頻出の単語とその単語の重要度を10段階評価で表したものになります。この時「{sys.argv[1]}」とリクエストがきた時に一番おすすめできるfile_nameとその理由を50文字以内で教えてください。またどれもおすすめできない場合は「おすすめできる投稿はありません」と出力してください"}              
    ],
    temperature=0
)

print(res["choices"][0]["message"]["content"])

これで音声から任意のファイルをレコメンドしてくれる機能ができました!やったね!
頻出単語の抽出のやり方や、スコアリングのやり方、Whisperで出力したテキストをそのままchatGPTに使ったりと他のやり方でも精度は色々と変わりそうですね!
また他のライブラリ等も使用して試してみたいと思います!

最後に

今回はOpenAIの恩恵をフルに活用してレコメンド機能を作成してみました!
AIがよしなにやってくれるというのはとてもありがたいですね
今回の実装でつまづいたところや情報のキャッチアップ等もchatGPTくんに大変お世話になりました
調べるところから実装まででおよそ3時間ぐらいで終わったので恐るべきAIの力、、、という感じでした(記事書いてる時間のほうが長かった)

今回はwhisperAPI等をメインで使用しましたが、最近はchatGPTのfunction callingが出たりLangChainにも興味があるので積極的に使ってみたいなあと思っています!

音声でワクワクする未来を作る方法をどんどん見つけていこうと思います!

Voicyテックブログ

Discussion