跳到正文
北京时间
原文
Hugging Face:Blog(RSS)·· 2026-06-23精选AI 评分67

huggingface_hub 实现每周发布:AI、开源工具、人工审核闭环

Shipping huggingface_hub every week with AI, open tools, and a human in the loop

AI 导读

Hugging Face 将 huggingface_hub 的发布周期从每 4‑6 周缩短至每周,全部由单个 GitHub Actions 工作流自动完成。流程依赖开源工具和开权重模型(当前为 Z.ai 的 GLM‑5.2)来起草发布说明和 Slack 公告,但保留人类在最终审核环节的决定权。自动步骤包括版本号更新、提交标签推送、PyPI 发布、下游测试分支创建、发布说明草稿、Slack 公告草稿、归档、后置版本提升以及对合入 PR 的评论。所有组件均基于开源生态构建,任何维护者都可直接复制使用。

推荐理由

Hugging Face 把周更流程完全开源,用 GLM-5.2 生成发布说明初稿,再加确定性校验和人工修订,成本低到两毛五一次。想提高发版频率的 Python 库维护者可以直接 fork 适配。

正文 · AI 翻译

是 Hugging Face 生态体系底层的 Python 客户端。

transformers

datasets

diffusers

sentence-transformers

以及数十个其他库都依赖它与 Hub 通信。我们每少发布一个新版本一周,就意味着有一周的修复和功能被卡在

main

在很长一段时间里,我们每 4 到 6 周发布一次。现在我们通过单个 GitHub Actions 工作流每周发布。我们使用开源工具和开放权重模型来构建它,并在唯一真正需要判断力的环节保留了人工介入。本文中的任何内容都不需要供应商合同、闭源模型,或者你无法自行运行的基础设施。这从一开始就是一个设计目标,因为我们希望其他维护者能够直接采用并加以调整。

读完本文,你将拥有构建自己工作流所需的一切。

我们最初的起点

旧流程部分自动化,但主要靠人工。

已经在 CI 中的:

  • 推送 tag 后发布到 PyPI。
  • 在下游库中打开测试分支,并固定使用候选发布版本。

每一次都仍然是手动操作:

  • 创建发布分支,在 __init__.py 中提升版本号,提交、打标签、推送。
  • 盯着下游 CI 运行并分诊失败。
  • 通读自上次发布以来合并的每一个 PR,并手写发布说明:按主题分组,带有背景信息,语气读起来不像是一堆 git log 的堆砌。
  • 在 RC 周期结束后切出稳定版本。
  • 起草内部 Slack 公告和社交媒体帖子。
  • 打开发布后的 PR,将 main 提升到下一个 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 手动触发。它只接受一个输入:

on:
  workflow_dispatch:
    inputs:
      release_type:
        type: choice
        options:
          - minor-prerelease   
          - minor-release      
          - 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。
  • 发布后版本更新。 在稳定版本发布后,在 main 上打开一个 PR,将其更新到下一个 dev0。
  • 在已发布的 PR 上评论。 在该发布中的每个 PR 上留下一条"此内容已在 vX.Y.Z 中发布"的评论。
  • 同步 CLI 文档。 向我们的 skills 仓库提交一个 PR,包含重新生成的 hf CLI 技能文档。
  • 报告到 Slack。 每个步骤都会以线程回复的形式发布其状态;最后一个任务会用 ✅ 或 ❌ 更新根消息。

剩余的手动步骤是审核并发布草稿版发布说明,以及审核并发布一条内部 Slack 消息。这两个步骤正是我们希望有人参与其中的环节。

信任但验证:人在环路的核心

以下是大家对 AI 生成的发布说明所担心的失败模式:模型悄悄漏掉了一个 PR,或者凭空捏造了一个并不属于本次发布的 PR。一份几乎正确的变更日志比没有变更日志更糟糕,因为没有人会再去复核它。

我们并不信任生成的发布说明第一次就能做到完整,而是以确定性的方式对其进行验证。在模型运行之前,一个 Python 脚本会检索属于本次发布的所有 PR,并将它们存储为基准真值。


PR_NUMBER_PATTERN = re.compile(r"\(#(\d+)\)$")

pr_numbers = [
    int(m.group(1))
    for commit in commits_since_last_tag
    if (m := PR_NUMBER_PATTERN.search(commit.title))
]
save_manifest(pr_numbers)  

然后模型根据它们起草发布说明。完成后,我们会将其输出与最初的 PR 列表进行核对:

expected = set(load_manifest())          
found    = extract_pr_refs(notes_md)     

missing = expected - found               
extra   = found - expected               

如果有任何遗漏或多余,我们不会失败,也不会交付一份错误的文件。我们会把差异交还给智能体,并要求它精确修复那些 PR:

for _ in range(MAX_ITERATIONS):
    missing, extra = validate(notes)
    if not missing and not extra:
        break  
    run_agent_fix(missing_prs=missing, extra_prs=extra)

这正是让整件事变得可信的模式:一个非确定性的模型被包裹在确定性的护栏之中。模型擅长撰写文字,但在做到穷尽无遗方面并不可靠。所以我们让它来写,让代码来强制保证一致性。

为模型提供依据,使其不会凭空捏造

完整性只是一半,准确性是另一半。一个仅凭标题就总结 PR 的模型,会兴高采烈地编造出一个与真实 API 不符的代码示例。

为防止这种情况,我们在获取 PR 元数据时,还会从每个 PR 中拉取实际的文档差异:即任何.md位于以下路径下的文件docs/的 PR 所改动内容的统一 diff。

