Skip to main content

LLM-ready document understanding package.

Project description

Documa

Documa logo

Documa 是給 agent 用的 document evidence runtime:讓 agent 用一小部分的 token 讀懂大文件、回答時指得出出處,而且引用可以被機器驗證。

如果你正在評估「有沒有比把整份文件塞進 context 更省、比 grep 原始文字更準」的文件讀取機制,這份 README 就是為你寫的。

問題:agent 讀文件的三種常見方式,各有一筆 token 帳

以一份 69 頁的 PDF(Basel III 流動性架構,全文 49,570 tokens)為例:

方式 Token 成本 痛點
整份塞進 context 49,570(每輪對話都攤提) 貴;長文件超過 context;模型在中段迷路(lost in the middle)
grep / 逐行搜尋原始文字 每個 hit 便宜(~20-40 tokens/行),但路徑長:命中後要反覆擴窗 Read 前後文,跨頁表格、雙欄版面直接斷裂 沒有結構、沒有頁碼出處、CJK 無詞界時 grep 幾乎失效
向量 RAG 檢索本身便宜 需要 embedding 前置成本與基礎設施;chunk 邊界破壞表格與章節;引用難以回溯到頁面座標
Documa 漸進式區塊讀取 大綱 2,813 + 搜尋 1,181 + 讀 2-3 個區塊 ~1,500 ≈ 5-6k tokens(約全文的 12%) 前置一次 documa process(確定性、離線、無 ML 依賴)

Documa 的核心主張:讓 LLM 的每一次工具呼叫都只換回「做下一步決策所需」的最小資訊,並在收尾時給出可驗證的頁碼級引用。

機制:四步漸進式揭露

process/ingest ──► block tree(大綱+梗概)──► search(排序過的候選)──► read(有界讀取)──► cite/verify
     一次性              ~2.8k tokens              ~1.2k tokens            每塊數百 tokens        出處可機器驗證
  1. Ingestdocuma ingest report.pdf 把文件處理成 parser-neutral 的 IR 與 block tree,拿到穩定的 document_id(同內容自動去重)。支援 PDF、Word、PowerPoint、HTML、email、notebook、Markdown。
  2. Overviewdocuma_block_tree 回傳章節大綱;include_sketches=true 直接附上 ingest 時算好的每節梗概(sketch)與讀取成本,總覽類問題常常零讀取就能回答。
  3. Search + Readdocuma_search_blocks 用 BM25-lite + coverage/proximity/intent 排序(TOC 與頁眉頁腳自動降權、近似重複去除),每個 hit 附帶結構路徑、頁碼、建議讀取量與可直接照發的下一步工具呼叫recommended_next.actions[]);documa_read_blockmax_chars/max_tokens 有界讀取,讀不完給續讀 cursor。
  4. Cite + Verifydocuma_cite_block 回溯到「第幾頁、頁面上哪個 bbox」,documa_verify_citations 機器檢查引用的區塊真實存在——答案不只便宜,還可稽核。

跨文件同理:documa_search_collection(SQLite FTS5,含 CJK 逐字索引)一次回答「哪幾份文件提到 X」,每份文件一列精確命中數 rollup。

回應層的 token 工程(v0.5.0)

省 token 不只靠「少讀」,也靠每個回應本身就瘦

  • 回應只傳一份 compact JSON(不重複傳 structuredContent + pretty text)。
  • Block id 去掉重複的文件 GUID 前綴,envelope 宣告一次 block_id_prefix;空欄位一律不序列化;常數(如 page_ref_kind)上提到 envelope。
  • 搜尋預設 nav profile:每個 hit 只回路由決策需要的欄位;citation/selection 細節留給 evidence,診斷留給 debug
  • 有 token counter 時,搜尋回應自動套 2,000 token 上限,超出時按「可有可無 → 低排名結果」順序優雅裁減並回報 dropped_results
  • Token 一律由真實 tokenizer 計算(tiktoken 自動偵測;Claude 可走 Anthropic count-tokens API),禁止 chars/4 估算

同一份 69 頁 PDF 的實測(compact JSON tokens,v0.4.0 → v0.5.0):

