DocETL:用 YAML 或 Python 宣告式管線處理非結構化資料,以及它不適合的場景
A system for agentic LLM-powered data processing and ETL
秒懂
- 它是什麼?
- DocETL 把 map、reduce、filter 等 LLM 操作包成宣告式運算子,並附上自動改寫最佳化(MOAR)。它解決的是「大量文件逐筆呼叫 LLM」的工程瑣事,代價是管線行為取決於模型與提示詞,除錯方式與傳統 ETL 不同。
- 適合誰用?
- 若你手上是數千到數萬份文件、要做的是分類、抽取、彙總這類可用自然語言描述的操作,而且願意接受「結果隨模型版本浮動」這件事,DocETL 的宣告式管線能省下大量樣板程式碼;反之,若你需要逐筆可重現的稽核紀錄、或處理的是低延遲的線上請求,它的批次與最佳化取向就不合適。採用前先確認三件事:docetl.default_model 與 rate_limits 在你的供應商配額下是否可行、pipeline.show() 在 5 份文件上的輸出是否符合預期、以及 MIT 授權下你自行外掛的 LLM 供應商條款。
- 可以商用嗎?
- 可以。MIT 是寬鬆授權:你可以使用、修改並販售以它為基礎的軟體,只需保留著作權與授權聲明。
- 還在維護嗎?
- 有在維護。儲存庫最近一次提交在 10 天前。
- 用什麼語言寫的?
- 主要是 Python(依據 GitHub 的語言統計)。
以上回答依據專案的 GitHub 資料(最近同步於 2026年9月15日)與我們的分析,不構成法律意見。
開源專案深度解析
DocETL 要解的不是 ETL,而是「每份文件都要問一次模型」的工程瑣事
傳統 ETL 的瓶頸在 I/O 與格式轉換,DocETL 的瓶頸在推論。README 開頭把問題講得很直白:如果沒有這層框架,你得自己寫每一次 LLM 呼叫、自己把它們接起來、再手動調整準確率、成本與延遲。這句話點出了目標使用者的輪廓。
它服務的是手上有文件集合、但不想把管線邏輯寫死在 Python 迴圈裡的人。README 給的例子是客服工單:先分類每張工單的類別與優先級,再依類別彙總。這種「先逐筆、再分組」的形狀,正好對應 map 與 reduce 兩個運算子。
值得注意的是它的輸入不限於純文字。README 描述的是「大型資料集合(結構化與非結構化)」,而運算子清單裡除了 map、filter、reduce 之外還有 resolve、split、gather、extract。resolve 這類運算子的存在,暗示它預期資料裡有需要對齊或去重的實體,而不只是把文字丟給模型摘要。
誰不該用?如果你的「非結構化資料」其實只有幾百筆,寫個 for 迴圈呼叫 API 可能比學一套 DSL 更快。DocETL 的價值隨資料量與管線複雜度上升,資料量小的時候,抽象層的成本大於收益。
管線的實際形狀:算子鏈、schema 推導與 collect 的執行邊界
從 README 的 Python 範例可以讀出執行模型。docetl.read_json("tickets.json") 建立一個 pipeline 物件,接著一連串的 .map() 與 .reduce() 呼叫是逐步疊加算子,而不是立即執行。真正的執行發生在最後:pipeline.collect() 才是完整跑一遍。
中間有兩個診斷用的方法。pipeline.schema() 回傳輸出欄位的型別,README 的範例註解顯示結果是 {'category': 'str', 'summary': 'str'}。pipeline.show() 則是在 5 份文件上試跑並印出結果。這個「先看 5 筆、再全跑」的節奏是刻意的,因為全跑的成本與時間都不小。
成本是可觀測的:pipeline.total_cost 以美元計價,README 範例直接把它格式化輸出。這表示框架在內部累計了 token 用量與對應價格,你不需要自己接帳。
提示詞用的是模板語法。map 的 prompt 寫成 "Classify this support ticket: {{ input.text }}",reduce 的 prompt 則用了 Jinja 風格的迴圈:{% for t in inputs %}{{ t.text }}{% endfor %}。這意味著 reduce 的輸入是一組同鍵的記錄,而不是單一文件。
至於平行化,README 只說它「orchestrates them, parallelizing work across your data」,沒有說明背後的排程器或並行模型。實際的並行度、重試策略與失敗處理,README 沒有交代,需要查文件或看原始碼才能確認。
兩種入口:Python API 與 YAML,以及 Claude Code 這條第三條路
安裝只有一行:pip install docetl,然後設定供應商金鑰,例如 export OPENAI_API_KEY=your_key。README 註明也可以是任何 LLM 供應商的 key,但沒有列出支援清單。
Python API 被標為 recommended,理由是適合 production code、notebook 與腳本。設定全域狀態的方式是直接賦值:docetl.default_model = "gpt-4o-mini",以及 docetl.rate_limits 這個字典。後者的結構值得注意,鍵是 "llm_call" 與 "llm_tokens",值是帶有 count、per、unit 三個欄位的清單。範例設定為每分鐘 500 次呼叫與每分鐘 20 萬 token。這是把供應商的速率限制內建到排程層,避免你被 429 打回來。
YAML 路線走的是同一個抽象,只是換成檔案。config 裡有 datasets 區塊宣告資料來源(type: file、path: tickets.json)、default_model、operations 清單,以及 pipeline.steps 把輸入與運算子串起來,最後由 output 指定寫出位置。執行指令是 docetl run pipeline.yaml。
第三條路是 docetl install-skill,README 標為 recommended,搭配 Claude Code 使用:執行後用自然語言描述任務,讓工具替你生出管線。不想裝 Claude Code 的話,README 提供另一個做法,把 docetl.org/llms-full.txt 的提示詞複製到 ChatGPT 或 Claude 對話裡。這是把「寫管線」這件事本身也交給 LLM,對不熟 DSL 的人是捷徑,代價是你得看得懂它生出來的東西。
互動式開發則有 DocWrangler,可以線上試(docetl.org/playground)或在本機跑。README 沒有給本機啟動的指令,只連到 playground 設定文件。
MOAR 與自動改寫:省成本的手段,也是可重現性的來源
README 對最佳化的描述相當具體:它會自動「swapping models, rewriting prompts, decomposing operations, and replacing subtasks with code wherever possible」。這四件事分別對應不同的成本結構。換模型與改寫提示詞影響準確率與單價;拆解操作會改變呼叫次數;把子任務換成程式碼則可能完全省掉推論。
這套機制在論文中名為 MOAR(Multi-Objective Agentic Rewrites for Unstructured Data Processing),README 引用的是 VLDB 2026 的論文,作者群包含 Wei 與 Shankar 等人。DocETL 本身則對應 VLDB 2025 的論文,標題提到 agentic query rewriting 與 evaluation。
這裡有個必須講清楚的張力。當框架會為了成本與準確率自動改寫你的提示詞、甚至替換模型,同一份管線設定在不同時間跑出來的結果就可能不同。對一次性分析這無所謂,對需要逐筆稽核的場景則是問題。README 沒有說明最佳化是否可關閉、是否有固定隨機種子、或改寫後的提示詞是否會被保存下來供人檢視。這幾點在採用前必須自己確認。
另一個現實限制是評估。自動最佳化要「raise accuracy」,前提是它知道準確率是多少,這通常需要標註資料或某種評估訊號。README 沒有交代評估資料從何而來、需要多少筆。如果評估機制不透明,你很難判斷最佳化後的管線是真的變好,還是只是迎合了某個代理指標。
什麼時候 DocETL 是錯的工具
第一種情況是低延遲的線上請求。DocETL 的設計圍繞批次處理:平行化、速率限制、成本累計、最佳化,這些都是為了跑完一大批資料。如果你要的是單一使用者請求進來、幾百毫秒內回覆,這層框架的每個設計選擇都在跟你作對。
第二種是結果必須逐位元可重現的場景。管線的行為取決於模型版本與提示詞,而 README 描述的 MOAR 還會主動改寫提示詞與替換模型。即使你固定 default_model,供應商端的模型更新也不在你的控制範圍內。
第三種是資料本身高度結構化、轉換規則明確。如果欄位對應關係可以用 SQL 表達,用 LLM 去做只是把確定性的轉換換成機率性的推論,同時引入成本與不確定性。README 自己也把適用範圍寫成「結構化與非結構化」並存,但真正需要這層框架的是後者。
還有一個容易被忽略的成本:YAML 路線的除錯體驗。當管線是一份 YAML,錯誤發生在提示詞模板還是運算子串接,從錯誤訊息不一定看得出來。Python API 至少還有 traceback 可循。這也是 README 把 Python API 標為 recommended 的原因之一,儘管它同時提供了 low-code 路線。
替代方案:LangChain 與 LlamaIndex 的差異在抽象層的位置
同樣處理 LLM 資料管線的專案裡,LangChain 與 LlamaIndex 是最常被拿來對比的。差別不在功能清單,而在抽象層擺放的位置。
LangChain 的核心是鏈與代理的組合,你組裝的是「元件」:提示詞模板、模型、輸出解析器、檢索器,然後把它們接起來。控制權在你手上,彈性大,代價是你得自己決定平行化、速率限制與成本追蹤怎麼做。DocETL 把這些當成框架職責,你宣告的是「做什麼」,不是「怎麼接」。
LlamaIndex 的重心在檢索與索引,主要回答的是「怎麼把文件餵進模型」這個問題,索引、切塊、查詢引擎是它的強項。DocETL 對檢索著墨不多,它的運算子清單裡沒有向量索引這類原語,重點放在對整份文件集合做轉換與彙總。
所以選擇的判準是:如果你的問題是「從大量文件裡找到相關段落再回答」,LlamaIndex 的抽象更貼合;如果你要的是「對每份文件做同一件事,然後按鍵彙總」,DocETL 的 map 與 reduce 更直接。而如果你需要對每個步驟做細緻控制、或要接進既有的非 LLM 元件,LangChain 的元件組合模式會比宣告式管線更容易塞進既有架構。
DocETL 的差異化在於它把「最佳化」也納入框架職責,這是另外兩者沒有直接對應的東西。但這也意味著你多了一層需要理解與信任的黑箱。
維護成本、授權與版本節奏
授權是 MIT,寬鬆,允許商業使用與修改,README 的 badge 也標明 MIT。這部分不需要法律意見,但要注意的是:DocETL 本身是 MIT,你接上的 LLM 供應商不是。你的管線會把資料送到第三方 API,資料處理條款取決於供應商,與 DocETL 的授權無關。
版本節奏可以從 release 紀錄看出輪廓。0.2.5 在 2025 年 8 月,0.2.6 在 2025 年 12 月,0.3.0 在 2026 年 6 月。前兩次是 patch 層級,間隔約四個月;0.3.0 是 minor 版本,距離前一個 patch 約半年。這個節奏意味著 API 大致穩定,但 minor 版本仍可能帶來行為變化,鎖定版本再升級是合理的做法。
開發者路線在 README 有寫:git clone 之後 make install,然後 make tests-basic,並註明成本低於 0.01 美元(用 OpenAI)。這個測試成本數字對想貢獻或想驗證環境的人是實用的資訊。
需要留意的是,README 沒有提供版本相容性政策、棄用時程或 changelog 的連結。當 0.3.0 這類 minor 版本出現時,你只能從 release note 或原始碼差異去判斷影響範圍。對於把 DocETL 放進生產管線的團隊,這代表升級前需要先在自己的資料上跑一遍 pipeline.show(),比對輸出是否一致。
最後,專案由 UC Berkeley 的 EPIC Data Lab 與 Data Systems and Foundations 團隊建立,並有對應的學術論文支撐,這通常意味著設計有明確的問題意識,但不保證長期的維護承諾。README 沒有提到商業支援或維護者規模,這點在評估長期依賴時是空白。
編輯結論
若你手上是數千到數萬份文件、要做的是分類、抽取、彙總這類可用自然語言描述的操作,而且願意接受「結果隨模型版本浮動」這件事,DocETL 的宣告式管線能省下大量樣板程式碼;反之,若你需要逐筆可重現的稽核紀錄、或處理的是低延遲的線上請求,它的批次與最佳化取向就不合適。採用前先確認三件事:docetl.default_model 與 rate_limits 在你的供應商配額下是否可行、pipeline.show() 在 5 份文件上的輸出是否符合預期、以及 MIT 授權下你自行外掛的 LLM 供應商條款。
社群筆記