Xinference interne Struktur#

Überblick#

Xinference verwendet das von uns entwickelte Actor-Programmierframework Xoscar als Kernkomponente zur Verwaltung von Maschinen, Geräten und Modellinferenzprozessen. Jeder Actor ist eine grundlegende Einheit der Modellinferenz, und verschiedene Inferenz-Backends können in den Actor integriert werden, sodass wir mehrere Inferenz-Engines und Hardware unterstützen können. Diese Actors werden in Actor-Pools gehostet und geplant, wobei die Actor-Pools die Funktion von Ressourcenpools haben. Das Design der Actors ist asynchron und nicht blockierend.

actor

Supervisor und Worker sind beides Actor-Instanzen. Zuerst muss auf jedem Server ein Actor-Pool als Ressourcenpool erstellt werden; jeder Actor kann einen CPU-Kern oder eine GPU-Einheit nutzen. Jeder Server hat seine eigene Adresse (IP-Adresse oder Hostname), sodass Actors auf verschiedenen Rechenknoten über diese Adressen miteinander kommunizieren können. Weitere Informationen finden Sie unter Actor.

RESTful API#

RESTful API wurde mit FastAPI implementiert, der spezifische Code befindet sich in api/restful_api.py.

self._router.add_api_route("/status", self.get_status, methods=["GET"])

Dies ist ein Beispiel für eine API. Die API /status entspricht der Funktion get_status. Sie können die Beziehung zwischen der RESTful-API und der entsprechenden Backend-Funktion in api/restful_api.py hinzufügen.

Kommandozeile#

Die Befehlszeile wird mit Click implementiert, der konkrete Code befindet sich in deploy/cmdline.py. Die Befehlszeile ermöglicht es Benutzern, direkt im Terminal mit Xinference zu interagieren.

Einstiegspunkt#

Nehmen wir die von uns implementierte Kommandozeile als Beispiel:

  • xinference: Bietet Befehle zur Modellverwaltung, einschließlich Registrieren/Abbestellen von Modellen, Auflisten aller registrierten/laufenden Modelle sowie Starten oder Beenden spezifischer Modelle. Es stellt auch interaktive Befehle wie Sprachgenerierung und Chat zur Verfügung, um bereitgestellte Modelle zu testen oder mit ihnen zu interagieren.

  • xinference-local: Starten eines lokalen Xinference-Dienstes.

  • xinference-supervisor: Starten des Supervisor-Prozesses zur Verwaltung und Überwachung von Worker-Actors in einer verteilten Umgebung.

  • xinference-worker: Startet den Worker-Prozess, nutzt verfügbare Rechenressourcen und führt die vom Supervisor zugewiesenen Aufgaben aus.

Jeder Befehl ist mit option und flag ausgestattet, um das Verhalten anzupassen, z. B. das Festlegen von Protokollierungsstufen, Hostadressen, Portnummern und anderen relevanten Einstellungen.

Python-Projekte definieren Befehlszeilen-Konsoleneinstiegspunkte in setup.cfg oder setup.py.

console_scripts =
    xinference = xinference.deploy.cmdline:cli
    xinference-local = xinference.deploy.cmdline:local
    xinference-supervisor = xinference.deploy.cmdline:supervisor
    xinference-worker = xinference.deploy.cmdline:worker

Der Befehlszeilenbefehl xinference kann im Code in xinference.deploy.cmdline:cli nachgeschlagen werden.

Click#

Wir verwenden Click, um bestimmte Befehlszeilen zu implementieren:

@click.option(
      "--host",
      "-H",
      default=XINFERENCE_DEFAULT_DISTRIBUTED_HOST,
      type=str,
      help="Specify the host address for the supervisor.",
  )
  @click.option(
      "--port",
      "-p",
      default=XINFERENCE_DEFAULT_ENDPOINT_PORT,
      type=int,
      help="Specify the port number for the Xinference web ui and service.",
  )

Zum Beispiel erlaubt der Befehl xinference-local Ihnen, die Hostadresse und den Port zu definieren.

Actor#

Xinference basiert auf Xoscar, einem Actor-Framework, das Rechenressourcen und Python-Prozesse verwaltet und skalierbare nebenläufige Programmierung unterstützt. Der folgende Pseudocode demonstriert die Funktionsweise des Worker Actors, wobei der tatsächliche Worker Actor wesentlich komplexer ist.

import xoscar as xo

class WorkerActor(xo.Actor):
    def __init__(self, *args, **kwargs):
        ...
    async def launch_model(self, model_id, n_gpu, ...):
        # launch an inference engine, use specific model class to load model checkpoints
        ...
    async def list_models(self):
        # list models on this actor
        ...
    async def terminate_model(self, model_id):
        # terminate the model
        ...
    async def __post_create__(self):
        # called after the actor instance is created
        ...
    async def __pre_destroy__(self):
        # called before the actor instance is destroyed
        ...

