背景

我幾乎都是用 Markdown 來撰寫軟體工程的設計文件
業務需求、使用情境清單、服務說明書、API 規格、ADR、知識庫。不知不覺間,內外部要處理的大多數文件都變成了 Markdown。
而且最近,GitHub Copilot 和 Claude Code 的輸出結果本身也會以 Markdown 回傳。也就是說,輸入與輸出都是 Markdown 的情境,已經逐漸成為現場的常態。

一旦如此,接下來最讓人困擾的就是:「這麼大量的 Markdown,要怎麼有效率地讓 AI agent 讀懂?

當你用 Vibe Coding 請 agent「依照這份規格實作」時,如果把所有相關 Markdown 都叫它 read_file 一遍,Context Window 很快就會被塞滿。
老實說,一開始我也以為「context window 變大了,應該沒問題吧」,但在實務上跑比較重的 session 時,實際上比想像中更快就會感到捉襟見肘。

基於這個體感,我做了一個專注於有效搜尋與讀取 Markdown 的技能 markdown-query 並公開出來。

本文會整理其背後的 Token 消耗概念、技能內容、安裝方式、從 GitHub Copilot 使用的方法,以及 benchmark 的解讀方式。


注意事項 / 前提

先說明一下。

  • 這僅是我個人的觀點,並非所屬組織的官方立場
  • 數值(後述的 Token 分配、削減率)會因工具、模型、任務、repository 內容而大幅波動
  • 不預設可直接用於 production 營運,或作為組織標準直接採用
  • 介紹的技能也不是「銀彈」,請把它視為在特定情境下有效的工具
  • benchmark 的數值是我在自己的 repository、自己的環境中測得的。無法保證在相同條件下得到同樣結果

它不是萬能的。若能先理解這點,再往下看會比較好。


整理:Context Window 到底是被什麼塞滿的?

當我們說「Token 不夠」時,我們到底在消耗什麼。
這裡先整理一下。

context window 的內容,大致可分成以下 5 類:

  • System / Tools / MCP / instructions
  • 對話歷史
  • 檔案讀取
  • 指令輸出與 log
  • 空間 / buffer

也就是說,送給 AI 的不只是使用者的問題,而是工具定義、指示文件、歷史紀錄、讀進來的檔案、執行 log 全部都包含在內。
如果誤解了這一點,就會搞不懂「我明明沒有講很久,為什麼 context 這麼快就被壓縮了」。

重點不是「對話量」,而是累積起來的周邊資訊


本文:Vibe Coding 中的 Token 消耗大略感

以 200k tokens 的 context window 為前提,較重的開發 session 大致會落在這樣的分配。

構成要素輕量狀態重量狀態System / Tools / MCP / instructions10〜20%25〜35%對話歷史10〜25%40〜70%檔案讀取10〜30%40〜60%指令輸出與 log5〜15%20〜40%空間 / buffer20〜60%0〜20%老實說,我第一次看到這個內部分配時,有點驚訝:「原來光是檔案讀取和對話歷史就吃掉大半了啊。」
不過仔細想想也很合理,AI agent 每讀一次檔案,就會把內容整份堆進 context 裡。grepcat 的輸出也是一樣。

GitHub Copilot CLI 的說明中提到,當使用量到約 80% 時會開始 background compaction,而接近 95% 時會出現等待 compaction 完成的行為。實務上的目標是:在超過 80% 之前先整理好

實務上的影響包括:

  • session 越到後段,修改建議越容易飄移
  • AI 會忘記之前已經決定好的前提,重複同樣的討論
  • 因為要等 compaction,體感回應速度會下降

這些地方雖然看起來不顯眼,但會慢慢累積成壓力。
所以我才會覺得,把檔案讀取做得更聰明,才是現場最有感的節省點。


markdown-query 技能是什麼

markdown-query 是一個能在 repository 內的 Markdown 群組(規格書、設計文件、知識庫、README 等)之間完全在本機進行橫向搜尋,並只把命中的標題層級小片段(snippet)回傳給 agent 的技能。

