> ## Documentation Index
> Fetch the complete documentation index at: https://novita.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# GPUs SDK-Nutzungsleitfaden

Dieser Leitfaden erklärt, wie Sie das `novita-gpus` SDK verwenden, um einen Async Serverless Endpoint aufzurufen, und wie Sie einen Worker-Handler anpassen.

## 1. SDK installieren

Installieren Sie das SDK in Ihrer Client-Umgebung oder Worker-Laufzeitumgebung:

```bash theme={"system"}
pip install novita-gpus
```

## 2. Jobs mit dem SDK übermitteln

Die Standard-Anfrage-URL des `novita-gpus` SDK ist `https://async-public.serverless.novita.ai/v1`. Um einen Endpoint aufzurufen, legen Sie Ihren API-Schlüssel fest und erstellen Sie einen Client mit dem Endpoint-Namen.

```python theme={"system"}
import novita_gpus

novita_gpus.api_key = "sk_xxxx"

endpoint = novita_gpus.Endpoint("0f43a6867e05fddd")
job = endpoint.run({
    "prompt": "a red apple on a table"
})

print(job.status())
output = job.output(timeout=300)
print(output)
```

## 3. ComfyUI-Jobbeispiel

Für `novitalabs/comfyui-worker:v0.0.1` muss die Job-Eingabe einen ComfyUI-Workflow enthalten. Das folgende minimale Beispiel entspricht dem getesteten Fall:

```python theme={"system"}
import novita_gpus

novita_gpus.api_key = "sk_xxxx"

endpoint = novita_gpus.Endpoint("0f43a6867e05fddd")

job = endpoint.run({
    "workflow": {
        "4": {
            "class_type": "CheckpointLoaderSimple",
            "inputs": {"ckpt_name": "flux1-dev-fp8.safetensors"},
        },
        "5": {
            "class_type": "EmptyLatentImage",
            "inputs": {"width": 512, "height": 512, "batch_size": 1},
        },
        "6": {
            "class_type": "CLIPTextEncode",
            "inputs": {"clip": ["4", 1], "text": "a red apple on a table"},
        },
        "7": {
            "class_type": "CLIPTextEncode",
            "inputs": {"clip": ["4", 1], "text": "blurry, low quality"},
        },
        "3": {
            "class_type": "KSampler",
            "inputs": {
                "model": ["4", 0],
                "positive": ["6", 0],
                "negative": ["7", 0],
                "latent_image": ["5", 0],
                "seed": 42,
                "steps": 10,
                "cfg": 7,
                "sampler_name": "euler",
                "scheduler": "normal",
                "denoise": 1,
            },
        },
        "8": {
            "class_type": "VAEDecode",
            "inputs": {"samples": ["3", 0], "vae": ["4", 2]},
        },
        "9": {
            "class_type": "SaveImage",
            "inputs": {"filename_prefix": "test", "images": ["8", 0]},
        },
    },
    "output_node_id": "9",
})

print(job.status())
print(job.output(timeout=300))
```

## 4. Benutzerdefinierter Handler

Rufen Sie auf der Worker-Seite `novita_gpus.start({"handler": handler})` auf, um die Task-Schleife zu starten. Die Plattform übergibt Task-Daten an `handler(job)`:

* `job["id"]`: aktuelle Job-ID
* `job["input"]`: vom Client übermittelter Eingabeinhalt
* Der Rückgabewert des Handlers wird als Job-Ausgabe verwendet
* Wenn das zurückgegebene dict ein `error`-Feld enthält, wird der Job als fehlgeschlagen markiert

Minimales Handler-Beispiel:

```python theme={"system"}
import time
import novita_gpus


def handler(job: dict) -> dict:
    job_id = job["id"]
    job_input = job.get("input", {})
    prompt = job_input.get("prompt", "hello")

    novita_gpus.progress_update(job, {
        "status": "running",
        "message": "job accepted",
    })

    time.sleep(1)

    return {
        "job_id": job_id,
        "prompt": prompt,
        "result": "ok",
    }


if __name__ == "__main__":
    novita_gpus.start({"handler": handler})
```

## 5. Vollständige Worker-Beispiele

Vollständigen Worker-Quellcode, Anweisungen zum Erstellen von Docker-Images und Skripte zur Task-Übermittlung finden Sie in den <Link href="https://github.com/novitalabs/gpus-python-example" target="_blank">Novita GPUs Python-Beispielen</Link>.