Wir nehmen WorkerActor als Beispiel, um zu erläutern, wie Xinference aufgebaut wird. Jede Actor-Klasse ist eine von xoscar.Actor abgeleitete Standard-Python-Klasse. Eine Instanz dieser Klasse stellt einen bestimmten Actor im Actor-Pool dar.

  • Verhalten des Actors definieren: Jeder Actor muss bestimmte Aktionen oder Verhaltensweisen definieren, um spezifische Aufgaben zu erfüllen. Beispielsweise muss der Modellinferenz-WorkerActor das Modell starten (launch_model), die Modelle in diesem Actor auflisten (list_models) und das Modell beenden (termininate_model). Zwei spezielle Methoden sind beachtenswert. __post_create__ wird vor der Erstellung des Actors aufgerufen, um notwendige Initialisierungen durchzuführen. __pre_destroy__ hingegen wird nach der Zerstörung des Actors aufgerufen, um Bereinigungsaufgaben auszuführen.

  • Actor referenzieren und Methoden aufrufen: Wenn ein Actor erstellt wird, erzeugt er eine Referenzvariable, damit andere Actors darauf verweisen können. Ein Actor kann auch über eine IP-Adresse referenziert werden. Angenommen, WorkerActor wurde erstellt und die Referenzvariable lautet worker_ref, dann kann die Methode launch_model dieser Actor-Klasse über den Aufruf worker_ref.launch_model() aufgerufen werden. Selbst wenn die Methode im Actor ursprünglich eine traditionelle, blockierende Methode war, wird sie bei Verwendung der Referenzvariable zu einer asynchronen Methode.

  • Inferenz-Engine: Ein Actor kann Prozesse verwalten, und eine Inferenz-Engine ist ebenfalls ein Prozess. Im Startmodell des WorkerActor können wir je nach Benutzeranforderung unterschiedliche Inferenz-Engines initialisieren. Daher kann Xinference mehrere Inferenz-Engines unterstützen und sich problemlos an zukünftige neue Inferenz-Engines anpassen.

Siehe Xoscar-Dokumentation für weitere Actor-Anwendungsfälle.

Asynchrone Programmierung#

Xinference und Xoscar sind stark von der asynchronen Programmierbibliothek asyncio abhängig. Asynchrone Programmierung ist ein nicht-blockierendes Programmierparadigma. Im Gegensatz zu herkömmlichen blockierenden Funktionsaufrufen werden Anfragen oder Funktionsaufrufe in der asynchronen Programmierung im Hintergrund ausgeführt, und die Ergebnisse werden zu einem späteren Zeitpunkt zurückgegeben. Der Vorteil der asynchronen Programmierung liegt darin, dass viele verschiedene Aktivitäten oder Aufgaben gleichzeitig parallel ausgeführt werden können.

Wenn Sie mit Pythons asyncio nicht vertraut sind, können Sie weitere Tutorials zur Hilfe heranziehen:

Modell#

Xinference unterstützt verschiedene Modelltypen, darunter große Sprachmodelle (LLMs), Bildmodelle, Audiomodelle, Einbettungsmodelle und mehr. Alle Modelle sind im Ordner model/ implementiert.

LLM#

Am Beispiel von model/llm/ wird hauptsächlich das LLM verwaltet und gestartet, einschließlich des Ladens, Konfigurierens und Ausführens großer Sprachmodelle.

Wir unterstützen verschiedene Inferenz-Backends wie GGML, PyTorch und vLLM. Die generierten Inhalte sind mit dem OpenAI-Format kompatibel, beispielsweise unterstützen wir Streaming-Ausgaben (stream), und das Dialogmodell gibt Ergebnisse im Chat-Completion-Format zurück. Daher sind nach der Modellausgabe viele Anpassungsarbeiten erforderlich. Diese Arbeiten sind nicht schwierig, benötigen jedoch einige Zeit. Beachten Sie beim Schreiben dieses Codeabschnitts die OpenAI API-Dokumentation und die Dokumentation der jeweiligen Inferenz-Backends, um die notwendigen Anpassungen vorzunehmen.

JSON#

In der Datei model/llm/llm_family.json verwenden wir JSON-Dateien, um die Metadaten neu auftauchender Open-Source-Modelle zu verwalten. Das Hinzufügen eines neuen Modells erfordert kein Schreiben neuen Codes, sondern lediglich das Einfügen der neuen Metadaten in die vorhandene JSON-Datei.

{
    "model_name": "llama-2-chat",
    "model_ability": ["chat"],
    "model_specs": [
        {
            "model_format": "ggmlv3",
            "model_size_in_billions": 70,
            "quantization": ["q8_0", ...],
            "model_id": "TheBloke/Llama-2-70B-Chat-GGML",
        },
        ...
    ],
    "prompt_style": {
        "style_name": "LLAMA2",
        "system_prompt": "<s>[INST] <<SYS>>\nYou are a helpful AI assistant.\n<</SYS>>\n\n",
        "roles": ["[INST]", "[/INST]"],
        "stop_token_ids": [2],
        "stop": ["</s>"]
    }
}

