Preise

Projektüberblick

Quelldateien

Diese Seite wurde aus den folgenden Quelldateien erstellt:

Nano-vLLM ist eine leichtgewichtige, von Grund auf neu implementierte vLLM-Variante, die für hohe Inferenzgeschwindigkeit und Code-Lesbarkeit optimiert ist. Das Projekt bietet eine saubere Implementierung in etwa 1.200 Zeilen Python-Code und erreicht vergleichbare Inferenzgeschwindigkeiten wie das ursprüngliche vLLM (README.md:9-17). Die offizielle Projektbeschreibung definiert es als "a lightweight vLLM implementation built from scratch" (pyproject.toml:5-13).

Projektvorstellung und Zielsetzung

Nano-vLLM wurde entwickelt, um eine vereinfachte, aber dennoch leistungsstarke Alternative zum etablierten vLLM-Framework bereitzustellen. Der Fokus liegt auf drei Kernzielen: schnelle Offline-Inferenz mit vLLM-komparabler Geschwindigkeit, eine lesbare und wartbare Codebasis sowie eine umfassende Optimierungssuite inklusive Prefix Caching, Tensor Parallelism, Torch Compilation und CUDA Graph (README.md:9-17).

Das Projekt richtet sich an Entwickler und Forscher, die:

  • Die internen Mechanismen von LLM-Inferenz-Engines verstehen möchten
  • Eine leichtgewichtige Alternative für Experimente und Prototypen suchen
  • Von fortschrittlichen Optimierungstechniken profitieren möchten, ohne die Komplexität des vollständigen vLLM-Frameworks

Die MIT-Lizenz ermöglicht eine breite Nutzung und Modifikation in sowohl akademischen als auch kommerziellen Kontexten (pyproject.toml:5-13).

Technologie-Stack und Abhängigkeiten

Das Projekt basiert auf einem modernen Technologie-Stack, der speziell für hochperformante LLM-Inferenz optimiert ist.

KomponenteVersionZweck
Python3.10-3.12Laufzeitumgebung
PyTorch≥2.4.0Deep Learning Framework
Triton≥3.0.0GPU-Kernel-Optimierung
Transformers≥4.51.0HuggingFace-Modellintegration
Flash-Attention-Effiziente Attention-Berechnung
xxhash-Hashing für Prefix Caching

Die Abhängigkeiten sind in pyproject.toml:13-20 definiert und spiegeln die Anforderungen für GPU-beschleunigte Inferenz wider. Die öffentliche API wird durch zwei Hauptsymbole exportiert: LLM als Haupteinstiegspunkt und SamplingParams zur Steuerung der Generierungsparameter (nanovllm/init.py:1-2).

python
1# Öffentliche API-Schnittstelle
2from nanovllm import LLM, SamplingParams
3
4# Initialisierung mit Modellpfad
5llm = LLM("/YOUR/MODEL/PATH", enforce_eager=True, tensor_parallel_size=1)
6sampling_params = SamplingParams(temperature=0.6, max_tokens=256)

Architektur und Hauptkomponenten

Die Architektur von Nano-vLLM folgt einem modularen Design mit klar definierten Verantwortlichkeiten zwischen den einzelnen Komponenten.

Systemarchitektur

正在加载图表渲染器...

Architektur-Erklärung:

  1. API-Schicht: Die LLM-Klasse fungiert als dünner Wrapper um LLMEngine und stellt die primäre Benutzerschnittstelle dar (nanovllm/llm.py:4-5). SamplingParams definiert die Generierungsparameter wie Temperatur und maximale Token-Anzahl.

  2. Engine-Schicht: Der LLMEngine ist das Herzstück und koordiniert alle Inferenzoperationen. Er verwaltet den Scheduler für Anfrage-Priorisierung und den ModelRunner für die eigentliche Modell-Ausführung (nanovllm/engine/llm_engine.py:15-35).

  3. Konfiguration: Die Config-Klasse bündelt alle Engine-Parameter einschließlich Tensor-Parallel-Grad, GPU-Speichernutzung und KV-Cache-Block-Konfiguration (nanovllm/config.py:7-26).

  4. Tensor Parallelism: Bei tensor_parallel_size > 1 werden zusätzliche Prozesse mittels mp.get_context("spawn") gestartet, um die Modellberechnung auf mehrere GPUs zu verteilen (nanovllm/engine/llm_engine.py:23-29).

