e3c8979e8d
- 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>
79 lines
2.5 KiB
Go
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
|
|
}
|