Das Repository enthält zwei Beispiele:

* <Link href="https://github.com/novitalabs/gpus-python-example/tree/main/workers/comfyui-worker" target="_blank">comfyui-worker</Link>: führt ComfyUI aus `handler.py` aus und gibt generierte Bilder zurück.
* <Link href="https://github.com/novitalabs/gpus-python-example/tree/main/workers/sleep-worker" target="_blank">sleep-worker</Link>: ein minimales `handler.py`, das für eine angeforderte Dauer wartet und ein JSON-Ergebnis zurückgibt.

Jedes Beispielverzeichnis enthält:

* `handler.py`: definiert `handler(job)` und startet den Worker mit `novita_gpus.start({"handler": handler})`.
* `Dockerfile`: erstellt das Worker-Image.
* `requirements.txt`: installiert `novita-gpus`.
* `submit_task.py`: übermittelt eine Task mit dem `novita-gpus` Client-SDK.

Erstellen Sie Ihr Worker-Image und pushen Sie es in Ihre eigene Registry:

```bash theme={"system"}
IMAGE=<your-registry>/comfyui-worker:v0.0.1

docker buildx build --platform linux/amd64 \
  -t "$IMAGE" \
  --push .
```

Die Task-Übermittlung verwendet das Endpoint-Namensformat `<endpoint-id>-<app-name>`.
Beispielsweise ergeben Endpoint-ID `o8UJWkag5WTn` und App-Name `async` Folgendes:

```text theme={"system"}
o8UJWkag5WTn-async
```

Die `submit_task.py`-Beispiele akzeptieren die Endpoint-ID und den App-Namen separat und setzen dann den endgültigen Endpoint-Namen zusammen:

```bash theme={"system"}
export NOVITA_API_KEY="sk_xxxx"
export NOVITA_ENDPOINT_ID="o8UJWkag5WTn"
export NOVITA_APP_NAME="async"

python submit_task.py \
  --endpoint "$NOVITA_ENDPOINT_ID" \
  --app-name "$NOVITA_APP_NAME" \
  --api-key "$NOVITA_API_KEY"
```

Im Skript wird der SDK-Client mit dem zusammengesetzten Endpoint-Namen erstellt:

```python theme={"system"}
endpoint_name = f"{args.endpoint}-{args.app_name}"
endpoint = novita_gpus.Endpoint(endpoint_name, api_key=args.api_key)
```

## 6. Bilder oder Dateien zurückgeben

Die Async Serverless Endpoint `status` API hat eine Größenbeschränkung für Ausgaben. Laden Sie große Dateien wie Bilder und Videos zuerst in einen Objektspeicher hoch und geben Sie URLs in der Ausgabe zurück.

Konfigurieren Sie Umgebungsvariablen für den Objektspeicher im Endpoint:

```bash theme={"system"}
BUCKET_ENDPOINT_URL=https://<your-bucket-endpoint>
BUCKET_ACCESS_KEY_ID=<your-access-key-id>
BUCKET_SECRET_ACCESS_KEY=<your-secret-access-key>
BUCKET_NAME=<your-bucket-name>
```

Laden Sie ein Bild im Handler hoch:

```python theme={"system"}
import novita_gpus


def handler(job: dict) -> dict:
    image_url = novita_gpus.upload_image(job["id"], "/tmp/output.png")

    return {
        "images": [
            {
                "filename": "output.png",
                "url": image_url,
            }
        ]
    }


if __name__ == "__main__":
    novita_gpus.start({"handler": handler})
```

Sie können auch reguläre Dateien oder Bytes hochladen:

```python theme={"system"}
import novita_gpus

file_url = novita_gpus.upload_file("result.json", "/tmp/result.json")
bytes_url = novita_gpus.upload_bytes("result.txt", b"hello")
```

## 7. FAQ

### Muss ich im Worker einen API-Schlüssel konfigurieren?

Normalerweise nicht. API-Schlüssel werden hauptsächlich von Clients verwendet, um Jobs zu übermitteln, abzufragen und abzubrechen.

### Welcher Handler-Rückgabewert markiert einen Job als fehlgeschlagen?

Wenn der Handler ein dict zurückgibt, das ein `error`-Feld enthält, wird der Job als fehlgeschlagen markiert:

```python theme={"system"}
return {"error": "invalid input"}
```
