用AI agent自动化fork维护 | Cohere
Automating fork maintenance with AI agents | Cohere
Cohere 团队提出一种基于 AI agent 的通用方法,将维护软件 fork 与上游同步的反馈循环自动化。该方法将循环分解为扰动注入、测量收集和控制器三个组件,每个组件由 agent skill 自动化。应用于 vLLM fork 的案例中,agent 自动将自定义提交 rebase 到新上游版本 v0.19.1,通过运行 Cohere 的 ASR 模型正确性测试检测回归(WER 从 11.92 升至 100),诊断出 transformers 版本升级导致的 tokenizer 行为变化并自动修复,最终将吸收新版本所需时间从数周压缩至数天。相关 skill 已在 cohere-ai/vllm-skills 开源。
你维护着一个 fork。上游在演进。你同步代码,然后出问题,你修复,验证,发布。几周后,上游又变了。这个循环周而复始。
这篇文章描述了一种使用 AI 编码 agent 来自动化这个循环的通用方法。我们将其应用于 vLLM 的 fork,通过一个具体案例来演示:一次常规的上游发布静默地破坏了我们 fork 中 Cohere 的 cohere-transcribe-03-2026 ASR 模型,而修复方案最终以 vLLM PR 的形式回流到了上游。
在实践中,这种方法将吸收新上游版本所需的时间从数周压缩到了数天,人类只需审查最终结果。驱动此工作流的技能已在 cohere-ai/vllm-skills 开源。
问题所在
维护一个活跃开发项目的长期 fork 是一项持续的成本。但上游版本也带来了你想要的特性、性能改进和 bug 修复。保持同步不仅仅是维护,更是让 fork 持续变得更好的方式。问题在于,每个上游版本也都会引入一个扰动:合并冲突、API 变更、函数移除、新依赖或测试失败。fork 维护者的工作就是吸收这个扰动,并恢复到一个可工作的状态。
这项工作的结构始终如一:
- 同步:将新的上游版本合并到 fork 中。
- 测量:通过运行测试、基准测试、评估来查看哪些地方出了问题。
- 修复:解决冲突,适配 API 变更,更新测试。
- 重复:重复步骤 2 和 3,直到所有测试通过。
- 发布:更新后的 fork。
这是一个反馈循环。每个维护 fork 的团队都存在这个循环;只是它缓慢且手动。对于我们的 vLLM fork,吸收一个典型的上游版本过去需要开发人员断断续续投入数周时间,而下面描述的工作目标是将其缩短到数天,主要由 agent 自主运行。
反馈系统
在控制理论中,闭环系统会持续比较其输出与参考值,并进行调整以缩小差距。但真实系统也面临扰动:将系统推离期望状态的外部输入。

- r(t) 是参考值,即系统应产生的期望值。
- y(t) 是输出,即系统产生的实际值。
- e(t) 是误差,即参考值与测量值之间的差距,计算公式为 r(t) − measured_output。
- d(t) 是扰动,作用于系统并将输出推离参考值的外部力量。
控制器利用误差来调整系统;反馈使输出更接近目标。一个设计良好的反馈循环不仅仅是跟踪参考值;它通过检测扰动对输出的影响,并在无需人工干预的情况下将误差驱回零,从而抑制扰动。
巡航控制是教科书式的例子。你设定一个期望速度(参考值),汽车维持这个速度(系统),但遇到上坡或逆风(扰动)。一个好的控制器会注意到速度下降并自动调整油门。
Fork 维护具有完全相同的结构。

