はじめに
2024/10 にClaude 3.5 Sonnet が新しくなり、2024/11 頃から AIコード生成 extension の Cline が話題になり、年末年始を経て、 Cline を触った感想が色々な媒体に投稿されるようになってきました。
Cline を使ってサービスを開発している人からは、実際に巨大なコードベースを開発した経験がある人から、まだ使えないという意見と、それに対する反論が上がっていたのが気になりました。
- まだ使えないという意見
- ノーコードツールが持て囃された時と同様、プロトタイピングは素早くできるようになったけど、結局その先の、複雑なコードベースに対してどうするか、が解決されない
- まだ業務では使えない。結局手直しがいる。
- 反論
- AI で作ったプロダクトをリリースして運用できている
- プロンプトの与え方が悪いだけ。活用しきれていない
どちらの言い分も理解できます。私の考えである本記事の結論を先に書いておきます。
- 現状の Cline でも、ある一定のサイズのレポジトリまでは、工夫次第で実務利用が可能。
- 本質的なボトルネックはLLMが理解できるコンテキストのサイズで、歴史や負債を含む巨大レポジトリではこの制約が課題。
- この課題を解決するのはファインチューニング等のLLMそのものに知識を入れるプロセスで、そのコストが下がれば、いよいよエンジニアの仕事がコーディングではなくなってくる
既に AI 生成でプロダクトが作れているという主張について
巨大なコードベースでは生成結果が精緻でない、という元の主張に対して、「AI で作ったプロダクトをリリースして運用できている」と反論しても論が成り立たりません(コードベースが小さいだけですよね?となる)
察するに、「コードベースが大きくても適切に与えるコンテキストを選べば動くコードが生成される」ということを言いたいのだと思います。
残念ながら、「巨大なコードベース」が意味するのは、単にコードの行数が長いということではありません。
- 歴史の中でデータスキーマが変わり、その互換性の担保のために残っているコード
- 依存関係が複雑に絡み合い、時にはコード上に表現されないがビジネス上関連のあるモジュール同士の依存関係
などなど、今現在のコードベースだけでなく、コードが書かれた背景を考慮できることも、巨大なコードベースを抱えるプロダクト開発では重要です。
そして、往々にしてこの "コードの背景" は、外部のサービス (Notion, JIRA) や昔からチームにいる人の頭の中にしかなかったりします。(理想的には、PR の Description に背景がしっかり記載されていればいいですが、 link だけ貼られたり、そもそも Description が書かれていないケースもあります。)
「0→1 でプロダクトを作れる」「1→10 でプロダクトを伸ばせる、運用できる」からと言って、10→100, 100→101 にプロダクトを伸ばせるわけではなく、概してソフトウェアエンジニアリングの経験と専門性を要するのは10→100, 100→101 なのです。そして、「Cline は実務で使えない」という主張は、「Cline では 10→100, 100→101 ができない」ことを言っているのです。
プロンプトの与え方を工夫すれば解決できるのか
Cline やAIコード生成に慣れた人は、Cline の使い方も初心者とは違います。大きな(巨大ではない)コードベースに対して Cline を実行すると、すぐに rate_limit にかかります。
この段階で、「ああ実務では使えないな」と判断する人もいるでしょう。
しかし、入力すべき内容を圧縮して context として与えると、より大きなコードベースでも扱えるようになります。
具体的には、
- ディレクトリごとの役割を README に記載して、実際のコードを読ませる量を少なくする
- ファイル全てを読ませるのではなく、タスクに必要な関数だけを抜粋して読ませる
- 過去のやり取りを全て入力として与えるのではなく、圧縮した上で次の会話の入力とする
などです。
こうしたアイデアは実際に Cline を元とした拡張機能としてリリースされており、より早い、より正確だという人もいます。
これらの工夫なしに、「実務で使えない」と判断してしまうのは、ツールの使い方を知らずに使えないと判断してしまっていることになります。
Clineの実務での可能性と限界
Cline の動作を観察してみると、人間の思考を再現できているようにみえます。
- まずディレクトリ構造を分析し、関連するコードの位置を特定
- 必要なファイルの内容を読み込み、既存の実装パターンを理解
- ファイル間の一貫性を保ちながら、新しい機能を実装
優秀なエンジニアを採用して、タスクを与えた時と同様の動きです。
- 既存の実装が interface で切られた綺麗に抽象化されたものならば、多くのファイルを見ずとも、実装できます。
- デザインの調整であれば、現状の rendering を見て、関連ファイルを掘って読むだけで十分実装できます。
このように、中規模のレポジトリや、大規模でも綺麗に設計されたレポジトリ、負債がすくなく、素直に実装できる場合であれば、 Cline で十分に開発が可能でしょう。
では、先に述べたような巨大コードベースにおける難しさが、どのように影響を与えるか考えてみます。
同じエンジニアに、歴史的経緯や負債を抱えたコードベースを渡して、タスクを与えたらどうなるかを考えます。
同様にディレクトリ構成から構造を理解して、必要なファイルにあたりをつけて、既存の実装を参考に実装しても、
- 実はその書き方はもうやめていきたいと思っている
- 実はその機能はこっちのモジュールを使った書き方をしてほしい
- 過去にこういうことがあるからデータの validation が追加で必要
といった指摘が入ります。
Cline であろうと人間であろうと、背景を何も知らない状態で実装すれば、求めるPRは実装できません。
こういった背景を地道に蓄積していけば、AI コード生成結果も精緻になっていきますが、「そこまでするなら自分で実装する」と思うエンジニアも少なくないでしょう。
昨今話題の Devin はPR への指摘をナレッジとして蓄積してくれており、背景知識の蓄積という面倒な作業のインターフェース (HCI の方の意) を人間に最適化させた良い仕組みだと思います。
しかし、結局は限界があります。
知見をどれだけ言語化して LLM の見えるところにおいても、事前情報をいかに圧縮しようと、コンテキストには限界があります。
巨大なコードベースにおいては、入力すべきファイルとコンテキストが共に巨大であり、生成結果は満足のいくものにならないでしょう。
レポジトリ特化型LLMの可能性
ここまで述べたように、現状の Cline の能力を人間に例えるなら、「優秀だが入社したばかりのエンジニア」といえます。
豊富な知識と優れた基礎能力を持っているものの、その会社とチーム特有の実装方針や歴史、暗黙の了解事項についてはまだ把握できていない状態です。
どれだけ優秀なエンジニアだって、入社初日に歴史のあるレポジトリの構造全体を把握した上で変更量もインパクトも大きいPRはかけません。
開発を通して徐々に過去の経緯やその会社とチームでのコーディング規約、特有のモジュールを知り、睡眠によって無意識レベルの理解になり、さらにわかる範囲を広げていくことで、だんだんと精緻な実装が可能になります。
同じプロセスを Cline に置き換えるならば、プロンプトを工夫するのではなく、LLM そのものをレポジトリに適応させていけば良い、となります。
レポジトリ固有の知識をモデルに組み込むファインチューニングを重ねれば、結果として以下を期待できます。
- コードベースの歴史や背景を完全に理解した上での実装
- チーム固有の設計思想や規約に完全に準拠したコード生成
- 過去の失敗や教訓を踏まえた、より安全で保守性の高い実装
言うなれば、チームに5年以上在籍してきたシニアエンジニアのような、深い文脈理解に基づいた実装になります。
当然、LLM がレポジトリ固有の知識を持っているので、その分だけコンテキストに余裕が生まれます。
「レポジトリ固有の知識をモデルに組み込む」方法がファインチューニングなのかどうかは定かではありませんが、
実装プロセスは既に人間のそれと非常に近しいので、モデルをファインチューニング、あるいはそれに類する「レポジトリの特徴量を追加で取得させる」技術を用いることで、巨大レポジトリにおいても精緻なコード生成が可能になる未来は、十分に予想できます。
実現までのロードマップ
未来の予想をしても仕方がないですが順番としては、モデルの巨大化に目処がついた後、上記の課題を解決するために、ファインチューニングの API もまた安価に提供されるようになると思います。
あるいはファインチューニングではないブレイクスルーが生まれ、個人がローカルでモデルを動かしたりチューニングできる簡単な仕組みが生まれるかもしれません。
今も一部のLLMでは既にファインチューニングの API はありますが、学習方法まで自分で実装して提供する人はまだいません。
ここ2年の AI 開発の加速度を考えると、今年中にはそういう変化が来てももう驚きません。