コンテキストエンジニアリングにおけるAST活用 — 有用性と実例¶
作成日: 2026-06-08(2026-06-08 海外文献・AST原理を追記) テーマ: LLM/エージェントに渡すコンテキストを「構文木(AST)」で構造化・選別する技術 関連: claude_code_long_session_guide、ai_agent_9社_本番運用アーキテクチャ
0. 要点(3行)¶
- コンテキストエンジニアリングの本質は「限られたコンテキスト窓に、何を・どの粒度で・どう構造化して入れるか」。コードを扱う場面では、テキストを行単位で切るよりも AST(Abstract Syntax Tree; 抽象構文木)の境界で切る・抜き出す ほうが圧倒的に精度とトークン効率が良い。
- ASTは「関数・クラス・import・呼び出し関係」を機械可読な木構造で持つため、意味のまとまりを壊さないチャンク分割・シグネチャだけ抜く骨組み化(skeleton)・依存関係を辿った関連コードの同梱 が可能になる。
- 実運用では tree-sitter(多言語パーサ)+ グラフランキング(PageRank等) の組み合わせがデファクト。Aider の repo map、Sweep、Cursor/Continue のインデックス、研究では cAST(EMNLP 2025) が代表例。
1. AST の基本原理(仕組み)¶
1-1. ソースコード → 木構造になるまで¶
ASTは、コンパイラ/インタプリタのフロントエンドが内部的に作る中間表現で、生成過程は2段階に分かれる。
- 字句解析(Lexing / Tokenizing): 文字列を意味の最小単位「トークン」に分解する。
int x = 1 + 2;→int,x,=,1,+,2,;。 - 構文解析(Parsing): トークン列を文法規則に従って木に組み上げる。演算子の優先順位や入れ子(ブロック・式)が木の親子関係になる。
ソース: return int(price * rate)
AST(簡略):
ReturnStatement
└─ Call (int)
└─ BinaryOp (*)
├─ Identifier (price)
└─ Identifier (rate)
ポイントは、木の「ノード」が言語の構文要素(関数定義・代入・呼び出し・式)に1対1で対応する こと。だから「関数の範囲」「この式の引数」を曖昧さなく特定できる。これが正規表現や行分割にはできないこと。
1-2. CST と AST の違い¶
- CST(Concrete Syntax Tree / 具象構文木、別名 parse tree): 括弧・セミコロン・空白・コメントまで、ソースの全情報を保持した木。
- AST(Abstract Syntax Tree / 抽象構文木): 意味に不要な記号(余分な括弧やセミコロン)を落とし、構造の本質だけ残した木。
実務上 tree-sitter が作るのは厳密には CST に近い(全バイト範囲を保持する)が、コード検索・チャンキング用途では「named node(意味のあるノード)」だけを辿るので、実質 AST として扱う。원文の start_byte/end_byte を持つので、ノードから元コードを正確に切り出せるのがチャンキングに都合がよい。
1-3. ノードが持つ情報¶
各ノードは典型的に次を持ち、これがコンテキスト操作の材料になる。
| 属性 | 内容 | 用途 |
|---|---|---|
type |
ノード種別(function_definition, class_definition, call 等) |
「関数だけ」「呼び出しだけ」を選別 |
start/end (byte, point) |
元ソースの範囲(バイト位置・行列) | 元コードの正確な切り出し・行番号付与 |
children / parent |
親子ノード | 木の再帰走査、スコープ復元(親クラス名など) |
field name |
子の役割(name, body, parameters 等) |
「関数名だけ」「引数リストだけ」を抜く |
1-4. 木の走査(traversal)¶
ASTからの情報抽出は基本的に 木の再帰下降(DFS) か visitor パターン。「このノードが関数なら抜く、そうでなければ子を見る」を再帰で回す。tree-sitter には クエリ言語(S式パターン) もあり、(function_definition name: (identifier) @name) のような構文パターンで該当ノードを宣言的に取得できる(ast-grep もこの発想)。
1-5. tree-sitter が事実上の標準である理由¶
- 多言語(100以上)を統一API・統一クエリ言語で扱える
- インクリメンタルパース: 編集差分だけ再パースするのでエディタ・インデクサで高速
- エラー耐性: 文法的に壊れた・書きかけのコードでも部分木を返す(LLMが生成中の不完全コードを扱える)
- Neovim / Helix / Zed / GitHub のシンタックスハイライトを支える実績
注意: tree-sitter は 構文 までで 型は解決しない。「この変数の型」「この呼び出しの実体」まで要るなら、型チェッカや LSP(後述)を併用する。
2. なぜコンテキストエンジニアリングでASTなのか¶
2-1. 「行ベース分割」の限界¶
RAG やコード補助でコードを LLM に渡すとき、素朴には固定行数(例: 50行ごと)や固定トークン数でチャンク分割する。しかしコードは自然文と違い、構造そのものが意味を持つ。固定長分割には以下の致命的な問題がある。
- 関数の途中で切れる → そのチャンク単体では意味不明(中括弧が閉じない、変数定義が前のチャンクにある)
- import やクラス宣言とその利用箇所が別チャンクに分断され、検索でヒットしても文脈が欠落する
- コメントとコード本体が分離する
- 1つの埋め込みベクトルに複数の無関係な関数が混ざり、検索精度が落ちる
2-2. ASTが与える「意味の境界」¶
AST はソースコードを 関数定義 / クラス定義 / メソッド / import文 / 式 といったノードの木で表す。この境界を使えば「人間がコードを読む単位」でコンテキストを操作できる。価値は4つに集約できる。
| 価値 | 内容 |
|---|---|
| 境界の正確さ | 関数・クラス単位で切るので、チャンクが常に構文的に完結する |
| トークン効率 | 本体を捨ててシグネチャ(型・引数・docstring)だけ残す「骨組み化」で、ファイル全体を 1/10 以下のトークンで俯瞰できる |
| 構造的検索 | 「この関数を呼ぶ箇所」「このクラスを継承するクラス」を木・グラフ走査で正確に取得(grep より誤検出が少ない) |
| 依存同梱 | 呼び出しグラフ(call graph)を辿り、対象関数が依存する型定義・ヘルパーを一緒にコンテキストへ入れられる |
3. ASTを使う代表的テクニック(パターン集)¶
3-1. AST-aware チャンキング(構文境界での分割)¶
埋め込み・RAG向けに、関数/クラス境界でチャンクを切る。ノードが大きすぎる(巨大関数)場合は子ノードで再帰分割し、小さすぎる場合は兄弟ノードをまとめる(greedy merge)。各チャンクに「ファイルパス・親クラス名・行番号」をメタデータとして付与しておくと、検索ヒット時に文脈を復元できる。
- LlamaIndex の
CodeSplitter、LangChain のRecursiveCharacterTextSplitter.from_language()がこのパターン。 - 研究では cAST(EMNLP 2025) が「split-then-merge」を定式化(後述)。
3-2. スケルトン化 / シグネチャ抽出(repo map)¶
リポジトリ全体を LLM に俯瞰させたいが全文は入らない。そこで 各ファイルから「クラス名・関数シグネチャ・重要な定義」だけを AST で抜き出した目次(map) を作る。本体(関数の中身)は捨てる。
(Aider の repo map のイメージ)
tax/calculator.py:
⋮
│class TaxCalculator:
│ def calc(self, price: int) -> int:
⋮
│def apply_discount(price: int, rate: float) -> int:
⋮
数万行のリポジトリでも数千トークンで「どこに何があるか」を提示でき、LLMが「次に詳細を読むべきファイル」を判断できる。
3-3. 呼び出しグラフによる依存同梱¶
対象シンボル(関数)を起点に、それが呼ぶ関数・参照する型を AST/LSP で辿り、N ホップ分を関連コンテキストとして同梱 する。Aider はさらにグラフに PageRank を掛け、チャットで言及されたシンボルやファイルを起点に「リポジトリ内で重要度の高い定義」をランキングして map に載せる量を予算内に収める。
3-4. 構造的検索・構造的編集(grep の代替)¶
- ast-grep / Comby: 正規表現ではなく構文パターンで検索・置換。「
foo()の呼び出し」を、コメントや文字列リテラル中のfooに誤マッチせず取得できる。 - LSP(Language Server Protocol)ベース:
go to definition/find references/document symbolsを使い、AST+型解決済みの正確なシンボル情報を取得(Serena MCP が代表)。
3-5. 差分の構文的圧縮¶
大きな diff をそのまま渡さず、変更があった関数のシグネチャと変更ハンク周辺だけ を AST 境界で抽出し、無関係な部分を畳む。レビュー系エージェントのコンテキスト節約に効く。
4. 実例(プロダクト・OSS)¶
4-1. Aider — repo map(最も有名な実例)¶
tree-sitterで各ファイルをパースしてシグネチャを抽出 → シンボルの定義/参照を有向グラフ化 → PageRank で重要度をランキング → トークン予算に収まるよう map を生成。- 意義: 「全文を渡す」でも「何も渡さない」でもなく、会話の文脈(言及されたファイル・シンボル)に応じて重要箇所だけを動的に選別する。
4-2. Sweep — Syntax Tree による大規模コードチャンキング¶
- tree-sitter で CST を作り、LangChain の recursive splitter に似たアルゴリズムを構文木上で走らせる。「関数ヘッダとその実装を同じチャンクに保つ」ことで検索品質を上げる。
- 「1日200万ファイルをチャンク」する規模で運用した実装ブログがあり、AST チャンキングの実務上の定番手順(ノードを window に詰める→大きすぎる節は子に再帰→入らなければ新 window)を公開している。
4-3. Cursor / Continue — コードベースインデックス¶
- ファイルを AST境界でチャンク化 → 埋め込み → ベクトルDB。
@codebase等で検索した結果を、構文的に完結したチャンクとしてプロンプトへ注入。Continue は OSS で tree-sitter ベースの chunker 実装が読める。
4-4. supermemory code-chunk — リッチなメタ付きチャンカ¶
- tree-sitter で関数・クラス・メソッド境界に分割し、各チャンクに スコープチェーン・import・兄弟ノード・エンティティのシグネチャ を同梱する OSS。「チャンク単体で文脈が完結する」ことを徹底した実装例。
4-5. Claude Code / Codex 系 — オンデマンド構造把握¶
- 全文インデックスを持たず、必要時に grep / ast-grep / LSP 的ツールで対象シンボルだけを読む「just-in-time」型。コンテキスト窓を汚さないため長時間セッションで効く(claude_code_long_session_guide のコンテキスト管理思想と同根)。
4-6. Serena(MCP サーバ)— LSPでセマンティックなコンテキスト¶
- Language Server を MCP 経由で公開し、
find_symbol/find_referencing_symbols/get_symbols_overviewを提供。シンボル単位で読む・編集する ことでトークンを節約しつつ正確な編集を実現。
4-7. Sourcegraph Cody / GitHub Copilot¶
- Cody はコード検索基盤(シンボル・参照グラフ)から関連定義・参照を構造的に取得。Copilot は補完時に近傍+シンボル定義元を周辺コンテキストとして集める。
5. 海外の記事・論文まとめ(一次資料)¶
論文¶
| 文献 | 出典 | 要点 |
|---|---|---|
| cAST: Enhancing Code RAG with Structural Chunking via AST | arXiv 2506.15655 / EMNLP 2025 Findings(CMU) | AST を再帰分割し、トークン上限を守りつつ兄弟ノードをマージする split-then-merge を提案。行ベース分割に対し RepoEval の Recall@5 を +4.3pt、SWE-bench の Pass@1 を +2.67pt 改善。AST-aware チャンキングの効果を定量的に裏づけた中心的論文 |
| AST-T5: Structure-Aware Pretraining for Code Generation and Understanding | arXiv 2401.03003(2024、ICML 2024) | チャンキングではなく事前学習側でASTを使う。動的計画法による AST-Aware Segmentation と AST-Aware Span Corruption で構文構造を保ったまま学習。Bugs2Fix・Java↔C#変換などコード間タスクで CodeT5 を上回る。「ASTは推論時の文脈整形だけでなく学習目的にも効く」ことを示す |
| Graph-RAG for Codebases: AST-Derived Graphs vs LLM-Extracted KG | arXiv 2601.08773(2026) | コードベースの Graph-RAG で、AST由来の確定的グラフ と LLM抽出の知識グラフ を比較。AST由来グラフの信頼性(再現性・正確さ)の優位を論じる。自分の研究テーマ(知識グラフ)とも接点あり |
エンジニアリングブログ・実装¶
| 記事 / リポジトリ | 媒体 | 要点 |
|---|---|---|
| Building a better repository map with tree-sitter | Aider 公式ブログ | tree-sitter + PageRank で repo map を作る設計思想と実装。AST スケルトン化の原典的解説 |
| Chunking 2M+ files a day for Code Search using Syntax Trees | Sweep(docs.sweep.dev/blogs) | CST上でのrecursive splitter。「ノードをwindowに詰める→大きすぎたら子に再帰→入らなければ新window」のアルゴリズムを実例で解説。HN でも議論された定番記事 |
| Building code-chunk: AST Aware Code Chunking | supermemory / nexxel.dev | スコープチェーン・import・シグネチャを同梱する chunker をゼロから作る過程。OSS は supermemoryai/code-chunk |
| Building a knowledge assistant over code | Databricks Blog | コード RAG で cAST を動機として引用し、AST チャンキングを採用。複数の code RAG ベンチで評価 |
| Semantic Code Indexing with AST and Tree-sitter for AI Agents | Medium(Dineshkumar、全3部) | AIエージェント向けの AST/tree-sitter セマンティックインデックスの構築手順を段階的に解説 |
体感的な比較値として、ある実装記事は「完全に正しい回答を返す率: AST分割 70% / 言語非依存分割 61% / 素朴分割 59%」と報告(個人ブログのベンチなので参考程度)。学術的な裏づけは cAST の +4.3pt / +2.67pt を一次根拠とするのが堅い。
6. 実装の足場(自分で組むなら)¶
6-1. パーサの選択¶
| 手段 | 特徴 | 向き |
|---|---|---|
| tree-sitter | 多言語(100+)、インクリメンタル、エラー耐性 | 多言語インデクサ・repo map。デファクト |
言語標準AST(Python ast、TS compiler API、Go go/ast) |
型・スコープまで取れるが言語ごとに別実装 | 単一言語で深い解析が要るとき |
| LSP / language server | 型・参照解決済み(最も正確) | 「定義へ移動」「参照検索」が要るエージェント |
6-2. tree-sitter で関数チャンクを抜く最小例(Python)¶
from tree_sitter_languages import get_parser
parser = get_parser("python")
source = open("calculator.py", "rb").read()
tree = parser.parse(source)
def iter_chunks(node, src):
# 関数・クラス定義ノードを構文境界チャンクとして取り出す
if node.type in ("function_definition", "class_definition"):
text = src[node.start_byte:node.end_byte].decode()
yield {
"type": node.type,
"start_line": node.start_point[0] + 1,
"code": text,
}
for child in node.children:
yield from iter_chunks(child, src)
for chunk in iter_chunks(tree.root_node, source):
print(chunk["start_line"], chunk["type"])
実運用ではこれに「大きすぎる関数は子ノードで再分割」「小さすぎる定義は束ねる」「トークン上限チェック」「メタデータ付与」を足す(= cAST / CodeSplitter / Sweep がやっていること)。
6-3. 設計時のチェックリスト¶
- [ ] チャンクは構文的に完結しているか(中途半端な関数で切れていないか)
- [ ] チャンクにファイルパス・シンボル名・行番号のメタデータを付けたか
- [ ] トークン予算を超えるノードの再帰分割と、過小ノードのマージを実装したか
- [ ] 全文埋め込みが必要か、エージェントにオンデマンドで辿らせる方が安いか(窓を汚さない設計か)
- [ ] 型・参照解決まで要るなら LSP を併用したか
- [ ] パース失敗(壊れたコード・未対応言語)時のフォールバック(行分割)を用意したか
7. 限界・注意点¶
- tree-sitter単体は型を解決しない。「呼び出しの実体」「変数の型」が要る用途では LSP/型チェッカが必要。
- 言語カバレッジと品質の差。JSX・Vue SFC・テンプレート埋め込みSQL等はパース品質にばらつき。
- インデックスの鮮度。AST インデックス/埋め込みはコード変更で陳腐化する。差分更新(インクリメンタルパース)かオンデマンド解析で回避。
- 過剰エンジニアリング。小規模・単一ファイル・短命タスクでは全文を渡す方が速くて安い(KISS)。AST化はリポジトリ規模・長時間セッションで効く。
- 構造だけでは意味が足りない。AST は「構文」であって「意図」ではない。最終的な関連度判定は埋め込み・LLM・グラフランキングと組み合わせる。
8. まとめ — いつ AST を使うか¶
| 状況 | 推奨アプローチ |
|---|---|
| 大規模リポジトリの俯瞰を LLM に渡したい | スケルトン化 repo map(tree-sitter + PageRank、Aider型) |
| コードRAGの検索精度を上げたい | AST-aware チャンキング(CodeSplitter / cAST / Sweep型) |
| エージェントに正確に編集させたい | LSP/ast-grep でシンボル単位 に読む・書く(Serena型) |
| 長時間セッションで窓を汚したくない | オンデマンドで構造を辿らせる(全文インデックスを持たない) |
| 単一ファイル・短いタスク | 素朴に全文を渡す(AST化しない、KISS) |
結論: コンテキストエンジニアリングでコードを扱うなら、「行」ではなく「構文木の境界」で切り・抜き・辿るのが基本戦略。tree-sitter による境界抽出と、グラフランキング/埋め込みによる重要度選別を組み合わせるのが、現時点の実用的な定石である。
参考リンク¶
論文 - cAST(EMNLP 2025): https://arxiv.org/abs/2506.15655 / https://aclanthology.org/2025.findings-emnlp.430/ - AST-T5(ICML 2024): https://arxiv.org/abs/2401.03003 / コード: https://github.com/gonglinyuan/ast_t5 - Graph-RAG for Codebases(2026): https://arxiv.org/pdf/2601.08773
ブログ・OSS
- Aider "Building a better repository map with tree sitter"(tree-sitter + PageRank)
- Sweep "Chunking 2M+ files a day for Code Search using Syntax Trees": https://docs.sweep.dev/blogs/chunking-2m-files-a-day-for-code-search-using-syntax-trees
- supermemory code-chunk: https://github.com/supermemoryai/code-chunk / 解説: https://www.nexxel.dev/blog/code-chunk
- Databricks "Building a knowledge assistant over code": https://www.databricks.com/blog/building-knowledge-assistant-over-code
- LlamaIndex CodeSplitter / LangChain from_language splitter(AST境界チャンカの実装)
- Continue(OSS、tree-sitter ベースの code chunker)
- Serena MCP(LSPベースのシンボル単位コンテキスト取得)
ツール - tree-sitter(多言語パーサ)/ ast-grep(構造的検索置換)/ Comby(構造的書き換え)
作成: 2026-06-08 / 最終更新: 2026-06-16