本セッションの概要

鈴木悠大氏(以下、鈴木):鈴木です。よろしくお願いします。オフラインはそんなに人がいなくて、オンラインにいっぱいいるので超不安です。思ったより聞いている人がいるんだろうなと思いながら話すのが不安です。

HRBrainの鈴木です。大学では経営工学を学んでいて、コードは今も昔もたくさん書いています。HRBrainでは、今はプロダクトチームのテックリードとプラットフォームチームを兼務しながらいろいろやっていて、冪等性なものが好きで、浮動小数点の誤差が嫌いです。

今日の概要ですが、今回はLuaをスポットで使いたかったので使った話をします。概要でいうと「ChatGPTにいろいろ聞きながら初めてLuaを書いたよ」という話になります。

株式会社HRBrainのドメインについて

まずHRBrainについてですが、HRBrainは1つのログインIDでログインをして、タレントマネジメント、組織診断サーベイ、人事評価、360度評価、労務管理などのいろいろなことができるものを提供しています。

(スライドを示して)なのでドメインがこんな感じになっていて、サブドメインの一番上に会社のテナントIDが来て、その下にサービスのIDが来て、hrbrain.jpみたいなドメインがあります。これは超重要なので、一応覚えてもらえるとうれしいです。

今回作りたいプロキシ

(スライドを示して)今はブランチデプロイ環境と社内で呼んでいるもの、プルリクエストごとに検証できる環境を作っています。会社によってはPull Request環境と呼んでいたりするのかなと思います。

これを弊社では今はプラットフォームチームとして提供しています。ただ、弊社は複数のサービスでブランチデプロイ環境を立ち上げているので、ちょっと複雑です。

もともとGKE(Google Kubernetes Engine)で動かしていたのですが、最近CloudRunに移行して、CloudRunで作っています。

CloudRunのリビジョンタグがあって、それを有効活用しています。リビジョン、バージョンごとに名前を付けられて、その名前を使って特定のリビジョン、バージョンにアクセスできます。

通常は一番上のURLにアクセスするのですが、今回の使い方ではpr123---service-aにアクセスすると、そのプルリクエストのAPIにアクセスできるようなものを使っています。

(スライドを示して)それを利用して、PR番号---テナントID.サービスID.hrbrain.jpというテナントを、先ほどのPR番号---○○という下のものに当てはめて、上のやつはそのまま流すプロキシを書きたいというのが今回の話です。

「コピペの400行」がしんどい問題

(スライドを示して)プロキシを書きたい時に何で書くかというと、Nginxが一番有名だと思います。Nginxで書こうとすると、例えばPRがついたものは1つ目のServer設定に飛ばして、PRがついていないものは2つ目のServer設定に飛ばすという……。細かいところはいいのですが、これに数分必要です。

だいたい20行ぐらいなんですが、サービスが増える予定なので、20×20の400行ぐらい(になります)。ほぼコピペの400行はしんどいじゃないですか。

緑色以外はコピペなんですよ。何も考えずに書こうと思えば書けるのですが、しんどいし、for文を書きたいと思って、ChatGPTに「for文を使えますか?」って聞いたら「使えないよ」と言われちゃって、「あぁ、終わった」ってなりました。

400行我慢するかどうするかと考えた時に、「OpenRestyがNginxを拡張したもので、Luaでちょっと難しいことが書ける」みたいなことを知識として知っていました。なのでこれを使おうと思って、いろいろ考えていました。

自分は前職でAPI GatewayみたいなものをLuaで書いていました。ただ上司がメンテしていたので、自分は1回か2回プルリクを出したか、もしかしたら出していないかもぐらいでした。文法なんて覚えてもいないです。

あとは4年に1回ぐらい、うるう年ぐらいのタイミングの時に、RedisでAtomicな処理を書きたくて、スライドに記載したくらいの行数を書くみたいなことはあるのですがそのぐらいで、毎回文法を調べては忘れている状態になります。

ChatGPTと会話をしながらコードを組み立てる

今日の話はここからが本題で、ChatGPTといろいろ会話をしながらやってきています。(スライドを示して)こんな感じで先ほどのNginxのファイルを最初に貼って、「これをOpenRestyで何とかならない?」と聞いてみました。そしたら行数だけを見るとけっこう短くなっていて、「お、いいじゃん」「これをこのまま貼ったら使えるじゃん」と思ったんです。

プログラミング言語としてのLuaは知らないんですが、コードの内容はだいたい理解できます。(スライドを示して)なので、これを見てみるとそのままマッピングをしちゃっています。

先ほどのスライドではダッシュを付けていたのですが若干違っていたりして、URLがそのまま使えないので、mapみたいなものを持ちたいと思いました。

自分はJS(JavaScript)が好きなので、JSっぽい感じでmapを作って。それで「マッピングをしたいんだ」と言ったらマッピングしてくれました。ChatGPTは本当にコードが読めないんですよね。

(スライドを示して)サンプルコード中央にexample.comが付いている部分があるのですが、ここが文字列と連結していて、それをmapで判定していて。そうなると「文字列の連結は不要じゃん」と思って「不要だよね」と(次のスライドで)ChatGPTに聞きました。

そしたらきれいになって。

こんな感じでいろいろChatGPTに聞きながら、自分がレビュアーみたいなかたちでいろいろ直してもらいました。次にservice-aとservice-bが適当になっていたので、「それはもう自由にしてよ」と言って自由にしてもらっています。

