コンテンツにスキップ

コンテキストエンジニアリングにおけるAST活用 — 有用性と実例

作成日: 2026-06-08(2026-06-08 海外文献・AST原理を追記) テーマ: LLM/エージェントに渡すコンテキストを「構文木(AST)」で構造化・選別する技術 関連: claude_code_long_session_guideai_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段階に分かれる。

  1. 字句解析(Lexing / Tokenizing): 文字列を意味の最小単位「トークン」に分解する。int x = 1 + 2;int, x, =, 1, +, 2, ;
  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 SegmentationAST-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