Modellladen und Inferenz
English | 简体中文 | 日本語 | Deutsch | Русский
Dokumentation · Schulung · 中文
ruLLM bietet Modellladen, Tokenisierung, zwischengespeicherte autoregressive Generierung und Anforderungsplanung. Sein Cargo-Paket ist ruLLM; Sein Rust-Importname ist rullm.
Bereiten Sie ein lokales Modell vor
Bewahren Sie die Modelldateien in einem Verzeichnis auf:
| Datei | Zweck |
|---|---|
config.json |
Modellarchitektur und Parameter |
model.safetensors |
Einzeldateigewichtungen |
model.safetensors.index.json und jeder aufgelistete Shard |
Geteilte Gewichtungen anstelle einer einzelnen Gewichtsdatei |
tokenizer.json |
Text-Tokenisierung und -Dekodierung |
tokenizer_config.json |
ChatML-Vorlage für Qwen2/Qwen2.5-Pipelines erforderlich |
generation_config.json |
Optionale Konfiguration der Qwen2/Qwen2.5-Generation, die EOS-Einstellungen bereitstellt |
preprocessor_config.json |
Qwen3.5-Bildvorverarbeitungskonfiguration, erforderlich für die Bildeingabe |
Loader akzeptieren lokale Verzeichnisse und laden keine Modelle herunter. Wählen Sie den Loader für Ihre Architektur aus:
| Modell/Eingabe | Lader |
|---|---|
| Unquantisierter Lama-Text | load_huggingface_llama_pipeline::<B> |
| Unquantisierter Qwen2/Qwen2.5-Text | load_huggingface_qwen2_pipeline::<B> |
| AWQ GEMM INT4 Qwen2/Qwen2.5 | load_huggingface_awq_qwen2_pipeline::<R> |
| Unquantisierter Qwen3.5-Text | load_huggingface_qwen35_text::<B> |
| Qwen3.5 Vision-Encoder | load_huggingface_qwen35_vision::<B> |
| Qwen3.5 Bilder und Text | load_huggingface_qwen35_multimodal::<B> |
B ist ein Tensor-Backend; R ist eine Gerätelaufzeit. Der Qwen3.5-Textlader verwendet eine qwen3_5_text-Konfiguration mit layer_types pro Schicht und lehnt Quantisierungskonfigurationen ab. Übergeben Sie AWQ-Dateien nicht an einen Gleitkomma-Loader.
Führen Sie die Beispiele zur Textgenerierung aus
Führen Sie nach dem Einrichten der Umgebung diese Befehle im Quellstammverzeichnis aus. Die relativen Pfade verweisen auf zwei lokale Modellverzeichnisse:
$env:RUDA_CUDA_COMPILER = 'nvrtc'
cargo run --locked -p ruda-llm --features nvidia --example qwen2_generate -- ./models/qwen2 "Hello" 32 1
Das Qwen3.5-Beispiel verwendet standardmäßig Ruda IR → PTX, wenn RUDA_CUDA_COMPILER nicht festgelegt ist. Verwenden Sie --release für eine optimierte Ausführung. Nicht unterstützte direkte PTX-Vorgänge geben Fehler zurück, anstatt auf NVRTC zurückzugreifen. Die PTX-Version muss mit der Zielversion GPU und dem Treiber übereinstimmen. siehe die PTX Backend-Referenz.
Remove-Item Env:RUDA_CUDA_COMPILER -ErrorAction SilentlyContinue
$env:RUDA_PTX_VERSION = '8.0'
cargo run --release --locked -p ruda-llm --features nvidia-ptx --example qwen35_generate -- ./models/qwen35 "Hello" 8 1
Der Pfad CUDA C++ / NVRTC bleibt mit einer expliziten Auswahl verfügbar:
$env:RUDA_CUDA_COMPILER = 'nvrtc'
cargo run --release --locked -p ruda-llm --features nvidia-ptx --example qwen35_generate -- ./models/qwen35 "Hello" 8 1
Argumente sind das Modellverzeichnis, die Rohtext-Eingabeaufforderung, die maximale Anzahl neuer Token und die Anzahl der Ausführungen. Die letzten beiden sind standardmäßig 32 und 1 für Qwen2 oder 8 und 1 für Qwen3.5. Die Laufanzahl muss positiv sein. Beispiele drucken JSON-Zeilen zum Laden und Generieren. Zu den Generationslinien gehören text, generated_token_ids und stopped_on_eos.
Diese Beispiele kodieren die Eingabeaufforderung direkt, ohne eine Chat-Vorlage hinzuzufügen. Bereiten Sie für Konversationsmodelle die Eingabeaufforderung mit render_chat wie folgt vor.
Erzeugen Sie eine Chat-Antwort in einer Anwendung
Für ein Anwendungsverzeichnis neben dem Quellverzeichnis RUDA verwenden Sie diese Abhängigkeiten.
[dependencies]
rullm = { package = "ruLLM", path = "../RUDA/ruLLM", features = ["nvidia"] }
ruda-tensor-device = { path = "../RUDA/ruda-tensor-device", default-features = false, features = ["std", "cuda"] }
ruda-driver-cuda = { path = "../RUDA/ruda-driver-cuda", default-features = false, features = ["std"] }
half = "=2.7.1"
Dieses vollständige src/main.rs akzeptiert ein Modellverzeichnis und eine Benutzernachricht als Befehlszeilenargumente. Spätere Funktionsbeispiele verwenden ihren B-Alias, ihre Importe und Abhängigkeiten wieder:
use half::bf16;
use ruda_tensor_device::cuda::{Cuda, CudaDevice};
use rullm::{
GreedyGenerationConfig, Qwen2ChatMessage, Qwen2ChatRole,
load_huggingface_qwen2_pipeline,
};
use std::{error::Error, io};
type B = Cuda<bf16, i32>;
fn main() -> Result<(), Box<dyn Error>> {
let mut args = std::env::args().skip(1);
let directory = args.next().ok_or_else(|| io::Error::other("model directory required"))?;
let prompt = args.next().ok_or_else(|| io::Error::other("prompt required"))?;
let device = CudaDevice::default();
let pipeline = load_huggingface_qwen2_pipeline::<B>(&directory, &device)?;
let messages = [Qwen2ChatMessage::new(Qwen2ChatRole::User, prompt)];
let prompt = pipeline.render_chat(&messages, true)?;
let output = pipeline.generate_text(
&prompt,
GreedyGenerationConfig {
max_new_tokens: 32,
eos_token_ids: pipeline.loaded.default_eos_token_ids.clone(),
},
false,
true,
&device,
)?;
println!("{}", output.generated_text);
Ok(())
}
render_chat verarbeitet Klartext-Qwen2/Qwen2.5 ChatML-Nachrichten. Durch die Übergabe von true wird das Präfix für die Assistentengenerierung hinzugefügt. Zu den Rollen gehören auch System und Assistant; Geben Sie Nachrichten in der Konversationsreihenfolge an. Dieser API akzeptiert keine Tool-Call-Nachrichten.
Die beiden booleschen Argumente für generate_text sind add_special_tokens und skip_special_tokens. Fügen Sie nach dem Rendern von ChatML keine weiteren Sondertoken hinzu. Beim Dekodieren können sie übersprungen werden. generated_text enthält nur die neue Antwort, während text sowohl Aufforderung als auch Antwort enthält.
Temperatur, Top-K- und Top-P-Probenahme
Übergeben Sie die gerenderte Eingabeaufforderung an generate_text_sampled:
use rullm::{
GeneratedText, HuggingFaceLoadError, HuggingFaceQwen2Pipeline,
SamplingConfig, SamplingGenerationConfig,
};
fn sample_text(
pipeline: &HuggingFaceQwen2Pipeline<B>,
prompt: &str,
device: &CudaDevice,
) -> Result<GeneratedText, HuggingFaceLoadError> {
pipeline.generate_text_sampled(
prompt,
SamplingGenerationConfig {
max_new_tokens: 32,
eos_token_ids: pipeline.loaded.default_eos_token_ids.clone(),
sampling: SamplingConfig {
temperature: 0.8,
top_k: 40,
top_p: 0.9,
seed: Some(42),
},
},
false,
true,
device,
)
}
| Parameter | Werte und Wirkung |
|---|---|
temperature |
Endlich und positiv; scales meldet sich zuerst an |
top_k |
Hält die Token mit der höchsten Punktzahl als nächstes; 0 deaktiviert die Filterung, Bindungen an der Grenze bleiben erhalten |
top_p |
Filtert schließlich nach kumulativer Wahrscheinlichkeit; Bereich (0, 1], wobei 1 die Filterung deaktiviert |
seed |
Anforderungs-Lokaler Probenahme-Seed; None verwendet Systementropie |
max_new_tokens |
Begrenzt neue Token, mit Ausnahme der Eingabeaufforderung |
eos_token_ids |
Stoppt nach der Generierung eines aufgelisteten Tokens |
Verwenden Sie generate_text für die Decodierung mit maximalem Logit, anstatt die Temperatur auf Null zu setzen. Ein fester Startwert legt die zufällige Stichprobensequenz fest, nicht die numerische Konsistenz zwischen Modellen oder Backends.
AWQ-Gewichte laden
Der AWQ-Loader verwendet CudaRuntime und nicht Cuda<bf16, i32> als generischen Parameter:
use ruda_driver_cuda::CudaRuntime;
use rullm::{HuggingFaceAwqQwen2Pipeline, load_huggingface_awq_qwen2_pipeline};
fn load_awq(
directory: &str,
device: &CudaDevice,
) -> Result<HuggingFaceAwqQwen2Pipeline<CudaRuntime>, HuggingFaceLoadError> {
load_huggingface_awq_qwen2_pipeline::<CudaRuntime>(directory, device)
}
Die zurückgegebene Pipeline stellt außerdem render_chat, encode, decode, generate_text und generate_text_sampled bereit. Für die AWQ-Konfiguration sind quant_method = "awq", bits = 4, version = "gemm" und zero_point = true erforderlich. group_size muss positiv sein oder -1. Lineare Projektionen verwenden F16-Aktivierungen. Siehe ruBLAS INT4 für gepackte Gewichtslayouts.
Qwen3.5-Bildeingabe
generate_image_files_greedy benötigt Token-IDs für eine Eingabeaufforderung, JPEG/PNG-Pfade in Eingabeaufforderungsreihenfolge, einen Bildprozessor und Generierungsoptionen:
use rullm::{
Qwen35ImageProcessor, TokenGenerationOutput,
load_huggingface_qwen35_multimodal,
};
fn generate_from_images(
directory: &str,
prompt_ids: &[i32],
paths: &[&str],
device: &CudaDevice,
) -> Result<TokenGenerationOutput, Box<dyn Error>> {
let model = load_huggingface_qwen35_multimodal::<B>(directory, device)?;
let processor = Qwen35ImageProcessor::from_huggingface(directory)?;
let output = model.generate_image_files_greedy(
prompt_ids,
paths,
&processor,
&GreedyGenerationConfig {
max_new_tokens: 32,
eos_token_ids: vec![model.text.config.eos_token_id],
},
)?;
Ok(output)
}
Kodieren Sie prompt_ids mit dem tokenizer.json des Modells. Befolgen Sie die Eingabeaufforderungsvorlage des Modells und behalten Sie ein Platzhaltertoken pro Bild bei, indem Sie image_token_id aus config.json verwenden. Bildpfade müssen mit der Anzahl und Reihenfolge der Platzhalter übereinstimmen. Dieser Einstiegspunkt erweitert Platzhalter intern; Erweitern Sie sie nicht vorher. Es verarbeitet Standbilder und lehnt Video-Tokens ab.
Für vorhandene RGB8-Daten verwenden Sie Qwen35RgbImage { pixels, height, width } mit generate_rgb_greedy. Pixel sind verschachtelte RGB-Bytes ohne Zeilenauffüllung. Für die separate Vorverarbeitung geben preprocess_files und preprocess_rgb FP32 patches, ein zweidimensionales shape und ein bildbezogenes grids zurück.
Wenn Sie mehrere Anfragen bedienen, laden Sie das Modell und den Prozessor außerhalb der Anfrageschleife. Dekodieren Sie den zurückgegebenen generated_token_ids mit demselben Tokenizer.
Caches und kontinuierliche Stapelverarbeitung
Generierungsfunktionen für einzelne Anforderungen erstellen und verwalten einen Cache für diese Generierung. Um Qwen3.5 manuell zu steuern, rufen Sie model.new_cache() auf, übergeben Sie den Prompt-Tensor an forward_cached_last(tokens, &mut cache) und übergeben Sie dann nur neue Token. Übermitteln Sie nicht das gesamte zwischengespeicherte Präfix erneut.
Um Ihren eigenen Batch-Executor zu integrieren, verwenden Sie ContinuousBatchScheduler:
- Erstellen Sie es mit
ContinuousBatchScheduler::new(config, kv_config).ContinuousBatchConfigsetztmax_active_sequencesundmax_batch_tokens.PagedKvCacheConfiglegtblock_size,num_pagesundmax_sequence_lengthfest. Alles muss positiv sein. - Senden Sie Anforderungen mit
submit(prompt_token_ids, generation)und behalten Sie alle zurückgegebenenRequestIdbei. - Rufen Sie
schedule()für einenScheduledBatchan. Seinkindzeichnet sich durch Prefill/Decode aus;sequencesstellt die Token, die Startposition, die Kontextlänge und die Blocktabelle jeder Zeile bereit. - Führen Sie das Modell in Zeilenreihenfolge aus, schreiben Sie die entsprechenden KV-Seiten und wählen Sie das nächste Token jeder Zeile aus. Rufen Sie bei Erfolg
complete_batch(batch.id, &generated_token_ids)mit einem Ergebnistoken pro Zeile auf. Rufen Sie bei einem Fehlerfail_batch(batch.id)auf, um die Seitenreservierungen dieses Stapels zu stornieren. - Abgeschlossene Anfragen und generierte Token mit
pop_finished()abrufen und dann mit der Planung fortfahren.
Der Scheduler verwaltet Anfragen und Seitenzuordnungsmetadaten. Der Ausführende des Aufrufers besitzt den Speicher und die Modellausführung des Geräts KV. Verwenden Sie token_matrix(), context_lengths() und flattened_block_table(), um Batch-Eingaben zu erstellen. Schließen Sie einen ausstehenden Stapel ab oder stornieren Sie ihn, bevor Sie schedule() erneut aufrufen.
API-Referenz: ruLLM-Exporte, Generierungsoptionen, Planer.
Qwen3.5: fusionierte seitenbasierte Attention
Qwen35BatchCache wählt seinen Attention-Pfad bei der Erstellung durch new_batch_cache. Setzen Sie RUDA_PAGED_ATTENTION=fused vor der Cache-Erstellung, um ruDNNs fusionierte seitenbasierte Attention im kontinuierlichen Batching von Qwen3.5 zu verwenden. Ohne Variable oder mit legacy bleibt der bisherige Pfad erhalten; andere Werte werden abgewiesen. Eine Änderung schaltet einen bestehenden Cache nicht um und ist kein globaler Schalter für alle Generierungseinstiege.
Der fusionierte Pfad hält pro Full-Attention-Schicht eine physische KV-Arena und verwendet die Seitentabellen des Schedulers für Prefill/Decode, ohne historische KV-Daten in aufgefüllte Tensoren zusammenzutragen. Die Arena-Dimensionen ergeben sich aus num_pages, block_size, KV-Kopfzahl und Kopfdimension; reservieren Sie GPU-Speicher für diese Kapazität. Eingaben folgen ruDNNs Vertrag für zusammenhängende F32/F16/BF16-Tensoren. Schreibzugriffe auf gemeinsame Präfixseiten erfordern Copy-on-Write durch den Scheduler. Nach einem fehlgeschlagenen geräteseitigen Append muss der Cache neu aufgebaut werden, statt an der vorherigen Position fortzufahren.
Wiederverwendbare Attention- und MoE-Komponenten
rullm::gpu_inference stellt TensorOps, gqa_scores, gqa_value_product, mla_absorb_query, mla_scores und mla_value_product bereit. Sie kombinieren geräteseitige Tensoroperationen des Aufrufers, ohne gecachte GQA-Köpfe zu vervielfachen oder historische latente MLA-Werte zu expandieren. Maskierung, Softmax, Positionskodierung und modellspezifische Skalierung stellt der Aufrufer bereit.
rullm::device_inference re-exportiert ruDNNs HostPlan, DevicePlan, PagedAttentionError, SwiGluExperts, RoutingOptions, GroupRoutingOptions, route_sigmoid_grouped und GroupedStrategy. Dies sind Bausteine, kein vollständiger MLA/MoE-Modelllader; Adapter müssen weiterhin Projektionen, Routing-Konfiguration und Cache-Eigentümerschaft bereitstellen.