先把当时的情况摆出来。dspy 3.0,用 BootstrapFewShot 编译分类器,抛 No examples in trainset,实际已经从 json 读了 300 条,过滤之后全被丢掉。
把日志和配置对完,能解释这个现象的基本就这几处。Example 的字段名与 signature 输入不一致。也可能是过滤函数把 label 为空的样本全删了。
还有一种情况,trainset 传成了生成器,遍历一次就空。另外,数据集划分时验证集把训练集全占了。
第一件事是打印第一条样本的字段名
python -c "import dspy;print(list(dspy.Example(question='q',label='a').toDict().keys()))"
随后统计过滤后的条数
python -c "import json;d=json.load(open('train.json'));print(len([x for x in d if x.get('label')]))"
编译前断言训练集非空
python -c "import json;d=json.load(open('train.json'));assert d, 'empty trainset';print(len(d))"
末了用四条 demo 编译一次
python -c "import dspy;from dspy.teleprompt import BootstrapFewShot;print(BootstrapFewShot(max_labeled_demos=4))"
报错是间歇性的,我蹲守了半小时才抓到一次完整现场。
白天有业务在跑,能验证的部分都压到了晚上做。
恢复的判定其实很直接。编译能跑完并产出 4 条 demo,之后调用准确率比零样本高 6 个点以上。
这里还有个坑。DSPy 的报错只说没有样本,不说为什么没有,先核对字段名和过滤条件再怀疑编译器。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。