Kernmodul: Config

Die Config-Klasse ist ein Dataclass, das alle Engine-Parameter definiert und validiert:

ParameterTypStandardBeschreibung
modelstr-Modellverzeichnispfad
max_num_batched_tokensint16384Maximale Token pro Batch
max_num_seqsint512Maximale parallele Sequenzen
max_model_lenint4096Maximale Sequenzlänge
gpu_memory_utilizationfloat0.9GPU-Speicherauslastung
tensor_parallel_sizeint1Anzahl paralleler GPUs
enforce_eagerboolFalseDeaktiviert CUDA Graph
kvcache_block_sizeint256KV-Cache-Blockgröße

Die __post_init__-Methode führt kritische Validierungen durch: Sie stellt sicher, dass das Modellverzeichnis existiert, die Blockgröße ein Vielfaches von 256 ist, und tensor_parallel_size zwischen 1 und 8 liegt (nanovllm/config.py:20-26). Zusätzlich wird die max_model_len gegen die HuggingFace-Konfiguration begrenzt.

Kernmodul: LLMEngine

Der LLMEngine implementiert die zentrale Inferenzlogik mit folgenden Hauptverantwortlichkeiten:

Initialisierung (nanovllm/engine/llm_engine.py:17-34):

  • Extrahiert gültige Konfigurationsparameter aus kwargs
  • Startet Tensor-Parallel-Prozesse für sekundäre GPUs
  • Initialisiert den primären ModelRunner
  • Lädt den Tokenizer und setzt EOS-Token-ID
  • Registriert Exit-Handler für sauberes Herunterfahren

Anfrageverwaltung:

  • add_request(): Konvertiert String-Prompts zu Token-IDs und erstellt Sequence-Objekte
  • step(): Führt einen Inferenzschritt aus (Prefill oder Decode)
  • generate(): Hauptschleife für Batch-Generierung mit Fortschrittsanzeige

Kernmodul: Sequence

Die Sequence-Klasse repräsentiert eine einzelne Generierungsanfrage mit folgenden Eigenschaften:

python
1@dataclass
2class Sequence:
3    block_size = 256  # Klasseneigene Konstante
4    counter = count()  # Globale Sequenz-ID-Zähler
5    
6    # Instanzattribute
7    seq_id: int           # Eindeutige Sequenz-ID
8    status: SequenceStatus  # WAITING, RUNNING, FINISHED
9    token_ids: list[int]  # Alle Token (Prompt + Completion)
10    num_cached_tokens: int  # Für Prefix Caching
11    block_table: list     # KV-Cache-Blockzuordnung

Die Klasse bietet mehrere berechnete Eigenschaften:

  • num_blocks: Berechnet die Anzahl benötigter KV-Cache-Blöcke
  • num_cached_blocks: Anzahl bereits gecachter Blöcke
  • last_block_num_tokens: Token im letzten (teilgefüllten) Block
  • is_finished: Prüft ob Sequenz abgeschlossen ist

Die __getstate__ und __setstate__ Methoden ermöglichen effiziente Serialisierung für die Inter-Prozess-Kommunikation bei Tensor Parallelism (nanovllm/engine/sequence.py:74-83).

Kernmodul: SamplingParams

Die SamplingParams-Klasse definiert die Generierungsparameter:

ParameterTypStandardBeschreibung
temperaturefloat1.0Sampling-Temperatur
max_tokensint64Maximale Generierungstoken
ignore_eosboolFalseEOS-Token ignorieren

Die Validierung in __post_init__ stellt sicher, dass temperature > 1e-10, da Greedy-Sampling (temperature=0) nicht unterstützt wird (nanovllm/sampling_params.py:10-11).

Datenfluss und Inferenzpipeline

Der Datenfluss durch das System folgt einer klaren Pipeline von der Anfrageeingabe bis zur Textausgabe.

正在加载图表渲染器...

