![見出し画像](https://assets.st-note.com/production/uploads/images/100162544/rectangle_large_type_2_12f666c08cd73a5f1e63304e99c454b7.png?width=800)
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に送信して、リアル
続けて
タイムにテキスト変換するために使用されます。まず、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を使用して、リアルタイムの音声認識を実行するために使用されます。
コードによるけど、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()メソッドはブロックされるため、別のスレッドがデータを追加する必要があります。したがって、適切な同期方法を使用することが重要です。
実際のコード設計を壁打ちしてもらう
なんとなく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でやりましょう。
あと自社サービスのデータを突っ込む… というよりは、オプソやサンプルコードをぶっ込んで、教えてもらう…という使い方が安全でオススメです。(あるいは自分用の共通ライブラリで)。
その他過去の実験
いただいたサポートは、コロナでオフィスいけてないので、コロナあけにnoteチームにピザおごったり、サービス設計の参考書籍代にします。