r(t), 参考值
自定义更改在最新上游上正确工作
d(t), 扰动
新的上游版本:冲突、API 变更、破坏性更改
控制器
解决冲突、更新补丁、修复测试
系统
Fork 本身(代码、测试、CI)
y(t), 输出
同步后 fork 的运行时行为
测量
测试套件、基准测试、评估
目标是自动化整个循环——同步、测量、修复、重复——这样我们就能以最少的人工干预吸收上游的改进。
我们之前的流程
有几种方法可以将 fork 与上游同步:merge、cherry-pick 和 rebase 是最常见的。Merge 保留了双方的历史,但会产生混乱的提交图,难以区分自定义更改和上游更改。Cherry-pick 提供了精确的控制,但当上游每个版本移动数百个提交时,它无法扩展;你最终会维护一个不断增长且容易不同步的 pick 列表。Rebase 将你的自定义提交在新的上游标签之上重放,产生一个干净、线性的历史,你的补丁清晰地位于顶部。权衡之处在于 rebase 会重写历史并强制 force-push,但对于一个在快速演进的上游之上只有少量自定义提交的 fork 来说,这种清晰性是值得的。
在 Cohere,我们很早就确定了使用 rebase。在下面描述的基于 agent 的工作流之前,我们的流水线已经混合了脚本化自动化和手动工作。
- Rebase: 一个 GitHub Actions 工作流尝试 rebase 到目标上游标签,从共享的
git rerere缓存中重放之前解决过的冲突。 - 解决冲突: 当工作流的自动 rebase 失败时,开发人员在本地接手,手动解决剩余的冲突(通常借助 LLM 助手),验证 CI,并上传更新后的 rerere 缓存。
- 验证并发布: 一旦 rebase 后的分支在 CI 上通过,它就成为 fork 的新基础。
这个流程已经结合了多种自动化:git rerere 重放已知的解决方案,GitHub Actions 运行 rebase 尝试和 CI,LLM 协助处理单个编码和调试任务。但人类仍然是控制器的一部分,负责拼接各个部分,选择应用哪些修复,并决定何时重新运行。反馈循环是有效的;只是转得慢。下面描述的基于 agent 的工作流保持了相同的结构,但让 agent 扮演控制器的角色,因此迭代以机器速度进行,人类只在边缘进行干预。
自动化每个组件
该方法将循环分解为三个可由 agent 自动化的组件。每个组件都对应控制图的一部分。
1. 扰动注入
一个 agent skill 检测并应用新的上游版本。它将 fork rebase 到新标签上,并自动解决合并冲突。这就是进入系统的扰动:一个故意的、自动化的操作,我们知道它会暂时破坏一些东西,但我们希望尽可能快地吸收它。
该 skill 需要:
- 检测 fork 当前基于哪个上游标签
- 检查是否存在更新的标签
- 使用 fork 的自定义提交执行
git rebase --onto - 解决冲突(利用上游 diff 上下文做出明智的决策)
2. 测量收集
Rebase 之后,fork 处于未知状态。测量告诉你离目标有多远:一个所有自定义行为都完好的工作 fork。没有它,agent 就是在盲目飞行。
测量本身(测试、基准测试、评估)由项目定义,并且在任何自动化之前就已经存在。Agent 自动化的是收集它们:一个测试运行器 skill,知道如何设置环境、执行验证套件并报告结果。
- 测试:单元测试、集成测试和正确性测试
- 基准测试:性能检查(吞吐量、延迟、资源使用)
- 评估:特定领域的质量指标(准确率、困惑度、任务分数)
输出是误差信号:哪些测试失败,哪些基准测试回归,哪些评估指标下降。测量越丰富、越可靠,控制器收敛得越快。测试套件薄弱的 fork 给出的信号很弱;agent 不知道哪里出了问题,也不知道离完成还有多远。
3. 控制器
一个 agent skill 负责闭环。在 rebase 完成且测量结果返回后,该 skill:
- 读取测试和基准测试结果
- 识别失败和回归
- 应用修复(解决构建错误、更新损坏的测试、适配 API 变更)
- 重新运行测量
- 重复直到所有测量通过,或升级给人类处理
这就是将误差驱向零的控制器。关键洞察在于,agent 不需要在第一次尝试时就正确完成 rebase,它只需要迭代——就像开发人员一样。
案例研究:vLLM
vLLM 是一个开源的 LLM 服务引擎。在 Cohere,我们在推理栈的各个层面使用它,从模型开发期间的 RL rollout 和评估,到生产环境中服务用户请求。我们维护一个 fork 来承载自定义提交——额外的模型支持、自定义 kernel 和优化、修改的入口点、额外的测试——其中一些正在向上游提交,另一些则是我们特有的需求。挑战在于将这些提交重放到每个新的上游版本上而不破坏任何东西。上游大约每隔几周发布一个版本,每个版本都很大:标签之间的 diff 通常涉及数百个文件。
Skill 栈
我们构建了五个 skill,已在 cohere-ai/vllm-skills 开源,它们实例化了这个通用模式。每个 skill 都是一个 markdown 文档,编码 agent 可以读取并交互式执行,并可以访问终端、文件系统和所需的工具。
install-vllm
环境设置
创建一个 uv virtualenv,以可编辑模式安装 vLLM,并附带正确的预编译 CUDA wheel
local-test-runner
测量
在本地 NVIDIA GPU 上运行等效于 Buildkite CI 的测试;解析 .buildkite/test_areas/*.yaml,管理 HuggingFace token,捕获日志
detect-upstream-base
扰动检测
通过 git merge-base + git describe 找到 fork 当前基于的上游标签 (v1)
rebase-assistant
控制器
将自定义提交从 v1 rebase 到 v2,使用上游 diff 作为上下文解决冲突,通过 test-runner 验证结果
Rebase 如何运行
在本节中:v1 / v2 是旧的和新的上游标签,b1 / b2 是 rebase 前后的 fork 分支。
一个典型的调用:"/auto-rebase sync 当前分支与最新的上游版本,并确保 <test> 通过。"
auto-rebase 检查先决条件(
gh auth status),然后调用 detect-upstream-base 找到 v1(例如v0.19.0)。它获取上游标签并发现 v2(
v0.19.1)。它向用户展示版本并等待确认。它从用户那里收集验证检查(例如
pytest tests/entrypoints/openai/correctness/test_transcription_api_correctness.py)。它调用 rebase-assistant,该 assistant:
- 分析 b1 上的自定义提交(
git log v1..HEAD) - 首先验证测试在 b1 上通过(使用 local-test-runner 和 v1 wheel),这是确保我们有一个已知良好基线的门控
- 备份 b1,创建 b2,可选地压缩自定义提交
- 运行
git rebase --onto upstream/v0.19.1 <fork-point> HEAD - 通过比较
upstream/v1..upstream/v2的 diff 来理解发生了什么变化,从而解决冲突 - 在 b2 上运行测试(使用 local-test-runner 和 v2 wheel)
- 如果测试失败:检查失败原因,与 v1 基线比较,应用修复,并重新运行(内部反馈循环)
- 分析 b1 上的自定义提交(
一旦所有检查通过,auto-rebase 呈现一个摘要(重放的提交、解决的冲突、测试结果)并提供推送选项。
作为一系列 skill 交互:
内部循环是控制器在 b2 上迭代:local-test-runner 报告失败,rebase-assistant 应用修复并重新运行,直到测试通过。
工作示例:v0.19.1 上的 Cohere Transcribe
以下是这个循环的一次真实调用,端到端。
设置: 我们的 fork 位于 cohere-transcribe-v0.19.0,在上游 v0.19.0 之上有一个自定义提交,该提交启用了 Cohere 的 cohere-transcribe-03-2026 ASR 模型的正确性测试。vLLM 在 v0.19.0 中添加了对该模型架构的支持,但上游测试被注释掉了,因为权重尚未发布。我们的自定义提交只是取消注释了一行。
# TODO (ekagra): turn on after asr release
# CohereASR is used to test the variable encoder length code paths
("CohereLabs/cohere-transcribe-03-2026", 11.92),
该测试在 earnings-22 验证集的一个过滤切片上运行模型,并断言 WER ≤ 11.92。这个单一数字就是我们的测量信号 y(t)。当 fork 健康时,该数字接近 11.92;当出现问题时,它会飙升。
扰动: 上游发布了 v0.19.1。这是一个增量版本,但并不小:它包括一个 transformers 版本升级和相关的重构。我们用一个 prompt 运行 auto-rebase。
/auto-rebase let's sync current branch with latest upstream release,
make sure the test CohereLabs/cohere-transcribe-03-2026 passes
@tests/entrypoints/openai/correctness/test_transcription_api_correctness.py:172-173
结果:
- 将自定义提交 rebase 到
v0.19.1并在 b2 上重新运行测试后,结果返回 WER = 100——完全失败,模型输出垃圾内容。 - 控制器循环诊断了回归:rebase-assistant 比较了
upstream/v0.19.0..upstream/v0.19.1的 diff,将失败追溯到升级的transformers版本,该版本改变了模型 tokenizer 处理其 prompt 前缀的方式,并应用了一个快速修复来绕过它。WER 恢复到 ~11.92,fork 在v0.19.1上通过,整个过程在一个交互式会话内完成。
循环端到端地工作:扰动到来,控制器吸收它,fork 自动恢复到健康状态。
后续: 由于该 bug 影响了该模型的每个下游用户,我们提交了 vllm-project/vllm#40582 将变通方案转化为一个合适的上游修复。一旦合并,下一个版本将不再需要为此模型打 fork 补丁;扰动对所有人都消失了。
超越 vLLM
每当一个代码库吸收外部变更并需要收敛回工作状态时,同样的闭环结构都适用。
另一个最近的例子是我们内部维护的 HuggingFace transformers fork,我们在其公开发布之前维护着 command-a-plus-05-2026。当 transformers v5 发布,移除了废弃参数、引入了新的必需签名、改变了 tokenizer 行为时,所有这些就是扰动。应用了相同的循环:升级到 v5,运行模型的正确性评估和生成测试,让 agent 在失败上迭代。在导入路径、API 调用和 tokenizer 默认值方面出现了几个问题;有些被自主修复,另一些需要人类介入解决。循环持续进行,直到模型在公开发布前在 v5 上正确生成。
Skill 不同,但结构相同:引入变更,测量差距,闭环。
结论
Fork 维护的结构不会改变:同步、测量、修复、重复。改变的是循环转动的速度。
在基于 agent 的工作流之前,将我们的 vLLM fork 与新的上游版本同步需要数周:等待某人切换上下文、手动分类冲突、重新运行 CI、一次一个地调试失败。通过 auto-rebase 驱动控制器循环,这个时间线已经压缩到了数天。而且由于预期的测量已预先设置在仓库中,整个流水线无需人工输入即可运行;只需要一个人审查最终结果。
该方法适用于任何具有可测量“工作”定义的 fork:检测扰动,收集测量,让 agent 在误差上迭代。这些 skill 是可组合的,控制理论的框架使其易于适应新的代码库。
本文中描述的 skill 已在 cohere-ai/vllm-skills 开源。如果你维护一个 fork 并想尝试这种方法,首先编写一个测量(测试、基准测试、评估)来捕获对你 fork 而言“健康”的含义。循环的其余部分由此展开。
致谢
感谢 Ekagra Ranjan 协助 Cohere Transcribe 实验,感谢 Zhoujie Zhao 和 Walter Beller-Morales 帮助塑造 agent skill,感谢 Bharat Venkitesh 支持这项工作。