This commit is contained in:
2026-09-09 21:05:25 +08:00
parent 87ab06221c
commit c590f74b1e
14 changed files with 229 additions and 208 deletions
+34
View File
@@ -39,6 +39,9 @@ type TrainingRunner interface {
FetchResult(ctx context.Context, job *TrainingJob) (string, error)
// FetchArtifact 把训练机产物文件拉回服务器本地路径
FetchArtifact(ctx context.Context, job *TrainingJob, remoteName, localPath string) error
// PushArtifact 把服务器本地文件推到训练机(增量训练基座权重,2026-09-09;
// remoteName 相对训练机 workdir
PushArtifact(ctx context.Context, job *TrainingJob, remoteName, localPath string) error
// SyncYoloDataset 把训练集包落到训练机(subprocess 直写 workdirssh 走 tar 流式管道,本地不落盘)
SyncYoloDataset(ctx context.Context, job *TrainingJob, pkg *YoloPackage) error
// WriteTaskJson 把任务参数文件写到训练机(随 Start 前的准备阶段调用)
@@ -222,6 +225,15 @@ func (r *subprocessRunner) FetchArtifact(ctx context.Context, job *TrainingJob,
return WriteFileAtomic(localPath, data)
}
func (r *subprocessRunner) PushArtifact(ctx context.Context, job *TrainingJob, remoteName, localPath string) error {
data, err := os.ReadFile(localPath)
if err != nil {
return gerror.Wrap(err, "读取待推送文件失败")
}
dst := filepath.Join(job.Workdir, filepath.FromSlash(remoteName))
return WriteFileAtomic(dst, data)
}
func (r *subprocessRunner) SyncYoloDataset(ctx context.Context, job *TrainingJob, pkg *YoloPackage) error {
// 同机训练:训练进程直接读 workdir 下文件,包直写目标目录(无中间暂存)
dst := filepath.Join(job.Workdir, job.DatasetDir, "yolo", job.DatasetName)
@@ -395,6 +407,28 @@ func (r *sshRunner) FetchArtifact(ctx context.Context, job *TrainingJob, remoteN
return WriteFileAtomic(localPath, data)
}
func (r *sshRunner) PushArtifact(ctx context.Context, job *TrainingJob, remoteName, localPath string) error {
client, err := r.dial(ctx)
if err != nil {
return err
}
defer func() { _ = client.Close() }()
session, err := client.NewSession()
if err != nil {
return err
}
defer func() { _ = session.Close() }()
dst := filepath.Join(job.Workdir, filepath.FromSlash(remoteName))
cmd := fmt.Sprintf("mkdir -p %s && cat > %s", filepath.Dir(dst), dst)
f, err := os.Open(localPath)
if err != nil {
return gerror.Wrap(err, "读取待推送文件失败")
}
defer func() { _ = f.Close() }()
session.Stdin = f
return session.Run(cmd)
}
func (r *sshRunner) SyncYoloDataset(ctx context.Context, job *TrainingJob, pkg *YoloPackage) error {
// tar 流式管道:原图直接读数据集目录打包,stdin 推远端解包,本地不落盘
client, err := r.dial(ctx)
+9
View File
@@ -14,6 +14,9 @@ import (
// datasets/<name>/ 数据集图片(平铺,文件名唯一,标注存 DB dataset_image.labels_json
// trainings/<model>.tflite 某数据集当前生效模型(训练成功即直写,客户端固定下载,无存档回退;
// <model> = 数据集文件名前缀 name_prefix,空则回退数据集名,2026-08-28)
// trainings/weights/<基名>.pt 增量训练基座权重存档(2026-09-09:基名同 tflite——单物种
// <前缀或数据集名>[_n]、综合 combined[_n];下次训练推训练机热启动,
// 删除即回落全量基座)
//
// 训练机与 Go 服务器异机时,数据集经 training 通道同步(见 common/training_runner.go)。
@@ -38,6 +41,12 @@ func TrainingModelPath(ctx context.Context, modelName string) string {
return filepath.Join(DatasetDir(ctx), "trainings", modelName+".tflite")
}
// TrainingWeightsPath 增量训练基座权重存档路径(trainings/weights/<基名>.pt,基名同 tflite 基名;
// 存在则下次训练推训练机热启动,删除即回落全量基座)
func TrainingWeightsPath(ctx context.Context, baseName string) string {
return filepath.Join(DatasetDir(ctx), "trainings", "weights", baseName+".pt")
}
// Sha256Hex 计算文件内容 SHA-256 十六进制(模型版本校验用)
func Sha256Hex(data []byte) (string, error) {
sum := sha256.Sum256(data)