Naia
Inhaltsverzeichnis
  1. 1Video-Handbuch
  2. 2Naia OS Live USB
  3. 3Installation und Bereitstellung
  4. 3.1Naia OS Installation (ISO)
  5. 3.2App-Installation
  6. 4Erste Schritte
  7. 4.1Naia Model Pricing
  8. 4.2naia-omni-cascade
  9. 4.3demo
  10. 4.4naia-offline
  11. 4.5naia-model-dev
  12. 4.6naia-online
  13. 5Hauptbildschirm
  14. 6Chatten
  15. 6.1Persönlicher Radio-DJ & Ausstellungsführer
  16. 7Gesprächsverlauf
  17. 8Arbeitsfortschritt
  18. 9Fähigkeiten
  19. 10Kanäle
  20. 11Agenten
  21. 12Diagnose
  22. 13Arbeitsbereich
  23. 14Browser
  24. 15Panel-Verwaltung
  25. 16Sprachgespräch
  26. 17Einstellungen
  27. 18Werkzeugdetails
  28. 19Naia-Konto
  29. 20Fehlerbehebung
  30. 21Open-Source-Nutzung und Beitrag

4.5. naia-model-dev

Entwicklerhandbuch zur Nutzung des Naia-Modells aus dem Code. Nachdem du das Modell über 4.4 Naia-Modell-Download ausgeführt hast, nutze die lokal bereitgestellte OpenAI-kompatible API (kein Gateway, keine Warteschlange) unverändert. Mit jedem OpenAI-SDK oder -Tool musst du nur die baseURL auf dieses Modell richten.

Nicht nur für naia-os/die Oberfläche — jeder Code, der OpenAI Realtime/Chat/Audio/Embeddings spricht, verbindet sich unverändert, und du kannst auf diesem Modell neue Anwendungen erstellen und ausführen.

1. Verbindung · Authentifizierung

  • REST-Basis: http://<host>:8892/v1 (127.0.0.1 auf demselben PC)
  • Realtime (WS): ws://<host>:8892/v1/realtime (ein nacktes ws://<host>:8892 funktioniert ebenfalls — Pfad /v1/realtime + Standardmodell werden automatisch angewendet)
  • Verbindung: lokal (127.0.0.1) / Tailscale, ist keine Authentifizierung erforderlich — der Container verifiziert seine Lizenz selbst. Clients, die ein Schlüsselfeld benötigen (OpenAI-SDK usw.), können einen beliebigen Wert übergeben (naia). Bei externer Bereitstellung §4.4 Tailscale/VPN davorschalten.

🔑 Ein Schlüssel — der Abonnementschlüssel

  • Abonnementschlüssel — der Abonnementschlüssel, den du aus dem Portal erhältst. Wird nur zur Laufzeit des Containers (Aktivierung) verwendet (-e NAIA_ACCOUNT_TOKEN=<subscription-key>). Er prüft das Abonnement und erhält eine zeitlich begrenzte Lizenz (Zertifikat).
  • Es gibt keinen separaten Verbindungsschlüssel. Nach der Aktivierung verifiziert der Container lokal selbst mit dem Zertifikat, sodass sich Clients (naia-os, OpenAI-SDK) nur noch per URL verbinden müssen — 127.0.0.1 auf demselben PC oder Tailscale/VPN (§4.4) von einem anderen Gerät. Er ruft das Gateway nicht pro Verbindung auf.
  • Der api_key in den folgenden Beispielen ist ein Platzhalter (das OpenAI-SDK verlangt das Feld) — der Offline-Container prüft ihn nicht, daher funktioniert jeder Wert wie "naia".

2. Endpunkte (OpenAI-kompatibel)

EndpunktVerwendung
GET /healthBereitschaft {"ready":true,"services":{tts,stt,llm},"vad":true} (ohne Authentifizierung)
GET /v1/modelsModellliste
WS /v1/realtimeEchtzeit-Sprachsitzung (VAD, Barge-in, Emotion)
POST /v1/chat/completionsChat (Streaming)
POST /v1/audio/speechSprachsynthese (TTS)
POST /v1/audio/transcriptionsSpracherkennung (STT)
POST /v1/embeddingsEmbeddings

Chat (curl):

curl -s http://127.0.0.1:8892/v1/chat/completions \
  -H "Authorization: Bearer naia" -H "Content-Type: application/json" \
  -d '{"model":"naia-0.9-omni-24g","messages":[{"role":"user","content":"hi"}],"stream":false}'

OpenAI-SDK (Python) — einfach baseURL austauschen:

