🐥

【Code Reading Agent 開発】探索を簡単にする機能を作りました(フォルダ検索機能)

に公開

この記事は、以下の記事らへんの続きです。

https://zenn.dev/coffeecupjp/articles/89bb2b40ced6eb

https://zenn.dev/coffeecupjp/articles/09eaa20edcf2c0

https://speakerdeck.com/ymbigo/potipotixuan-ze-surudakedeosswodu-meruvscodekuo-zhang-ji-neng

これまでの振り返り

LLMによるコーディングは、この1年で進化しました。
去年5月に自分はOpenDevin(現OpenHands)を使った時は、使いづらさに失望したものでした。しかしいつの間にかClineが出てきて、CursorやDevinも進化していき、LLMによるコーディングはまさに大爆発を起こしました。

コーディングは変わったが、リーディングは検索する限りあまり特殊なツールが出てきていないと思い、自分はコードリーディングに特化したLLMツールを作りました。

https://zenn.dev/coffeecupjp/articles/89bb2b40ced6eb

基本形は、以下の流れです。

  1. 【ユーザ】コードのエントリーポイントとコードリーディングの目的を入力
  2. 【LLM】LLMが現在の関数から重要で目的と合う関数を5個まで候補として出す
  3. 【ユーザ】その中から重要な関数を選ぶ
  4. 2に戻り、ユーザーがいいと思うまで続ける

この3の部分で、ユーザーは追加で以下のことができるようになっていました。

  1. 過去の関数追跡経路を木構造で可視化
  2. 過去の関数追跡経路に戻る
  3. 過去の関数追跡経路を説明するレポートを出力
  4. 過去の関数追跡経路を保存(基本形の1で探索する代わりにこちらを再現できる)
  5. 過去の関数追跡経路からバグらしい箇所を出力
  6. 現在の関数をマーメイド図で出力

個人的には4が重要かなと思っていて、大規模OSSのコードの可視化ができるのではないかと思います。

使用できる言語は増えています

今のところ、以下のVSCode拡張機能を作りました。

Linux Reader(C言語向け)

https://marketplace.visualstudio.com/items?itemName=coffeecupjapan.linux-reader

Java-Reader(Java向け)

https://marketplace.visualstudio.com/items?itemName=coffeecupjapan.java-reader

Go-Reader(Go向け)

https://marketplace.visualstudio.com/items?itemName=coffeecupjapan.go-reader

Ruby-Reader(Ruby向け)

https://marketplace.visualstudio.com/items?itemName=coffeecupjapan.ruby-reader

TypeScript-Reader(TypeScript向け)

https://marketplace.visualstudio.com/items?itemName=coffeecupjapan.typescript-reader

会社の人に意見を聞いた

作ってみた以上は、一回意見を聞くのが吉日。
そこで会社の人に意見を聞いてみました。そしたら3つの意見をいただきました。

  1. 会社のセキュリティを考えたら、gpt-ossなどOSSモデルを使えるようにしたい
  2. コメントをつけられるようにして、実際に探索している人の理解度が分かるようにしたい
  3. エントリーポイントを探して入力してもらうのは面倒。レポジトリのパスを入力して検索できるようにしたい

1は自分のPCでgpt-ossを使うにはマシンスペックが足りず、困っています...つい7月に買い換えたばかりなので。先見の明があまりにもありませんでした。またメモリ32GBの20Bでも応答まで時間がかかるという情報があるのもネックで困っています。

2は実際に作ってみました。

https://github.com/YmBIgo/go-reader/commit/c8a5db2d542d72fb04d67f2eb4c2fa89bca06b06

3は言われてみれば確かに思いましたが、すぐに方法が分からず少し難しいなと思っていました。
そこでヒントになったのが、Serena!

https://github.com/oraios/serena

このSerenaには、get_symbols_overview というコードベースのシンボルの概要を取得する機能がありました。
この機能、実はLSPの textDocument/documentSymbol という機能で作られていました!

https://github.com/Microsoft/language-server-protocol/blob/main/versions/protocol-2-x.md#textDocument_documentSymbol

自分の作っている CodeReadingAgentも LSPを使っていたので、似たような感じで作りました。
改善点はあるかもしれませんが、以下の流れです。

  1. コードベースのパスと読みたい内容の目的を入力
  2. コードベースのパスからglobし、目的に合ったパスを複数、LLMに抽出してもらう
  3. 2の結果のパスから内容を読み出しLSPで関数・メソッドを抽出し、その中から目的に合ったものをLLMに抽出してもらう
  4. LLMが抽出した結果から、探索可能になる

これが「フォルダ検索機能」です。

https://github.com/YmBIgo/go-reader/commit/6ff7185e4ea07b5f437637958a34d291e6b4f150

今はこの「フォルダ検索機能」は、Linux-Reader以外には実装されています(Linuxのコードベースでglobしてその結果をLLMに投げるなんて考えたくもなかったので...)。

フォルダ検索機能の効果

個人的に Luceneという検索ライブラリのOSSを少し内容を見たことがあったので、これで少しフォルダ検索機能の効果を試しました。

https://github.com/apache/lucene/tree/main

Luceneにはjavaファイルが5500ファイル以上あり、その全てをベクトルデータなどにインデックスするのは無駄が多いのかなと思っているので、「ファイルパス検索→ファイル中身の検索」の順番でいいのかなと思います。

検索結果取得までの時間は2〜5分くらいかかります。

肝心のフォルダ検索の精度ですが、上手くいくこともありましたが、以下のような点が気になりがちでした。

  1. demo機能のパスなどを探索結果に残してしまうことがあった
  2. ユーザーから見たら最終的に出てくる5つの候補のうち、どれが正しいか判断がつきにくいので、少し使いづらい
  3. フォルダ検索機能から探索したら、関数の行き止まりに当たってしまった(エントリーポイントというより詳細の方を選んでしまった)

ということで、まだフォルダ検索機能のv1の精度は高くないですが、今後は上げていければいいなと思っています。

Discussion