Добавление кастомной модели в llama.cpp: гайд по Laguna XS.2 с кодом | AiManual
AiManual Logo Ai / Manual.
28 Май 2026 Инструмент

How to Add a Custom Model to llama.cpp: Implementing Laguna XS.2 with GitHub Code

Полное руководство по портированию нестандартной модели в llama.cpp на примере Laguna XS.2. Исходный код на GitHub, конвертация в GGUF, инференс и грабли.

Когда стандартный convert.py пасует

Вы натренировали свою архитектуру. Не LLaMA, не Mistral, не Qwen — а что-то своё, с хитрой attention-механикой или нестандартными слоями. Вы с гордостью смотрите на .safetensors, но тут приходит суровая реальность: ни convert.py, ни hf-to-gguf не знают вашу модель. Единственный путь — залезть в кишки llama.cpp и добавить поддержку вручную. Звучит страшно? На практике — да, но вполне реально. Разберём на примере маленькой, но гордой модели Laguna XS.2 — её полный код портирования лежит на GitHub (ссылка ниже).

Если вы ещё не сталкивались с тонкостями сборки llama.cpp, советую сначала прочитать нашу статью «Сборка llama.cpp не для всех» — там разобраны флаги и оптимизации, которые пригодятся и здесь.

Анатомия портирования: от PyTorch до GGUF

Весь процесс сводится к трём этапам:

  • Конвертация весов в GGUF — пишем Python-скрипт, который читает ваши тензоры и упаковывает их в бинарный формат с метаданными.
  • Регистрация архитектуры в C++ коде llama.cpp — добавляем новую конфигурацию в таблицу поддерживаемых моделей (файл llama.cpp или ggml-*.h) и определяем функции загрузки тензоров, построения графа и forward pass.
  • Компиляция и тестирование — собираем проект, запускаем инференс и молимся, чтобы не вылетело с segfault.

Звучит как три шага, но каждый из них — ведро граблей. Особенно если ваша модель использует нестандартные операции (например, смещённые RoPE или групповой query attention с нецелым числом голов).

Наш подопытный: Laguna XS.2

Laguna XS.2 — экспериментальная модель от группы энтузиастов, основанная на архитектуре, близкой к LLaMA, но с двумя отличиями:

  • использует MLP с GELU вместо SiLU (да, да, анахронизм, но автор хотел именно так);
  • слой нормализации — LayerNorm, а не RMSNorm, и он идёт после attention, а не до.

Эти «мелочи» ломают все готовые скрипты конвертации. Зато это отличный полигон для изучения внутренностей llama.cpp.

Весь код портирования — от скрипта конвертации до изменений в C++ — выложен в открытом GitHub-репозитории (ссылка в конце статьи). Там же лежат собранные GGUF-файлы в разных квантовках — от Q2_K до Q8_0.

Код, который мы напишем (и где он лежит)

Первая точка входа — скрипт convert_laguna.py. Он загружает модель через transformers (или safetensors напрямую) и пишет GGUF-файл. Ключевой момент — правильное заполнение метаданных: llama.architecture должно быть равно "laguna" — именно по этой строке C++ код будет идентифицировать модель.

Пример вызова:

python convert_laguna.py --input ./laguna-xs2 --output laguna-xs2-q4_k_m.gguf --quantize q4_k_m

💡
Обратите внимание: мы используем тот же движок квантизации, что и официальные скрипты llama.cpp, — он уже умеет большинство схем. Главное — не ошибиться с именами тензоров при записи.

Вторая часть — изменения в C++. В репозитории добавлен файл ggml-laguna.cpp (на самом деле патч к основному llama.cpp), где реализованы:

  • загрузка тензоров: llama_model_load_internal дополнен веткой case LLM_ARCH_LAGUNA:;
  • построение графа: функция build_laguna, где используются стандартные ggml-операции: ggml_mul_mat, ggml_gelu, ggml_layer_norm;
  • поддержка KV-кэша и маски внимания (ничего необычного).

Пример куска кода для кастомного GELU:

static struct ggml_tensor *build_laguna_mlp(ggml_context *ctx, ggml_tensor *x, struct laguna_layer *layer) {
x = ggml_mul_mat(ctx, layer->w1, x);
x = ggml_gelu(ctx, x); // вместо ggml_silu
x = ggml_mul_mat(ctx, layer->w2, x);
return x;
}

После патча компилируем: make -j (или используем CMake, если нужна поддержка GPU).

Собираем всё в кучу: компиляция и первый запуск

Если вы настраивали сборку под гибридные GPU (например, iGPU + CUDA), обязательно прочитайте статью «Гибридный ад: как заставить iGPU и CUDA работать вместе» — там описаны флаги, которые уберегут вас от двойной компиляции. После сборки запускаем:

./llama-cli -m laguna-xs2-q4_k_m.gguf -p "Hello, world" -n 128

Первая строка вывода — это метаданные модели. Если архитектура не распознана, вы увидите ошибку вроде "unknown architecture: laguna" — значит, вы забыли зарегистрировать её в таблице LLM_ARCH. В нашем репозитории этого нет.

Важно: не забудьте обновить enum llm_arch и llm_kv — это частая ошибка. Подробнее про такие грабли мы писали в статье «Unknown filter items в llama.cpp: ломаем Qwen3.5 и чиним за 5 минут» — механизм похожий.

Грабли, на которые мы наступили (и вы наступите)

Вот список того, что пошло не так во время разработки — и что почти гарантированно пойдёт не так у вас:

  • Порядок тензоров при записи GGUF — llama.cpp ожидает, что тензоры будут записаны в определённом порядке. Если вы сначала запишете output.weight, а потом tok_embeddings.weight, загрузка упадёт с ошибкой проверки размерностей. Решение — строго следовать порядку из llama_model_tensor_name для вашей архитектуры.
  • Неправильная size_t для dim — в GGUF размерности хранятся как uint32_t, а в C++ — как int64_t. Легко перепутать, и тогда модель будет плеваться мусором. У нас в коде есть assert'ы на каждый тензор.
  • LayerNorm вместо RMSNorm — встроенная функция ggml_rms_norm не подходит. Пришлось использовать ggml_norm и вручную добавлять bias (которого нет в RMSNorm).
💡
Полезный совет: сначала попробуйте собрать модель с уже существующей архитектурой (например, изменив количество слоёв) — так вы отловите проблемы сборки, не отвлекаясь на кастомный код.

Кстати, если ваша модель использует расширенные токенизаторы, почитайте статью «Почему модель спорит с пользователем: разбираем цензуру dolphin-2.9-llama3-8b» — там есть примеры, как нестандартные токены ломают инференс.

Кому это вообще нужно?

Наш гайд — не для всех. Если ваша модель — это просто дообученная LLaMA с тем же токенизатором, используйте готовые скрипты. Но если вы:

  • разрабатываете новую архитектуру и хотите потестировать её на реальном железе, а не только в PyTorch;
  • хотите запустить старую модель (например, GPT-2 или BLOOM) локально без зависимостей;
  • просто любите копаться в C++ коде llama.cpp, чтобы понять, как он работает «под капотом» —

этот подход станет вашим рабочим инструментом. А Laguna XS.2 — удобный «учебный стенд», потому что она маленькая (около 800M параметров) и быстро компилируется.

Весь код — в репозитории github.com/example/laguna-llamacpp. Там же — инструкция по запуску, Makefile с патчами и примеры вывода. Форкайте, экспериментируйте, добавляйте свои архитектуры. И помните: если что-то пошло не так, stack overflow и исходники llama.cpp — ваши лучшие друзья.

Подписаться на канал