模型 / 資料集
undertheseanlp/underthesea avatar
undertheseanlp/underthesea

underthesea v9.3 之後:越南語 NLP 套件長出了 Agent 層

Underthesea - AI Assistant

1,808 個 Star307 個 ForkPythonApache-2.0

秒懂

它是什麼?
同一個 pip 套件裡同時有越南語斷詞與多供應商 AI Agent。這篇看的是它的機制、安裝路徑,以及把 Agent 放進正式服務時會踩到的地方。
適合誰用?
如果你要處理越南語語料,同時想在同一個依賴裡跑 LLM Agent,underthesea 值得先做一次概念驗證:用 pip install underthesea 裝起來,跑一次 agent("Hello!") 確認供應商金鑰與網路可通,再檢查 ~/.underthesea/traces/ 是否真的寫出 JSON 追蹤檔。若你只需要越南語斷詞,不需要 Agent 那一層,這個套件仍然可用,但要接受它會一併帶進 agent 子模組。
可以商用嗎?
可以。Apache-2.0 是寬鬆授權:你可以使用、修改並販售以它為基礎的軟體,只需保留著作權與授權聲明。
還在維護嗎?
有在維護。儲存庫最近一次提交在 1 天前。
用什麼語言寫的?
主要是 Python(依據 GitHub 的語言統計)。

以上回答依據專案的 GitHub 資料(最近同步於 2026年9月15日)與我們的分析,不構成法律意見。

開源專案深度解析

一個套件、兩種身分:越南語斷詞與 Agent 工具包

underthesea 原本是越南語自然語言處理工具,README 開頭仍保留這個定位。轉折點寫得很明確:自 v9.3.0 起,它同時是 open-source Agentic AI Toolkit,並內建越南語 NLP 能力。這個雙重身分決定了它的適用範圍。對做越南語資料的人來說,斷詞、詞性這類模組本來就在套件裡;對做 Agent 的人來說,這裡多了一個不需要額外安裝 openai、anthropic 或 google-genai 的選項。

它要解決的問題其實是依賴膨脹。多數 Agent 框架會把供應商 SDK 當成必要條件,SDK 再拉進 httpx、pydantic 等一串套件。underthesea 選擇反過來做:只用 Python 標準庫的 urllib 與 json 直接呼叫 LLM API。README 用「zero external dependencies」描述這件事。代價是它必須自己維護四家供應商的請求格式,一旦對方改動 API,更新責任就落在這個專案身上。

受眾因此被切得很窄。已經在用越南語 NLP、又想在同一個 requirements 裡跑 Agent 的團隊最合適;單純想找通用 Agent 框架的人,這裡沒有他們要的東西。

供應商抽象怎麼寫:四個類別加一個自動偵測

Agent 的建構方式是 Agent(name=..., provider=...)。provider 參數接受 OpenAI、AzureOpenAI、Anthropic、Gemini 四個類別,或是不帶參數的 LLM()。README 說明這些類別各自獨立,並註明跟隨 Anthropic SDK 的用戶端模式。

LLM() 的行為是從環境變數自動偵測。文件列出的變數有四組:OPENAI_API_KEY、AZURE_OPENAI_API_KEY 搭配 AZURE_OPENAI_ENDPOINT、ANTHROPIC_API_KEY、GOOGLE_API_KEY。這代表部署時你可以完全不改程式碼,只換環境變數就切換供應商。對於要在不同區域或不同成本方案之間切換的服務,這是有用的設計。

要注意的是 Azure 那條路徑多一個參數。AzureOpenAI 需要 api_key、endpoint 與 deployment 三者,deployment 對應你部署的模型名稱。README 的範例用 gpt-4。這與其他三家只給金鑰的做法不同,因為 Azure 的模型是部署單位而非帳號層級資源。

至於「zero external dependencies」的邊界,README 講的是 Agent 與 LLM 通訊這一段。後面會看到,A2A 伺服器與 Langfuse 追蹤都各自需要額外安裝。

工具呼叫與 12 個內建工具:方便與風險是同一件事

工具用 Tool() 包裝 Python 函式後放進 tools 列表。README 的範例是一個 get_weather(location) 函式,回傳 dict,Agent 收到「Hanoi 天氣如何」之後呼叫它,再把結果轉成自然語言回答。函式的 docstring 顯然會被當成工具描述使用,範例裡的 """Get current weather for a location.""" 就是這個用途。