特色

  • 擁有獨立索引 — 將 chunk 與 metadata 儲存在 .mdq/index.sqlite,可進行增量更新
  • 使用日文 tokenizer — 即使是日文 Markdown 也能實用地命中
  • 完全離線運作 — 不會呼叫任何外部 API(embedding、向量搜尋服務等)
  • 支援 BM25 / grep / 標籤・路徑篩選
  • 也能做 標題階層總覽,以及指定 chunk ID 取得本文

因為不使用雲端 embedding 或遠端 vector DB,所以即使是公司內部封閉的設計文件,也能安心使用。
相對地,它不會編輯或生成 Markdown。這是唯讀工具。

有什麼好處(Why)

  • 「把全文都 read_file 進來」 → 消耗數萬 tokens,連無關章節也一起讀進去
  • 經由 markdown-query → 只會把對應 chunk 的數百到一千 tokens 左右壓縮後送進去

實測數值會在後面說明,但在特定條件下能達到 97% 以上的 Token 削減。當然,這是「特定條件下」的結果。


技能套件包含的內容

不只技能本體,還附帶 CLI 與 benchmark 工具。

路徑內容skills/markdown-query/SKILL.md技能本體。agent 讀取的觸發定義與步驟skills/markdown-query/references/cli-reference.md``mdq CLI 的所有子命令與選項規格skills/markdown-query/references/query-patterns.md常見查詢範例skills/markdown-query/references/indexing-internals.md索引的資料模型與 chunk 分割規則skills/markdown-query/examples/prompt-snippets.md適用於 Copilot Chat / Custom Agent 的 prompt 範例mdq/技能內部會呼叫的 Python 製 CLI 本體setup/setup-markdown-query.{ps1,sh}mdq 安裝到 .venv 的腳本tools/markdown-query/用來數值驗證 Context 削減效果的 benchmark CLI---

安裝步驟

前提條件

  • Git CLI
  • Python 3.11 以上(mdq CLI 的運作需求)
  • 要使用的 agent CLI(copilot / claude / gemini / apm 其中之一)

1. 技能安裝

以 GitHub Copilot CLI 為例,在互動 session 中執行以下指令(第一次需先加 marketplace)。

/plugin marketplace add dahatake/skills
/plugin install dahatake-skills@dahatake-skills

Claude Code、Gemini CLI、透過 APM 的安裝步驟請參考 README。

2. mdq CLI 的安裝(必須)

技能內部會呼叫 mdq CLI。只安裝 plugin 是不能運作的
先 clone repository,然後依作業系統執行對應的 setup script。

Windows (PowerShell)

git clone https://github.com/dahatake/skills.git
cd skills
./setup/setup-markdown-query.ps1

macOS / Linux (bash)

git clone https://github.com/dahatake/skills.git
cd skills
chmod +x ./setup/setup-markdown-query.sh
./setup/setup-markdown-query.sh

腳本會在 repository root 建立 .venv,並在其中安裝 mdq
加上 -WithWatch / --with-watch 的話,也會安裝用於監看檔案變更的 watchdog,供 mdq watch 使用。


使用方式 — 從 GitHub Copilot 開始

重點從這裡開始。
以下依照平常在 Vibe Coding 中整合使用的順序說明。

1. 建立索引(第一次・必須)

使用這個技能之前,請務必先執行 1 次。請在要搜尋的 repository root 執行。

mdq index
  • 預設會遞迴掃描目前目錄,索引 .md / .markdown
  • 預設會排除 .git / node_modules / .venv 等目錄
  • 預設會尊重 .gitignore
  • 建議將 .mdq/ 本身也加入 .gitignore

2. 索引更新

在新增或編輯檔案後,再執行一次 mdq index 即可。它會以 SHA-1 + mtime 做增量更新,因此未變動的檔案不會重新處理。

如果想即時反映檔案變更,可以在另一個 terminal 啟動 watch 模式。

mdq watch

3. 從 GitHub Copilot 呼叫的範例