Datenfluss-Erklärung:

  1. Anfrageeingabe: Der Benutzer ruft LLM.generate() mit einer Liste von Prompts und Sampling-Parametern auf. Die API akzeptiert sowohl String-Prompts als auch vorab tokenisierte Token-ID-Listen (nanovllm/engine/llm_engine.py:59-64).

  2. Sequenz-Erstellung: Jeder Prompt wird in eine Sequence-Instanz umgewandelt. Bei String-Eingaben erfolgt die Tokenisierung durch den AutoTokenizer (nanovllm/engine/llm_engine.py:42-46).

  3. Scheduling-Schleife: Die Hauptschleife ruft wiederholt step() auf, bis alle Sequenzen abgeschlossen sind. Jeder Schritt besteht aus:

    • Scheduler-Aufruf zur Auswahl der nächsten Sequenzen
    • ModelRunner-Ausführung für Forward Pass
    • Postprocessing zur Token-Extraktion und Status-Updates
  4. Prefill vs. Decode: Der Scheduler unterscheidet zwischen Prefill-Phase (erste Verarbeitung des Prompts) und Decode-Phase (iteratives Generieren neuer Token). Die step()-Methode gibt is_prefill zurück, um den aktuellen Modus zu kennzeichnen (nanovllm/engine/llm_engine.py:48-54).

  5. Ausgabeformat: Die Ergebnisse werden als Liste von Dictionaries zurückgegeben, wobei jedes Dictionary text (dekodierter String) und token_ids (Token-ID-Liste) enthält (nanovllm/engine/llm_engine.py:89-90).

Leistungsbenchmark und Ergebnisse

Die Leistung von Nano-vLLM wurde gegen das etablierte vLLM-Framework unter kontrollierten Bedingungen getestet.

Testkonfiguration (bench.py:8-18):

  • Hardware: RTX 4070 Laptop (8GB VRAM)
  • Modell: Qwen3-0.6B
  • Gesamtanfragen: 256 Sequenzen
  • Eingabelänge: Zufällig zwischen 100-1024 Token
  • Ausgabelänge: Zufällig zwischen 100-1024 Token

Ergebnisse (README.md:57-62):

Inferenz-EngineAusgabe-TokenZeit (s)Durchsatz (tokens/s)
vLLM133.96698,371.361,84
Nano-vLLM133.96693,411.434,13

Nano-vLLM erreicht einen 5,3% höheren Durchsatz im Vergleich zu vLLM unter identischen Testbedingungen. Die Benchmark-Implementierung verwendet ignore_eos=True, um konsistente Ausgabelängen zu gewährleisten und den Vergleich zu vereinfachen (bench.py:18).

python
1# Benchmark-Konfiguration
2llm = LLM(path, enforce_eager=False, max_model_len=4096)
3sampling_params = [
4    SamplingParams(temperature=0.6, ignore_eos=True, max_tokens=randint(100, max_ouput_len)) 
5    for _ in range(num_seqs)
6]

API-Design und Verwendungsbeispiel

Die API von Nano-vLLM ist an die vLLM-Schnittstelle angelehnt, um eine einfache Migration zu ermöglichen.

Grundlegende Verwendung

python
1from nanovllm import LLM, SamplingParams
2from transformers import AutoTokenizer
3
4# Modell initialisieren
5path = "~/huggingface/Qwen3-0.6B/"
6tokenizer = AutoTokenizer.from_pretrained(path)
7llm = LLM(path, enforce_eager=True, tensor_parallel_size=1)
8
9# Sampling-Parameter konfigurieren
10sampling_params = SamplingParams(temperature=0.6, max_tokens=256)
11
12# Prompts vorbereiten (mit Chat-Template)
13prompts = ["introduce yourself", "list all prime numbers within 100"]
14prompts = [
15    tokenizer.apply_chat_template(
16        [{"role": "user", "content": prompt}],
17        tokenize=False,
18        add_generation_prompt=True,
19    )
20    for prompt in prompts
21]
22
23# Generierung ausführen
24outputs = llm.generate(prompts, sampling_params)
25
26# Ergebnisse ausgeben
27for prompt, output in zip(prompts, outputs):
28    print(f"Prompt: {prompt!r}")
29    print(f"Completion: {output['text']!r}")

API-Parameter

LLM-Initialisierung (README.md:39):

  • model: Pfad zum HuggingFace-Modellverzeichnis
  • enforce_eager: Deaktiviert CUDA Graph für Debugging
  • tensor_parallel_size: Anzahl paralleler GPUs (1-8)
  • max_model_len: Maximale Sequenzlänge