あとはinit_lua_scriptという、全体を定義するところで定義しているものがあって。ただ、全体を定義するところで定義するよりも、スライド中央部分の中でできたほうがコードが読みやすいんじゃないかと思い、「こっちに入れてよ」と言いました。そうすると入れられるんだけどパフォーマンスのオーバーヘッドを使用するので「あまり良くないよ」と言われたりしました。

あとは「正規表現がなんか不安なんだけど大丈夫?」と聞いたら間違っていたり、「---が入っていないと使えないじゃん」みたいな正規表現になっていたりしました。

あとはセルフレビューとして「もっと良くできるところってある?」と聞いたら、アーリーリターンしていたのを止めてネストをくくってきたりとか。

先ほど「init_by_lua_blockを使いたくないよ」と言ったんですが、「オーバーヘッドがある」と言われるとちょっとイヤなので戻してもらったり。

Dockerfileを書いてもらったりしました。

それを実際に自分で試して動かしたらエラーが出ちゃって、「eventsが必要だよ」と言われました。

eventsぐらい考えれば追加できるかもしれないのですが、面倒くさかったのでChatGPTに聞いて。

(スライドを示して)そうしたら「これは絶対に必要だよ」とChatGPTに言われて、そのまま追加したらなんとか動いてこんな感じになりました。

400行から54行に圧縮できた

今回のポイントは、サービスを追加する時に、プロダクトチームのエンジニアが1行追加すればサービスを追加できて、他は何も触らなくてもいい状態にできたのが大きいかなと思っています。

400行だったのが54行になって13.5パーセントに圧縮できたので、今回のアレとしては成功かなと思っています。

まとめです。結局Luaの文法については詳しく知らないまま、動くものを作ることが可能になりました。OpenRestyやNginxでは手の届きにくいところを簡単にカバーできるので、ちょっとした処理に使うのには良かったです。

ただ、ChatGPTにニュアンスを伝えるのが重要だったり、デバッグ自体は自分でがんばらなきゃいけなかったことは大変でした。以上です。

(会場拍手)

質疑応答

司会者:会場のみなさんは質問どうでしょうか?

(会場挙手)

司会者:ありがとうございます。

質問者1:ありがとうございます。最後に「ニュアンスの伝え方が重要だよ」という記述がありましたが、ニュアンスをどう伝えるかという部分で気をつけていることはありますか?

鈴木:そうですね。わりと親切に物事を伝えられるようにしたほうがいいなとは思っています。何て言うんでしょう……。抽象的なかたちというよりは、「こうしたいんだ」とか「ここがおかしいからここを見てくれ」ということをしっかり伝えたほうが良い返答が得られたなという感じですね。回答が抽象的ですね。

質問者1:できるだけ曖昧な点がない状態で指示をするみたいな感じですか。

鈴木:そうですね。「こうしたい」ということをしっかり伝えるという感じですね。

質問者1:“ニュアンス”は個人的に“曖昧な部分”というイメージを勝手に持っていたんですが、そういった曖昧な内容をなくすみたいな。

鈴木:そうですよね。「ニュアンスをなくす」が正しいかもしれないですね。

質問者1:すみません。

鈴木:ありがとうございます。

質問者1:ありがとうございます。

司会者:ありがとうございます。他に会場で(質問がある方は)いますか? あっち行ったりこっち行ったりしてすみません。Zoomは特に来ていません。「質問に困ったら登壇者に聞きます」と言っていたので、2人のどちらかで今の発表に聞きたいことはありますか? Twitter(現X)でも続々と感想が来ています。

鈴木:ちょっと怖いですね。

司会者:(コメントを見て)「13.5パーセントに圧縮できたのメチャクチャすごくない?」とか。

鈴木:ありがとうございます。

司会者:(コメントを見て)「ChatGPTは嘘言うからなぁ」。(質問者をさして)あ、どうぞ。

質問者2:gpt-3.5-tarboで試したんですか?

鈴木:GPT-4で試しました。

質問者2:GPT-4でもけっこう嘘つくんですね。

鈴木:嘘つかれましたね。

質問者2:自分の体感だと、GPT-4だとハレーションがなくなって嘘をつかなくなったりしたのですが。

鈴木:それはそうですね。技術的にOpenRestyもそんなに使われているわけではないので、そこはあるのかな。何て言うんでしょう、正規表現だけだったらぜんぜん大丈夫だと思いますが、わりと狭い領域の狭いことを聞いているので、そこらあたりが難しくなった要因なのかなと感じましたね。

質問者2:ありがとうございます。

質問者3:普通に「こういう聞き方をしたらうまくいかなくて失敗した」とか。スライドにはない、いろいろな試行錯誤があったと思うのですが、おもしろかったエピソードはありますか?

鈴木:おもしろいのは本当に嘘はつかれましたということですね。今回見せたのは実は2回目で、実際にはもう1回別で聞いていて、それを再現してやり直しています。なのに実は結果が違ったり、あとは何があったかな。正規表現も間違っていた感じがして、正規表現もChatGPTには難しかったみたいですね。

なので、ちゃんとテストケースを伝えるというか、「こういうパターンの時は大丈夫か」と聞くと、ちゃんと答えてくれるんですね。自分がテストをしたり、テストケースでちゃんと動くかどうかを聞いてみるのは大事でしたね。

質問者3:ありがとうございます。

司会者:ありがとうございます。会場の方は後ほど交流会もあるので、またその時に聞いてもらえればと思います。「ChatGPTと仲良くするにはやはり対話が必要なんだな」というTwitterのコメントがありました。

では、ありがとうございました。

鈴木:ありがとうございました。