建立索引後,可以像這樣在 Copilot Chat 或 Copilot CLI 中請求。

請找出這個 repository 底下 Markdown 中與「會員 同意管理」相關的設計,並只告訴我重點。

請從 docs/** 底下的 Markdown 找出包含 "context window" 的標題,並橫向整理,附上引用來源的 path:lines

請根據業務需求與使用情境清單,只摘錄忠誠點數給付的服務說明書相關段落。

當技能啟動時,內部會呼叫 mdq search,並且只把命中的標題層級 chunk 放進 Context。
和讓它讀全文相比,對 Context Window 的影響會是數量級的差異。

4. 手動試著打 mdq 看看(動作確認)

在交給 agent 之前,自己先手動執行看看,熟悉一下手感也很推薦。

mdq search --q "會員 同意管理" --top-k 5 --max-tokens 800

主要選項:

選項說明--q搜尋查詢(必填)--top-k回傳的命中數量(預設 5,建議 3〜5)--max-tokens輸出的最大 token 數(預設 800,建議 400〜800)--paths限制搜尋目標路徑(例如: "docs/**"--tags用 frontmatter 的 tag 篩選--mode``bm25(預設) / grep``--snippet-radius顯示命中行前後幾行(預設 ±2)輸出為 JSONL(1 行 = 1 筆命中)。如果有在意的 chunk,可以用 chunk_id 指定並取得本文。

mdq get --chunk-id <ID>

Benchmark:真的有節省 Token 嗎

只有「感覺不錯」還不夠可信,所以我另外附了一個用來在自己的 repository 驗證數值的 benchmark CLI

要測什麼

對同一組查詢,比較 3 種情境。

情境投入到 Context 的內容預期用法baseline_full索引範圍內的全部 Markdown 本文不使用技能時的上限值mdq_bm25``mdq search --mode bm25 的命中結果預設搜尋模式mdq_grep``mdq search --mode grep 的命中結果嚴格比對模式在每個情境中都會測量回應 token 數 / 搜尋 wall-clock / 相較 baseline 的削減率 / coverage(可選)

執行步驟

  1. 建立索引(若尚未建立,也可用 --ensure-index 自動建立)

    mdq index
  2. 準備一個檔案,每行 1 筆查詢(範例:tools/markdown-query/queries.sample.txt
  3. 執行 benchmark

    python tools/markdown-query/benchmark.py \
      --queries-file tools/markdown-query/queries.sample.txt \
      --top-k 5 --max-tokens 800 --repeat 3 --ensure-index
  4. 結果會輸出到 tools/markdown-query/results/bench-<UTC時間戳>.{json,md}

報告的解讀方式

bench-*.md 會依序列出以下區塊。

  1. Environment — tokenizer、Python、OS、commit hash。若要和其他環境做絕對比較,務必先確認這裡
  2. Parameters--top-k --max-tokens --repeat 等執行條件
  3. Index summary--ensure-index 時建立索引所需時間
  4. baseline_full — 投入全文時的 files / chars / tokens。這是削減率的分母
  5. 沒有 Skill vs 有 Skill(prompt token 比較) — 逐一顯示各情境的:
    • avg_response_tokens — 各查詢平均回應 token 數(越小越省)
    • avg_vs_baseline_savings_pct — 削減率(例如 98.5% 代表相較全文只剩 1.5%)
    • latency_ms_all — 全查詢 × --repeatmean / p50 / p95 / min / max
    • per_query[] — 每個查詢的 hits 數、token、削減率、coverage_proxy

實際範例(參考值)

以下是在 repository 內附的 sample/ 目錄(業務需求・使用情境・服務說明書 4 個檔案)上,以 5 個查詢執行的結果。

這只是「範例」。不保證使用者環境會得到相同的結果或精準度

測量環境: tiktoken/cl100k_base / Python 3.12.10 / Windows 11 / top_k=5, max_tokens=800, repeat=3

baseline_full: 4 files / 83,230 chars / 68,440 tokens

情境平均 tokens(with skill)相較 baseline 的平均削減率延遲 mean / p50 / p95 (ms)mdq_bm251,794.697.38%13.35 / 13.65 / 14.20mdq_grep700.698.98%1.45 / 0.47 / 3.33逐查詢(mdq_bm25,節錄):

queryhits tokens削減率 %忠誠計畫52,48496.37生成式 AI 個人化51,81697.35點數給付 失效51,25098.17會員 同意管理51,40297.95使用情境52,02197.05在這個例子中,prompt tokens 被壓縮到全文投入的約 1〜3%
另一方面,mdq_grep 對詞彙表記差異較敏感,也會出現沒有命中的查詢(savings % = 100 表示「沒有命中」,因此還需要另外透過 coverage_proxy 確認精準度)。

重點是不要只看削減率。 我認為把預期路徑綁定到 JSON,連 coverage 一起看,才是比較實際的評估方式。


Repository 結構

README.md                           專案 README
LICENSE                             MIT 授權
plugin.json                         plugin 定義(Copilot CLI / 共通)
apm.yml                             APM marketplace 定義
.claude-plugin/marketplace.json     Claude Code / Copilot CLI 用 marketplace
.claude-plugin/plugin.json          Claude Code 用 plugin 定義
gemini-extension.json               Gemini CLI 擴充定義
setup/                              各技能額外 CLI 安裝腳本
  setup-markdown-query.ps1
  setup-markdown-query.sh
skills/                             技能本體
  markdown-query/
    SKILL.md
    examples/prompt-snippets.md
    references/
      cli-reference.md
      query-patterns.md
      indexing-internals.md
mdq/                                Python 製 CLI 本體
tools/markdown-query/               benchmark CLI 與結果
  benchmark.py
  queries.sample.txt
  results/
sample/                             示範用 Markdown 群組

plugin.json(根目錄)與 .claude-plugin/plugin.json 的內容是重複的,因此更新其中一個時,也必須同步另一個。apm.yml.claude-plugin/marketplace.json 也是同樣的情況。


到這裡的整理

先用條列整理一下。

優點

  • 在把 Markdown 設計文件交給 AI agent 時,Token 消耗有機會減少到數量級差異
  • 完全離線運作,因此可用於公司內部封閉的設計文件群
  • 支援日文 tokenizer,所以日文 Markdown 也能實用地命中
  • 可透過 path:lines 明確標示引用來源

注意事項

  • 不只技能本體,還需要設定 mdq CLI(只裝 plugin 是不能動的)
  • 索引需要事先建立與更新(前提是不會在 session 之間共享)
  • grep 模式對表記差異較敏感

限制

  • 唯讀(不能用來編輯或生成 Markdown)
  • 不做以 embedding 為基礎的語意搜尋
  • benchmark 數值依環境而定,不保證回答品質

總結

我認為,未來會有越來越多現場是「設計文件是 Markdown,輸出也同樣是 Markdown」。
在那種情境下,如何設計檔案讀取周邊的 Token 消耗,會是左右 Vibe Coding 體驗的一個低調但重要的關鍵。

markdown-query 並不是萬能解法。
不過,

  • 平常就用 Markdown 寫設計文件
  • 已經有很多 Markdown 化的檔案
  • 也想把 Copilot 的輸出結果(Markdown)一起納入,讓 agent 能橫向參照

在這類情境下,我認為它很容易發揮效果。

建議先在自己的 repository 建立索引,實際跑一次 benchmark.py
看著跑出來的數字,決定自己現場要怎麼取捨,我認為這是最實際的做法。

沒有萬用解。
但只要開始把 Context Window 當成「有限資源」來看待,你和 AI 的相處方式一定會開始改變。
至少到這裡為止,我認為很值得先在現場試試看。


原文出處:https://qiita.com/dahatake/items/ce9917268d8d18aa9b6c


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝16   💬11   ❤️1
542
🥈
alicec
📝1   ❤️2
77
🥉
我愛JS
💬2  
7
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
📢 贊助商廣告 · 我要刊登