Загрузка моделей и инференс
English | 简体中文 | 日本語 | Deutsch | Русский
Документация · Обучение · 中文
ruLLM обеспечивает загрузку модели, токенизацию, кэшированную авторегрессионную генерацию и планирование запросов. Его пакет Cargo — ruLLM; его имя для импорта в Rust — rullm.
Подготовьте локальную модель
Храните файлы модели в одном каталоге:
| Файл | Цель |
|---|---|
config.json |
Архитектура и параметры модели |
model.safetensors |
Веса отдельных файлов |
model.safetensors.index.json и каждый указанный фрагмент |
Сегментированные веса вместо одного файла весов |
tokenizer.json |
Токенизация и декодирование текста |
tokenizer_config.json |
ChatML Шаблон, необходимый для конвейеров Qwen2/Qwen2.5 |
generation_config.json |
Дополнительная конфигурация поколения Qwen2/Qwen2.5, обеспечивающая настройки EOS |
preprocessor_config.json |
Конфигурация предварительной обработки изображения Qwen3.5, необходимая для ввода изображения |
Загрузчики принимают локальные каталоги и не загружают модели. Выберите загрузчик для вашей архитектуры:
| Модель/вход | Загрузчик |
|---|---|
| Неквантованный текст ламы | load_huggingface_llama_pipeline::<B> |
| Неквантованный текст Qwen2/Qwen2.5 | load_huggingface_qwen2_pipeline::<B> |
| AWQ GEMM INT4 Qwen2/Qwen2.5 | load_huggingface_awq_qwen2_pipeline::<R> |
| Неквантованный текст Qwen3.5 | load_huggingface_qwen35_text::<B> |
| Видеокодер Qwen3.5 | load_huggingface_qwen35_vision::<B> |
| Qwen3.5 изображения и текст | load_huggingface_qwen35_multimodal::<B> |
B — тензорный бэкенд; R — это среда выполнения устройства. Текстовый загрузчик Qwen3.5 использует конфигурацию qwen3_5_text с послойным layer_types и отклоняет конфигурации квантования. Не передавайте файлы AWQ в загрузчик с плавающей запятой.
Запустите примеры генерации текста
После настройки среды запустите эти команды из корня исходного кода. Относительные пути указывают на два локальных каталога модели:
$env:RUDA_CUDA_COMPILER = 'nvrtc'
cargo run --locked -p ruda-llm --features nvidia --example qwen2_generate -- ./models/qwen2 "Hello" 32 1
В примере Qwen3.5 по умолчанию используется Ruda IR → PTX, если RUDA_CUDA_COMPILER не установлен. Используйте --release для оптимизации выполнения. Неподдерживаемые прямые операции PTX возвращают ошибки, а не возвращаются к NVRTC. Версия PTX должна соответствовать целевому GPU и драйверу; см. Справочник по бэкенда PTX.
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
Путь CUDA C++/NVRTC остается доступным при явном выборе:
$env:RUDA_CUDA_COMPILER = 'nvrtc'
cargo run --release --locked -p ruda-llm --features nvidia-ptx --example qwen35_generate -- ./models/qwen35 "Hello" 8 1
Аргументами являются каталог модели, текстовое приглашение, максимальное количество новых токенов и количество запусков. Последние два по умолчанию равны 32 и 1 для Qwen2 или 8 и 1 для Qwen3.5. Число пробегов должно быть положительным. В примерах печатаются строки JSON для загрузки и генерации. Линии генерации включают text, generated_token_ids и stopped_on_eos.
В этих примерах приглашение кодируется напрямую, без добавления шаблона чата. Для диалоговых моделей подготовьте подсказку с render_chat, как показано ниже.
Создание ответа в чате в приложении
Для каталога приложения рядом с исходным каталогом RUDA используйте эти зависимости.
[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"
Этот полный src/main.rs принимает каталог модели и сообщение пользователя в качестве аргументов командной строки. Более поздние примеры функций повторно используют псевдоним B, импорт и зависимости:
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 обрабатывает текстовые сообщения Qwen2/Qwen2.5 ChatML. При передаче true добавляется префикс поколения помощника. Роли также включают System и Assistant; подавайте сообщения в порядке разговора. Этот API не принимает сообщения о вызове инструмента.
Два логических аргумента для generate_text: add_special_tokens и skip_special_tokens. Не добавляйте специальные токены повторно после рендеринга ChatML; декодирование может их пропустить. generated_text содержит только новый ответ, а text включает как приглашение, так и ответ.
Выборка температуры, top-k и top-p
Передайте визуализированное приглашение 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,
)
}
| Параметр | Значения и эффект |
|---|---|
temperature |
Конечный и положительный; scales входит в систему первым |
top_k |
Оставляет токены с высокими показателями следующими; 0 отключает фильтрацию, связи на границе сохраняются |
top_p |
Наконец фильтруется по кумулятивной вероятности; диапазон (0, 1], где 1 отключает фильтрацию |
seed |
Запросить начальное значение локальной выборки; None использует системную энтропию |
max_new_tokens |
Ограничивает количество новых токенов, исключая запрос |
eos_token_ids |
Останавливается после создания любого токена из списка. |
Используйте generate_text для декодирования с максимальным логитом вместо установки температуры на ноль. Фиксированное начальное число фиксирует случайную последовательность выборки, а не числовую согласованность между моделями или серверными модулями.
Загрузка весов AWQ
Загрузчик AWQ принимает в качестве общего параметра CudaRuntime, а не Cuda<bf16, i32>:
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)
}
Возвращенный конвейер также предоставляет render_chat, encode, decode, generate_text и generate_text_sampled. Для конфигурации AWQ требуются quant_method = "awq", bits = 4, version = "gemm" и zero_point = true. group_size должен быть положительным или -1. Линейные проекции используют активации F16. См. ruBLAS INT4 для получения информации о весе в упаковке.
Ввод изображения Qwen3.5
generate_image_files_greedy принимает идентификаторы токенов для одного запроса, пути JPEG/PNG в порядке запроса, процессор изображений и параметры генерации:
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)
}
Закодируйте prompt_ids с помощью tokenizer.json модели. Следуйте шаблону подсказки модели, сохраняя один токен-заполнитель для каждого изображения, используя image_token_id из config.json. Пути к изображениям должны соответствовать количеству и порядку заполнителей. Эта точка входа расширяет заполнители внутри; не расширяйте их заранее. Он обрабатывает неподвижные изображения и отклоняет видеотокены.
Для существующих данных RGB8 используйте Qwen35RgbImage { pixels, height, width } с generate_rgb_greedy. Пиксели представляют собой чередующиеся байты RGB без заполнения строк. Для раздельной предварительной обработки preprocess_files и preprocess_rgb возвращают FP32 patches, двумерный shape и grids для каждого изображения.
При обслуживании нескольких запросов загружайте модель и процессор вне цикла запросов. Декодируйте возвращенный generated_token_ids с помощью того же токенизатора.
Кэши и непрерывная пакетная обработка
Функции генерации одного запроса создают и поддерживают кэш для этого поколения. Чтобы запустить Qwen3.5 вручную, вызовите model.new_cache(), передайте тензор приглашения forward_cached_last(tokens, &mut cache), затем передавайте только новые токены. Не отправляйте повторно весь кэшированный префикс.
Чтобы интегрировать собственный пакетный исполнитель, используйте ContinuousBatchScheduler:
- Создайте его с помощью
ContinuousBatchScheduler::new(config, kv_config).ContinuousBatchConfigустанавливаетmax_active_sequencesиmax_batch_tokens.PagedKvCacheConfigустанавливаетblock_size,num_pagesиmax_sequence_length. Все должно быть позитивно. - Отправляйте запросы с помощью
submit(prompt_token_ids, generation)и сохраняйте каждый возвращенныйRequestId. - Вызовите
schedule()для полученияScheduledBatch. Егоkindотличает предварительное заполнение/декодирование;sequencesпредоставляет токены каждой строки, начальную позицию, длину контекста и таблицу блоков. - Запустите модель в порядке строк, запишите соответствующие страницы KV и выберите следующий токен каждой строки. В случае успеха вызовите
complete_batch(batch.id, &generated_token_ids)с одним токеном результата в каждой строке. В случае неудачи позвоните поfail_batch(batch.id), чтобы отменить резервирование страниц этого пакета. - Получите выполненные запросы и сгенерированные токены с помощью
pop_finished(), а затем продолжите планирование.
Планировщик управляет запросами и метаданными распределения страниц. Исполнитель вызывающего объекта владеет устройством хранения и исполнения модели KV. Используйте token_matrix(), context_lengths() и flattened_block_table() для создания пакетных входных данных. Завершите или отмените невыполненный пакет, прежде чем снова звонить по schedule().
API Ссылка: Экспорт ruLLM, Параметры генерации, Планировщик.
Qwen3.5: объединённое постраничное внимание
Qwen35BatchCache выбирает путь внимания при создании через new_batch_cache. Установите RUDA_PAGED_ATTENTION=fused до создания кэша, чтобы использовать объединённое постраничное внимание ruDNN при непрерывной пакетной обработке Qwen3.5. Отсутствие переменной или legacy сохраняет прежний путь; другие значения отклоняются. Изменение переменной не переключает существующий кэш и не является глобальным переключателем для всех точек входа генерации.
Объединённый путь хранит физическую KV-арену для каждого слоя полного внимания и использует таблицы страниц планировщика для prefill/decode, не собирая исторические KV в тензоры с дополнением. Размеры арены задаются num_pages, block_size, числом KV-голов и размерностью головы; предусмотрите GPU-память для этой ёмкости. Входы следуют контракту ruDNN для непрерывных F32/F16/BF16-тензоров. Запись в общий префикс требует copy-on-write со стороны планировщика. После неудачного добавления на устройстве перестройте кэш, а не продолжайте с прежней позиции.
Повторно используемые компоненты внимания и MoE
rullm::gpu_inference предоставляет TensorOps, gqa_scores, gqa_value_product, mla_absorb_query, mla_scores и mla_value_product. Они комбинируют переданные вызывающим кодом операции с тензорами на устройстве без повторения кэшированных голов GQA и развёртывания исторических латентных значений MLA. Маскирование, softmax, позиционное кодирование и масштабирование модели задаёт вызывающий код.
rullm::device_inference реэкспортирует HostPlan, DevicePlan, PagedAttentionError, SwiGluExperts, RoutingOptions, GroupRoutingOptions, route_sigmoid_grouped и GroupedStrategy из ruDNN. Это вычислительные компоненты, а не полный загрузчик модели MLA/MoE; адаптеры по-прежнему должны обеспечивать проекции, конфигурацию маршрутизации и владение кэшем.