from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:8892/v1", api_key="naia")
print(client.chat.completions.create(
    model="naia-0.9-omni-24g",
    messages=[{"role": "user", "content": "hi"}],
).choices[0].message.content)

Transkription (STT):

curl -s http://127.0.0.1:8892/v1/audio/transcriptions \
  -H "Authorization: Bearer naia" \
  -F file=@sample.wav -F model=naia-0.9-omni-24g

3. Echtzeit-Sprache — Verbindungsablauf (WS)

Derselbe Ablauf, den die 4.3 Live-Demo nutzt. (Offline startet sie sofort, ohne Gateway-Warteschlange/-Zuweisung.)

  1. Verbinden — öffne ws://<host>:8892.

  2. Erster Frame (Authentifizierung · Sprache) — Browser-WebSockets können keine Header senden, also sende dies als erste Nachricht:

    { "setup": { "apiKey": "naia", "locale": "en" } }
    
  3. Wenn der Server session.created sendet, konfiguriere die Sitzung mit session.update:

    {
      "type": "session.update",
      "session": {
        "modalities": ["text", "audio"],
        "input_audio_format": "pcm16",
        "output_audio_format": "pcm16",
        "instructions": "<persona instructions>",
        "turn_detection": { "type": "server_vad" },
        "input_audio_transcription": { "language": "en" },
        "ref_audio_url": "<URL of a voice sample to mimic (optional)>"
      }
    }
    
  4. Austausch

    Client → Server
    Spracheingabe{"type":"input_audio_buffer.append","audio":"<base64 PCM16 24kHz>"} (das Server-VAD erkennt das Ende der Sprache)
    Texteingabeconversation.item.create, dann response.create
    Barge-inresponse.cancel
    Server → Client
    response.audio.deltabase64-PCM16-24kHz-Audiosegment
    response.audio_transcript.delta / response.text.deltaAntworttext (Streaming)
    conversation.item.input_audio_transcription.completedTranskription deiner Sprache
    emotion.updatedEmotions- / Prosodie-Tag (§5)
    response.doneEnde eines Turns

4. Sprachen — 30 Sprachen (Standard = auto/global)

Das Modell unterstützt 30 Sprachen (Arabisch, Birmanisch, Chinesisch, Dänisch, Niederländisch, Englisch, Finnisch, Französisch, Deutsch, Griechisch, Hebräisch, Hindi, Indonesisch, Italienisch, Japanisch, Khmer, Koreanisch, Laotisch, Malaiisch, Norwegisch, Polnisch, Portugiesisch, Russisch, Spanisch, Swahili, Schwedisch, Tagalog, Thai, Türkisch, Vietnamesisch).

  • Standard (nicht gesetzt) = global/auto — es erkennt die von dir gesprochene Sprache und antwortet in dieser Sprache (pro Turn).
  • Um eine bestimmte Sprache festzulegen, gib einen ISO-639-1-Code (z. B. ko/en/ja) in setup.locale oder in input_audio_transcription.language von session.update an.

5. Ausgabeformat (Emotions- · Prosodie-Tags)

Das Ausgabeformat ist abgestimmt auf die Sprachunterhaltung — wenn der Client es kennt, kann er sich reicher ausdrücken.

  • Prosodie-Tags: Der Antworttext enthält englische Tags in eckigen Klammern in Kleinschreibung wie [laughing], [sigh], [breath], [pause], [hesitation], eingestreut dort, wo sich die Emotion verschiebt (für die Sprachprosodie). Das Modell wird angewiesen, keine koreanischen Tags wie [웃음], eingeklammerte Regieanweisungen wie (smiling) oder Sternchen wie *smiles* zu verwenden. Bekanntes Vokabular: laughing/laugh/laughter/chuckle/giggle · sigh/exhale · breath/inhale · pause · hesitation · gasp/cough/sneeze/yawn/sniff/hum · cry/sob/moan/whisper/shout/cheer (andere Tags werden unverändert durchgereicht).
  • Für jedes Tag sendet der Server ein 1:1-emotion.updated-Ereignis (state == Tag-Name, Kleinschreibung):
    { "type": "emotion.updated", "state": "laughing", "tag": "[laughing]", "known": true }
    
  • Der TTS-Pfad behält die Tags bei und gibt sie in die Synthese ein, um die Sprachprosodie zu erzeugen, während das Chat-text.delta sauberen Text mit entfernten Tags sendet. (Keine Emojis, kein Markdown und keine eingeklammerte Selbst-Narration in der Ausgabe.)
  • Client-Mapping (naia-os-Referenz): Ordne emotion.updated.state (Prosodie-Tag) den Avatar-Ausdrücken zu — laughing/chuckle/giggle/cheer → happy, sigh/exhale/cry/sob → sad, gasp → surprised, shout → angry, hesitation → think. Nicht-emotionale Prosodie wie breath·pause ändert den Ausdruck nicht (behalte den vorherigen bei — damit er nicht bei jedem Atemzug auf neutral zurückspringt).
  • Robuste Verarbeitung empfohlen: Die LLM-Ausgabe ist nicht immer exakt. Bevorzuge emotion.updated, aber falls es fehlt, erkenne automatisch Tags in der Transkription selbst (Großschreibung [HAPPY] / Prosodie-Tags in Kleinschreibung) oder durchgesickerte Regieanweisungen ((smiles)·*sigh*) und spiegle sie im Ausdruck wider; gibt es keinen Hinweis, behalte den aktuellen Ausdruck bei (vgl. naia-os shell/src/lib/vrm/expression.ts extractExpression).

