用 AI、开放工具和人工审核,每周发布 huggingface_hub

huggingface_hub 是 Hugging Face 生态底层的 Python 客户端。transformers、datasets、diffusers、sentence-transformers 等数十个库依赖它与 Hub 通信。每多等一周才发布,就意味着修复与功能继续滞留在 main 上。

长期以来,原作者所在的 Hugging Face 团队每隔4到6周发布一次。现在只需一套 GitHub Actions 工作流,就能每周发布。Hugging Face 团队使用开源工具和开放权重模型搭建流程,并在判断最重要的环节保留人工审核。本文中的方案无需供应商合同、封闭模型或无法自行运行的基础设施。Hugging Face 团队从一开始就希望其他维护者能够取用并调整这套流程。

读完本文,你将具备构建自己发布流程所需的全部信息。

Hugging Face 团队的起点

旧流程部分自动化,但主要依靠手工操作。

已经在 CI 中完成的工作:

  • 推送标签后发布到 PyPI。
  • 在下游库中创建测试分支,将依赖固定为候选发布版本。

每次仍需手工完成的工作:

  • 创建发布分支,修改 __init__.py 中的版本号,提交、打标签并推送。
  • 观察下游 CI 运行,分析和处理失败。
  • 阅读上次发布以来合并的所有 PR,手写发布说明:按主题分组、补充背景,让语气不像直接倾倒 Git 日志。
  • 在 RC 阶段结束后发布稳定版。
  • 起草内部 Slack 公告与社交媒体帖子。
  • 在发布之后创建 PR,将 main 的版本提升为下一个 dev0。

写好一个新版本的发布说明是最费力的部分,需要汇总不同主题的数十个 PR。这在技术上并不难,却需要数小时专注。加上公告,一次次要版本发布很容易消耗半天工作,而且分散在数天里。

两类工作

Hugging Face 团队决定精简整个流程。从上述列表来看,工作可分为两类。

一些步骤纯属机械操作,可以自动化:提升版本、提交、打标签、推送、创建下游测试分支、创建发布后 PR。它们不需要人工思考,只需每次按正确顺序执行,而 CI 工作流正擅长此事。

其他步骤则不同。撰写发布说明、选择突出内容、面向读者措辞公告,都需要判断。这些工作使发布流程多年来保持手动。AI 可以在数秒内将空白页面变为扎实的初稿;但也必须小心,因为看起来很自信、却存在隐蔽错误的初稿,可能比没有初稿更糟。

设计原则:开放组件,人人可复用

开始改进时,Hugging Face 团队先设下一条约束:所有组件都必须能由维护者自行运行。不依赖无法替换的封闭模型 API、专有发布平台或秘密技术。

完整技术栈如下:

组件 作用
GitHub Actions 编排整个发布流程
OpenCode 驱动模型的代理运行时
开放权重模型,原文使用 Z.ai 的 GLM-5.2 起草发布说明与 Slack 公告
HF Inference Providers 提供模型推理服务
PyPI Trusted Publishing 发布软件包

(OpenCode · GLM-5.2 · HF Inference Providers · PyPI Trusted Publishing)

第二条原则是:模型起草,人工决定。语言模型擅长将三十个简短的 PR 标题整理成可读的发布说明,却不适合被盲目信任。因此,流程由人工监督:模型完成初稿,确定性脚本检查其结果,然后在交付前由人工审阅和编辑。下文将详细介绍。

浏览发布流水线

完整工作流位于单个文件 .github/workflows/release.yml,从 Actions 界面手动触发。它只接受一个输入:(.github/workflows/release.yml)

on:
  workflow_dispatch:
    inputs:
      release_type:
        type: choice
        options:
          - minor-prerelease   # cut an RC from main
          - minor-release      # promote the RC to final
          - patch-release      # bugfix on an existing release branch

随后,各任务大致依次运行:

  • 准备:计算下一个版本,创建或复用发布分支,提升 __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 报告:每一步都将状态作为线程回复发出;最后一个任务用成功或失败标记更新主消息。

剩下的手动步骤是审阅并发布 GitHub 发布说明草稿,以及审阅并发送内部 Slack 消息。这两个步骤正是Hugging Face 团队希望保留人工参与的地方。

信任但验证:人工参与的核心

大家最担忧 AI 发布说明出现的错误是:模型悄悄遗漏某个 PR,或编造一个不属于本次发布的 PR。几乎正确的更新日志甚至比没有更糟,因为读者不会逐项复查。

Hugging Face 团队不相信初次生成的发布说明一定完整,而是进行确定性验证。在运行模型之前,Python 脚本取得本次发布的全部 PR,将其存为事实基准。

# Deterministic: extract PR numbers from squash-merge commits in the range.
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)  # the source of truth

模型基于这些 PR 起草说明。完成后,将输出与最初的 PR 清单比较:

expected = set(load_manifest())          # what should be there
found    = extract_pr_refs(notes_md)     # what the model wrote (#1234 -> 1234)

missing = expected - found               # silently dropped
extra   = found - expected               # belongs to a different release

如果存在遗漏或多出的 PR,不会简单失败,也不会交付错误文件。Hugging Face 团队把差异反馈给代理,要求它只修复这些 PR:

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

这套模式使流程可靠:用确定性的约束包裹非确定性的模型。模型擅长写文字,却无法可靠地穷尽全部项目;因此让模型写作,让代码强制保证一致性。

给模型事实依据,避免凭空编造

完整性是一方面,准确性是另一方面。仅依据 PR 标题总结时,模型可能轻易编造与真实 API 不符的代码示例。