Hier ist ein Beispiel, wie das Llama-2 Chat-Modell definiert wird. model_specs definiert die Informationen des Modells, da eine Modellfamilie normalerweise unterschiedliche Größen, Quantisierungsmethoden und Dateiformate aufweist. Beispielsweise kann model_format den Wert pytorch (mit Hugging Face Transformers oder vLLM als Backend), ggmlv3 (Tensor-Bibliothek im Zusammenhang mit llama.cpp) oder gptq (Post-Training-Quantisierungsframework) haben. model_id definiert das Repository im Modellhub, von dem Xinference die Checkpoint-Dateien herunterlädt. Darüber hinaus haben verschiedene Modellfamilien aufgrund unterschiedlicher Instruction-Tuning-Prozesse unterschiedliche Prompt-Stile. Das prompt_style in der JSON-Datei gibt das Format des Prompts für dieses spezifische Modell an. Beispielsweise werden system_prompt und roles verwendet, um die Anweisungen und die Persönlichkeit des Modells zu definieren.

Code-Leitfaden#

Der Hauptcode befindet sich in xinference/:

  • api/restful_api.py ist der Kern für die Einrichtung und Ausführung der RESTful-API. Es integriert einen Authentifizierungsdienst (der spezifische Code befindet sich in oauth2/), da einige oder alle Ports eine Benutzerauthentifizierung erfordern.

  • client/:Dies ist der Client von Xinference.

    • oscar/ definiert den Actor-Client, eine Clientschnittstelle zur Interaktion mit Modellen in Xinference.

    • restful/ implementiert den RESTful-Client für die Interaktion mit dem Xinference-Dienst.

  • core/: Dies ist der Kernbereich von Xinference.

    • metrics.py und resource.py definieren eine Reihe von Werkzeugen zur Erfassung und Meldung von Metriken sowie des Knotenressourcenzustands, einschließlich Modelldurchsatz, Latenz, CPU- und GPU-Auslastung, Speichernutzung usw.

    • image_interface.py und chat_interface.py implementieren die Gradio -Schnittstellen für Bild- und Chat-Modelle. Diese Schnittstellen ermöglichen es Benutzern, über die Weboberfläche mit den Modellen zu interagieren, wie z. B. Bilder zu generieren oder Gespräche zu führen. Der Code verwendet das Gradio-Paket zur Erstellung der Benutzeroberfläche und kommuniziert über unsere RESTful-API mit den Backend-Modellen.

    • worker.py und supervisor.py definieren die Logik des Worker-Actors bzw. des Supervisor-Actors. Der Worker-Actor ist für die Ausführung spezifischer Modellberechnungsaufgaben zuständig, während der Supervisor-Actor den Lebenszyklus der Worker-Knoten und die Aufgabenplanung verwaltet sowie den Systemzustand überwacht.

    • status_guard.py implementiert einen Statusmonitor zur Verfolgung des Modellstatus (z. B. Erstellung, Aktualisierung, Beendigung). Es ermöglicht das Abfragen von Statusinformationen einer Modellinstanz anhand ihrer UID.

    • cache_tracker.py definiert einen Cache-Tracker, der verwendet wird, um den Cache-Status und die Modellversionsinformationen aufzuzeichnen und zu verwalten. Er unterstützt das Aufzeichnen des Cache-Speicherorts und des Status der Modellversion sowie das Abfragen von Modellversionsinformationen anhand des Modellnamens.

    • event.py definiert einen Ereignissammler, der verschiedene Laufzeitereignisse von Modellen wie Informationen, Warnungen und Fehler sammelt und meldet. model.py definiert einen Modell-Actor, der die zentrale Komponente für die direkte Interaktion mit Modellen darstellt. Der Modell-Actor ist für die Ausführung von Modell-Inferenzanfragen, die Verarbeitung von Eingabe- und Ausgabedatenströmen sowie die Unterstützung verschiedener Modelloperationen verantwortlich. Beide Teile verwenden Xoscar für die nebenläufige und verteilte Ausführung.

  • deploy/: Es stellt eine Befehlszeilenschnittstelle (CLI) zur Verfügung, um mit dem Xinference-Framework zu interagieren, sodass Benutzer über die Befehlszeile operieren können. Weitere Informationen finden Sie unter Command Line.

  • locale/:Es unterstützt mehrsprachige Lokalisierung. Fügen Sie einfach JSON-Übersetzungsdateien hinzu und aktualisieren Sie diese, um weitere Sprachen zu unterstützen und die Benutzererfahrung zu verbessern.

  • model/: Es stellt ein Framework für die Beschreibung, Erstellung und das Caching von Modellen bereit. Weitere Informationen finden Sie unter Model.

  • web/ui/: Der JavaScript-Code des Frontends (Benutzeroberfläche).