Cline AIアシスタントは魅惑的だ
原文は Michael Lynch により に公開されました。 このブログを購読する
昨日、Cline AIアシスタントを試してみたのだが、そこから5時間もの間、トランス状態に陥ったようにClineが自分の代わりにバグを直していく様子を、ただ呆然と見つめ続けることしかできなかった。
プロの開発者として、それは魅惑的であると同時に恐ろしい体験だった。AIがここまでの水準に達したことが魅惑的なのだ。そして同じ理由で恐ろしくもある。AIが自分より上手く、より速くコードを書ける世界で、自分にどんな役割が残るのかわからなくなるからだ。
この流れにはすっかり乗り遅れていたのは自覚している。ほとんどの開発者はとっくにAIツールをワークフローにはるかに深く統合しているのだろう。ただ、まだそれを体験していない人たちに向けて、自分が見たものを共有したいと思った。
これまでもAIツールは使ってきた
Clineが初めてのAI体験というわけではない。
ここ2年ほどLLMアシスタントを試してきた。特にここ半年は、モデルが安定して正しいコードを生成できるレベルに達したこともあり、使う頻度がぐっと増えている。
検索エンジンにはKagiを使っていて、そのUltimateプランでは主要なLLMがすべて使い放題になる。LLMとのやり取りはもっぱらKagi Assistantという、LLMとチャットするためのWeb UI経由で行っている。

検索エンジンのKagiには、主要なLLMとチャットできる便利なWebインターフェースが付属している。
念のため:私はKagiのクラウドファンディングに参加しているので、よくわからない形ではあるが、多少の出資をしている。
AIツールを使うと、自分がボットになった気がする
最近気づいた問題は、AIツールを使うと自分が機械になったような気分になることだ。エディタとチャット画面の間でコードをただぼんやりとコピペし、「うまくいきませんでした」と言ってエラーメッセージを貼り付け、同じことを4、5回繰り返すだけになるのだ。


チャットボット型のLLMは何度も間違った修正を提示し、完全な解決策を示すまでに何度も促す必要があった。
もっと良いツールがあるはずだ
自分がやっているやり方よりも、もっとましなAIとの統合方法があるはずだと思った。
「コードとエラーメッセージを往復してコピペする係」という自分の役割を肩代わりしてくれるツールが必要だったのだ。
1年ほど間を空けてSourcegraph Codyを2回試してみたが、どちらもがっかりさせられた。コードをその場で編集してくれるのは、ブラウザとエディタの間で貼り付けを繰り返すよりはましだったが、Codyは動作が遅くバグも多かったので、結局またWebブラウザへのコピペ作業に戻ってしまった。
最近いくつかのブログ記事でClineのことを知り、いくつかの点で魅力的に思えた。
- コードがオープンソースである。
- メインエディタであるVS Codeと統合できる。
- ローカルファイルの編集、コマンドの実行、実行結果を踏まえた反復作業を任せられる。
- 必要ならローカルでホストするLLMを使える。
- 他の多くのAIアシスタントのように、AIのAPIへのアクセス購入で中間マージンを取ろうとしない。
欠点は、Clineには投資家の資金を燃やす以外に収益源が見当たらないことだ。だから持続可能かどうかはわからないが、今のところは問題なく使えている。
語彙の錯覚:AIアシスタントにとって格好のテストプログラム
最近、ブログ内の「語彙の錯覚(lexical illusions)」をスキャンしてくれるツールが欲しいと思っていた。Matt Might氏がそう呼んでいるもので、テキスト中の重複した単語に気づかない現象のことだ。例えば次のようなものだ。
Many readers are not aware that the
the brain will automatically ignore
a second instance of the word “the”
when it starts a new line.
私はブログでこのミスを頻繁にやらかすのだが、校正の終盤や公開後にようやく気づくことが多い。
Matt Might氏は語彙の錯覚を見つけるPerlスクリプトを公開しているが、ごく単純なもので、Markdownの書式文字のせいで私のブログでは誤検出が大量に出てしまった。
Kagi Assistantに、Markdownに対応したPython版を作ってくれるよう頼んだが、バグのあるコードばかり返ってきた。
これはClineにとって絶好のテストケースだと気づいた。問題の定義が簡単だからだ。期待する挙動を示すテストケースをAIアシスタントに見せ続ければ、テストが通るまでコードを編集し続けてくれるはずだ。
それにZigで書く良い口実にもなった。大量のファイルをできるだけ高速にスキャンしたいし、Zigで書くのが大好きだからだ。
問題の定義
ツールのメインインターフェースはシンプルなものにした。ファイルの中身を文字列(Zigでは[] const u8)として受け取り、重複した単語とその行番号のリストを返すようにする。
基本的なインターフェースはこんな感じだ。
pub const DupeWord = struct {
line_number: u32,
word: []const u8,
};
pub fn FindAdjacentDupes(allocator: std.mem.Allocator,
input: []const u8) !ArrayList(DupeWord) {
// TODO: Implement this.
}そして、これが最初のユニットテストだ。
test "FindAdjacentDupes" {
// Don't consider distinct words to be duplicates.
try testFindDupes("cat dog", &[_]DupeWord{});
// Find simple dupes.
try testFindDupes("cat cat", &[_]DupeWord{
.{ .line_number = 1, .word = "cat" },
});
}
fn testFindDupes(input: []const u8, expected: []const DupeWord) !void {
const allocator = testing.allocator;
var result = try FindAdjacentDupes(allocator, input);
defer {
for (result.items) |item| {
allocator.free(item.word);
}
result.deinit();
}
try testing.expectEqual(expected.len, result.items.len);
for (expected, 0..) |expected_dupe, i| {
try testing.expectEqual(expected_dupe.line_number, result.items[i].line_number);
try testing.expect(std.mem.eql(u8, expected_dupe.word, result.items[i].word));
}
}Clineの初期結果
約30秒、LLMのクレジットにして0.09ドルほどで、Clineはテストをパスさせた。

