WorkForge 训练环境起不来 / 该先查依赖还是任务配置?

文章导读
WorkForge 训练环境起不来时,先判断报错停在哪一层,再决定改依赖还是改任务配置。启动过程通常分三段:解释器导入依赖包 → 解析任务配置文件 → 进入训练入口初始化。报错停在导入期,多是依赖缺失或版本不匹配;停在配置解析、字段校验阶段,多是任务配置字段名、类型或必填项不对;如果日志里还没开始导入就报找不到模块或文件,优先怀疑运行入口(解释器、工作目录、启动脚本路径)不对。建议先用一个空任务把
📋 目录
  1. 一 在启动日志里找到第一条报错
  2. 二 用最小空任务排除依赖问题
  3. 三 逐项核对任务配置字段与类型
  4. 四 确认运行入口与依赖版本一致
  5. 五 把复现命令与报错原文固定下来
A A

WorkForge 训练环境起不来时,先判断报错停在哪一层,再决定改依赖还是改任务配置。启动过程通常分三段:解释器导入依赖包 → 解析任务配置文件 → 进入训练入口初始化。报错停在导入期,多是依赖缺失或版本不匹配;停在配置解析、字段校验阶段,多是任务配置字段名、类型或必填项不对;如果日志里还没开始导入就报找不到模块或文件,优先怀疑运行入口(解释器、工作目录、启动脚本路径)不对。建议先用一个空任务把三层切开,再逐项核对,而不是反复重装依赖。

适用场景:启动 WorkForge 时只看到一段报错,判断不了该改依赖还是该改任务配置。操作动作:先读启动日志的第一条报错做分层,再用最小空任务跑一次;空任务跑通说明问题在任务配置,空任务同样失败说明问题在依赖或运行入口。验证方式:每次只改一处,跑一次,比对新报错是否前移或消失。风险边界:这套分层的依据是完整日志,若包装脚本吞掉异常、只留最后一行,要先把完整 traceback 输出到控制台再判断。

在启动日志里找到第一条报错

日志从上往下读,先定位第一个 Traceback (most recent call last),而不是直接看最后一行。最后一行只是异常类型和消息,往往是最终表现;如果中间出现「During handling of the above exception, another exception occurred」,后一段通常是外层包装代码重新抛出的结果,根因在前一段。比较实用的判断方式是:看第一条 traceback 里第一帧落在哪个文件——落在依赖包的 import 阶段,偏依赖问题;落在项目自己的配置加载或参数校验函数里,偏任务配置问题。

报错位置典型消息样式优先怀疑第一步动作
依赖导入阶段ModuleNotFoundError、ImportError、cannot import name、版本不兼容提示依赖缺失或版本不匹配用同一解释器单独执行该 import 验证
配置解析阶段KeyError、TypeError: expected str ... not int、字段校验失败、NoneType 相关任务配置字段错打开任务配置文件逐字段核对
入口与路径阶段No module named 'workforge'、FileNotFoundError 指向配置路径、命令不存在解释器或工作目录不对核对解释器路径与当前目录

用最小空任务排除依赖问题

目的是把「环境坏」和「配置错」分开。写一个字段最少、不引用外部数据的空任务配置,用与正式启动完全相同的解释器和命令跑一遍。下面只是骨架,字段名和层级按你仓库实际的任务 schema 替换,不要直接照抄。

# minimal_task.yaml
task_name: minimal_check
seed: 0
model: {}
data: {}
train: {}

启动命令同样按实际入口替换模块名和子命令,例如:

python -c "import sys; print(sys.executable, sys.version)"
python -m workforge.cli train `--config` minimal_task.yaml

空任务跑通代表:依赖能导入、运行入口可达、配置加载链路本身正常,问题收敛到具体的任务配置文件上;空任务也报同样的错,说明是依赖或运行入口,此时不要再去改任务配置字段,改了也验证不了效果。

WorkForge 训练环境起不来 / 该先查依赖还是任务配置?

逐项核对任务配置字段与类型

字段级错误有比较明显的样式:数值字段写成字符串会报 ValueError: invalid literal for int() with base 10;路径字段塞了数字会报 TypeError: expected str, bytes or os.PathLike object, not int;必填字段漏写或拼错,表现为 KeyError: 'xxx';布尔值写成字符串 "false",多数解析器会当成真值而不报错,属于静默走偏。逐字段自查可以按下面顺序过一遍:

  • 字段名与 schema 或示例配置完全一致,注意下划线与连字符、单复数。
  • 类型正确:int、float、str、list、dict、bool,尤其列表里元素的类型。
  • 必填项是否齐全,可选项是否用了正确默认值而不是留空。
  • 相对路径的基准目录是哪个,是仓库根目录还是配置文件所在目录。
  • 枚举值大小写与合法取值是否匹配。
  • 嵌套层级和缩进是否正确,YAML 缩进错位经常表现为字段「消失」。

确认运行入口与依赖版本一致

在错误的解释器或错误的目录下启动,最典型的表现是「依赖明明装过,却一直导入失败」。先确认当前用的是哪个解释器,再看依赖装在哪:

which python
python -c "import sys; print(sys.executable)"
python -m pip show <依赖包名>
python -c "import workforge; print(workforge.__file__)"

入口脚本路径要一起核对:用 ls -l $(which workforge) 看它的 shebang 指向哪个解释器;用上一行的 __file__ 输出确认导入的是仓库源码目录,还是另一个环境里残留的安装副本,两者混用会出现「代码改了但行为没变」。同时确认当前工作目录在仓库根目录,配置里的相对路径才按预期解析。

把复现命令与报错原文固定下来

排查过程中改动会累积,如果没有固定记录,很难判断是改对了还是错位了。一份最小复现记录建议包含:完整的启动命令与执行时的工作目录;解释器绝对路径与版本;关键依赖的版本号;任务配置文件名与最近一次修改;从第一条 traceback 起点到最后一行的报错原文,完整粘贴而不要只摘最后一句;以及改动前后的命令和输出对照。把这份记录写进 issue 或仓库里的排查笔记,每改一处配置就跑一次并追加一条,看报错是消失、前移到别的阶段,还是原样不动——报错位置前移,往往说明上一层的判断是对的。