huggingface_hub 是 Hugging Face 生態系統的 Python 客戶端核心。transformers、datasets、diffusers、sentence-transformers 等數十個函式庫都依賴它與 Hub 進行溝通。每當我們沒有發布新版本,就意味著修復和新功能會停留在主分支上,無法及時釋出。
長期以來,我們大約每 4 到 6 週發布一次。現在,我們透過單一的 GitHub Actions 工作流程,實現了每週發布。我們使用開源工具和開源權重模型來建構這套系統,並在需要判斷力的關鍵環節保留了人工審核。
這篇文章中提到的任何部分,都不需要供應商合約、閉源模型或您無法自行運行的基礎設施。這從一開始就是我們的設計目標,因為我們希望這套工作流程能被其他維護者採用和調整。讀完這篇文章,您將擁有建構自己系統所需的一切。
我們從何開始
舊有的發布流程部分自動化,但大部分仍需手動操作。在持續整合 (CI) 方面,我們已經實現了:一旦標籤被推送,就發布到 PyPI;為下游函式庫開啟測試分支,並鎖定發布候選版本。
然而,每次發布仍需手動完成以下步驟:建立發布分支、在 __init__.py 中提升版本號、提交、標記、推送;監控下游 CI 運行並分類失敗;閱讀自上次發布以來合併的所有合併請求 (PR),並手動撰寫發布說明,這些說明需要按主題分組、提供上下文,並以非 Git 日誌傾印的方式呈現。
此外,還需要:在發布候選版本 (RC) 期間結束後,進行穩定版本發布;草擬內部 Slack 公告和社群貼文;開啟發布後的 PR,將主分支版本提升到下一個 dev0。撰寫新版本的良好發布說明是其中最繁重的工作,需要整合數十個不同主題的 PR。
這項工作在技術上並不困難,但需要數小時的專注。再加上公告的準備,一個次要版本發布輕易地就會變成耗時半天的工作,而且分散在好幾天內完成。
兩種工作
因此,我們決定簡化整個流程。檢視上述清單,工作可以分為兩類。有些步驟純粹是機械性的,可以自動化:提升版本號、提交、標記、推送、開啟下游測試分支、開啟發布後的 PR。這些步驟無需人工思考,只需每次按正確順序執行,這正是 CI 工作流程所擅長的。
其餘的工作則不同。撰寫發布說明、決定要強調的內容、為人類受眾撰寫公告:這些都是腦力工作。正是這種判斷力,使得發布流程多年來一直保持手動。這正是 AI 發揮作用的地方,它能在幾秒鐘內將空白頁面變成紮實的初稿。這也是我們必須謹慎的地方,因為一份看起來自信卻隱含錯誤的草稿,比完全沒有草稿還要糟糕。
設計原則:開放部件,人人可用
當我們決定改進這個問題時,我們預設了一個限制:每個可動部件都必須是任何維護者都能自行運行的。不能是我們無法替換的閉源 API 模型,不能是專有發布平台,也不能有任何秘密配方。
以下是整個技術堆疊:GitHub Actions 負責協調整個發布流程;OpenCode 作為驅動模型的代理程式執行環境;一個開源權重模型(目前是 Z.ai 的 GLM-5.2)負責草擬發布說明和 Slack 公告;HF Inference Providers 提供模型服務;PyPI Trusted Publishing 負責發布套件。
第二個原則是:模型起草,人工決定。語言模型擅長將三十個簡潔的 PR 標題轉化為可讀的發布說明,但它們不適合被盲目信任。因此,工作流程是人工監督的:模型完成初稿,確定性腳本檢查其工作,然後人工在發布前進行審閱和編輯(詳見下文)。
流程導覽
完整的工作流程是一個單一檔案,位於 .github/workflows/release.yml,透過 Actions UI 手動觸發。它只接受一個輸入:release_type,選項包括 minor-prerelease(從主分支發布 RC)、minor-release(將 RC 提升為最終版本)和 patch-release(在現有發布分支上進行錯誤修復)。
從那裡開始,各個任務大致按以下順序運行:準備階段,計算下一個版本,建立或重用發布分支,提升 __version__,提交,標記,推送。接著是發布到 PyPI,建構並上傳 huggingface_hub,同時建構並上傳 hf CLI 作為其獨立的 PyPI 套件。
然後是發布說明,比較自上次標籤以來的提交範圍,從 GitHub API 提取 PR 元數據,並讓模型草擬結構化的變更日誌(這是一個最近的範例),並儲存為 GitHub 發布草稿。對於 RC 版本,會開啟 transformers、datasets、diffusers、sentence-transformers 中的測試分支,並鎖定 RC 版本,以便它們的 CI 能快速告知我們是否造成了任何問題。
接著是 Slack 公告,閱讀發布說明並以團隊語氣產生內部公告。然後是歸檔說明,將 AI 的原始草稿和人工編輯版本並排上傳到 Hugging Face Bucket。穩定版本發布後,會開啟一個 PR 到主分支,將版本提升到下一個 dev0。
最後,在每個發布中的 PR 上留下「此版本已在 vX.Y.Z 中發布」的評論,並開啟一個 PR 到我們的技能儲存庫,其中包含重新生成的 hf CLI 技能文件。每個步驟都會將其狀態作為執行緒回覆發布,最後一個任務會用 ✅ 或 ❌ 更新根訊息。
剩餘的手動步驟是審閱和發布發布說明草稿,以及審閱和發布內部 Slack 訊息。這兩個步驟正是我們希望人工參與的環節。
信任但驗證:人工審核的核心
每個人都擔心 AI 生成發布說明的失敗模式:模型悄悄地遺漏了一個 PR,或者憑空捏造了一個不在本次發布中的 PR。一個幾乎正確的變更日誌比沒有變更日誌更糟糕,因為沒有人會重新檢查它。
我們不信任生成出的發布說明在第一次嘗試時就是完整的,我們會透過確定性方法進行驗證。在模型運行之前,一個 Python 腳本會檢索屬於該發布的所有 PR,並將它們儲存為真實數據。
腳本會從提交範圍內的壓縮合併提交中提取 PR 編號,並將其儲存為真實來源。然後模型根據這些 PR 草擬說明。完成後,我們會將其輸出與初始的 PR 清單進行檢查:預期的 PR 集合與模型寫出的 PR 集合進行比較,找出遺漏的 PR(被悄悄遺漏)和多餘的 PR(屬於不同發布)。
如果發現任何遺漏或多餘的 PR,我們不會讓流程失敗,也不會發布錯誤的檔案。我們會將差異交還給代理程式,並要求它精確地修復這些 PR。這個模式使得整個系統值得信賴:一個非確定性模型被確定性防護機制所包裝。模型擅長撰寫散文,但在窮盡性方面不可靠。因此,我們讓它撰寫,並讓程式碼來強制執行一致性。
讓模型有所依據,避免憑空捏造
完整性是一方面,準確性是另一方面。一個僅憑標題摘要 PR 的模型,可能會愉快地編造出與實際 API 不符的程式碼範例。為防止這種情況,當我們獲取 PR 元數據時,也會從每個 PR 中提取實際的文件差異:任何 PR 觸及的 docs/ 目錄下的 .md 檔案的統一差異。
這個差異會被納入模型的上下文,這樣當它寫下「這是新的 CLI 命令」時,它引用的是 PR 作者實際在文件中寫的範例。這與之前的邏輯相同:給模型真實的原始資料和一個狹窄的任務。提示詞本身以「技能」的形式存在:儲存庫中包含的 Markdown 檔案(SKILL.md 加上參考模板)。發布說明技能會詳細說明如何選擇重點、如何組織章節、何時添加文件連結等。它讀起來就像入職說明,這正是正確的心智模型。
人工檢查點
RC 發布後,GitHub 發布草稿會包含 AI 的初稿。這就是人工介入的地方:審閱者閱讀草稿,編輯語氣和重點,修正模型過度或不足強調的任何內容。只有在那之後,他們才會觸發 minor-release 運行,將 RC 提升為最終版本。
審閱者的時間用於潤飾,將半天的寫作工作轉變為十五分鐘的編輯會話。我們還保留了記錄,以便隨著時間改進。我們將兩個檔案並排歸檔到 Hugging Face Bucket:AI 的原始草稿(在 RC 發布時上傳,未經人工修改)和人工編輯版本(在最終版本發布時上傳)。
每週收集這兩份檔案,為我們提供了一個不斷增長的數據集,記錄了「模型寫了什麼」與「我們希望它寫什麼」。這個數據集隨後可以用來更新代理程式的技能。
開放且安全的管道
改進發布流程也是一個加強安全性的好機會,特別是針對供應鏈攻擊。我們不使用 PyPI 權杖。發布使用信任發布 (Trusted Publishing):PyPI 驗證 GitHub 為此工作流程鑄造的短期 OIDC 權杖,並為每個構件發布 PEP 740 證明 / Sigstore 出處證明。沒有長期存在的密鑰會洩漏或需要輪換。
代理程式執行環境被鎖定並驗證。我們不會隨意下載最新版本的 OpenCode。我們會鎖定一個版本並在運行前檢查其 SHA256 雜湊值。開放工具並不意味著粗心大意。
成本如何?
幾乎沒有成本。一次完整的發布(發布說明加上 Slack 公告,涉及 20-40 個 PR 和幾輪提示)在 Inference Providers 上大約花費 0.25 美元。由於開源權重模型是按用量付費,每週唯一真正的問題是「是否有值得發布的東西?」,而答案總是肯定的。
實際上的變化
發布節奏從每 4 到 6 週一次變為每週一次。次要影響則更有趣:發布說明變得更好,而不是更糟。初稿總是存在,因此審閱時間用於潤飾。分組更一致,遺漏的內容也更少。問題更早浮現。每個 RC 上的下游測試分支在候選版本期間就能捕捉到整合問題。貢獻者循環縮短了。
自動化的「已在 vX.Y.Z 中發布」評論比我們預期的更重要。當有人在已關閉的 PR 上報告問題時,每個人都可以立即看到修復在哪個版本中。這以前需要手動搜尋標籤。
讓它成為您的
這是我們最關心的部分。這個工作流程是圍繞 huggingface_hub 設計的,但其結構是通用的。幾乎可以原封不動地重複使用:觸發器和版本管理...(文章在此處結束)

