Files
fn_registry/functions/ml/sdcli_parse_progress.go
egutierrez a802f59f55 chore: auto-commit (95 archivos)
- cmd/fn/doctor.go
- cmd/fn/main.go
- cpp/apps/primitives_gallery/playground/tables/CMakeLists.txt
- cpp/apps/primitives_gallery/playground/tables/data_table.cpp
- cpp/apps/primitives_gallery/playground/tables/data_table_logic.cpp
- cpp/apps/primitives_gallery/playground/tables/data_table_logic.h
- cpp/apps/primitives_gallery/playground/tables/self_test.cpp
- cpp/apps/primitives_gallery/playground/tables/tql.cpp
- cpp/apps/primitives_gallery/playground/tables/viz.cpp
- cpp/apps/primitives_gallery/playground/tables/viz.h
- ...

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-13 00:50:34 +02:00

79 lines
2.5 KiB
Go

package ml
import (
"regexp"
"strconv"
)
// SdcliProgress contiene el estado de progreso parseado de una linea de stderr de sd-cli.
type SdcliProgress struct {
Step int `json:"step"`
TotalSteps int `json:"total_steps"`
ItPerSec float64 `json:"it_per_sec"`
Percent float64 `json:"percent"`
}
// reProgress1 parsea el formato compacto: " 3/30 | 0.84it/s | 10%"
var reProgress1 = regexp.MustCompile(`\s*(\d+)\s*/\s*(\d+)\s*\|[^|]*?([\d.]+)\s*it/s[^|]*?\|\s*([\d.]+)\s*%`)
// reProgress2 parsea el formato verbose: "sampling: step 3 of 30 (0.84 it/s)"
var reProgress2 = regexp.MustCompile(`step\s+(\d+)\s+of\s+(\d+)\s*\(\s*([\d.]+)\s*it/s\)`)
// reProgress3 parsea el formato minimal: "step 3/30" o "progress: 3/30"
var reProgress3 = regexp.MustCompile(`(?:progress[:\s]+)?(\d+)\s*/\s*(\d+)`)
// SdcliParseProgress parsea una linea de stderr de stable-diffusion.cpp / sd-cli
// y extrae el estado de progreso. Retorna (SdcliProgress, true) si la linea
// contiene informacion de progreso reconocible; (zero, false) en caso contrario.
// Funcion pura: sin I/O, sin estado mutable, determinista.
func SdcliParseProgress(line string) (SdcliProgress, bool) {
// Formato 1: " 3/30 | 0.84it/s | 10%"
if m := reProgress1.FindStringSubmatch(line); m != nil {
step, err1 := strconv.Atoi(m[1])
total, err2 := strconv.Atoi(m[2])
itPerSec, err3 := strconv.ParseFloat(m[3], 64)
pct, err4 := strconv.ParseFloat(m[4], 64)
if err1 == nil && err2 == nil && err3 == nil && err4 == nil {
return SdcliProgress{
Step: step,
TotalSteps: total,
ItPerSec: itPerSec,
Percent: pct,
}, true
}
}
// Formato 2: "sampling: step 3 of 30 (0.84 it/s)"
if m := reProgress2.FindStringSubmatch(line); m != nil {
step, err1 := strconv.Atoi(m[1])
total, err2 := strconv.Atoi(m[2])
itPerSec, err3 := strconv.ParseFloat(m[3], 64)
if err1 == nil && err2 == nil && err3 == nil && total > 0 {
pct := 100.0 * float64(step) / float64(total)
return SdcliProgress{
Step: step,
TotalSteps: total,
ItPerSec: itPerSec,
Percent: pct,
}, true
}
}
// Formato 3: "step 3/30" o "progress: 3/30" sin velocidad
if m := reProgress3.FindStringSubmatch(line); m != nil {
step, err1 := strconv.Atoi(m[1])
total, err2 := strconv.Atoi(m[2])
if err1 == nil && err2 == nil && total > 0 {
pct := 100.0 * float64(step) / float64(total)
return SdcliProgress{
Step: step,
TotalSteps: total,
ItPerSec: 0,
Percent: pct,
}, true
}
}
return SdcliProgress{}, false
}