Руководство по сборке локального AI-стека. Часть 3. Наполнение моделями
На этом шаге мы наполняем папку models/ моделями под разные задачи, раскладываем их по правилам (плоско vs подпапки с mmproj) и делаем HTML-шпаргалку — статическую страницу, которая отвечает на вопрос «какая модель для какой задачи», не требуя лезть в конфиги или документацию.
Зачем это нужно
После части 2 у нас есть одна тестовая модель (Qwen3.5-2B) и рабочий llama-server. Но для реальной работы нужен набор моделей: одна сильна в коде, другая — в ролевом общении, третья — в русском, четвёртая — в OCR. Держать это в голове сложно, а лезть в интернет за описанием каждой — долго.
HTML-шпаргалка решает две задачи:
Быстрый выбор. Таблица «задача -> модель -> почему» вверху страницы: 80% случаев решаются за 5 секунд.
Карточки моделей. Плюсы, минусы, «лучше всего для», кнопка «Копировать
-m <модель>» — чтобы не набирать имя вручную.
Страница статическая, открывается через file:// в браузере, работает без сервера и без интернета.
Правила раскладки моделей
Из части 2: обычные модели — плоско, мультимодальные — в подпапке с mmproj. Финальная структура models/ в этом проекте выглядит так:
models/
├── Blitzar-Coder-4B-F.1.Q4_K_M.gguf <- кодинг, компактно
├── MN-12B-Runeweaver-RP-RU.Q4_K_M.gguf <- РП без цензуры
├── OxCoder-9B.Q4_K_M.gguf <- кодинг, агентский
├── qwen2.5-coder-7b-instruct-q4_k_m.gguf <- кодинг, быстрый
├── Qwen3-4B-Instruct-2507-Q4_K_M.gguf <- чат, альтернатива
├── RusMind-Momentum-4.7-Q4_K_M.gguf <- русский, перевод
│
├── gemma-4-E2B-it-Q4_K_M/ <- РП + vision
│ ├── gemma-4-E2B-it-Q4_K_M.gguf
│ └── mmproj-F16.gguf
├── gemma-4-E4B-it-Q4_K_M/ <- РП + vision (чемпион)
│ ├── gemma-4-E4B-it-Q4_K_M.gguf
│ └── mmproj-F16.gguf
├── Qwen3.5-2B-Q4_K_M/ <- сверхбыстрый чат + vision
│ ├── Qwen3.5-2B-Q4_K_M.gguf
│ └── mmproj-F16.gguf
├── Qwen3.5-4B-Q4_K_M/ <- быстрый чат + vision
│ ├── Qwen3.5-4B-Q4_K_M.gguf
│ └── mmproj-F16.gguf
├── Qwen3.5-9B-Q4_K_M/ <- универсал + vision
│ ├── Qwen3.5-9B-Q4_K_M.gguf
│ └── mmproj-F16.gguf
├── Qwen3VL-4B-Instruct-Q4_K_M/ <- vision, OCR
│ ├── Qwen3VL-4B-Instruct-Q4_K_M.gguf
│ └── mmproj-Qwen3VL-4B-Instruct-F16.gguf <- имя проектора другое — норм
│
└── media/ <- diffusion (часть 4) ├── z_image_turbo-Q4_K.gguf ├── mage_flow_turbo_bf16.safetensors └── vae/
Важные моменты:
Имя
mmprojне обязано точно совпадать с именем модели. Главное — начинается сmmproj.mmproj-Qwen3VL-4B-Instruct-F16.ggufиmmproj-F16.ggufодинаково валидны. Режим роутера подхватывает любой файл в папке модели, имя которого начинается сmmproj.models/media/исключается из списка LLM. Скриптrun_llama_mmap.shявно отсекает эту папку (! -path "$MEDIA_MODELS_DIR/*"), чтобы диффузионные модели не попадали в дропдаун чата.llama.cppне проверяет «правильность» имени. Файлqwen2.5-coder-7b-instruct-q4_k_m.ggufв нижнем регистре — это нормально, скрипт найдёт его по*.gguf.
Каталог моделей по задачам
Ниже — что скачано и зачем. Все модели — в квантовании Q4_K_M (если не указано иное), это оптимум «качество/размер» для CPU.
Универсальные (чат, саммари)
Модель | Размер | Зачем |
|---|---|---|
Qwen3.5-9B | ~6 ГБ | Основная «рабочая лошадка». Лучший баланс качества и скорости, хороший русский, контекст до 160 страниц. Для большинства задач — первый выбор. |
Qwen3.5-4B | ~3 ГБ | Когда 9B долго думает. Достаточно умна для чата и лёгких саммари, в 2–3 раза быстрее. |
Qwen3.5-2B | ~1.5 ГБ | Сверхбыстрая: черновики, проверка идей, «спросить и забыть». Тестовая модель из части 2. |
Qwen3-4B-Instruct-2507 | ~3 ГБ | Альтернатива Qwen3.5-4B с другим стилем ответа. Полезна для «второго мнения» на технических вопросах. |
Gemma-4-E4B | ~3 ГБ | Хорошо держит контекст и понимает смысл. В саммари на уровне qwen3.5-9b. |
Кодинг
Модель | Размер | Зачем |
|---|---|---|
Qwen2.5-Coder-7B | ~4.5 ГБ | Быстрый и сильный в коде. HumanEval 76.0 — один из лучших в классе 7–8B. Для повседневных правок и объяснений. |
OxCoder-9B | ~6 ГБ | Специализация Qwen3.5-9B под агентский кодинг: планы рефакторинга, работа с проектами. Медленнее 7B, но глубже. |
Blitzar-Coder-4B | ~2.5 ГБ | Компактный кодер. Только с ручным контролем: зацикливается на генерации тестов, «тесты» в виде голых |
Ролевое общение
Модель | Размер | Зачем |
|---|---|---|
Gemma-4-E4B | ~3 ГБ | Чемпион по русскому РП. Живой язык, действия в скобках, без перебора с «йо-хо-хо». Также сильна в саммари (глубина вопросов) и анализе перевода с иронией. Vision (с |
Gemma-4-E2B | ~1.5 ГБ | Лёгкая версия E4B: атмосферная, быстрая, но иногда забывает детали промпта. Для коротких РП-сессий. Vision (с |
MN-12B-Runeweaver-RP-RU | ~7 ГБ | Специализированная русскоязычная RP-модель без цензуры. В тестах склонна к морализаторству («поговори с ребёнком о самооценке» вместо драмы) — требует точных промптов и |
Русский язык
Модель | Размер | Зачем |
|---|---|---|
RusMind-4.7-Momentum | ~3.4 ГБ | Специализированная русскоязычная модель. Лучший перевод с сохранением иронии (8.5/10 в тестах). В саммари «додумывает» — не для фактологии, а для «живого» русского. |
Vision (изображения, OCR)
Модель | Размер | Зачем |
|---|---|---|
Qwen3VL-4B | ~3 ГБ | Отдельная VL-модель: OCR (включая рукописный), описание фото, вопросы по скриншотам. Как текстовый чат слабее Qwen3.5-4B. |
Qwen3.5-2B/4B/9B + mmproj | +300–600 МБ | Уже есть в списке «Универсальные». С |
Gemma-4-E2B/E4B + mmproj | +300–600 МБ | Уже есть в списке «Ролевое». С |
Что скачать в первую очередь: Qwen3.5-9B (универсал), OxCoder-9B (кодинг), Gemma-4-E4B (РП + саммари + vision), Qwen3VL-4B (OCR). Это 4 модели, которые покрывают 90% задач. Остальные — по мере необходимости.
HTML-шпаргалка
web/models.html — статическая страница. Устроена так:
Таблица «Быстрый выбор по задаче» — 12 строк «задача -> модель -> почему». Самое полезное: не нужно читать карточки, чтобы найти «чем сделать OCR».
Фильтры по задачам — кнопки «Чат», «Код», «РП», «Тексты», «Зрение», «Быстро». Нажатие скрывает карточки, не относящиеся к задаче.
Карточки моделей — для каждой: описание, теги задач, плюсы/минусы, «лучше всего для», кнопка «Копировать
-m <модель>».Адаптивность — на телефоне карточки в один столбец, таблица сжимается.
Печать — ссылка в футере, если захотите распечатать.
Как открыть:
file:///path/to/llama_server/web/models.html
Или из плашки run_llama_mmap.sh — там есть строка Шпаргалка: file://....
Как добавить новую модель. В <script>, в массив MODELS, добавить объект:
{
name: 'Название-модели-Q4_K_M',
size: '7B', vision: false,
tasks: ['code', 'fast'], // теги из TASKS
desc: 'Краткое описание одной строкой.',
pros: ['плюс 1', 'плюс 2'],
cons: ['минус 1'],
best_for: 'Для чего лучше всего'
}
И, если нужно, добавить строку в <tbody> таблицы quick-table. Больше ничего править не надо — карточка и фильтры подхватят автоматически.
Как добавить новую задачу. В объект TASKS:
const TASKS = {
// ...
audio: { label: 'Аудио', color: '#9c27b0' }
};
Кнопка фильтра появится сама.
Код HTML-шпаргалки (web/models.html)
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LLM Cheat Sheet — выбор модели</title>
<style>
:root {
--bg: #121212;
--surface: #1e1e1e;
--surface-hover: #2a2a2a;
--primary: #bb86fc;
--primary-dim: #9a67ea;
--text: #e1e1e1;
--text-dim: #9e9e9e;
--border: #333;
--green: #4caf7d;
--orange: #ffb74d;
--blue: #64b5f6;
--pink: #f06292;
--purple: #ba68c8;
--cyan: #4dd0e1;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
background: var(--bg); color: var(--text);
font-family: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
line-height: 1.55;
padding: 32px 16px;
}
.container { max-width: 1200px; margin: 0 auto; }
header {
margin-bottom: 32px; padding-bottom: 20px;
border-bottom: 1px solid var(--border);
}
h1 { font-size: 1.8rem; font-weight: 400; margin-bottom: 8px; }
h1 .accent { color: var(--primary); }
.subtitle { color: var(--text-dim); font-size: 0.95rem; }
h2 {
font-size: 1.2rem; font-weight: 500;
margin: 32px 0 16px; color: var(--text);
display: flex; align-items: center; gap: 8px;
}
h2::before {
content: ''; width: 3px; height: 20px;
background: var(--primary); border-radius: 2px;
}
/* Quick picks table */
.quick-table {
width: 100%; border-collapse: collapse;
background: var(--surface); border-radius: 12px; overflow: hidden;
}
.quick-table th, .quick-table td {
padding: 12px 16px; text-align: left;
border-bottom: 1px solid var(--border);
font-size: 0.92rem;
}
.quick-table th {
background: #252525; color: var(--text-dim);
font-weight: 500; font-size: 0.8rem;
text-transform: uppercase; letter-spacing: 0.5px;
}
.quick-table tr:last-child td { border-bottom: none; }
.quick-table tr:hover { background: var(--surface-hover); }
.quick-table .task { color: var(--primary); font-weight: 500; white-space: nowrap; }
.quick-table .model { font-family: 'Consolas', monospace; font-size: 0.85rem; color: var(--text); }
/* Filters */
.filters {
display: flex; flex-wrap: wrap; gap: 8px;
margin-bottom: 20px;
}
.filter-btn {
background: var(--surface); color: var(--text-dim);
border: 1px solid var(--border); padding: 6px 14px;
border-radius: 16px; cursor: pointer;
font-size: 0.85rem; font-family: inherit;
transition: all 0.2s;
}
.filter-btn:hover { color: var(--text); border-color: var(--primary-dim); }
.filter-btn.active {
background: var(--primary); color: #000;
border-color: var(--primary); font-weight: 500;
}
/* Cards */
.models-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
gap: 16px;
}
.card {
background: var(--surface); border-radius: 12px;
padding: 20px;
box-shadow: 0 2px 8px rgba(0,0,0,0.4);
transition: transform 0.15s, box-shadow 0.15s;
display: flex; flex-direction: column;
}
.card:hover {
transform: translateY(-2px);
box-shadow: 0 4px 16px rgba(0,0,0,0.6);
}
.card-header {
display: flex; justify-content: space-between;
align-items: flex-start; gap: 12px;
margin-bottom: 12px;
}
.card-title {
font-size: 1.05rem; font-weight: 500;
font-family: 'Consolas', monospace;
word-break: break-word;
}
.card-badges { display: flex; gap: 4px; flex-shrink: 0; }
.badge {
font-size: 0.7rem; padding: 2px 8px;
border-radius: 10px; font-weight: 600;
text-transform: uppercase; letter-spacing: 0.3px;
}
.badge.size { background: #2a2a2a; color: var(--text-dim); }
.badge.vision { background: var(--blue); color: #000; }
.card-desc {
font-size: 0.9rem; color: var(--text-dim);
margin-bottom: 14px;
}
.section-label {
font-size: 0.75rem; text-transform: uppercase;
letter-spacing: 0.5px; color: var(--text-dim);
margin-bottom: 4px;
}
.pros-list, .cons-list {
list-style: none; margin-bottom: 12px;
}
.pros-list li, .cons-list li {
font-size: 0.87rem; padding-left: 18px;
position: relative; margin-bottom: 3px;
}
.pros-list li::before {
content: '+'; position: absolute; left: 4px;
color: var(--green); font-weight: bold;
}
.cons-list li::before {
content: '−'; position: absolute; left: 4px;
color: var(--orange); font-weight: bold;
}
.best-for {
background: #252525; border-radius: 8px;
padding: 10px 12px; margin-bottom: 12px;
font-size: 0.87rem;
}
.best-for strong { color: var(--primary); font-weight: 500; }
.tasks-row {
display: flex; flex-wrap: wrap; gap: 4px;
margin-bottom: 12px;
}
.task-tag {
font-size: 0.72rem; padding: 2px 8px;
border-radius: 10px;
background: #252525; color: var(--text-dim);
}
.launch-row {
display: flex; align-items: center; gap: 8px;
padding-top: 12px; border-top: 1px solid var(--border);
margin-top: auto;
}
.launch-cmd {
flex: 1; font-family: 'Consolas', monospace;
font-size: 0.8rem; color: var(--text-dim);
overflow: hidden; text-overflow: ellipsis;
white-space: nowrap;
}
.copy-btn {
background: var(--surface-hover); color: var(--text-dim);
border: 1px solid var(--border); padding: 4px 10px;
border-radius: 6px; cursor: pointer;
font-size: 0.75rem; font-family: inherit;
transition: all 0.2s;
}
.copy-btn:hover { color: var(--primary); border-color: var(--primary); }
.copy-btn.copied { color: var(--green); border-color: var(--green); }
.hidden { display: none !important; }
footer {
margin-top: 48px; padding-top: 24px;
border-top: 1px solid var(--border);
color: var(--text-dim); font-size: 0.85rem;
text-align: center;
}
@media (max-width: 600px) {
body { padding: 16px 8px; }
h1 { font-size: 1.4rem; }
.quick-table th, .quick-table td { padding: 8px 10px; font-size: 0.82rem; }
.models-grid { grid-template-columns: 1fr; }
.card { padding: 16px; }
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>LLM <span class="accent">Cheat Sheet</span></h1>
<div class="subtitle">Быстрый выбор модели по задаче. Все модели: Q4_K_M, запуск через <code>llama-server</code>.</div>
</header>
<h2>Быстрый выбор по задаче</h2>
<table class="quick-table">
<thead>
<tr><th>Задача</th><th>Модель</th><th>Почему</th></tr>
</thead>
<tbody>
<tr><td class="task">Универсальный чат</td><td class="model">Qwen3.5-9B</td><td>Лучший баланс качества/скорости, хороший русский</td></tr>
<tr><td class="task">Быстрый чат</td><td class="model">Qwen3.5-4B/2B</td><td>Когда нужен простой чат без сложных контекстов</td></tr>
<tr><td class="task">Ролевое (чемпион)</td><td class="model">Gemma-4-E4B</td><td>Живой русский, действия в скобках, без перебора</td></tr>
<tr><td class="task">Ролевое (лёгкое)</td><td class="model">Gemma-4-E2B</td><td>2B, но атмосферно — быстрая альтернатива</td></tr>
<tr><td class="task">Ролевое (без цензуры)</td><td class="model">MN-12B-Runeweaver</td><td>Поддерживает все кроме реальных правонарушений (план действий)</td></tr>
<tr><td class="task">Кодинг (агентский)</td><td class="model">OxCoder-9B</td><td>План рефакторинга 9/10, хороший кодинг</td></tr>
<tr><td class="task">Кодинг (быстро)</td><td class="model">Qwen2.5-Coder-7B</td><td>HumanEval 76, но нужно проверять вручную (есть упущения)</td></tr>
<tr><td class="task">Кодинг (компактно)</td><td class="model">Blitzar-Coder-4B</td><td>Только с контролем: зацикливается на тестах</td></tr>
<tr><td class="task">Саммари / ключевые мысли</td><td class="model">Qwen3.5 (9B, 4B), Gemma-4 (E2B, E4B)</td><td>9B, E4B - самые сильные кандидаты. 4B, E2B - для простых задач</td></tr>
<tr><td class="task">Перевод с иронией</td><td class="model">RusMind / Gemma-E4B</td><td>RusMind — лучше результат; Gemma — выдает варианты</td></tr>
<tr><td class="task">Изображения / OCR</td><td class="model">Qwen3VL-4B, Qwen3.5 (2B, 4B, 9B), Gemma (e2b, e4b)</td><td>VL, рукописный текст, контекст</td></tr>
<tr><td class="task">Сверхбыстро</td><td class="model">Gemma-4-E2B, Qwen3.5-2B</td><td>Мгновенно, минимум RAM</td></tr>
</tbody>
</table>
<h2>Все модели</h2>
<div class="filters" id="filters"></div>
<div class="models-grid" id="models-grid"></div>
<footer>
<div>Шпаргалка по моделям в <code>models/</code> · <a href="#" onclick="window.print(); return false;" style="color: var(--primary);">Печать</a></div>
</footer>
</div>
<script>
const TASKS = {
chat: { label: 'Чат', color: '#64b5f6' },
code: { label: 'Код', color: '#4dd0e1' },
roleplay: { label: 'РП', color: '#f06292' },
text: { label: 'Тексты', color: '#ba68c8' },
vision: { label: 'Зрение', color: '#ffb74d' },
fast: { label: 'Быстро', color: '#4caf7d' }
};
const MODELS = [
{
name: 'Qwen3.5-9B-Q4_K_M',
size: '9B', vision: true,
tasks: ['chat', 'text', 'vision'],
desc: 'Универсальная рабочая лошадка: связность, грамматика, длинный контекст.',
pros: ['Лучший баланс качества и скорости', 'Хороший русский', 'Точнее RusMind в саммари', 'Vision (с mmproj)'],
cons: ['Медленнее младших версий', 'В коде пропускает edge case с пустой строкой'],
best_for: 'Основной чат, саммари, перевод, обработка результатов поиска'
},
{
name: 'Qwen3.5-4B-Q4_K_M',
size: '4B', vision: true,
tasks: ['chat', 'text', 'fast', 'vision'],
desc: 'Хороший компромисс между скоростью и качеством.',
pros: ['Заметно быстрее 9B', 'Достаточно умен для большинства задач', 'Vision (с mmproj)'],
cons: ['Сложные тексты хуже, чем у 9B', 'В РП склонна к «маньячному» тону'],
best_for: 'Быстрый чат, простой перевод, лёгкие саммари'
},
{
name: 'Qwen3.5-2B-Q4_K_M',
size: '2B', vision: true,
tasks: ['fast', 'vision'],
desc: 'Сверхбыстрая, для черновиков и проверки идей.',
pros: ['Мгновенный отклик', 'Минимум RAM', 'Vision (с mmproj)'],
cons: ['Простое качество', 'Перевод с сарказмом проваливает (3/10)', 'Не для сложных рассуждений'],
best_for: 'Черновики, быстрые вопросы, проверка идей'
},
{
name: 'Qwen3-4B-Instruct-2507-Q4_K_M',
size: '4B', vision: false,
tasks: ['chat', 'text', 'fast'],
desc: 'Альтернатива Qwen3.5-4B с другим стилем ответа, только текст.',
pros: ['Другой стиль ответа', 'Хорош для технических вопросов'],
cons: ['Нет зрения', 'Слабее Qwen3.5-4B в целом'],
best_for: 'Текстовые задачи без vision, альтернативный взгляд'
},
{
name: 'qwen2.5-coder-7b-instruct-q4_k_m',
size: '7B', vision: false,
tasks: ['code'],
desc: 'Один из сильнейших в классе 7-8B для кодинга.',
pros: ['HumanEval 76.0', 'Хорош в Python, JS, C++, Go', 'Понимает длинные файлы'],
cons: ['Слабее в общем чате, чем 9B', 'Не защищает от пустой строки в edge case'],
best_for: 'Генерация, редактирование кода, объяснение кода'
},
{
name: 'OxCoder-9B',
size: '9B', vision: false,
tasks: ['code'],
desc: 'Специализация Qwen3.5-9B под агентский кодинг и длинные задачи.',
pros: ['Лучший в тестах: план рефакторинга 9/10, код 9/10', 'Обрабатывает edge cases', 'Не зацикливается'],
cons: ['Тяжелее 7B-кодеров', 'Избыточен для простых скриптов'],
best_for: 'Агентские задачи, рефакторинг больших проектов, сложный код'
},
{
name: 'Blitzar-Coder-4B-F.1',
size: '4B', vision: false,
tasks: ['code', 'fast'],
desc: 'Компактный кодер на базе Qwen3-4B, обучен на большом кодовом датасете.',
pros: ['4B — быстрый', 'Мультиязычный кодинг', 'Мало RAM', 'Защищает от пустой строки'],
cons: ['Зацикливается на генерации тестов', '«Тесты» в виде голых assert — мёртвый код', 'Просит запустить инструмент'],
best_for: 'Простые скрипты — только с ручным контролем и без автоматики'
},
{
name: 'Qwen3VL-4B-Instruct-Q4_K_M',
size: '4B', vision: true,
tasks: ['vision', 'chat'],
desc: 'VL-модель: читает изображения, OCR, отвечает по картинкам.',
pros: ['Понимает изображения', 'OCR (включая рукописный)', 'Отвечает по контексту картинки'],
cons: ['Как текстовик слабее Qwen3.5-4B'],
best_for: 'Описание фото, распознавание текста, вопросы по скриншотам'
},
{
name: 'Gemma-4-E4B-it-Q4_K_M',
size: '4B', vision: true,
tasks: ['roleplay', 'chat', 'fast', 'vision', 'text'],
desc: 'Лучшая для русского РП: живой язык, действия в скобках, без перебора.',
pros: ['Естественный диалог', 'Держит персонажа', 'Отличный анализ перевода с иронией', 'Сильна в саммари: глубина вопросов, точность терминов', 'Vision (с mmproj)'],
cons: ['Меньше знаний, чем у Qwen3.5-9B', 'Иногда переименовывает объекты из промпта'],
best_for: 'Ролевое общение, перевод с анализом нюансов, саммари, живой русский'
},
{
name: 'Gemma-4-E2B-it-Q4_K_M',
size: '2B', vision: true,
tasks: ['roleplay', 'fast', 'vision'],
desc: 'Сверхлёгкая Gemma для быстрых РП-сессий и черновиков.',
pros: ['Мгновенная', 'Минимум RAM', 'Атмосферная для 2B', 'Саммари на уровне 4B-моделей, несмотря на размер', 'Vision (с mmproj)'],
cons: ['Простое качество', 'Иногда забывает ключевые детали промпта'],
best_for: 'Быстрое РП, черновики, быстрые саммари, простые диалоги'
},
{
name: 'RusMind-4.7-Momentum',
size: '4.7B', vision: false,
tasks: ['text', 'chat'],
desc: 'Специализированная русскоязычная модель, высокие баллы MERA v2.',
pros: ['«Живой» русский', 'Лучший перевод с сохранением иронии (8.5/10)', 'Q4_K_M ~3.4 ГБ'],
cons: ['Слабее в коде и математике', 'В саммари «додумывает» (философия, сленг)'],
best_for: 'Перевод с сохранением тона, работа с русскими текстами (не фактология)'
},
{
name: 'Meta-Llama-3.1-8B-Instruct-abliterated',
size: '8B', vision: false,
tasks: ['roleplay', 'chat'],
desc: 'Ролевая модель без цензурных срывов. Официально русский не поддерживает.',
pros: ['Без фильтров', 'Сильна в англоязычном РП', 'Пишет стихи, сцены'],
cons: ['На русском промпте соскакивает на английский', 'Слабее в кодинге и математике'],
best_for: 'Англоязычное РП и творческие сценарии; для русского — не подходит'
},
{
name: 'MN-12B-Runeweaver-RP-RU',
size: '12B', vision: false,
tasks: ['roleplay'],
desc: 'Специализированная русскоязычная RP-модель без цензуры.',
pros: ['Без фильтров', 'Русский язык', 'Специально под РП'],
cons: ['Заговаривается', 'Иногда переименовывает объекты', 'Тяжелее 4–8B'],
best_for: 'РП без цензуры, требует точных промптов'
}
];
// --- Render filters ---
const filtersEl = document.getElementById('filters');
const allBtn = document.createElement('button');
allBtn.className = 'filter-btn active';
allBtn.textContent = 'Все';
allBtn.dataset.filter = 'all';
filtersEl.appendChild(allBtn);
for (const [key, info] of Object.entries(TASKS)) {
const btn = document.createElement('button');
btn.className = 'filter-btn';
btn.textContent = info.label;
btn.dataset.filter = key;
btn.style.setProperty('--task-color', info.color);
filtersEl.appendChild(btn);
}
// --- Render model cards ---
const grid = document.getElementById('models-grid');
MODELS.forEach(m => {
const card = document.createElement('div');
card.className = 'card';
card.dataset.tasks = m.tasks.join(',');
const taskTags = m.tasks.map(t => `<span class="task-tag" style="color:${TASKS[t].color}">${TASKS[t].label}</span>`).join('');
const pros = m.pros.map(p => `<li>${p}</li>`).join('');
const cons = m.cons.map(c => `<li>${c}</li>`).join('');
const visionBadge = m.vision ? '<span class="badge vision">vision</span>' : '';
card.innerHTML = `
<div class="card-header">
<div class="card-title">${m.name}</div>
<div class="card-badges">
<span class="badge size">${m.size}</span>
${visionBadge}
</div>
</div>
<div class="card-desc">${m.desc}</div>
<div class="tasks-row">${taskTags}</div>
<div class="section-label">Сильные стороны</div>
<ul class="pros-list">${pros}</ul>
<div class="section-label">Слабые стороны</div>
<ul class="cons-list">${cons}</ul>
<div class="best-for"><strong>Лучше всего для:</strong> ${m.best_for}</div>
<div class="launch-row">
<span class="launch-cmd">-m ${m.name}</span>
<button class="copy-btn" onclick="copyLaunch(this, '-m ${m.name}')">Копировать</button>
</div>
`;
grid.appendChild(card);
});
// --- Filter logic ---
filtersEl.addEventListener('click', e => {
if (!e.target.classList.contains('filter-btn')) return;
const filter = e.target.dataset.filter;
filtersEl.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
e.target.classList.add('active');
grid.querySelectorAll('.card').forEach(card => {
if (filter === 'all' || card.dataset.tasks.split(',').includes(filter)) {
card.classList.remove('hidden');
} else {
card.classList.add('hidden');
}
});
});
// --- Copy button ---
function copyLaunch(btn, text) {
navigator.clipboard.writeText(text).then(() => {
const orig = btn.textContent;
btn.textContent = '✓';
btn.classList.add('copied');
setTimeout(() => {
btn.textContent = orig;
btn.classList.remove('copied');
}, 1200);
});
}
</script>
</body>
</html>
Проверка после наполнения
1. Все модели видны в роутере:
./run_llama_mmap.sh
В логе должно быть: Router mode: каталог ./models (N шт.). Число N — количество .gguf без mmproj и без media/. Для текущего листинга — 10 (Blitzar, MN-12B, OxCoder, qwen2.5-coder, Qwen3-4B, RusMind, Gemma-E2B, Gemma-E4B, Qwen3.5-2B, Qwen3.5-4B, Qwen3.5-9B, Qwen3VL-4B).
2. Модель с mmproj видит картинки:
./run_llama_mmap.sh -m Qwen3VL-4B-Instruct-Q4_K_M
В логе — Найден mmproj: mmproj-Qwen3VL-4B-Instruct-F16.gguf и clip_model_load: .... В UI прикрепите картинку — модель должна её описать.
3. Шпаргалка открывается:
xdg-open web/models.html # или file:// в браузере
Проверьте: таблица сверху, фильтры работают, кнопка «Копировать» копирует -m <модель>.
4. Тест «какая модель для чего»:
Откройте шпаргалку, найдите «Кодинг (агентский)» ->
OxCoder-9B. Скопируйте-m OxCoder-9B.Q4_K_Mили любую другую модель.Запустите
./run_llama_mmap.sh-m OxCoder-9B.Q4_K_M.Отправте промпт для теста.
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.