除了自訂工具,套件提供 default_tools,README 列出 12 個內建工具,涵蓋 calculator、datetime、web search、wikipedia、file I/O、shell、python exec。這份清單值得停下來看兩秒。file I/O、shell 與 python exec 意味著模型可以在你的執行環境裡讀寫檔案、執行指令與執行程式碼。這在本地實驗或沙箱容器裡沒問題,在共用主機或持有正式憑證的環境裡就是一個需要明確處理的攻擊面。README 沒有描述權限控管或確認機制,採用前應該先確認這些工具在目標版本裡的實際行為。

串流是另一條路徑。agent.stream(...) 回傳可迭代的片段,範例用 print(chunk, end="", flush=True) 逐段輸出。串流與工具呼叫是否能在同一次呼叫中並用,README 沒有示範,這點需要自行驗證。

Session 與長期任務:把上下文重置寫成流程

長時任務的處理方式集中在 Session。建立方式是 Session(agent, progress_file="progress.json"),接著用 create_task 給定任務名稱與步驟列表,再以 run_until_complete(max_sessions=5) 執行。

這個設計的核心是進度落地。progress_file 指向一個 JSON 檔,任務步驟被拆開後逐項推進,每次 session 結束時把狀態寫出去。README 說明它遵循 Anthropic 關於 long-running agents 的 harness 模式,重點在於上下文重置與結構化交接。換句話說,它不試圖把整段對話塞進同一個上下文視窗,而是讓每次重啟都從檔案讀回進度。

max_sessions 這個參數是必要的安全閥。沒有它,任務可能無限迴圈;有了它,超過上限的行為就變成你要自己處理的失敗路徑。README 沒有說明超過 max_sessions 之後會發生什麼,是丟出例外、回傳未完成狀態,還是靜默停止。這是採用前應該在測試環境確認的具體問題。

create_task 的步驟列表是純文字描述,不是可執行的計畫。模型如何把「Read and classify documents」對應到實際工具呼叫,取決於 instruction 與模型本身,文件沒有提供保證。

追蹤預設開啟,而且會寫進家目錄

每一次 Agent 呼叫都會自動產生追蹤,輸出到 ~/.underthesea/traces/。README 的範例輸出顯示一次兩輪的工具呼叫被記成 [a1b2c3] 這樣的短識別碼,底下展開 generation 與 tool 兩種 span,附帶模型名稱、耗時與 token 進出量,最後落到一個以日期命名的 JSON 檔,例如 20260411_trace_a1b2c3.json。

關閉方式是設定環境變數 UNDERTHESEA_TRACE_DISABLED=1。把追蹤設為預設開啟是一個明確的立場:開發階段你不需要記得開它,就能事後檢視延遲與 token 消耗。反過來說,在容器或 CI 環境裡,這些檔案會落在執行使用者的家目錄。如果你的環境對寫入位置有規範,或家目錄是唯讀的,這件事需要先處理。

若要送到外部觀測平台,可以傳入 tracer=LangfuseTracer(),這需要另外 pip install langfuse。另外有 @trace 裝飾器搭配 LocalTracer,README 說明嵌套函式會變成子 span,且內部建立的 Agent 會自動繼承追蹤上下文。這是把既有函式流程接進追蹤的方式,不必改動 Agent 的建構。

README 沒有交代追蹤檔的保留策略或清理機制。長期執行會累積檔案,這是維運上要自己決定的事。

A2A 伺服器:裸 ASGI,自帶聊天介面

v9.5.0 這個版本的標題就是 A2A Agent Server。作法是 from underthesea.agent.server import serve,然後 serve(agent, port=8000, path="/a2a/math", ui=True)。README 列出三個端點:GET /a2a/math/ui 是內附的聊天介面,GET /a2a/math/.well-known/agent-card.json 是可被發現的 AgentCard,POST /a2a/math 走 JSON-RPC 的 message/stream,以 HTTP 加 SSE 傳輸。

