見出し画像

AIにコードまるごと解説してもらうと、界王拳100倍すぎる件

最近、見つけた技。知らない言語でコードかくときChatGPTが神すぎる。

そのテクはなんと「プログラミングまるごとを、ChatGPTに突っ込む」というもの。

え、そんなの動くの!? と思うんですが、動くんですそんなの。直球すぎて盲点だった。


試してみよう


たとえば、下記はGoogleサービス使って、リアルタイムにマイク音声を文字起こしするサンプル。

こいつをチャットAIで音声会話をやろうと、軽く読んでみたのですが…うん、よくわからん。

Pythonだし、Streamingだし、音声の操作だし、普段つかわない技術が満載すぎてわからん。


雑にコードを突っ込むと人生が解決

こういう時は

以下のコードを、わかりやすく説明して。

<以下、上記コードをそのままコピペ>

とすると……  こうなる。

このコードは、Google Cloud Speech-to-Text APIを使用して、マイクからの音声をリアルタイムにテキストに変換するPythonスクリプトです。以下は、コードの主要な機能についての説明です。

必要なモジュールのインポート
スクリプトの先頭で、必要なモジュールをインポートしています。reモジュールは、正規表現を使用するために、sysモジュールは、システムからの入出力を扱うために、timeモジュールは、時間を測定するために、pyaudioモジュールは、オーディオを扱うために、queueモジュールは、キューを扱うために、google.cloud.speechモジュールは、Google Cloud Speech-to-Text APIを使用するために、sixモジュールは、Python 2と3の互換性を保つために使用されています。

オーディオの録音パラメーターの設定
このスクリプトでは、オーディオのストリーミングを制御するために、いくつかのオーディオ録音パラメータを定義しています。STREAMING_LIMITは、ストリーミングの制限時間を示し、SAMPLE_RATEは、サンプリング周波数を示し、CHUNK_SIZEは、オーディオの1つのチャンクサイズを示します。

ResumableMicrophoneStreamクラスの定義
このクラスは、マイクからの音声ストリームを生成し、APIに送信するために使用されます。オーディオストリームを開始し、音声入力をキューに入れます。さらに、各ストリームについて必要な変数を初期化し、ストリームを生成するためのメソッドを提供します。

listen_print_loop関数の定義
この関数は、Google Cloud Speech-to-Text APIからの応答を受け取り、テキストを表示するために使用されます。APIからの応答には、最上位の代替テキストなどの情報が含まれます。この関数では、最上位の代替テキストのみを表示するために、応答をフィルタリングしています。また、途中経過のテキストと最終結果のテキストを区別するために、is_final属性を使用しています。

main関数の定義
この関数は、マイクからのオーディオストリームを取得し、Google Cloud Speech-to-Text APIに送信して、リアル

Chat GPT
続けて

タイムにテキスト変換するために使用されます。まず、speech.SpeechClient()を使用して、APIクライアントを初期化し、speech.RecognitionConfigとspeech.StreamingRecognitionConfigを設定します。次に、ResumableMicrophoneStreamを使用して、マイクからのオーディオストリームを生成し、audio_generatorにオーディオチャンクを渡して、APIに送信するためのリクエストを作成します。APIからの応答は、listen_print_loop関数によって処理され、最終的にテキストが表示されます。

その他の関数や変数
このスクリプトには、その他の関数や変数も含まれています。get_current_time関数は、現在の時間をミリ秒単位で取得するために使用されます。RED、GREEN、YELLOWなどの色を定義するために、ANSIエスケープコードが使用されています。また、STREAMING_LIMITを超えると、ストリームが再起動されるために、いくつかのストリーム制御変数が定義されています。

以上が、このスクリプトの主な機能についての説明です。このスクリプトは、Google Cloud Speech-to-Text APIを使用して、リアルタイムの音声認識を実行するために使用されます。

Chat GPT

コードによるけど、Googleのサンプルや有名なオプソであれば、かなりの精度で解説してくれる。


解説してもらう

listen_print_loop という概念をしらなかったので質問。たぶんasyncioやソケット通信みたいなループでのブロックだと思うのだが…

このメインスレッドは、listen_print_loop でブロックされて、無限ループの待機になりますか?

はい、main関数の最後の部分で呼び出されるlisten_print_loop関数は、APIからの応答を取得するためにジェネレーターを使用しているため、呼び出されるとブロックされ、応答がない限り無限ループで待機します。したがって、このスクリプトは、マイクからの音声ストリームをリアルタイムに取得し、APIに送信して応答を待機し、それを表示するために設計されています。このため、このスクリプトを実行する場合、キーワードを発話して、プログラムの実行を停止する必要があります。

改善案を議論する

やはり、ループ処理のブロック部分だった。普通に音声認識するならいいけど、ゲームやVTuber動かす場合は、非同期に処理させたいんですよね。

なので、非同期にするための質問をする。
ThreadならQueueを使って、別スレと通信すればいけるかな??