def fetch_doc_diffs(pr):
    return [
        {"filename": f.filename, "status": f.status, "patch": f.patch}
        for f in pr.get_files()
        if f.filename.startswith("docs/") and f.filename.endswith(".md") and f.patch
    ]

这个 diff 会进入模型的上下文,因此当它写出“这是新的 CLI 命令”时,它引用的是 PR 作者实际写在文档中的示例。这和之前的逻辑一样:给模型真实的源材料和一项范围明确的任务。

提示词本身以 Skills 的形式存在:一些小型 Markdown 文件(SKILL.md 加上参考模板)签入到仓库中。release-notes 技能明确规定了如何挑选亮点、如何组织章节、何时添加文档链接等。它读起来就像入职指引,而这正是恰当的心智模型。

人工检查点

RC 发布后,GitHub release 草稿就摆在那里,里面是 AI 的第一版内容。这时就该人工介入了:

  1. 审阅者阅读草稿,调整语气和重点,修正模型权重过高或过低的内容。
  2. 只有在这之后,他们才会触发 minor-release 运行,将 RC 提升为正式版本。

审阅者的时间花在打磨上,把半天的写作变成十五分钟的编辑。

我们还保留书面记录,以便随时间推移不断改进。我们将两个文件并排归档到 Hugging Face Bucket:原始 AI 草稿,在 RC 阶段、任何人触碰之前上传;以及人工编辑版本,在正式发布时上传。


hf cp release_notes_raw.txt    "hf://buckets/huggingface/releases/huggingface_hub/${V}/release_notes_raw.txt"


hf cp release_notes_edited.txt "hf://buckets/huggingface/releases/huggingface_hub/${V}/release_notes_edited.txt"

每周收集这两者,就为我们积累了一个不断增长的数据集,记录“模型写了什么”与“我们希望它写了什么”的对比。这个数据集随后可以用来更新智能体的技能。

开放且安全的管道

改造发布流程是加强安全性的好机会,尤其是防范供应链攻击。

无需 PyPI token。发布使用 Trusted Publishing:PyPI 验证由 GitHub 为此确切工作流签发的短期 OIDC token,并为每个制品签发 PEP 740 认证 / Sigstore 来源证明。不存在可泄露或需要轮换的长期密钥。

permissions:
  id-token: write       
  attestations: write   

- uses: pypa/gh-action-pypi-publish@v1.14.0
  with:
    attestations: true  

智能体运行时是固定版本并经过验证的。我们不会curl | bash最新的 OpenCode 然后碰运气。我们会固定一个版本,并在运行前校验其 SHA256:

curl -fsSL https://opencode.ai/install | bash -s -- --version "${OPENCODE_VERSION}"
echo "${OPENCODE_SHA256}  $(which opencode)" | sha256sum -c -

开放的工具链并不意味着粗心的工具链。

那么,它花了多少钱?

几乎不花钱。一次完整发布(发布说明加上 Slack 公告,涉及 20-40 个 PR 和几轮提示词)在 Inference Providers 上大约花费 $0.25。开放权重按用量付费计费,每周唯一真正的问题是"有没有值得发布的东西?",而答案总是有。

实践中发生了什么变化

发布节奏从每 4 到 6 周一次变成了每周一次。更有意思的是那些次生效应:

  • 发布说明变得更好了,而不是更差。初稿总是现成的,所以审查时间都用在打磨上。分组更一致,我们遗漏的东西也更少。
  • 故障更早暴露。每个 RC 上的下游测试分支都会在候选窗口期内捕获集成问题。
  • 贡献者循环缩短了。 自动的"已在 vX.Y.Z 中发布"评论,其重要性超出了我们的预期。当有人在已关闭的 PR 上报告问题时,所有人都能立即看到修复包含在哪个版本中。过去这需要手动翻找标签。

让它成为你自己的

这是我最关心的部分。工作流是围绕 huggingface_hub 构建的,但其结构是通用的。

几乎可以原样复用:

  • 触发器和版本号递增逻辑(minor-prerelease 然后 minor-release 然后 patch-release)。
  • 信任但验证的循环:确定性清单、模型草稿、验证、重新提示。这是可迁移的思路,与你生成什么内容无关。
  • OIDC 可信发布、固定并经过校验和验证的运行时、Slack 线程。
  • 基于技能的提示词:替换模板,保留结构。

我们特有的:

  • 下游仓库列表及其依赖固定格式。
  • 技能中确切的章节分类和语气。
  • Slack 和 bucket 目标。

要适配它:fork workflow 文件和脚本,将其指向你的包,为你的项目风格重写技能 Markdown,设置两个仓库变量(模型 ID 和你的 OpenCode 版本),在 PyPI 上设置 Trusted Publishing,如果你没有下游就删除下游测试任务。信任但验证的循环是值得原样复用的部分。正是它让生成的产物可以安全发布。

下一步

  • 自动分诊下游故障。目前该工作流会打开测试分支,由人工阅读 CI。一个显而易见的下一步是检查失败的日志,以便在内部 Slack 消息中报告它们。
  • 扩展这一模式。其中大部分是通用的。我们预计会在生态系统中其他 Python 库中复用很大一部分。

要点

发布流程中那些过去需要人类半天专注工作的部分(撰写说明、起草公告、协调下游检查),正是模型擅长起草的部分。其余一切都是机械性的,可以放进一个 YAML 文件。诀窍从来不只是“让 AI 来做”。而是让模型起草,让确定性代码验证,让人来做决定。它完全由开放工具和开放权重构建,因此成本几乎为零,任何人都可以运行它。

完整的工作流文件已公开。如果你维护着一个 Python 库,fork 它,按需调整,并告诉我们效果如何!

来源:Hugging Face:Blog(RSS) · huggingface.co