コードベース解析アーキテクチャ
概要
コードベース解析は、AI Dev Agentがソフトウェアリポジトリを理解し推論できるようにするサブシステムです。
大規模なリポジトリには以下が含まれることがあります:
- 数千のファイル
- 複雑な依存グラフ
- 複数のプログラミング言語
- レイヤードアーキテクチャ
リポジトリ全体を言語モデルのコンテキストにロードすることは実現不可能です。
代わりに、システムはリポジトリの構造化された理解を構築し、推論中に最も関連性の高い情報のみを取得しなければなりません。
コードベース解析システムはこの機能を提供します。
目標
コードベース解析アーキテクチャは以下の目標を達成するよう設計されています。
スケーラブルなコード理解
システムは推論品質を低下させることなく任意のサイズのリポジトリをサポートしなければなりません。
高速な取得
関連するコードとシンボルは迅速に取得可能でなければなりません。
エージェントはタスク中に数十の取得操作を必要とすることがあります。
構造的認識
システムはテキストだけでなくコード構造を理解しなければなりません。
例:
- 関数
- クラス
- インターフェース
- インポート
- モジュール依存関係
言語拡張性
アーキテクチャは複数のプログラミング言語をサポートすべきです。
初期サポート:
- TypeScript
- JavaScript
- Rust
追加言語は簡単に追加できるべきです。
高レベルアーキテクチャ
コードベース解析サブシステムにはいくつかのコンポーネントが含まれています。
リポジトリ
│
▼
ファイルスキャナー
│
▼
パーサーレイヤー
│
▼
シンボルインデックス
│
▼
依存グラフ
│
▼
セマンティックインデックス
│
▼
クエリエンジン各コンポーネントはリポジトリの理解に貢献します。
ファイルスキャナー
ファイルスキャナーはリポジトリ内のファイルを検出・追跡します。
責務:
- ソースファイルの検出
- ファイル変更の検出
- 無関係なファイルのフィルタリング
フィルター例:
node_modules/
dist/
build/
.git/スキャナーはさらなる処理のためのソースファイルのリストを生成します。
パーサーレイヤー
パーサーレイヤーはソースファイルを構造化された表現に変換します。
典型的な出力:
- 抽象構文木(AST)
- シンボル定義
- インポート文
- 関数シグネチャー
TypeScriptの例:
function getUser(id: string): Userパーサーは以下を抽出します:
- シンボル名
- パラメーター
- 戻り値の型
- ファイル内の場所
パーサーの実装には以下を使用することがあります:
- TypeScriptコンパイラーAPI
- Tree-sitter
- Rustベースのパーサー
シンボルインデックス
シンボルインデックスはコードベースで定義されたシンボルに関する情報を保存します。
シンボルの例:
- 関数
- クラス
- インターフェース
- 型
- 定数
エントリー例:
シンボル:
UserService
型:
クラス
ファイル:
src/services/UserService.ts
メソッド:
getUser()
createUser()シンボルインデックスにより、エージェントは定義を迅速に特定できます。
依存グラフ
依存グラフはモジュール間の関係を表現します。
例:
- ファイルのインポート
- モジュールの依存関係
- 型参照
例:
UserService
↓
UserRepository
↓
DatabaseClientこのグラフにより、エージェントは変更がシステム全体にどのように伝播するかを理解できます。
ユースケース例:
- 依存モジュールの取得
- 変更の影響の特定
- 実行パスのトレース
セマンティックインデックス
セマンティックインデックスは意味ベースの検索を可能にします。
構造的情報を保存するシンボルインデックスとは異なり、セマンティックインデックスはコードフラグメントの埋め込みを保存します。
インデックス化されるアイテムの例:
- 関数
- クラス
- コメント
- ドキュメント
クエリ例:
"キャッシュユーザープロファイル"システムは以下のような関連コードを取得することがあります:
UserCache.ts
ProfileCache.ts
CacheClient.ts埋め込みは言語モデルを使用して生成されることがあります。
クエリエンジン
クエリエンジンはエージェントのための関連コード情報を取得します。
いくつかのクエリタイプをサポートします。
シンボルルックアップ
シンボルの定義を取得します。
例:
find_symbol("UserService")参照検索
シンボルが使用されている場所を見つけます。
例:
find_references("UserService")依存関係トラバーサル
依存関係または依存されているものを取得します。
例:
get_dependencies("UserService")セマンティック検索
意味でコードを検索します。
例:
search_code("ユーザー認証ロジック")クエリエンジンは複数のインデックスから結果を組み合わせます。
コンテキストエンジニアリングとの統合
コードベース解析システムはコンテキストエンジニアリングパイプラインにコードコンテキストを供給します。
フロー例:
エージェントがコードコンテキストを必要とする
│
▼
コンテキストプランナーがシンボルをリクエスト
│
▼
クエリエンジンがコードを取得
│
▼
関連するファイルとシンボルがコンテキストに追加されるこれにより、エージェントはリポジトリについて効率的に推論できます。
インクリメンタルインデックス作成
リポジトリは頻繁に変更されます。
システムはインクリメンタルな更新をサポートしなければなりません。
ワークフロー例:
ファイルが変更される
↓
ファイルを再パース
↓
シンボルインデックスを更新
↓
依存グラフを更新これにより、インデックス全体の再構築が避けられます。
マルチ言語サポート
システムは言語固有のパーサーを使用して複数の言語をサポートします。
アーキテクチャ例:
パーサーインターフェース
│
├─ TypeScriptパーサー
├─ Rustパーサー
├─ Pythonパーサー
└─ Goパーサー各パーサーは共通の中間表現を生成します。
例:
シンボル
場所
依存関係
ドキュメントこの統一フォーマットによりインデックス作成が簡略化されます。
コードチャンキング
大きなファイルは小さなチャンクに分割されることがあります。
チャンクタイプの例:
- 関数
- クラス
- モジュール
- コメントブロック
チャンキングによりセマンティック検索が改善され、コンテキストサイズが削減されます。
例:
ファイル: UserService.ts
チャンク:
* class UserService
* method getUser
* method createUser各チャンクは独立して取得できます。
ランキングと関連性
クエリ結果は関連性でランク付けされなければなりません。
ランキングシグナルには以下が含まれることがあります:
- シンボルマッチ
- 依存関係の距離
- セマンティック類似性
- ファイルの近接性
- 変更の最近性
これらのシグナルを組み合わせることで取得品質が向上します。
可観測性
コードベース解析システムはその動作の可視性を提供すべきです。
メトリクス例:
- インデックスサイズ
- クエリレイテンシー
- 取得頻度
- キャッシュヒット率
ログには以下が含まれることがあります:
- 実行されたクエリ
- 取得されたシンボル
- ランキング決定
これにより取得の問題を診断できます。
キャッシュ
頻繁にアクセスされるコードフラグメントはキャッシュされることがあります。
例:
- 人気のモジュール
- コアユーティリティ
- 頻繁にクエリされるシンボル
キャッシュによりクエリのレイテンシーが削減され、エージェントの応答性が向上します。
失敗モード
一般的な問題:
不完全なインデックス
インデックス作成が失敗した場合、エージェントは関連するコードを見逃すことがあります。
誤ったパース
パーサーエラーにより無効なシンボル情報が生成されることがあります。
セマンティック検索のドリフト
埋め込みベースの検索が無関係な結果を返すことがあります。
システムはこれらの問題を検出し軽減すべきです。
将来の改善
潜在的な改善:
- 学習されたランキングモデル
- コードグラフ埋め込み
- 動的コード要約
- クロスリポジトリ推論
これらの機能によりリポジトリの理解がさらに向上する可能性があります。
まとめ
コードベース解析はAI Dev Agentが大規模なソフトウェアリポジトリを理解できるようにします。
システムは以下を使用して構造化された知識を構築します:
- ファイルスキャニング
- 言語パース
- シンボルインデックス作成
- 依存グラフ
- セマンティック検索
統一されたクエリエンジンにより、エージェントは関連するコードを効率的に取得できます。
このアーキテクチャにより、エージェントはリポジトリ全体をモデルのコンテキストにロードせずに複雑なコードベースを推論できます。