kmizuの日記

プログラミングや形式言語に関係のあることを書いたり書かなかったり。

環境変数CUDA_VISIBLE_DEVICESでハマったのでメモ

 最近はすっかりLLMにハマってるわけですが、ハマり過ぎたあまり一台のPCに複数のGPUを搭載(といっても、RTX A4000(VRAM 16GB)とQuadro M6000(VRAM 24GB)という妙な組み合わせですが)してたりするのですが、どうにもLLMの出力速度が遅いなーなどと思っていました。

 感覚的には主にM6000の方が使われてる感じで、こいつはVRAMこそ多いもののRTX A4000より圧倒的に遅い(数世代前)ので、メインで使ってほしくない。というわけで、CUDA_VISIBLE_DEVICESという環境変数をいじってやればいいってところまではたどりついたのですが、CUDA_VISIBLE_DEVICES=2とかしてやってcuda:1みたいに指定すると妙なエラーが出る。色々調べてわかったのは、

export CUDA_VISIBLE_DEVICES=0,1
python llm.py # この中でcuda:1なりcuda:0なりを指定する

 のようにすればいいらしいということ。この環境変数はデバイスの数ではなくて、GPUのリストを指定するものだったわけですね。盲点でした。

ChatGPT に「形式が整った俳句」を作ってもらう(あるいは「文字数指定」をする)

 おはようございます。今日も元気にChatGPTをしています。さてさて、ChatGPTに俳句を作らせようとしても失敗するという話は一部界隈では有名です。たとえば、次のように「俳句を作ってください」とだけ指定しても五・七・五を平然と無視してくれやがります。

俳句(うまく行ってしまった)

 あれ?うまく行ってしまいましたね。ChatGPTは非決定的に答えを返すのでこんなこともありますよね。同じプロンプトでリトライします。

俳句(きちんと間違えた)

 これでようやく間違えてくれたので本題に入れます。と、このように俳句を詠んでと言っても五・七・五を平然と無視してしまうのです。では、俳句のフォーマットを指定してやった場合はどうでしょうか?

俳句(一回の修正で通ってしまった)

 あれれ?一回の修正でちゃんと五・七・五になおしてきましたね。う、うーん。まぐれ当たりのハズなので、三句くらい詠めばはずしてくれるはず。

はずしてくれた

 今度は予定通り(?)です。文字数に関する指定をしても、どうにもうまく行きません。

 この「文字数制限の指定をChatGPTは無視する」というのは廃ChatGPTerには有名な話なのですが、一方で「5個」とかの数量は理解してくれますし、リストの長さは理解してくれるんですよね。とここで昨夜思いついたのが「文字列を文字のリストとして表現すれば、ChatGPTはちゃんと文字数制限に相当するものを理解してくれるのでは」ということでした。というわけで、トライです。

お願い(1)

お願い(2)

 文字リストとして出力してもらう形にしたのでだいぶ「改善しています」。しかし、制限をもうちょっと厳密に守ってもらおうかと、より形式的に文字リストを出力してもらうようにしました。

文字数指定(厳密)

 今度は指示こそ通ったももの「本当に5文字、7文字、5文字からなる文字リストを出力する」だけですね。文字数をそのまま指定しようと無視するし、厳密に指定させると今度は単なる文字列長制限つき文字列生成になってしまうようです。しかし、ここで諦めては負けです。「文字リストを出力させる」アプローチはいいはずなので、あとは3つのリストが五・七・五に対応させるとこまでやればいけるハズ。てことで

成功例(1)
成功例(2)

 やってみたら見事行けました!季語が一部入ってないですが、五・七・五にきちんと従わせられたので及第点としていいでしょう。ただ、欲を言えば1回の質問でちゃんと「俳句になっている文字リスト」が欲しいですよね。もうちょっと頑張ってみました。

俳句(成功)

 ここまでやって思ったのですが、ChatGPTさんはやはり俳句の意義自体は理解しているように感じるので、プログラミング言語のコレクションのような、ChatGPTが間違えようがない形式を経由するとうまく行きやすいかもしれません。

ChatGPT APIで仮想人格を作り込む

 おはようございます。さて、皆さん。ChatGPT、使いこなしてますか?私は……使いこなしてるかはわかりませんが、ドはまりしてることだけは確かです。プログラミング言語間のトランスパイルをできるツール

github.com