6. Konversationsmodell wechseln · neue Version aufspielen (Betrieb)

Ausführliche Anleitung zum direkten Wechsel über die Kommandozeile. Auch Privatabonnenten können sie unverändert nutzen (kein Schlüssel nötig), und für den gemeinsamen Betrieb bzw. den Kiosk-Betrieb sind Sperroptionen enthalten. Eine einfache Zusammenfassung findest du unter 4.4 Offline.

6.1 Konversationsmodell wechseln (ab 0.91)

Du lässt den Container unverändert und wechselst zur Laufzeit nur das Modell, das die Konversation übernimmt. Stimme (Sprechen · Hören), Wasserzeichen und Abonnementverifizierung bleiben erhalten.

Drei Dinge, die du zuerst wissen solltest:

  1. Das Standardmodell ist ein integriertes Open-Weight-LLM. Du kannst jederzeit auf den Standard zurückkehren, nachdem du gewechselt hast.
  2. Das neu aufzuspielende Modell muss im GGUF-Format vorliegen. Und da die Sprachfunktionen etwa 10 GB Speicher belegen, kann das Konversationsmodell bis etwa 14 GB groß sein. Größere Modelle werden abgelehnt, und falls das Aufspielen fehlschlägt, wird automatisch auf das bisher genutzte Modell zurückgeschaltet (die Konversation wird nicht unterbrochen).
  3. Privatabonnenten brauchen keinen separaten Schlüssel. Die Abonnementverifizierung (Lizenz) auf deinem eigenen Rechner ist gleichbedeutend mit der Berechtigung, daher kannst du einfach mit dem untenstehenden Befehl wechseln — genau wie die Stimme keinen Schlüssel benötigt. (Nur auf einer gemeinsam genutzten Kiosk-Box, die mehrere Personen verwenden, kann der Betreiber beim Start mit -e NAIA_ADMIN_KEY=festgelegtes_passwort eine Sperre setzen; dann sendet man bei der Anfrage zusätzlich -H "Authorization: Bearer festgelegtes_passwort".)

Praxis — lege nur die Adresse fest:

BASE=http://127.0.0.1:8892     # auf einem anderen Gerät: die https-Adresse aus §4.4 (z. B. ...:8443)

① Sieh nach, welches Modell gerade läuft und wie viel Speicher übrig ist:

curl -s $BASE/admin/llm/status