回應 v0.4.0 v0.5.0
block_tree max_depth=2 9,756 2,813(-71%)
list_blocks depth=1 3,476 1,092(-69%)
search_blocks 5 hits 1,344 1,181
MCP wire(傳輸層) 每回應兩份 單份(再省一半)

固定成本也可控:MCP 工具面分 agent(16 工具,schema 約 3.3k tokens,涵蓋完整 evidence 工作流)/advanced/admin 三個 profile,plugin 預設最小的 agent

可重現的量測入口:python benchmarks/token_economy/run_agent_benchmark.py(真實 tokenizer 計分:Tokens-to-Supported-Answer、Evidence Recall、Search Path Length、Budget Correctness)。

15 分鐘評估路徑

需要 Python 3.10+。以下以 PowerShell 為例(macOS/Linux 改路徑分隔符即可):

python -m pip install -e ".[documents,mcp]"   # documents = PDF/DOCX/PPTX/HTML/MSG/IPYNB 依賴

1. 處理一份你自己的 PDF(挑一份你熟悉內容的長文件,才能評估答案品質):

documa process .\your.pdf --out .\out\eval --export-format block-json

2. 看大綱與梗概(評估點:不讀內文能否掌握文件結構):

documa block-tree .\out\eval\documa.ir.json --max-depth 2

3. 問一個具體問題(評估點:hit 的排序品質與每 hit 的 token 成本):

documa search-blocks .\out\eval\documa.ir.json --query "你關心的主題"

4. 只讀命中的區塊(評估點:有界讀取 + 續讀 cursor):

documa block .\out\eval\documa.ir.json --id "<搜尋結果的 block id>" --read --max-chars 1500

5. 產生可驗證引用

documa cite-block .\out\eval\documa.ir.json --id "<block id>"

回傳類似:

{
  "page_label": "PDF p.2",
  "grounding": "visual",
  "bboxes": [{ "page": 2, "x0": 56.0, "y0": 240.0, "x1": 486.0, "y1": 328.0 }],
  "citation_string": "[PDF p.2, bbox(56,240,486,328)]"
}

6.(選配)看完整離線 demo——不呼叫任何 LLM,輸出一份 trace 展示「搜尋→選塊→讀取→合成答案」全程與逐步 token 用量:

documa block-demo .\your.pdf --question "這份文件的主要風險是什麼?" --out .\out\eval-demo

多文件評估:把幾份文件 documa ingest 進同一個 store,然後:

documa search-collection --query "違約金" --group-by-document

接進你的 agent

同一套能力有四個入口,行為一致:

入口 使用方式
MCP documa-mcp(需 [mcp] extra)。DOCUMA_MCP_PROFILE=agent 只暴露 evidence 工作流的 16 個工具。repo 內附三個現成 plugin:Claude Code(plugins/claude-code-documa)、Codex(plugins/codex-documa)、OpenClaw(plugins/openclaw-documa),各含引導 LLM 走短搜尋路徑的 documa-evidence skill。
OpenAI function calling from documa.interfaces import openai_tool_schemas, call_documa_tool
CLI 上面評估路徑用的指令;適合 shell-based agent 或人工檢查。
Python API documa.adapters + documa.pipeline.run_default_pipeline,或直接 call_documa_tool(name, args)

Python 最小範例:

from documa.interfaces import call_documa_tool

result = call_documa_tool(
    "documa_search_blocks",
    {"ir_path": "out/eval/documa.ir.json", "query": "資本適足率", "limit": 5},
)
# result["structuredContent"]["results"] 每筆含 block_id/path/page/score/snippet/read_chars,
# recommended_next.actions[] 是可直接照發的下一步呼叫

給 LLM 的回應約定(plugin skill 已內建教學):回應在 envelope 宣告一次 block_id_prefix 後發短 block id,回傳工具時原樣帶回即可;空欄位不出現=空值;page 是引用標籤、page_refs 是實體頁碼。

