bugfixes
This commit is contained in:
parent
c6c6bad6cf
commit
83120174a6
@ -1607,12 +1607,21 @@ def predict_batch(req: PredictBatchRequest):
|
|||||||
"error": "no paths supplied",
|
"error": "no paths supplied",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
imgsz = int(req.imageSize or _IMGSZ or 640)
|
||||||
|
|
||||||
current_model = get_model()
|
current_model = get_model()
|
||||||
if current_model is None:
|
if current_model is None:
|
||||||
|
predictions = [empty_prediction("detector_model_missing") for _ in paths]
|
||||||
|
if not req.detectorOnly:
|
||||||
|
apply_pose_batch_to_predictions(paths, predictions, imgsz)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"ok": True,
|
"ok": True,
|
||||||
"predictions": [empty_prediction("model_missing") for _ in paths],
|
"available": False,
|
||||||
"error": _MODEL_ERROR or f"YOLO model not found: {DEFAULT_MODEL_PATH}",
|
"modelAvailable": False,
|
||||||
|
"predictions": predictions,
|
||||||
|
"modelError": _MODEL_ERROR,
|
||||||
|
"expectedModel": str(DEFAULT_MODEL_PATH),
|
||||||
}
|
}
|
||||||
|
|
||||||
if DETECTION_LABELS_PATH is None or _LABEL_ERROR:
|
if DETECTION_LABELS_PATH is None or _LABEL_ERROR:
|
||||||
@ -1622,8 +1631,6 @@ def predict_batch(req: PredictBatchRequest):
|
|||||||
"error": f"detection labels missing: {_LABEL_ERROR}",
|
"error": f"detection labels missing: {_LABEL_ERROR}",
|
||||||
}
|
}
|
||||||
|
|
||||||
imgsz = int(req.imageSize or _IMGSZ or 640)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
results = current_model.predict(
|
results = current_model.predict(
|
||||||
source=paths,
|
source=paths,
|
||||||
@ -1642,6 +1649,8 @@ def predict_batch(req: PredictBatchRequest):
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
"ok": True,
|
"ok": True,
|
||||||
|
"available": True,
|
||||||
|
"modelAvailable": True,
|
||||||
"predictions": predictions,
|
"predictions": predictions,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1703,7 +1712,7 @@ def health():
|
|||||||
|
|
||||||
status_payload = {
|
status_payload = {
|
||||||
"ok": True,
|
"ok": True,
|
||||||
"ready": current_model is not None,
|
"ready": True,
|
||||||
"modelAvailable": current_model is not None,
|
"modelAvailable": current_model is not None,
|
||||||
"model": _MODEL_PATH,
|
"model": _MODEL_PATH,
|
||||||
"modelError": _MODEL_ERROR,
|
"modelError": _MODEL_ERROR,
|
||||||
@ -1751,8 +1760,8 @@ def reload_model():
|
|||||||
names = getattr(current_model, "names", {}) or {} if current_model is not None else {}
|
names = getattr(current_model, "names", {}) or {} if current_model is not None else {}
|
||||||
|
|
||||||
status_payload = {
|
status_payload = {
|
||||||
"ok": current_model is not None,
|
"ok": True,
|
||||||
"ready": current_model is not None,
|
"ready": True,
|
||||||
"modelAvailable": current_model is not None,
|
"modelAvailable": current_model is not None,
|
||||||
"model": _MODEL_PATH,
|
"model": _MODEL_PATH,
|
||||||
"modelError": _MODEL_ERROR,
|
"modelError": _MODEL_ERROR,
|
||||||
|
|||||||
BIN
backend/dist/nsfwapp-linux-amd64
vendored
BIN
backend/dist/nsfwapp-linux-amd64
vendored
Binary file not shown.
BIN
backend/dist/nsfwapp.exe
vendored
BIN
backend/dist/nsfwapp.exe
vendored
Binary file not shown.
BIN
backend/dist/nsfwapp_amd64.deb
vendored
BIN
backend/dist/nsfwapp_amd64.deb
vendored
Binary file not shown.
@ -9,6 +9,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@ -112,11 +113,22 @@ func mlPythonSetupConfigFromEnv() mlPythonSetupConfig {
|
|||||||
appDir: filepath.Clean(appDir),
|
appDir: filepath.Clean(appDir),
|
||||||
requirementsPath: filepath.Clean(requirementsPath),
|
requirementsPath: filepath.Clean(requirementsPath),
|
||||||
venvDir: filepath.Clean(venvDir),
|
venvDir: filepath.Clean(venvDir),
|
||||||
venvPython: filepath.Join(filepath.Clean(venvDir), "bin", "python"),
|
venvPython: mlPythonVenvPythonPath(venvDir),
|
||||||
requirementsMark: filepath.Join(filepath.Clean(venvDir), ".requirements-ml.txt"),
|
requirementsMark: filepath.Join(filepath.Clean(venvDir), ".requirements-ml.txt"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mlPythonVenvPythonPath(venvDir string) string {
|
||||||
|
venvDir = filepath.Clean(strings.TrimSpace(venvDir))
|
||||||
|
if venvDir == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
return filepath.Join(venvDir, "Scripts", "python.exe")
|
||||||
|
}
|
||||||
|
return filepath.Join(venvDir, "bin", "python")
|
||||||
|
}
|
||||||
|
|
||||||
func defaultMLPythonVenvDir() string {
|
func defaultMLPythonVenvDir() string {
|
||||||
base := strings.TrimSpace(os.TempDir())
|
base := strings.TrimSpace(os.TempDir())
|
||||||
if base == "" {
|
if base == "" {
|
||||||
|
|||||||
@ -206,6 +206,10 @@ func aiServerPythonPath() string {
|
|||||||
return raw
|
return raw
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if venvPython := configuredMLPythonVenvPythonPath(); venvPython != "" {
|
||||||
|
return venvPython
|
||||||
|
}
|
||||||
|
|
||||||
// Windows py launcher zuerst versuchen.
|
// Windows py launcher zuerst versuchen.
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
if _, err := exec.LookPath("py"); err == nil {
|
if _, err := exec.LookPath("py"); err == nil {
|
||||||
@ -224,6 +228,34 @@ func aiServerPythonPath() string {
|
|||||||
return "python"
|
return "python"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func configuredMLPythonVenvPythonPath() string {
|
||||||
|
if strings.TrimSpace(os.Getenv("NSFWAPP_SKIP_ML_SETUP")) == "1" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
candidates := []string{}
|
||||||
|
if venvDir := strings.TrimSpace(os.Getenv("NSFWAPP_ML_VENV")); venvDir != "" {
|
||||||
|
candidates = append(candidates, venvDir)
|
||||||
|
}
|
||||||
|
if strings.TrimSpace(os.Getenv("NSFWAPP_ML_SETUP")) == "1" {
|
||||||
|
candidates = append(candidates, defaultMLPythonVenvDir())
|
||||||
|
}
|
||||||
|
|
||||||
|
seen := map[string]bool{}
|
||||||
|
for _, dir := range candidates {
|
||||||
|
path := mlPythonVenvPythonPath(dir)
|
||||||
|
key := filepath.Clean(path)
|
||||||
|
if path == "" || seen[key] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
seen[key] = true
|
||||||
|
if info, err := os.Stat(path); err == nil && info != nil && !info.IsDir() {
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func findAIServerScriptDir() (string, error) {
|
func findAIServerScriptDir() (string, error) {
|
||||||
cwd, _ := os.Getwd()
|
cwd, _ := os.Getwd()
|
||||||
|
|
||||||
@ -544,7 +576,7 @@ func startAIServer(ctx context.Context) (*aiServerProcess, error) {
|
|||||||
|
|
||||||
// Modell ebenfalls standardmäßig aus generated/training nehmen,
|
// Modell ebenfalls standardmäßig aus generated/training nehmen,
|
||||||
// aber YOLO_MODEL darf weiterhin extern überschrieben werden.
|
// aber YOLO_MODEL darf weiterhin extern überschrieben werden.
|
||||||
if strings.TrimSpace(os.Getenv("YOLO_MODEL")) == "" {
|
if strings.TrimSpace(os.Getenv("YOLO_MODEL")) == "" && defaultModel.EffectiveExists {
|
||||||
env = upsertEnv(env, "YOLO_MODEL", defaultModelPath)
|
env = upsertEnv(env, "YOLO_MODEL", defaultModelPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2557,7 +2557,38 @@ func trainingCancelHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func trainingRunJob(ctx context.Context, root string, count int) {
|
func trainingRunJob(ctx context.Context, root string, count int) {
|
||||||
|
if err := ensureMLPythonSetup(ctx); err != nil {
|
||||||
|
if errors.Is(err, context.Canceled) {
|
||||||
|
trainingFinishCancelled(root)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
appLogln("ML-Python setup for training failed:", err)
|
||||||
|
trainingSetJobStatus(func(s *TrainingJobStatus) {
|
||||||
|
finishedAt := time.Now().UTC()
|
||||||
|
var durationMs int64
|
||||||
|
if startedAt, parseErr := time.Parse(time.RFC3339, strings.TrimSpace(s.StartedAt)); parseErr == nil {
|
||||||
|
durationMs = finishedAt.Sub(startedAt).Milliseconds()
|
||||||
|
if durationMs < 0 {
|
||||||
|
durationMs = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Running = false
|
||||||
|
s.Progress = 100
|
||||||
|
s.Step = "Training fehlgeschlagen."
|
||||||
|
s.Message = "ML-Python-Umgebung konnte nicht vorbereitet werden."
|
||||||
|
s.Error = err.Error()
|
||||||
|
s.FinishedAt = finishedAt.Format(time.RFC3339)
|
||||||
|
s.DurationMs = durationMs
|
||||||
|
s.PreviewURL = ""
|
||||||
|
})
|
||||||
|
trainingClearJobCancel()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
python := trainingPythonExe()
|
python := trainingPythonExe()
|
||||||
|
appLogln("ML-Python für Training:", python)
|
||||||
|
|
||||||
cleanOutput := func(text string) string {
|
cleanOutput := func(text string) string {
|
||||||
out := strings.TrimSpace(text)
|
out := strings.TrimSpace(text)
|
||||||
@ -6504,7 +6535,7 @@ func trainingPythonExe() string {
|
|||||||
if v != "" {
|
if v != "" {
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
return "python"
|
return aiServerPythonPath()
|
||||||
}
|
}
|
||||||
|
|
||||||
func trainingProjectRoot() string {
|
func trainingProjectRoot() string {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user