② Wechsle das Modell — ersetze nur die Modellstelle innerhalb der Anführungszeichen und füge es ein. Gib die Adresse der HuggingFace-Modellkarte (https://huggingface.co/Qwen/Qwen2.5-7B-Instruct-GGUF) oder deren id (Qwen/Qwen2.5-7B-Instruct-GGUF) unverändert an:

curl -s -X POST $BASE/admin/llm/swap \
  -H "Content-Type: application/json" \
  -d '{"model":"Qwen/Qwen2.5-7B-Instruct-GGUF","pull":true}'

Das hf.co/-Präfix und die Quantisierung (quant) werden automatisch angehängt (Standard ist Q4_K_M). Wenn du eine bestimmte Quantisierung möchtest, schreibst du sie wie Qwen/Qwen2.5-7B-Instruct-GGUF:Q5_K_M hinten dran. Beim ersten Herunterladen eines Modells dauert es einige Dutzend Sekunden bis ein paar Minuten.

②-Offline — ohne Internet, mit einer eigenen GGUF-Datei wechseln. Wenn es wie bei einer Ausstellung oder Beratung kein Internet gibt, lädst du nicht von HuggingFace, sondern registrierst eine bereits vorhandene GGUF-Datei und wechselst zu ihr. (Unterscheidungsregel: Enthält der Name einen Schrägstrich wie organisation/repository, ist es HuggingFace online; ist es ein einfacher Name ohne Schrägstrich, ist es ein lokales Modell.)

Kopiere die Zeilen einzeln und füge sie ein. Setze an die Stelle meinmodell den gewünschten Namen und an die Stelle meinmodell.gguf den tatsächlichen Dateinamen:

podman cp ./meinmodell.gguf naia-omni:/app/models/meinmodell.gguf
podman exec naia-omni sh -lc 'printf "FROM /app/models/meinmodell.gguf\n" > /tmp/Modelfile && ollama create meinmodell -f /tmp/Modelfile'
curl -s -X POST $BASE/admin/llm/swap -H "Content-Type: application/json" -d '{"model":"meinmodell:latest","pull":false}'

⚠️ Bei einer selbst konvertierten · zusammengeführten GGUF fehlt unter Umständen die Chat-Vorlage, sodass die Antworten zusammenhanglos werden oder abgeschnitten sind. In diesem Fall füge im Modelfile aus Schritt 2 die Chat-Vorlage der Modellfamilie (TEMPLATE) und die Stopp-Tokens (PARAMETER stop) hinzu und registriere es so — Entwicklerdetails unter [Referenzimplementierung §7]. (Offizielle Instruct-GGUFs von HuggingFace enthalten sie meist bereits und funktionieren unverändert.)

③ Auf das Standardmodell zurücksetzen:

curl -s -X POST $BASE/admin/llm/restore

Auf einer gemeinsam genutzten Kiosk-Box (wenn der Betreiber NAIA_ADMIN_KEY gesetzt hat) füge jedem der obigen Befehle -H "Authorization: Bearer festgelegtes_passwort" hinzu. Privatabonnenten brauchen das nicht.

Auch nach dem Wechsel verbinden sich Apps wie naia-os einfach unverändert mit derselben Adresse (eine erneute Verbindung ist nicht nötig). Wenn du möchtest, dass auch nach einem Neustart oder Update weiterhin mit diesem Modell gestartet wird, gib beim Start des Containers mit -e NAIA_LLM_MODEL=Qwen/Qwen2.5-7B-Instruct-GGUF das Standardmodell an.

6.2 Auf eine neue Version aktualisieren

Wenn eine neue Version erscheint, wechselst du nur das Image (die Version) und lässt Abonnement und Einstellungen unverändert. Beim ersten Start der neuen Version reauthentifiziert sich der Container automatisch über das Internet (Abonnement · Gerät bleiben gleich — der Schlüssel muss nicht von Hand erneut eingegeben werden). Daher musst du beim Aktualisieren mit dem Internet verbunden sein.

podman pull ghcr.io/nextain/naia-0.9-omni-24g:latest      # die neueste Version holen
podman stop naia-omni && podman rm naia-omni      # nur den Container aufräumen (siehe Hinweis unten)
# Führe denselben Startbefehl erneut aus, den du bei der Erstinstallation verwendet hast — du musst nur dasselbe Lizenz-Volume erneut einbinden.

⚠️ Drücke beim Aktualisieren nicht auf „Gerät freigeben (release)". Die Freigabe ist nur dafür da, wenn du den genutzten Computer auf einen anderen Computer umziehst. Gibst du beim Versuch zu aktualisieren das Gerät frei, musst du dich von Grund auf neu authentifizieren. Beim Update bleiben Abonnement und Geräteregistrierung erhalten, solange du nur das Lizenz-Volume unverändert lässt.

Wer sich zuvor schon authentifiziert hat, muss wie oben nur die neueste Version holen und neu starten, und geht damit direkt zur neuen Version über, die den Modellwechsel erlaubt (Authentifizierung bleibt erhalten). Um eine bestimmte Version gezielt zu holen, schreibe statt :latest eine Versionsnummer wie :0.91.

7. Siehe auch

  • Referenzimplementierung / Beispielcode (Open Source): der Sprach-Client von naia-os shell/src/lib/voice/ (Apache 2.0) — enthält den tatsächlichen Client, der mit dieser API kommuniziert (naia-omni.ts), sowie die Emotions-/Prosodie-Verarbeitung (emotion-tags.ts; Ausdrucks-Mapping & robuste Extraktion in vrm/expression.ts). Nutze ihn als Ausgangspunkt zum Testen neuer Modelle und zum Erstellen von Tauri-Apps. Probiere ihn live aus auf der 4.3 Live-Demo.
  • Modellpalette & Preise: 4.1 Modellpreise
  • Cloud (geplant): 4.6 Online