为避免这一点,取得 PR 元数据时,也拉取该 PR 的实际文档差异:docs/ 下所有受影响 .md 文件的 unified 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
    ]

这些差异进入模型上下文。因此模型写“下面是新 CLI 命令”时,引用的是 PR 作者实际写入文档的例子。逻辑与前面相同:提供真实来源材料,并限制模型的任务范围。

提示本身以 Skills 形式存放:提交到仓库的小型 Markdown 文件,包括 SKILL.md 与参考模板。发布说明技能规定如何选重点、组织章节、何时添加文档链接等。它读起来像新人入职说明,这正是适合的理解方式。(技能文件)

人工检查点

发布 RC 后,GitHub 发布草稿中已有 AI 的初次结果。这时由人工介入:

  • 审阅者阅读草稿,调整语气与重点,修正模型过度强调或强调不足的内容。
  • 完成后才触发 minor-release,将 RC 提升为最终版本。

审阅者的时间用于润色,把半天写作变成约十五分钟的编辑。

Hugging Face 团队也保留审计轨迹,持续改进。两个文件并排归档到 Hugging Face Bucket:RC 阶段任何人尚未修改时上传的 AI 原始稿,以及正式发布时上传的人工编辑版。

# at RC time: straight from the model, untouched
hf cp release_notes_raw.txt    "hf://buckets/huggingface/releases/huggingface_hub/${V}/release_notes_raw.txt"

# at release time: after the human review
hf cp release_notes_edited.txt "hf://buckets/huggingface/releases/huggingface_hub/${V}/release_notes_edited.txt"

每周积累两份文件,就得到不断增长的数据集,记录“模型写了什么”与“Hugging Face 团队希望它写什么”的差别,随后可以用它更新代理的技能。

开放而安全的基础流程

重构发布流程也是强化安全的好机会,尤其是防范供应链攻击。

无需 PyPI token。发布使用 Trusted Publishing:PyPI 验证 GitHub 为这个具体工作流签发的短期 OIDC token,并为每项产物生成 PEP 740 证明与 Sigstore 来源证明。不存在需要轮换或可能泄漏的长期密钥。(Trusted Publishing · PEP 740)

permissions:
  id-token: write       # mint the OIDC token for PyPI
  attestations: write   # generate Sigstore provenance
# ...
- uses: pypa/gh-action-pypi-publish@v1.14.0
  with:
    attestations: true  # no password, no API token, just OIDC

代理运行时固定版本并验证。Hugging Face 团队不会直接用 curl | bash 安装最新版 OpenCode 后寄希望于一切正常,而是固定版本,运行前检查 SHA256:

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

采用开放工具,并不意味着可以疏于管理。

成本是多少?

原作者团队报告几乎没有成本。一次完整发布,包括20到40个 PR 的发布说明、Slack 公告与数轮提示,在 Inference Providers 上约花费0.25美元。开放权重模型按用量收费,每周只需考虑“有没有值得交付的内容”,而答案总是有。此费用是原文当时的使用案例。

实践中发生了什么变化

Hugging Face 原作者团队的发布节奏从每4到6周一次变成每周一次。更有意思的是随后出现的效果:

  • 说明质量提升。总有一份初稿,审阅时间因此用于润色;分组更一致,遗漏更少。
  • 破坏性问题更早暴露。每个 RC 的下游测试分支都能在候选阶段捕捉集成问题。
  • 贡献者反馈循环缩短。“已随 vX.Y.Z 发布”的自动评论比预期更有价值:有人在已关闭 PR 中报告问题时,所有人马上能看到修复属于哪个版本,以前还需要手动查标签。

调整为自己的流程

这是Hugging Face 团队最重视的部分。工作流围绕 huggingface_hub 设计,但整体结构通用。

几乎无需修改即可复用的部分:

  • 触发与版本提升逻辑:minor-prerelease、minor-release、patch-release。
  • “信任但验证”循环:确定性清单、模型草稿、验证、重新提示。这个思路可以迁移,不取决于正在生成什么。
  • OIDC Trusted Publishing、固定版本并校验摘要的运行时、Slack 线程。
  • 基于技能的提示:更换模板,保留结构。

属于Hugging Face 团队项目特定内容的部分:

  • 下游仓库列表,以及各仓库固定依赖版本的格式。
  • 技能中的具体章节分类与语气。
  • Slack 与 bucket 的目的地。

调整时,可以 fork 工作流文件和脚本,指向自己的包,改写技能 Markdown 以符合项目语气,设置两个仓库变量(模型 ID 与 OpenCode 版本),在 PyPI 配置 Trusted Publishing;没有下游项目时,删除下游测试任务。最值得原样复用的是“信任但验证”循环,它使生成产物能够可靠交付。(工作流文件 · 脚本 · 技能 Markdown)

下一步

  • 原作者团队希望自动分析下游失败。目前工作流创建测试分支,人工读取 CI。下一步可以检查失败日志,将结果报告在内部 Slack 消息中。
  • 原作者团队希望扩展这一模式。大部分内容通用,预计会在生态中其他 Python 库上复用大量组件。

要点

在原作者团队的实践中,以前需要人工专注半天的发布工作,如写说明、起草公告、协调下游检查,正适合由模型起草;其他机械操作则可以写在 YAML 中。诀窍不只是“交给 AI”,而是模型起草、确定性代码验证、人工决定。整个方案由开放工具与开放权重构建,成本很低,任何人都能运行。

完整工作流已经公开。如果你维护 Python 库,可以 fork、调整它,再向原文作者分享使用情况。(复制并调整工作流)

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容