本篇讨论内容已经发布在 transformers 社区:Why can’t transformers be decoupled?

本文主要提出笔者对于 transformers 目前项目架构的一些疑惑,以及对 python 包管理机制的一些吐槽。笔者由于对于 python 和 ai 方面并不是非常熟悉,因此可能会有一些考虑不周甚至错误的地方,还请各位指正。

步入正题,最近在进行一些将模型代码合并进 transformers 仓库 的工作,碰到了诸多问题。当一些接手这个项目时,我就很疑惑:为什么 transformers 的耦合度这么高?我不理解,为什么所有模型都要提交代码到 transformers 的仓库中。这样显而易见地会出现一个常见且严重的问题:版本管理。

试想一下,你在 transformers=4.43 的环境下完成了你的所有实验和代码工作,现在你要申请合并进 transformers 仓库,此时 transformers 的版本为 4.53,一些方法和实现做出了改变,你将花费大量的精力去适配新版本的实现,其中还可能出现一些 break changes 导致无法正常的合入。

上面的场景是十分合理且常见的,除了最基础的库以外,更严重的是你可以会依赖一些基础模型的实现,如 llama、qwen 等。我认为这些模型是不会也不应该对自己具体实现的任何修改所负责(仅仅保证自己可用,无需关注是否有其他模型调用了自己的方法),如果他们在某些方法中进行了改变,你将很难甚至无法去适配(这也是我当前所遇到的问题)。你的代码在 transformers=4.43 时一切正常,而在 transformers=4.53 时一切都将崩溃,你无能为力,因为在目前条件下你只能向 master 版本去合并代码。

那么问题来了,为什么不将 transformers 的实现解耦呢?transformers 官方只需要维护一个 transformers-core 仓库,该仓库提供一系列基础的方法和调用。当新模型适配时可以选择去适配指定版本的 transformers-core,他将发布一个新的包名字叫做 transformers-new-model。相应地,在使用时也可以指定使用如 transformers-qwen=4.43。这样只需要所有人在自己的代码库中遵循 transformers 的写法规则并保证版本号的正确,一切都将会工作正常,同时也将不会有上述的依赖问题出现。

所以呢,为什么不这么做呢,是还有哪些我没考虑到潜在因素吗?

另外地,倘若 python 有一个良好的机制可以解决依赖冲突(如 java 的 maven 中的 exclude),上述方法也将会变得更加灵活。


在上面社区的讨论中有人给出了一些transformers 的设计哲学 相关的文章和讨论,对于这些观点我只能说有些赞同有些却并不合适:

  1. 为每个模型设置独立的代码仓库,会让阅读代码的人更方便,而且对一个仓库的修改不会破坏其他模型的代码。
  2. 把所有必要的代码都放在一个文件里真的能提高可读性吗?似乎并非如此。一个 5000 行的文件终究比一个 500 行的文件更难读。合理的抽象才是真正提升可读性的关键。
  3. “Machine Learning models are static” 事实真的如此吗?我目前遇到程序错误,恰恰就是因为 Llama 重构了它的代码。在这一点上,有些观点和我一致:依赖方无需考虑更新兼容性。但我们不应该假设用户不会修改他们的代码。相反,我认为我们应该提前针对这类修改采取预防措施,即:独立的版本管理。

说实话,我对single file policy没有异议。我认为不合适的是把所有模型代码都放进一个仓库的做法。或许更独立一些会更好,比如采用single repo policy