Releases: linkerlin/leaves
Release list
v2.4.0: BackendAuto opt-in profiling probe
leaves v2.4.0
主题:BackendAuto 第二轮 — opt-in profiling 探测。
Highlights
tree.ProfileBackend:对实际 workload warm-up + 计时 Native / BornCPU / BornGPU,返回各后端实测 ns/op 与最快推荐。给 BackendAuto 2.0 启发式阈值补上数据驱动选项。- 不破坏 2.0 决策表:
SelectBackendExplained(batch 64/256、稀疏 0.15)行为零变更;profiling 是 opt-in。 - 可解释:结果带 Rule 码(
profile_native|born_cpu|born_gpu|none_ok|invalid)+ 含各后端 ns/op 的 Reason —— 遵守docs/backend-auto.md「任何自动选择必须能被 Rule 码解释」 原则。
Usage
// 用真实批量样本测一遍,拿测量证据替代启发式
res := tree.ProfileBackend(caps, sampleVals, nrows, ncols, 20) // iters 建议 ≥10
fmt.Println(res.Reason)
// "profiling: native fastest at 410 ns/op (native=410 born_cpu=9120 born_gpu=0)"
opts.Backend = res.Pick // 用最快后端
// 也可直接读 res.Native.NsPerOp / res.BornCPU.NsPerOp / res.BornGPU.NsPerOpDesign notes
- 为何 opt-in 而非接入 Auto:profiling 需要代表性批量样本(调用方才知道真实输入),且首调用有计时延迟。强行接入
BackendAuto会引入「样本从哪来」+「首调用延迟」两个难题。故保持 2.0 决策表为默认,profiling 作为需要测量证据时的显式工具。 - 公平性:各后端 nEstimators=0(全量树)、同输入、同 warm-up(2 轮)。
- 安全:Native 始终参与计时(golden 不变);cat-small 森林或无 WebGPU 的后端
Ok=false自动排除。
Verification
TestProfileBackendPicks:Pick 与实测最快一致(断言一致性,非机器相关具体值)。TestProfileBackendInvalid:非法输入 →profile_invalid回落 Native。TestProfileBackendNoBornOnUnsupported:cat-small 森林 → Born 排除、Native 选中。- tree 全量、docs gate、build、6-linter 门禁全绿。
Compatibility
- Breaking:无。新增
ProfileBackend函数 +ProfileResult/BackendTiming类型;既有SelectBackend/SelectBackendExplained不变。
Recommended API
- 默认推理选型:
BackendAuto(2.0 决策表,无需样本) - 数据驱动选型:
ProfileBackend(传样本,拿测量) - 详见
docs/backend-auto.md§第二轮
v2.3.0: complete ONNX graph import via born runtime
leaves v2.3.0
主题:完整 ONNX Graph 导入(复用 born 运行时,原列「明确不做」)。
Highlights
io.LoadOnnxGraph:加载任意 ONNX 模型(30+ 算子,opset 1–21)——复用github.com/born-ml/born/onnx运行时,不在 leaves 重实现算子。- 双路径 ONNX:
LoadONNX(TreeEnsembleRegressor 子集,转 ForestIR,wasm 可用)+LoadOnnxGraph(完整 Graph,born 运行时,非 wasm)互补。 - 化解 born API internal 泄漏:born 公共
onnx.Model接口引用internal/tensor.RawTensor,leaves 经born/tensor.RawTensor公共别名构造张量调用 Forward。
Usage
// 任意 ONNX 模型(NN / 通用图)
data, _ := os.ReadFile("model.onnx")
m, err := io.LoadOnnxGraph(data)
if err != nil { return err }
out, err := m.Predict([]float32{...}) // 单样本前向
fmt.Println(m.InputNames(), m.OutputNames(), m.OpsetVersion())OnnxModel 接口:Predict([]float32) ([]float32, error) + InputNames/OutputNames/OpsetVersion。要求模型恰有 1 输入 / 1 输出(多输入输出需直接用 born onnx.ForwardNamed)。
Design notes
- 复用而非重造:完整 ONNX 算子集(MatMul/Gemm/Conv/Softmax/…)是 born 的领域;leaves 作为 GBRT 库不重实现,直接桥接 born 运行时。
- 平台取舍:born ONNX 运行时为 non-wasm。leaves 的 TreeEnsemble 子集路径仍 wasm 可用;通用 Graph 路径在 wasm 返回可操作错误(指向转 leaves.json)。
- 既有路径不变:
LoadONNX(树模型子集)行为零变更;LoadOnnxGraph是新增的并列 API。
Verification
TestLoadOnnxGraphRelu:用 leaves 自身 pb helpers 构造Z=Relu(X)ONNX 图 →LoadOnnxGraph→Predict→ 断言Relu([-1,0,2])=[0,0,2](端到端通)。TestLoadOnnxGraphGarbage:非法字节返回错误不 panic。- io 全量、docs gate、build、6-linter 门禁全绿。
Compatibility
- Breaking:无。新增
OnnxModel接口与LoadOnnxGraph函数;既有LoadONNX不变。 - 新增运行时依赖:
LoadOnnxGraph路径经 born(已在 go.mod);TreeEnsemble 子集与树/线性推理路径不触达新代码。
Recommended API
- 树模型 ONNX(TreeEnsembleRegressor):
LoadONNX(wasm 可用) - 通用 ONNX 图:
LoadOnnxGraph(非 wasm) - XGB / LightGBM / leaves.json:
LoadFromFile - 详见
docs/api-surface.md与docs/interop-matrix.md
v2.2.0: vector-leaf multi_output_tree training
leaves v2.2.0
主题:向量叶 multi_output_tree 训练(multi-target 一棵树、叶子为向量)。
Highlights
- 向量叶训练落地(原列「明确不做」):XGBoost
multi_output_tree(size_leaf_vector=num_groups)—— 每轮长一棵树,叶子为numGroups维向量;分裂增益跨输出组求和,叶权重逐类-G_c/(H_c+λ)。此前仅推理/加载支持向量叶,训练只有one_output_per_tree。 - 统一 k 维 treebuilder:grad/hess
[n*k]、splitGain跨类求和、leaf-majorLeafValue。k=1退化为标量 —— 现有训练路径零回归(全量 golden 套件验证)。 - exact + hist 双路径都支持向量叶;Born/WebGPU 增益扫描对
k>1回退纯 CPU(标量路径仍享加速)。
Usage
learner, _ := train.NewLearner(train.Config{
Objective: "multi:softprob", // 或 reg:squarederror + NumTarget>1
NumClass: 5, // 多输出
MultiOutputTree: true, // ← 向量叶(默认 false = one_output_per_tree)
NumRound: 50,
TreeMethod: "hist",
// ...
})
learner.Fit(dm)MultiOutputTree=true 时:每轮一棵 OutputDim=numGroups 的树;推理按 OutputDim scatter 到所有输出组(与加载的 XGBoost 向量叶模型一致)。NewLearner 校验:单输出目标开此选项会报错。
Design notes
- 为何统一而非复制:把 treebuilder 数学参数化为
k,而非为向量叶复制一套并行代码 —— 更少代码、单一代码路径可测,k=1由现有 golden 套件保证不变。 - accel 取舍:Born/WebGPU 增益扫描当前为标量 kernel;向量叶(
k>1)回退纯 CPU gain scan。正确优先,性能留信号再开(k=1 标量训练仍享 Born/WebGPU 加速)。
Verification
- 确定性手算测试(4 样本×k=2:分裂点、leaf 向量、OutputDim 逐项断言)
- 端到端多目标训练:每棵树 OutputDim=2、收敛(rmse<0.35)、leaves.json 往返保留 OutputDim
- 单输出 + MultiOutputTree → NewLearner 报错
- 全量回归:13 包
-short全绿、6-linter 门禁 0 issues、race detector 无竞争
Compatibility
- Breaking:无。
MultiOutputTree默认false,现有one_output_per_tree行为完全不变。 - 向量叶推理/加载/保存此前已支持,本版本补齐训练端到端闭环。
Recommended API
- Infer:
LoadFromFile+DefaultLoadOptions - Train:
NewLearner(多输出可开MultiOutputTree)/LoadDataAuto/ CLIleaves train - 详见
docs/api-surface.md
v2.1.6: data race + transformation panic fix; golangci-lint v2 gate
leaves v2.1.6
主题:并发 DATA RACE 与 transformation panic 修复;golangci-lint v2 门禁全量落地。
Highlights
- 修复并发 DATA RACE(
treebuilder.parallelEvalHistFeats):多 goroutine 共享同一rowbuffer 写入Dense.Row(),race detector 首启即捕获;改为每 goroutine 独立 buffer。影响多线程hist训练正确性。 - 修复 transformation 数组越界 panic:
TransformType(Exponential).Name()因transformNames缺exponential项而越界崩溃;TransformExponential.Name()因此被绕成错报 "logistic"。加载 LightGBM exponential objective 模型时触发。 - golangci-lint v2 门禁全量 blocking:
govet/ineffassign/unused/staticcheck/errcheck+ gofmt formatter,6 项 0 issues 基线;附race detectorCI job。 - 死代码清除 ~360 行:unused linter 全清零(explain interventional SHAP、treebuilder 被取代的 GPU hist 旧路径、孤立 helper、永跳测试、失效 GoMLX 脚本、误入库产物)。
- 3 包从 0 测试覆盖(
transformation/predict/booster,+17 测试)、6 包补doc.go、文档治理(维护期→开发期、版本一致性 gate)。
Fixed
treebuilder/hist_parallel.go:per-goroutinerowbuffer,消除parallelEvalHistFeats数据竞争。transformation/transformation.go+exponential.go:补transformNames的exponential项;TransformExponential.Name()返回正确名称。
CI / 工程
.golangci.yml(v2):6 项门禁全 blocking,基线 0 issues。.github/workflows/ci.yml:新增lint(golangci/golangci-lint-action@v6, v2.11.4)与race(go test -race -short)job。- 全仓
gofmt归一(CRLF→LF + 对齐 + 1 处 composite literal 类型名简化)。
Compatibility
- Breaking:无。
- 推理 / 训练主路径行为不变;修复仅提升并发训练正确性与 exponential 模型加载健壮性。
- 根包兼容层
LGEnsembleFromFile/XGEnsembleFromFile仍委托可用。
Recommended API
- Infer:
LoadFromFile+DefaultLoadOptions - Train:
NewLearner/LoadDataAuto/ CLIleaves train - 详见
docs/api-surface.md
Docs
- 维护期 → 开发期;
演进计划v5.4 /演进方案v1.5 版本引用全局一致(新增TestDocVersionRefsConsistentgate)。 - 6 个公共包补
doc.go:train/explain/objective/metrics/mat/util。
v2.1.5 — MovieLens four-stage prep→recall→rank→deal
leaves v2.1.5
主题:MovieLens 四段推荐流水线(prep → 召回 → LTR → 发牌)。
Highlights
- 真实数据四段:
recsys/movielens纯 Go 加载 ml-100k → 四元User/Item/Score/Tag+ catalog 特征 + 片名旁车。 - 共用串联:
pipeline.RunFromDataset(合成 smoke 与 MovieLens 同一路径)。 - 入口齐全:
go run ./recsys/cmd/movielensgo run ./demos/movielens/cmd/agent four-stage- MCP
movielens_four_stage
- 召回 / 发牌加固:部分正样本 + 未交互补齐;
deal.fillOverflow可凑满 DeckSize。
Quick start
# Agent JSON
go run ./demos/movielens/cmd/agent four-stage
# 人类 CLI
go run ./recsys/cmd/movielens -workspace demos/movielens/out/fourstage
# 回归
go test ./recsys/pipeline/ -run TestMovieLensFourStage -count=1首次需网络下载 ml-100k,或预置 .cache/ml-100k.zip。
Compatibility
- 库 API / CLI schema:无破坏
- 精排-only(
full-pipeline/ ranking TSV)路径不变 - Breaking: 无
Docs
v2.1.4 — MovieLens recommend titles + walkthrough
leaves v2.1.4
主题:MovieLens 推荐结果带片名(meta 旁车)+ 一键 walkthrough。
Highlights
- meta 旁车:
testdata/rank_movielens_*_meta.jsonl(movie_id/title/user_id),由testdata/gen_rank_movielens.py写出。 - 可读推荐:
agent recommend/cmd/recommend/ MCPmovielens_recommend输出片名与 movie_id。 - 一键脚本:
demos/movielens/scripts/walkthrough.ps1·.sh。 - 教程同步:
TUTORIAL.md示例 JSON 与故障表。
Quick start
.\demos\movielens\scripts\walkthrough.ps1
# 或仅推荐
go run ./demos/movielens/cmd/recommend -group 0 -topk 10
go run ./demos/movielens/cmd/agent recommend -group 0 -topk 5Compatibility
- 库 API / CLI schema:无破坏
- meta 文件缺失时仍可推荐(仅 row/score/label;stderr 提示生成旁车)
- Breaking: 无
Docs
v2.1.3 — MovieLens Ranker Agent/MCP demo
leaves v2.1.3
主题:MovieLens 推荐 Ranker 全流程 — Agent JSON CLI + MCP + 详尽教程。
Highlights
- Agent 契约 CLI:
go run ./demos/movielens/cmd/agent(prepare → train → eval → recommend,stdout JSON)。 - MCP server:
go run ./demos/movielens/cmd/mcp(stdio;movielens_status|prepare|train|eval|recommend|full_pipeline)。 - 教程:
demos/movielens/TUTORIAL.md(架构、数据、Shell/MCP、调参剧本、验收)。 - 案例数据:MovieLens 100K ranking TSV + XGB NDCG baseline。
Quick start
go run ./demos/movielens/cmd/agent full-pipeline
go test ./demos/movielens/agentops -count=1MCP 配置示例见教程 §6。
Compatibility
- 库 API / CLI schema:无破坏
- MCP 为 demo 可选适配层(库核心仍不强制 MCP 运行时)
- Breaking: 无
Docs
v2.1.2 — explain perf + serving template
leaves v2.1.2
主题:Explain 性能(LIB-22)、可拆 serving 模板(LIB-30)、文档/回归门禁加固。
Highlights
- Tree SHAP 更快、更少分配:
TreeExplainer预计算节点覆盖权重与背景 margin,多样本复用 path 缓冲。 - Serving 脚手架:
examples/serving-template可整目录复制为独立服务(非官方 serving 框架)。 - 质量门禁:sklearn 实验边界写实 +
testdata-matrix.md工件存在性测试。
Recommended API
- Infer:
LoadFromFile+DefaultLoadOptions - Explain:
explain.NewTreeExplainer(forest).ShapleyValues(rows) - Embed HTTP:
examples/http(最小)或examples/serving-template(可拆仓)
Compatibility
- SHAP 数值语义不变(既有 golden / 可加性测试仍绿)
- metrics/CLI schema:无破坏;
schema_version仍为1 - Breaking: 无
CI / 本地
go test ./explain -count=1
go test ./explain -bench=TreeSHAP -benchmem -count=1
go test ./examples/serving-template/... -count=1
go test ./docs -run 'TestdataMatrix|SkillsMirror' -count=1Docs
v2.1.1 — Agent hardening + ONNX subset + multi-target
leaves v2.1.1
主题:v2.1.0 之后的 Agent 契约加固、ONNX TreeEnsemble 实验子集、多目标回归闭环。
Highlights
- Agent 契约门禁:skills 镜像 CI 哈希、
--strict-flags/cv_conflict、错误码表、--print-repro、--out-final、train_accel。 - ONNX(实验):仅
TreeEnsembleRegressor(BRANCH_LEQ/SUM/NONE);完整 Graph 仍不做。 - 多目标回归:
one_output_per_tree(API + CLI--num-target+ predict/eval)。 - 示例:
examples/extension、examples/multitarget;docs/bench样例工件。
Recommended API
- Infer:
LoadFromFile+DefaultLoadOptions - Train:
NewLearner/LoadDataAuto/ CLIleaves train - Multi-target:
data.NewMultiTargetDense+Config.NumTarget,或leaves train --num-target N - ONNX 子集:
io.LoadONNX/.onnx(实验)
Compatibility
- metrics/CLI:只增字段(
train_accel、final_model、num_target等);schema_version仍为1 - ONNX:由占位升为实验子集(失败时仍给转换 hint)
- Breaking: 无
CI
- test (3 OS) / wasm ≤16MiB / bench-gate
- skills mirror:
go test ./docs -run TestSkillsMirrorSync
Docs
- CHANGELOG · interop-matrix · cli.md · TODO
leaves v2.1.0
leaves v2.1.0
主题:Agent 可驱动的训练闭环契约收口,以及库稳定/平台化第一轮(扩展点、BackendAuto、互操作、发版治理)。
Highlights
- Agentic CLI(无 MCP):
sniff → train → eval → inspect → explain → publish,JSON 契约 + SKILL 决策表。 - 定稿安全:
--early-stop默认--save-best,磁盘模型树数 =best_round。 - 可复现:完备
params账本、train --from-run、publish --emit-repro-script、manifest.reproduce。 - BackendAuto 2.0:小批 Native、中大批 BornCPU、GPU 大批 BornGPU;规则可测可文档解释。
- 互操作写实:格式支持等级(稳定/实验/占位)+ 加载失败带
hint:。 - 发版可勾选:
docs/release-checklist.md/api-surface/versioning。
Recommended API
| 场景 | 入口 |
|---|---|
| 推理 | LoadFromFile + DefaultLoadOptions() |
| 训练 | NewLearner / LoadDataAuto / NewLearnerFromModelAndData |
| Agent | go run ./cmd/leaves … + skills/leaves-autotrain |
| 后端 | LoadOptions{Backend: BackendAuto, Workload: …} — 见 docs/backend-auto.md |
兼容旧 API(LGEnsembleFromFile 等)仍可用,不作为新代码首发入口 — 见 docs/api-surface.md。
Compatibility
- AutoTransform 默认 true:logistic 等返回变换后值;raw margin 请设
AutoTransform: false(NOTES.md)。 - BackendAuto:batch≥64 数值树倾向 BornCPU;batch=1 仍为 Native。
- 破坏性:无删除稳定 API;metrics 字段只增不改义。
- 实验:scikit-learn pickle;占位:ONNX(请先转 JSON/leaves)。
CLI(Agent)
go run ./cmd/leaves sniff --data train.csv --metrics sniff.json
go run ./cmd/leaves train --data train.csv --objective reg:squarederror --cv 5 `
--runs runs.jsonl --tag baseline --out-model m.leaves.json --metrics metrics.json
go run ./cmd/leaves train --data train.csv --from-run runs.jsonl --tag baseline `
--out-model final.leaves.json --metrics final.json
go run ./cmd/leaves publish --model final.leaves.json --out-dir release/ `
--metrics final.json --quantize --export-xgb --emit-repro-script bothDocs
docs/api-surface.md— API 分层docs/backend-auto.md— 后端决策表docs/interop-matrix.md— 格式支持等级docs/extension-points.md— 自定义 objective/metricdocs/release-checklist.md— 发版检查表docs/versioning.md— v2.x 变更边界演进方案.md— Agentic DoD(已达成)CHANGELOG.md— 变更列表
CI
go test ./...(3 OS)- WASM 体积 ≤16 MiB
- Windows:batch=1 BornCPU ≥20× Native
Install
go get github.com/linkerlin/leaves@v2.1.0
# 或
go install github.com/linkerlin/leaves/cmd/leaves@v2.1.0(需 tag 推送后模块代理可见。)