Clineが更新したFindAdjacentDupesの実装はこうなっていた。
pub fn FindAdjacentDupes(allocator: std.mem.Allocator, input: []const u8) !ArrayList(DupeWord) {
var result = ArrayList(DupeWord).init(allocator);
var it = std.mem.splitScalar(u8, input, ' ');
var prev_word: ?[]const u8 = null;
while (it.next()) |word| {
if (prev_word) |prev| {
if (std.mem.eql(u8, prev, word)) {
const dupe_word = try allocator.dupe(u8, word);
try result.append(DupeWord{
.line_number = 1,
.word = dupe_word,
});
}
}
prev_word = word;
}
return result;
}Clineはvarの代わりにconstを使うべきところを間違えたり、非推奨のAPIを使ったりと何度か遠回りしたが、エラーメッセージをもとに人間のように自己修正していた。
もちろん、この実装はまだ不完全だった。Markdownの書式や大文字・小文字、句読点などには対応していない。行番号が1以外のテストケースをまだ見せていなかったので、現状の実装では行番号が常に1を返すようにハードコードされていたのだ。
そこから抜け出せなくなった
Clineが最初の実装を終えた後も、私は新しいテストケースを書き続け、Clineがそれを満たすようにコードを更新していくのを眺め続けた。
そして、そこから抜け出せなくなった。こんな方法でソフトウェア開発ができることに心底驚いたのだ。自分がやりたいことを伝えるだけで、ツールが求め通りのことをやり続けてくれるのである。
この記事の冒頭で紹介した動画が、実際の様子だ。
結果
その日は残りの時間をClineと一緒にツールの実装に費やし、ついに重複単語検出ツールの動作するバージョンが完成した。wordwordと名付けた。
このwordwordを使って、ブログ上の語彙の錯覚による誤りを7件見つけることができた。
合計でかかった費用は、OpenRouterでのクレジットでわずか6ドル。Clineと5時間ぶっ通しで作業した分である。
これまでに学んだこと
監視なしの作業は非効率だが、安すぎて気にならない
Clineには、各ステップの前に計画を承認するよう求めるオプションがある。5秒ごとに「承認」を押すのにすぐ飽きてしまったので、ファイルの読み取り、書き込み、コマンド実行は自動承認するように設定した。
目を離していると、Clineは時々行き詰まり、どう考えても失敗するはずの戦略を何度も繰り返し試みることがあるのに気づいた。
それでも、解決策にたどり着くか、20回の試行上限に達するまで、ほとんど監視せずにClineを走らせ続けた。行き詰まりでAPIクレジットを無駄にすることはあったが、所詮数セントの話だ。数セントを無駄にするリスクを取る方が、アシスタントをいちいち細かく管理するよりましだと思った。
Clineはあなたを無条件に信頼するので、言葉は慎重に選ぶ
Clineが最も混乱したのは、私が誤った挙動を書いたテストケースをうっかり書いてしまったときだった。
急いで書いてしまったテストケースがこれだ。
// Detect duplicates after a heading
try testFindDupes(
\\## Foods
\\
\\These potatoes potatoes are the best!
, &[_]DupeWord{
.{ .line_number = 1, .word = "potatoes" },
}行番号を本来3とすべきところを、誤って1と書いてしまったのだ。
このテストをパスさせようとしたとき、Clineは、本来明らかに3であるはずの行番号をどうやって1として正当化するのかを考え込んで、少々パニックに陥ってしまった。
Clineにデバッグ用のprint文を追加させる
LLMは、コードがなぜそのように振る舞うのかについて情報を集めて立ち止まるよりも、解決策を当てずっぽうに推測しがちなことに気づいた。
Clineがバグ修正で盲目的に試行を繰り返すループに陥ったときは、一旦作業を中断させ、コードについての仮定を検証するためにデバッグ用のprint文を挿入するよう指示すると効果的だった。Clineは有用なデバッグ出力を追加し、解決が完了したと宣言する前に、それらをすべてきちんと削除することも覚えていた。
Kagiは私で損をしているに違いない
従量課金制のLLM APIを使うのはこれが初めてだ。トークンコストの話を耳にしたことはあったが、Kagiが基本的に「コストは気にしなくていい」と言ってくれるので、直感的な感覚がなかった。
Clineは、各コーディングタスクでどれだけクレジットを消費したかを随時表示してくれるので親切だ。

だから、Kagiの月25ドルの使い放題プランでは、明らかに私の方が得をしている。Clineでは5時間で6ドルかかったが、Clineはトークン消費を抑えるためにいろいろ工夫している。私はKagi Assistantを毎日使っていて、会話の中で巨大なファイルを10回以上貼り付けることもよくある。コストがわかった今では、おそらく1日あたり5〜10ドル分のAPIクレジットをKagiに負担させているのだろう。
その他の参考資料
AIについての投稿の多くは内容が薄かったり、実践的な学びがなかったりする。私が可能性を知る上で最も役立ったのは次のものだ。
記事をランダムに読む
コメント
ログインしてコメントする