このストリーミングクラスをスレッドAで走らせながら、スレッドBで音声認識されたテキストを処理したいと思います。 
queue.Queue を使って実装するのがよいでしょうか?

はい、queue.Queueは、スレッド間の同期や通信に役立つPythonの標準ライブラリです。一般的に、マルチスレッドアプリケーションでは、1つのスレッドが生成したデータを別のスレッドで処理する必要があります。その場合、スレッド間でデータを受け渡すために、queue.Queueを使用することができます。

具体的には、マイクからの音声ストリームを生成するためのResumableMicrophoneStreamクラスをスレッドAで実行し、音声認識されたテキストを処理するための別の関数をスレッドBで実行する場合、queue.Queueを使用してテキストを受け渡すことができます。具体的には、スレッドBでqueue.Queueオブジェクトを作成し、listen_print_loop関数内でテキストが生成された場合に、queue.Queueに追加します。その後、スレッドBで、queue.Queueからテキストを取得し、必要な処理を行います。

ただし、queue.Queueを使用する場合は、適切な同期方法を使用する必要があります。たとえば、queue.Queueはスレッドセーフですが、複数のスレッドで同時に更新する場合は、適切なロックを使用する必要があります。また、queue.Queueにデータがない場合、get()メソッドはブロックされるため、別のスレッドがデータを追加する必要があります。したがって、適切な同期方法を使用することが重要です。

ChatGPT

実際のコード設計を壁打ちしてもらう

なんとなくThreadでいけそうな気がしてきたので、コードのキモになりそうな、main実行周辺の書き換え方を

ストリームを別スレッドで行うためのコード改変を考えます。

main() を呼び出す部分で、というような型にすればよいでしょうか?

q = queue.Queue()
#オーディオストリームのスレッド
threadA = thread.threading(target=main, args=(q,))
#文章解析のスレッド
threadB = thread.threading(target=precess_text, args=(q,))

threadA.start()
threadB.start()


ご提案のコードには、いくつかの修正が必要です。以下に、修正すべき箇所を示します。

threadingモジュールをインポートします。
import threading


main関数の引数にキューを追加します。
def main(q):


main関数の終了後にキューにNoneを追加するようにします。
q.put(None)


listen_print_loop関数を修正して、処理した結果をキューに追加するようにします。
if result.is_final:
    # 最終結果の場合
    q.put(transcript)


threading.Threadクラスを使用して、スレッドを開始します。第1引数には、実行する関数を指定し、第2引数には、関数に渡す引数を指定します。
q = queue.Queue()
#オーディオストリームのスレッド
threadA = threading.Thread(target=main, args=(q,))
threadB = threading.Thread(target=process_text, args=(q,))

threadA.start()
threadB.start()


注意点としては、main関数とlisten_print_loop関数が、1つのスレッドで実行されるようになっているため、両方を同時に実行することはできないことです。したがって、別々のスレッドでそれぞれを実行する必要があります。また、process_text関数がどのように実装されるかによって、スレッド間通信の具体的な方法が異なる場合があります。例えば、キューを使用する方法以外にも、マルチプロセスや共有メモリを使用する方法もあります。

雑にかいたコンセプトのコードに、必要な続きをしっかり書いてくれる(読みやすいように、ちょっと改行とか整形しました)。
わーすごい、だいたい全部なんとかしてくれた!!!!


仕事の生産性が100倍

普段つかわないPythonのストリームのコードなんて、普通にググりながら調べたら、理解するのに3日ぐらいかかりそうな代物。それが、たった30分かからず、概要と使い方と、応用までオール解決。

たまに嘘もつきますが、コード関係はだいたい合ってることが多い。(最後に自分で、走らせれば簡単に確認できる)。

これフリーランスや、インディーズでソフト開発してる人なら、年収2倍とか夢じゃないレベルの生産性アップを狙えそう。

自分は現役のActionScript職人だったころ、3000〜5000行 / 日ぐらいが限回だったのですが… これとCopilotの支援があれば1日に1万行ぐらいかけそうな気すらしてきます。

シンプルすぎる使い方で、試してなかったのだけど…ここまでできるとは思わなんだ。


大事な注意

この技法、会社のお仕事で使うときはセキュリティポリシー等を確認してつかってね。

GPT3のAPI経由での利用は、「データは学習に使われない」ことが明記されてるけど、 ChatGPTのウェブインターフェース上は、保証されてない気がします。心配な人はGPT3のAPIでやりましょう。

あと自社サービスのデータを突っ込む… というよりは、オプソやサンプルコードをぶっ込んで、教えてもらう…という使い方が安全でオススメです。(あるいは自分用の共通ライブラリで)。


その他過去の実験


この記事が参加している募集

やってみた

AIとやってみた

いただいたサポートは、コロナでオフィスいけてないので、コロナあけにnoteチームにピザおごったり、サービス設計の参考書籍代にします。