を作ったり、仮想人格を作ってそのキャラとチャットしてみたり、テキスト->音声ソフトウェア(VOICEPEAKやVOICEVOX)を使って、キャラに声をつけてみたり。さらにWhisper APIと組み合わせて[キャラクタと音声会話できるツール

github.com

を作ったりと色々変なことも試しています。ちなみに、VOICEPEAK(東北ずん子)についてはこちらから、

www.ah-soft.com

VOICEVOX

voicevox.hiroshiba.jp

についてはこちらから。VOICEPEAKはさすがに有料で公開されてるソフトウェアだけあって、普通に読み込ませるだけでもより自然なイントネーションでしゃべってくれるなどの利点がありますが、1万円超と逸般人でない人が試すにはちょっとお高いので無料かつライセンスが比較的ゆるい(詳細は上記を参照)VOICEVOXを使ってみるのがいいのかなと思います。

それはともかく、ChatGPT APIを使えば、あの生真面目なChatGPT君のキャラだって自由自在にカスタマイズできます。試しにちょっとしたキャラ設定を作ってみましょう。手元のSlack Botなどを使ってもいいのですが、試しやすいようにOpenAIのPlaygroundを使います。

ChatGPT APIでキャラを作り込んでみた

顔文字の使い方が20代の女性っぽいのかは不明ですが、キャラ付けした部分はうまく反映されているように見えます。

ChatGPT APIでは「system」「user」(主にユーザからの質問に使われる)」「assistant(主にChatGPTからの応答に使われる)」の3種類のrole=役割があるのですが、systemでキャラ設定を最初に作り込んでおけば、以後(倫理規定に引っかからない限りは)、その設定を演じてくれます。これはWeb版のChatGPTでも使えることは知られていますが、APIを使えば一度作り込んだキャラ設定をずっと維持できるのがメリットでしょうか。

ちょっと設定を付け加えて、魚介類、得にサバが好きということにしてみましょう。

サバ好き女子大生

うまく反映されていますね。苦手なものとして、大人数の飲み会というのも追加してみましょう。

大人数の飲み会が苦手な女子大生

User=私が「30名くらいの大所帯」で愚痴ったところに、ちゃんと「私も大人数の飲み会って苦手だから」と返していますよね。「わかるよ」とも。こんな風に言葉だけで仮想人格を作り込める万能ソフトウェアって今まで存在しなかったわけで、こういうところにもChatGPTの凄さがあるなと感じます。

ちなみに、今回はgpt-4-0314というモデルを使っていますが、gpt-3.5-turboでもそれなりにはキャラを演じてもらえます。ただ、仮想人格を作り込むという目的だと今一つという感がありまして、設定が中途半端にしか反映されません。たとえば、こんな感じです。

女子大生(GPT-3.5)

共感しつつ、というのは反映されていますが、大人数の飲み会が苦手って部分が中途半端にしか反映されていませんよね。タメ口設定も無視されています。この辺りを見ても、gpt-4の賢さが伺えます。

というわけで、APIを使える皆さんはせっかくなので、自分好みの「アシスタント」のキャラを作り込んで答えてもらうといいかもしれませんね。いやまあ、書いてから気づいたんですが、キャラを作り込めるのはgpt-4からということなので、まだgpt-3.5までしか使えないケースだと(そして、現状だとgpt4をAPIで使えるのはごく一部っぽいので)作り込みに多少苦労するとは思いますが、それについてもプロンプトを工夫すればある程度はうまくやってくれます。

ChatGPT APIベースの多言語トランスパイラGPTranslatorを公開しました!

 この日記やTwitterなどで、ChatGPT (GPT-3.5, GPT-4)はプログラミング言語間の変換(に限らないですが)が得意ということを書きましたが、試している内に「毎回似たような指示するのだるいな」と思うようになりました。というわけで、Reactベースで動くChatGPT APIを使ったトランスパイラGPTranslatorを作ってみました。ちなみに最近はトランスパイラという言い方がすっかり主流になった気がするのですが、一昔前だとトランスレータと呼ばれてた気がしますね……。

github.com

 といっても、要はChatGPT APIに投げる前に適当なプロンプトを付加しているだけという代物です。ただ、コードフラグメントを別言語に変換するときや、YAML -> JSONみたいな設定ファイルの形式を変換するときなんかには多少役に立つのではないかなと思います。

 詳細はGitHubリポジトリを見てもらうとして、OpenAIのAPI KEYを

export REACT_APP_OPENAI_API_KEY=<api key> # this must be set before npm start

 という形で指定しなければいけないところは多少使い勝手が悪いかもしれません(設定ファイルに書けた方がいいような気もします)。ともあれ、使ってみてバグや改良点などあればPull Requestなどがんがんいただければと思います。言うまでもないですが、ChatGPTベースということで精度は完璧ではありませんし、変換元や変換先の言語によってはうまくいかなかったりすることもあります。

以下のスクリーンショットだと、Javaにはメソッドの中に直接メソッドを書く機能はないのになんか入っちゃってますね。そもそも型がないJavaScriptをそのままJavaに変換しようと思うと無理が生じるのは必然でもありますが。

JavaScript to Java

一方、PythonからJavaScriptへの変換は比較的素直に行きやすいようです(もっと複雑なサンプルになればまた別ですが)。

a

Python to JavaScript

ChatGPT API (gpt-3.5-turbo) をお試しできる簡易アプリを作ってみました

 今朝未明、ChatGPT APIのリリースが告知されたわけですが、

openai.com

 色々あって手早くとりあえず動くBOTを作ってみました(元々、GPT-3 BOTを作ってあったのでそれの微修正ですが)。ドキュメントは最低限ですが、

  • コマンドラインで動く簡易BOTchat.shexport OPENAI_API_KEYを修正した上、sh chat.sh`でいける)
  • Slack Bot(こっちはSlack Botを作る知識が多少いる)

 として使えます。試したいけどコード書くのめんどいなーという人の参考になれば。

github.com

ChatGPT-BOTのデモ

「謝ったら死ぬ病」と人は言うけれど

 ずっと前から、特にネットの世界で炎上事件が起こるたびに言われる言葉に「謝ったら死ぬ病」というものがあります。この言葉が趣味悪すぎるなら、「早く誤りを認めて謝罪した方が傷が浅いのに」とか「なんでこの人は謝れないんだろう」とか色々バリエーションがあるのでそれでも構わないです。

 この言葉、「自分の誤りを認められない頑固な人がいるよね」といういわば他人事として語られることが多いのですが、果たしてそうだろうかというのがずっと思っていることです。これまでネット上でもリアルでも、ですが、色々な論戦や喧嘩や炎上事案を見てきましたが、そのような人は自分を含めてほとんどいないというのが正直な実感です。より正確には、そういう人も傍観者でいる間は冷静に聴衆の反応とかを見て「謝った方が得策だ」とか「傷が浅いうちに訂正した方がまだマシである」という判断ができるものですが、自分が当事者になったときに速やかに自分のミスを認めて訂正することはあんまりできていないように思います。自分も含めて

 最初から控えめな言い方をしている人は、そもそも「この部分は論拠があやふやかもしれないなあ」という自覚を持って発言していることが多いので、ミスを認めるのが早い傾向にありますが、特に一度断定的な物言いをしてしまって、あちこちに影響を与えてしまった後に「すいません。大間違いでした」と素直に言える人はとても稀有だというのが正直な実感です。稀有だからこそ、そういう事案があったときに「この人はすぐに誤りを認められて凄い」という評価を受けるといいますか。

 結局、人間というものは怒りに我を忘れてしまったら、あるいは感情を激しく傷つけられているときには、誰でも「謝ったら死ぬ病」にかかってしまうものじゃないのかなと最近思うのです。統計的な根拠を持ってこいと言われると弱いところですが、自分の黒歴史を振り返っても、あるいは「謝ったら死ぬ病」と揶揄する人が「すぐ謝る」を実践できているかというと大体できてないので、そうとしか思えない。

 もし人間が誰しも「謝ったら死ぬ病」になりえるのだとして、対策があるとしたら

  • 普段から断定的な物言いを控えて訂正するときの心理コストを下げる
  • 訂正することや相手に傷ついた旨を表明されたときに速やかに頭を下げることを習慣づける
  • そもそも、自分の意見を述べない(これはこれで一つの処世術だとも思います)

 くらいしかないんでしょう。ただ、どちらも心構えだけで実践できるかというと多分難しくて、結局、訂正することや傷つけた相手に謝ることを生涯実践し続けることしかないんじゃないかなというのが最近思うことです。もちろん、その時点ではどうしても意地や理屈が邪魔をして素直に認められないことは、それこそ人間だから仕方ないとも思います。後日(が下手したら数年後になることもありますが)、冷静になったときに「この言動は相手を深く傷つけてしまったかもなあ」とか「あの時は偉そうな物言いをしたけど、自分が間違っていたなあ」と認めていくことが肝要だろうなと。

 特に有意義な結論はないのですが、年末にちょっとこれまで思っていたことをまとめてみたのでした。

 追記:このお話の帰結として、私たちは軽度であれ重度であれ誰しも「謝ったら死ぬ病」にかかっているので、傍から見て「この人は謝れないでいるなあ」と思っても、あんまり揶揄しないであげた方がいいと思うんですよね。自分もまた別の場面では「謝れない」かもしれないわけですし、謝れないことを揶揄したりいたずらに糾弾するなんてことは、謝るコストを上げるだけで、結局誰にとっても得にならないなあと思うのです。もちろん、立場上、謝れない相手に対して粛々と対処せざるを得ないことはありますが、それはそれとして。

ChatGPTで日本語プログラミング(本当)をやってみた

 さて、相変わらずChatGPTにハマっておりますが、ふと思いついたアイデアがあります。どうも、ChatGPT君はプログラミング言語「そのもの」の普遍的な理解があるのではと思えてきたので、それを考えると自然言語をプログラムとして解釈させることも可能な気がしてきたのですよね。というわけで、以下がスクショです。階乗を計算させるのが目的ですが、階乗と書くと空気読まれそうなので「ほげ数」にしてあります。

 なんか「どのプログラミング言語で解釈すればいいかわからないタスク」についてはどうもPythonに内部的に変換して解釈してる節があります。ともあれ、再帰を含む日本語疑似コード(表記ゆれあり)をそのまま解釈できるのは凄いですね。

 不完全ですが対話ログを gist に保存しておきました。回答はプロンプトごとに微妙に違うものが返ってくる可能性があるのでご注意をば。