背景
ざっくり言うと「コードの関係(どれがどれを呼ぶ・依存する)を型付きのグラフにしてエージェントに渡すと、ファイルを grep しまくらずに済んでトークンが減るよ」という話。
元記事は Claude Code の話だけど、GitHub Copilot でも効くやろってことでお試し
オントロジーって何?
情報科学の用語で、ある領域の「概念」と「概念どうしの関係」を明示的に定義したもの。タグやフォルダは"並べる"だけだけど、オントロジーは depends-on(依存する)・implements(実装する)・calls(呼ぶ)みたいに関係を型として持てるのが違い。AI に渡すと「たぶん呼び出し関係だろう」という推測が減る。
有名なパランティアさんがこれを使って大儲け ![]()
概要
-
モノレポ(Python のクリーンアーキテクチャ構成)に、コミット型の
docs/architecture/ontology.mdを1枚作った。中身はモジュール/インターフェース/実装の型付き関係(depends-on/implements/calls)。 -
copilot-instructions.mdに「構造・依存・影響範囲の問いはまずこれを読む」を1行足した。 -
GitHub Copilot CLI + OpenTelemetry(ファイル出力) で実トークン取得
-
同じ「アーキテクチャ説明して」を オントロジー有り/無し・同一モデルで投げた結果:
| 指標 | 無し(実ソース探索) | 有り(オントロジー) | 削減 |
|---|---|---|---|
| input tokens(Σ) | 364,614 | 67,609 | −81.5% |
| in+out 合計 | 369,242 | 68,800 | −81.4% |
| ツール実行回数 | 29 | 2 | −93% |
| LLM 実時間 | 91.9s | 25.2s | −72.6%(約3.6倍速) |
用途によっては効くので、入れておいてもいいかなって気はした。
問題は、ontology.md の更新を CI で行うかどうかってところだね
詳細
1. なぜ Copilot でも効くか
だって、エージェントだから ![]()
仕組みはシンプル。「アーキテクチャ全体を説明して」みたいな広い問いを投げると、エージェントは関連ファイルを片っ端から grep して read する。これが大量のトークンを食う。
オントロジーは、その「広く浅く読む」作業を1枚のグラフで肩代わりする。点(ファイル)がバラバラに散らばっている代わりに、点と点が型のついた線で結ばれているので、関係を辿るだけで答えが出る。
2. オントロジーを書く(最小フォーマット)
厳密な RDF/OWL は要らない。Markdown にエンティティと関係を書くだけで推測は減る。
ポイントは2つ。
- 関係を型(
depends-on/implements/calls/produces)で書く。自由文にしない。 - 正本はソースコード。関係を変えたら同じ PR でこのファイルも直す、と決めておきたい。
ってことで、deepwiki-open とか、copilot cli なんかで、定期的に構造化をさせるのがよさげ。
3. instructions から参照させる
書いただけだと読んでくれない。copilot-instructions.md に1行入れて、広い問いでは先にグラフを読むよう仕向ける。
> 構造・依存・影響範囲の問いはまず docs/architecture/ontology.md を読む。
> モジュール/Protocol/実装の型付き関係がまとまっており、
> 広い問いでファイルを grep する前に参照するとトークンを節約できる。
4. Copilot での計測
ダメだった方法
-
セッション履歴 DB(VS Code の Copilot ローカル index)→
turnsテーブルはユーザー発話と応答のテキストだけ。token 列が無い。 -
デバッグログ(
main.jsonl)→ trace span のみで、トークン使用量は記録されていない。
chatからは出来そうになかったので・・
GitHub Copilot CLI + OpenTelemetry
そして決め手が OpenTelemetry のファイルエクスポータ。環境変数 COPILOT_OTEL_FILE_EXPORTER_PATH を渡すと、トークン数・ツール呼び出し・コスト・所要時間を JSONL でローカル出力してくれる(コレクタ不要・オフライン)。
レシピ(A/B 実行)
公平性のため、両方とも 同一の問い・同一モデル・--no-custom-instructions(instructions のオントロジー誘導を無効化)で揃える。
$core = "このリポジトリのアーキテクチャを説明して。主要モジュールと依存・呼び出し関係を整理して。"
# Arm A: オントロジー無し(実ソース探索)
$env:COPILOT_OTEL_FILE_EXPORTER_PATH = "$PWD\otel-A.jsonl"
copilot -p "$core ただし docs/architecture/ontology.md は読まず実ソースを調べて答えること。" `
--allow-all-tools --allow-all-paths --no-custom-instructions --no-color
# Arm B: オントロジーのみ
$env:COPILOT_OTEL_FILE_EXPORTER_PATH = "$PWD\otel-B.jsonl"
copilot -p "$core docs/architecture/ontology.md だけを根拠に答えること。" `
--allow-all-tools --allow-all-paths --no-custom-instructions --no-color
--allow-all-tools はツール承認をスキップして自動実行する(公式も Security considerations で注意喚起)。信頼できるディレクトリでだけ使うこと。計測用途なので read 中心の問いにしている。
パース(フラット JSON に注意)
このCLIの OTel ファイルは 1行1span のフラット JSON(よくある resourceSpans 入れ子ではない)。attributes 直下にトークンが入っている。
{
"type": "span",
"name": "chat claude-sonnet-4.6",
"attributes": {
"gen_ai.request.model": "claude-sonnet-4.6",
"gen_ai.usage.input_tokens": 21092,
"gen_ai.usage.output_tokens": 109,
"gen_ai.usage.cache_read.input_tokens": 21089,
},
}
なので chat span を拾って gen_ai.usage.input_tokens / output_tokens を合算するだけ。PowerShell ならこんな感じ。
$in=0;$out=0;$chat=0
foreach ($l in Get-Content .\otel-A.jsonl) {
$o = $l | ConvertFrom-Json
if ($o.type -ne 'span' -or $o.name -notlike 'chat*') { continue }
$chat++
$in += [double]$o.attributes.'gen_ai.usage.input_tokens'
$out += [double]$o.attributes.'gen_ai.usage.output_tokens'
}
"chat=$chat input=$in output=$out"
属性名は OpenTelemetry の GenAI Semantic Conventions に準拠している(gen_ai.usage.* など)。だから他の OTel 対応ツールでも同じ要領で集計できる。
5. 結果
同じ問い・同一モデル claude-sonnet-4.6(OTel の span で確認できた)での実測。
| 指標 | A: オントロジー無し | B: オントロジー | 削減 |
|---|---|---|---|
| input tokens(Σ) | 364,614 | 67,609 | −81.5% |
| output tokens(Σ) | 4,628 | 1,191 | −74.3% |
| cache_read(Σ) | 298,029 | 57,832 | −80.6% |
| in+out 合計 | 369,242 | 68,800 | −81.4% |
| LLM 呼び出し(chat) | 10 | 3 | −70% |
| ツール実行(execute_tool) | 29 | 2 | −93.1% |
| LLM 実時間 | 91.9s | 25.2s | −72.6% |
入力トークン約 5.4 分の1、ツール往復 29→2、時間 約3.6倍速。回答の質は劣化どころか、依存制約(「indexer は base を import せず subprocess 経由」みたいな話)まで正確になった。グラフが推測を消したぶん、嘘が減った感じ。
コスト表記の注意
GitHub Copilot の課金は「トークン$」ではなく AI クレジット(旧 premium request) 単位(GitHub Copilot billing)。なので元記事の"コスト半減"とは課金体系が違う。ただし処理トークンとレイテンシが直接クレジット消費に効くので、この削減はそのままコスト削減に効く。
あとがき
効きそうだけど、問題は頻度と、同期、だろうね。
CI か、PR 時に構造検出して、更新させるようにするのが良さそうな気もするけど、とりあえず暫し更新は手動で放置予定