SamplingParams (nanovllm/sampling_params.py:5-9):

  • temperature: Kontrolliert die Zufälligkeit der Generierung
  • max_tokens: Maximale Anzahl zu generierender Token
  • ignore_eos: Wenn True, wird das EOS-Token ignoriert

Verzeichnisstruktur

nano-vllm/
├── nanovllm/
│   ├── __init__.py          # Öffentliche API-Exporte
│   ├── llm.py               # LLM-Klasse (Wrapper)
│   ├── config.py            # Engine-Konfiguration
│   ├── sampling_params.py   # Sampling-Parameter
│   └── engine/
│       ├── llm_engine.py    # Kern-Engine-Logik
│       └── sequence.py      # Sequence-Datenstruktur
├── example.py               # Verwendungsbeispiel
├── bench.py                 # Benchmark-Skript
├── pyproject.toml           # Projektmetadaten
└── README.md                # Dokumentation

Kernmerkmale und Optimierungen

Nano-vLLM bietet eine Reihe fortschrittlicher Optimierungen:

MerkmalBeschreibungImplementierung
Prefix CachingWiederverwendung von KV-Cache für gemeinsame Prompt-Präfixenum_cached_tokens in Sequence
Tensor ParallelismVerteilte Inferenz auf mehrere GPUsMultiprocessing mit Spawn-Kontext
CUDA GraphOptimierung für wiederholte Kernel-Aufrufeenforce_eager=False
Flash AttentionSpeichereffiziente Attention-BerechnungFlash-Attention-Abhängigkeit
Paged KV-CacheBlockbasierte Cache-Verwaltungkvcache_block_size=256
Batch SchedulingDynamische Batch-ZusammenstellungScheduler-Komponente

Anwendungsgebiete

Nano-vLLM eignet sich für folgende Szenarien:

  1. Forschung und Bildung: Die kompakte Codebasis ermöglicht ein tiefes Verständnis von LLM-Inferenz-Mechanismen ohne die Komplexität produktionsreifer Systeme.

  2. Prototyp-Entwicklung: Schnelle Iteration bei der Entwicklung neuer Modelle oder Inferenzstrategien mit minimaler Setup-Zeit.

  3. Ressourcenbeschränkte Umgebungen: Optimiert für Consumer-Hardware wie Laptop-GPUs mit begrenztem VRAM.

  4. Benchmarking und Vergleich: Standardisierte Testumgebung für Modellvergleiche ohne Overhead produktionsreifer Systeme.

  5. Custom Optimierungen: Die saubere Codebasis erleichtert die Implementierung eigener Optimierungen und Experimente.

Berichtsstruktur und Leseführung

Die folgende Grafik zeigt die empfohlene Lesereihenfolge für die technische Dokumentation:

正在加载图表渲染器...

Empfohlene Lesereihenfolge:

  1. Projektüberblick (aktuelle Seite): Grundlegende Konzepte und Architektur
  2. Architektur: Detaillierte Analyse der Engine-Komponenten
  3. API-Design: Vollständige API-Referenz und erweiterte Nutzung
  4. Performance: Detaillierte Benchmark-Analysen und Optimierungsstrategien
  5. Deployment: Produktionsbereitstellung und Skalierung

Quantifizierte Projektkennzahlen

MetrikWert
Codezeilen (Kern)~1.200
Python-Dateien6
Öffentliche API-Klassen2 (LLM, SamplingParams)
Unterstützte Python-Versionen3 (3.10, 3.11, 3.12)
Kernabhängigkeiten6
Maximale Tensor-Parallel-Größe8
Standard-KV-Cache-Blockgröße256 Token
Maximale Batch-Token16.384
Maximale parallele Sequenzen512
GPU-Speicherauslastung90% (konfigurierbar)

Das Projekt repräsentiert eine gelungene Balance zwischen Einfachheit und Leistungsfähigkeit, die es sowohl für Lernzwecke als auch für praktische Anwendungen attraktiv macht. Die Benchmark-Ergebnisse zeigen, dass eine saubere, verständliche Implementierung nicht zwangsläufig Performance-Einbußen bedeuten muss.