あなたはAIに「待った!」が言えるか?
0. まえがき
弊社にはTips発表会という文化があり、一週間に一回、交代制で30分ほどの発表を行います。10月入社だった私ですが、ついに出番が回ってきて発表したのです。
弊社のメンバーはほとんどがエンジニア未経験でスタートしながらも、AIを巧みに使いこなすAIマスターが多数在籍しており、「AIをどう活かすか?」を常に考える環境です。
そこで、私はAIとの付き合い方について考えていることを形にして発表してみました。
1. はじめに
我々Xincereのメンバーは「人の価値創造をテクノロジーで最大化する」というスローガンのもと、生成AIをフルに活用して日々コードと戦っています。
もちろん私もその一員として、まだまだ上手いとは言えないながらAIをさまざまな形で活かして仕事を進めています。
- プロジェクトに関わる一般的な知識の理解補助
- プロジェクトそのものやコードベースの把握
- 新規機能や修正の設計と判断
- コーディング
- コードに粗がないかの見直し
- その他、業務周りの一般論やタイムマネジメントなど
1から10まで使っていると言っても過言ではありません。
しかし一方で、こんなケースも少なくありません。
- 「おい全然バグ残ってんじゃねーか!」
- 「こういうのは禁止って2回前に書いたんだけどなぁ……」
- 「公式ドキュメントと真逆のこと言ってんな?」
当然のことです。なにせ生成AIは一番それっぽい答えを確率的に返すのが得意なのであって、正しさを保証するものではないからです。
動かないミスはともかくとして、「多少方針がズレてるくらいなら問題ないでしょ?」と思うかもしれません。実際、使い捨て前提のPoCや社内や個人のちょっとした雑用など、短期的には「動けばいい」が正義になることもあります。
しかし半分かそれ以上は、長期運用を見越して作成、納品するのではないでしょうか。AIを前提に開発速度が上がる世界では、
- 小さなズレが大量に発生する
- 小さな妥協が積み重なる
- 「誰も前提を説明できないコード」が増える
この構造により負債が累積され、いつか無視できない問題として立ちはだかります。それも散らばった状態で。
もしAIのミスをコントロールできず、それを見過ごすことを良しとし始めてしまうと、エンジニアの存在意義は大きく揺らぐことになります。
ミスを防ぐ、コントロールするためのアプローチはさまざまありますが、現時点のAIコーディングにおいて、私は何よりも大事だと思っているのは、これです。
『待った!』
AIの間違った、あるいはちょっとズレている実装や決定に対して、軌道修正をかけられるかが、エンジニアの大きな仕事だというのが私の考えです。
どうすれば「待った!」をかけられるのか。そんな話をしていきます。
2. AIは速い。でも、常に“適切”とは限らない
AIは基本的には非常に優秀です。
- 構文的に正しいコードを書く
- 型を通す
- 一般的なベストプラクティスを提示する
- 論理的かつ自信を持って説明する
と、一見すれば完璧なコードを書いてくれそうに見えます。一方で、
- プロジェクト固有の前提
- 暗黙の制約
- DB設計上の保証
- 仕様変更の履歴
といった「文脈」が大きいと、特にズレた実装が増える傾向にあります。一度「文脈」を教えたとしても、それに反する内容を出すことも往々にしてあります。
それを最終的に正すのが、書き手の「待った!」であるというわけです。
3. 実例①:過剰なnullガード
最近Typescriptを書いていないのですが、CursorでTSを書いていた頃はよく出てきたタイプのコードです。
if (user && user.email && user.profile && user.profile.name) {
...
}
一見堅牢に見えますが、実際その周辺のコードや環境を見渡してみると、
- DBレベルでNOT NULL制約
- relationも必須
- アプリケーション設計上nullになり得ない
ということがままありました。この「文脈」においては、過度に防御的で冗長なコードといえます。こうしたコードは一般的に、次のような問題を持ちやすいです。
- 可読性が下がる
- 意図が不明確になる
- 「本当にnullがあり得る箇所」が埋もれる
これくらいなら致命的な問題になることは多くありませんが、TSを使うからには型システムを適切に使わないと、保守性を損ないます。
- 「この値は本当にnullになり得る?」
- 「DB制約は確認した?」
- 「設計上の保証は何?」
こうした「待った!」が必要になる場面といえます。
4. 実例②:問題のスケールを誤ったケース
私が見たことのあるものを紹介します。色々とぼかした例ではあるのですが、
- 店舗ごとの商品管理文字列
- 客ごとの購買リスト
的なデータがあるとします。例えば、
- 店舗側: "りんご: 5個, みかん: 3個, ぶどう: 10個"
- 客側: ["りんご”, “バナナ”, "みかん”]
これらデータに対し、店舗が客の望む商品を網羅しているかというマッチ度を測る要件がありました。
おそらくAIで書いたと思われる実装では、
- トークン化
- TF-IDFベクトル化
- コサイン類似度
- Jaccard係数
- 上記3つの重み付き平均
という処理が組まれていました。これらは何かというと、自然言語処理でよく使われる、文書類似度を測るための本格的な手法だとのことです。
これを目にしたときは、待ったどころか「おい待てえええええええい!!!!」という感じでした。
これらのデータ形式に対して、本当に自然言語レベルの曖昧一致判定が必要なのか?
少しでもコード上でデータを取り扱った経験があれば、すぐにNoと判断がつくでしょう。しかし、現実としてこのコードはリポジトリに上がってきたのです。
私の思いつく限りではコーディングAIがこの品質のコードをしれっと出してくるのは想像がつかないのですが、「待った!」のない環境では、下手をすればこんなコードが出てくるという好例でしょう。
5. 実例③:こじつけの肯定
今回の資料もAI(ChatGPT)の補助をもとに書いているわけですが、実は没になった案でも、AIのズレた判断が露呈していました。
没案
「元々ORMなしで書かれていたupdate処理をPrismaに置き換える」という作業をしていた時のことです。
Prismaには単一対象のupdateと複数対象のupdateManyがありますが、単一行の置き換えだったので私は「updateで十分だな」と判断しました。
しかしAIは「whereに非uniqueカラムが混じっており、updateは使えずエラーになる。updateManyを使うべきだ」と説明しました。
それを見た私は「なるほど。Prismaの思想では単一行を保証するためにuniqueキーしか許可されないのか」と納得しました。しかし「いや、updateでエラー出ませんでしたけど?」という知らせが入り、さらに調べることになりました。
さらにAIとの壁打ちを進めてみると、AIが前提にしていたのは過去バージョンの仕様で、知識カットオフ後の新バージョンでは許容されるということが判明しました。
なぜ没にした?
「AIが間違えた例」として使えそうだと最初は思いました。しかし、「じゃあどんな『待った』をかけるんだ?」と考えると、
- バージョン情報が古いことを疑う?
- 「こっちの方がいい」と言われてもダメらしい方で実行してみる?
- どちらでも無理なく実装できるのをいちいち検証し直す?
という手段が考えられました。
当然、どれもこれも割に合いません。基本的に人間はAIに知識量で勝てないので、「これはこういうものだ」を疑うのは分が悪く、常に疑うくらいならいっそ使わないほうが早いです。
そこで、「疑うコストが高いので例としては使いにくい。(しかし捨てるのはもったいないので)うまくこの例を使う方法はあるか?」とAIに投げました。するとAIは
- 「検証をやめないという態度の問題に昇華すれば」
- 「実際に実行してみるなど反証可能性の話にすれば」
と、半ばこじつけで「使える」という結論を持ってきました。しかし、肝心の 「疑うコストが高すぎる」という問題は一切解消されないままでした。
「疑うコストにぶつかりっぱなしで、今回の話には使えない。他の例を考えよう」
この会話自体もまた、「待った!」が必要だった一例というわけです。
6. 「待った!」が言えない状態とは
AIに待ったが言えない状態とは、
- なぜその実装なのか説明できない
- 依存関係を説明できない
- 制約を把握していない
- 影響範囲を想像できない
ことです。これら「文脈」が押さえられていないと、出力されたコードにどんな問題が発生しているか/今後発生するかの予想が立てられません。こうなると、人間はコードを読むこともなく受け入れる状態に陥ります。
🤖 < あなたいなくても変わらなくないですか?
もしこう言われて何も言い返せなくなったその時は、私はエンジニアを辞めます。
7. だが現実。「待った!」だけでは進まない
「待った!」をかける重要性を話してきましたが、当然それだけで満足していては何も始まりません。通常のコードレビューでも同じですが、「これは違う」の一言を放っただけでは、何一つ進歩はないのです。
そこから必要なのは、
- なぜ違うのかを説明する
- 正しい方向を示す
- 修正方針を決める
ことです。ここはレビューのみならずAIコーディングでも同じ、いやむしろもっと正確に説明する必要があります。そして正確に説明するためには、人間側の深い理解が不可欠です。
- 本当に満たすべき仕様、要件は何か
- プロジェクトの性質による制約は何か
- ロジックやUIの需要を見抜き、どこまでを一般化すべきか
これら「文脈」を整理して初めて、AIにやり直しをさせることができます。すなわち、
「待った!」はゴールではなく、次のスタート地点に過ぎないのです。
8. 待った。これ本当に人間がする必要があるのか?
ところで、先日他のメンバーが、OpenAIのこんな発表をSlackで紹介していました。
1行たりとも手動コーディングせずに、数人のエンジニアがものの5ヶ月で数百万行のコードを書き上げたというのです。驚異的な数値と言わざるを得ません。その中には、次のような言葉がありました。
Humans steer. Agents execute.
正直な話をすると、これを見たとき「しめた!」と思いました。私がここで語りたい内容らしいキャッチコピーだったので、記事をダシにしてやろうと思ったのです。
ところが記事を読み進めてみると、私の期待とは裏腹に、人間の関与する領域がどんどん少なくなっていったという話でした。
- AIエージェント同士によるレビュー
- エージェントが使いやすい知識基盤の作成
- エージェントが自走できる開発環境の整備
といった話が紹介されており、次第にほとんどのPRのレビューをエージェントに委任するようになったといいます。
これが次世代のコーディングスタイルとして、生産性の面で優れているのは言うまでもありません。この世界観と比べると、今回語っている私の思想はなんと古臭いのだろうと思わずにはいられませんでした。
コーディングエージェントが間違えることをどうこうしようとするのではなく、間違えにくい環境を作るのが人間の役割であり、そこで生じる軌道修正でさえも人間ではなく別のAIエージェントが担うほうがよいと。
私がこうしたAIエージェントの活用法についてまだまだ疎いのは認めざるを得ない事実です。そう遠くない未来には、こうしたコーディングスタイルが主流になり、ほとんどのエンジニアは不要になっているのかもしれません。
9. それでも今、必要な能力
しかし、です。AIで完結するコーディングの世界観には大きな前提があります。
- AIリソースが潤沢にある
- エージェントが自走できる環境が用意できている、あるいは導入できる人材がいる
- AIに読ませれば進められるような知識基盤が整備されている
多くの現場は、まだそこまで到達していないことでしょう。一つのコーディングエージェントを重用して、難しい判断のいらない実装タスクを任せるというのが関の山です。
今この時点ではコーディングAIはまだまだ発展途上で、
- 文脈を誤解する
- 過剰な一般解を作る
- 前提を補強してしまう
といった問題を抱えています。そんなAIの弱みをカバーする体制を組まずに使っている限り、「待った!」を言える人間がどうしても必要になります。
ゆえに私は、曲解だとしてもOpenAIの記事にあったキャッチコピーを改めて紹介します。
Humans steer. Agents execute.
あなたは、エージェントたちの舵取りをすることができますか?
株式会社シンシア
株式会社シンシアでは、実務未経験のエンジニアの方や学生エンジニアインターンを採用し一緒に働いています。
※ シンシアにおける働き方の様子はこちら
https://www.wantedly.com/companies/xincere-inc/stories シンシアでは、年間100人程度の実務未経験の方が応募し技術面接を受けます。
その経験を通し、実務未経験者の方にぜひ身につけて欲しい技術力(文法)をここでは紹介していきます。