設計性質(評估 checklist)

  • 確定性、可離線:core 無 ML/LLM 依賴、無網路呼叫,同輸入同輸出;適合放進 CI 與資安敏感環境。
  • 出處可驗證:每個 block 帶頁碼與 bbox 來源鏈;documa_verify_citations 做引用存在性檢查(明確不是語義驗證——語義驗證的 AnswerSupportChecker 介面在 core、實作在 examples)。
  • CJK 完整支援:關鍵詞抽取用 CJK n-gram + 邊界熵新詞發現;collection FTS 逐字索引讓中文子詞查詢可用;snippet 視 CJK/ASCII 分別以字元/詞窗置中。
  • 格式統一:PDF(.pdf)、Word(.docx)、PowerPoint(.pptx)、HTML、email(.eml/.msg,含 mailbox 批次 documa ingest-mailbox)、Jupyter(.ipynb)、Markdown/text 全部進同一種 IR,下游只依賴 IR。
  • IR 是 semver 契約ir_version minor 只允許 additive 欄位;schema 由 dataclass 生成並有 CI 同步閘門(documa validate-ir 可驗檔)。
  • 品質有 gold 基準documa benchmark --mode quality 對 13 個 gold case 計分(表格 TEDS、閱讀順序 NED、關係連結 F1);雙欄/三欄/sidebar 閱讀順序 1.0。兩個已知缺口(footnote 與 caption 連結)蓄意保留為 failed,不調門檻掩蓋。
  • OCR 選配不混料documa[ocr](RapidOCR,CPU)處理掃描件;所有 OCR 產物標記 origin: "ocr" 與信心值,永不冒充原生文字。
  • 索引皆可拋棄重建:collection index(SQLite FTS5)與 retrieval sidecar 都是版本化衍生物,來源真相只在 IR + registry。

什麼時候不該用 Documa

  • 文件很短(幾頁以內)而且只問一次——直接塞 context 更簡單,前置處理不划算。
  • 你需要語義相似檢索(同義改寫、跨語言概念對齊)——Documa 檢索是 lexical/statistical 的;它預留了 hybrid/vector adapter 邊界,但目前不內建 embeddings。
  • 你要的是視覺/版面渲染判斷(「第 3 頁有沒有蓋章」)、完整 UI 文件管理系統,或生產級 OCR 產品。
  • 你只要最底層的 PDF 文字抽取,且已滿意 PyMuPDF / pdfplumber。

升級注意(v0.5.0)

  • v0.5.0 前建立的 collection index 與 search sidecar 會被 documa doctor --store-dir 標為 stale,首次搜尋前請 documa index-collection 重建(或重跑 process)。
  • 工具回應形狀有 breaking 變更:搜尋列移除 read_ref/ir_document_id/bbox_refs(讀取對=document_id + block_id)、block_tree 預設不含 per-node citation、空欄位不再序列化。細節見 CHANGELOG

深入閱讀

主題 位置
架構分層與各 stage 演進 docs/documa/architecture.md
IR 相容性契約 docs/spec/ir-compatibility.md
Gold 標註格式與品質門檻 fixtures/pdf/gold/README.md
Token 經濟 benchmark benchmarks/token_economy/
Plugin 安裝與 skill plugins/README.md

開發與測試

python -m pip install -e ".[dev,documents,mcp]"
python -m pytest                      # 全套(含 snapshot 回歸)
documa doctor                         # 環境診斷
documa benchmark --mode quality       # gold 品質計分

Snapshot 回歸測試把 3 份真實 PDF 的完整 pipeline 輸出與 golden files 比對;只有「預期內的輸出變更」才能 pytest --force-regen 重建,且 commit 訊息必須說明原因。

新增 parser adapter:在 src/documa/adapters/ 實作並於 registry.py 註冊副檔名,adapter 只回傳 IR、不外洩 parser 原生物件。新增 public tool:同步更新 interfaces/tools.pytool_schemas.pymcp_server.pycli.py 與測試。

License

MIT.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

documa-0.5.0-py3-none-any.whl (187.4 kB view details)

Uploaded Python 3

File details

Details for the file documa-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: documa-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 187.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for documa-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 eb0ce9d8a442d4f54a21069daf773084a4c2728c2c4ee97135576d83509b4a3d
MD5 22d2d22e30dd60d66750ff6dedcbb550
BLAKE2b-256 77e03936c254b3e4184da11109ecc0f86fea8461a376a516d7432ede55d9175a

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page