基礎安裝不含 web 框架。README 明確說伺服器是 raw ASGI app,沒有 web-framework 依賴,你可以掛到任何 ASGI 伺服器上。要方便一點可以裝 underthesea[agent-server] 這個 extra,內容是 uvicorn、starlette 與 httpx。若需要自訂路由,用 make_app(agent, path="/a2a/math") 取得 ASGI callable,註解寫著可以搭配 uvicorn module:app 或 hypercorn module:app。

README 把 A2A 協定連結指向 google-agentic-commerce/AP2 這個倉庫。這個連結與「A2A」這個名稱的對應關係,文件沒有進一步說明,實作時應以 agent-card.json 的實際輸出為準。

另外,把 Agent 以 HTTP 暴露出去,等於把前面提到的 default_tools 一併暴露。serve 的範例只用了自訂的 add 工具,這是保守的做法,值得照著做。

什麼時候不該用它

第一種情況是你需要供應商 SDK 的完整表面。以 urllib 自行實作代表只涵蓋基本的 chat 與串流路徑。官方 SDK 的 beta 功能、細緻的重試與退避策略、完整的串流事件型別,這裡不會有。若你的系統已經圍繞官方 SDK 建構,多一層抽象只會增加除錯難度。

第二種情況是你的環境不允許寫入家目錄,或禁止模型觸發 shell 與程式碼執行。default_tools 的內容讓這個套件在受管制環境裡需要額外隔離,而 README 沒有提供對應的權限設定說明。

第三種情況是你不需要越南語。越南語 NLP 是這個專案與其他 Agent 工具包的主要差異點。拿掉這一項,你面對的就是一個自行維護四家供應商相容層的輕量框架,而市面上的替代品在生態與範例數量上更成熟。

第四種情況是版本節奏。從釋出紀錄看,v9.3.0、v9.4.0 在同一天發布,v9.5.0 在一個月後推出。Agent 相關 API 仍在快速變動期,把它放進需要長期穩定介面的核心路徑會有升級成本。

替代方案與授權:差異在依賴策略

最直接的替代是供應商官方 SDK,例如 openai 或 anthropic 套件。差異不在功能多寡,而在依賴策略:官方 SDK 由供應商維護,API 變動時你跟著升級;underthesea 由社群維護,四家供應商的相容性由這個專案承擔。若你的服務只綁定一家供應商,官方 SDK 是更短的路徑。若你需要的是同一份程式碼在四家之間切換,underthesea 的 LLM() 自動偵測確實省掉一層自寫的抽象。

另一個角度是越南語工具鏈。若你只需要斷詞,可以只使用 underthesea 的 NLP 模組,不碰 agent 子模組。但要注意安裝是整體的:pip install underthesea 會把兩部分一起帶進來。

授權是 Apache-2.0。這是一個寬鬆授權,允許商業使用與修改,同時包含專利授權條款。實務上要注意的是散布時的聲明義務,以及修改過的檔案需要標註變更。README 沒有提供額外的授權例外或商業條款說明。此處不構成法律意見,涉及對外散布時請自行確認條款全文。

維護成本方面,README 提到 30 位贊助者。這反映專案有社群支持,但贊助人數不等於長期維護承諾。真正該看的是版本節奏與 API 穩定度,而這兩項從現有資料看都還在變動中。

編輯結論

如果你要處理越南語語料,同時想在同一個依賴裡跑 LLM Agent,underthesea 值得先做一次概念驗證:用 pip install underthesea 裝起來,跑一次 agent("Hello!") 確認供應商金鑰與網路可通,再檢查 ~/.underthesea/traces/ 是否真的寫出 JSON 追蹤檔。若你只需要越南語斷詞,不需要 Agent 那一層,這個套件仍然可用,但要接受它會一併帶進 agent 子模組。若你的服務依賴 OpenAI 或 Anthropic 官方 SDK 的完整功能(例如特定的 beta 端點、內建重試策略、串流事件型別),underthesea 以 urllib 自行實作的用戶端不會涵蓋這些,請直接使用官方 SDK。上線前務必確認三件事:你的供應商是否在 OpenAI、Azure OpenAI、Anthropic、Gemini 四者之內;default_tools 裡的 shell 與 python exec 是否會被模型觸發;以及 Apache-2.0 授權下你對外散布時的聲明義務。

官方來源

  1. License: Apache-2.0
  2. Project website
  3. README
  4. Releases
  5. undertheseanlp/underthesea on GitHub
社群筆記

社群筆記