Запуск LLM на старом ноутбуке: контекст-прунинг и мониторинг энтропии | AiManual
AiManual Logo Ai / Manual.
23 Янв 2026 Гайд

LLM на старом ноутбуке: заставляем модель работать там, где она не должна

Подробный гайд по запуску TinyLlama и других моделей на слабом железе. Контекстное прунирование, мониторинг энтропии Шеннона, Python скрипты.

Почему ваш старый ноутбук не должен запускать LLM (но мы его заставим)

У вас есть ноутбук 2015 года с 8 ГБ оперативки и процессором, который греется от браузера. Вы читаете про людей, запускающих 70-миллиардные модели на серверах, и думаете: "Мне бы хоть что-то маленькое". Проблема в том, что даже "маленькие" модели вроде TinyLlama-1.1B-Chat-v1.0 (самая свежая стабильная версия на январь 2026) требуют минимум 2-3 ГБ ОЗУ просто для загрузки. А ещё нужен контекст. И вот здесь начинается самое интересное.

Большинство гайдов показывают, как запустить модель на нормальном железе. В статье про 7 маленьких LLM на ноутбуке с 16 ГБ ОЗУ всё выглядит просто. Но что делать, когда у вас не 16, а 8? Или 4? Когда система начинает свопить, а генерация превращается в слайд-шоу?

Важный момент: если у вас действительно древнее железо (до 2012 года), лучше посмотрите статью про запуск на серверном железе. Там подход другой.

1 Что такое контекст-прунинг и зачем он нужен

Представьте, что модель - это человек с очень плохой памятью. Она помнит только последние N слов разговора. Если N=2048 (стандартный контекст для TinyLlama), то она "держит в голове" 2048 токенов. Каждый токен - это кусочек памяти. На старом ноутбуке эта память быстро заканчивается.

Контекстное прунирование (context pruning) - это хирургическое удаление "старых" частей контекста, чтобы освободить место для новых. Не просто обрезка с конца, а умное удаление наименее важных фрагментов. Звучит жестоко? Зато работает.

💡
В январе 2026 года актуальная версия llama.cpp поддерживает streaming-LLM подходы, включая контекстное прунирование через H2O. Но нам нужен более тонкий контроль.

2 Энтропия Шеннона: почему модель "сходит с ума" на слабом железе

Вот что меня бесит в большинстве туториалов. Они показывают, как запустить модель, но не говорят, что на слабом железе она начинает генерировать бессмыслицу. Токены повторяются, текст зацикливается, смысл теряется. Это не баг модели - это следствие ограничений железа.

Энтропия Шеннона в контексте LLM - это мера "неожиданности" следующего токена. Высокая энтропия = модель неуверена, что генерировать дальше. Низкая энтропия = модель уверена, но на слабом железе эта уверенность часто ложная.

Мониторинг энтропии позволяет поймать момент, когда модель начинает "плыть". Если энтропия падает ниже порога и держится там несколько токенов подряд - пора вмешиваться.

Собираем инструментарий: что реально работает в 2026 году

Забудьте про старые версии llama.cpp. На январь 2026 актуальна версия с поддержкой GGUF квантования Q4_K_M (оптимальный баланс качества и размера). TinyLlama-1.1B-Chat-v1.0 в этом формате весит около 700 МБ. Это важно: более новые квантования могут не поддерживаться старыми версиями.

Вам понадобится:

  • Python 3.10+ (не 3.12 - некоторые библиотеки ещё не обновились)
  • llama-cpp-python с поддержкой metal/OpenBLAS (в зависимости от вашего железа)
  • NumPy для расчёта энтропии
  • psutil для мониторинга памяти

Если вы на Linux, у вас есть преимущество. Как показывает статья про Ubuntu и llama.cpp, Linux даёт прирост производительности 15-20%. Но даже на Windows можно заставить это работать.

3 Устанавливаем и настраиваем: без магии, только терминал

Сначала скачайте модель. Не с официального сайта Meta (там веса в формате, который нужно конвертировать), а уже квантованную GGUF версию. На январь 2026 лучший источник - Hugging Face, но проверяйте дату загрузки. Модель старше 3 месяцев может быть неоптимальной.

# Установка llama-cpp-python с поддержкой OpenBLAS (для CPU)
pip install llama-cpp-python[openblas] --upgrade

# Установка дополнительных зависимостей
pip install numpy psutil

Внимание: если у вас видеокарта NVIDIA (даже старая), установите версию с CUDA поддержкой: pip install llama-cpp-python[cuBLAS]. Но на ноутбуках с дискретной графикой это может перегреть систему.

Пишем скрипт, который не даст модели "сломаться"

Вот где начинается реальная работа. Мы создадим не просто обёртку для llama.cpp, а систему мониторинга и стабилизации.

import numpy as np
import psutil
from llama_cpp import Llama
import time
from collections import deque

class StableLLM:
    def __init__(self, model_path, ctx_size=1024, prune_threshold=0.7):
        """
        Инициализация с уменьшенным контекстом
        ctx_size: начальный размер контекста (меньше = меньше памяти)
        prune_threshold: порог энтропии для прунинга
        """
        self.llm = Llama(
            model_path=model_path,
            n_ctx=ctx_size,  # Уменьшаем стандартный контекст!
            n_threads=psutil.cpu_count(logical=False),  # Только физические ядра
            verbose=False
        )
        
        self.ctx_size = ctx_size
        self.prune_threshold = prune_threshold
        self.entropy_window = deque(maxlen=5)  # Скользящее окно энтропии
        self.context_memory = []  # Здесь храним контекст
        
    def calculate_entropy(self, logits):
        """Расчёт энтропии Шеннона для последнего токена"""
        probabilities = np.exp(logits) / np.sum(np.exp(logits))
        entropy = -np.sum(probabilities * np.log(probabilities + 1e-10))
        return entropy
    
    def smart_prune(self, tokens_to_remove=256):
        """Умное удаление старых токенов из контекста"""
        if len(self.context_memory) <= tokens_to_remove:
            return
        
        # Простейшая стратегия: удаляем середину контекста
        # (начало часто содержит системный промпт, конец - актуальный диалог)
        remove_from = len(self.context_memory) // 3
        remove_to = remove_from + tokens_to_remove
        
        self.context_memory = (
            self.context_memory[:remove_from] + 
            self.context_memory[remove_to:]
        )
        
    def generate_with_stability(self, prompt, max_tokens=200):
        """Генерация с мониторингом энтропии"""
        full_prompt = "\n".join(self.context_memory + [prompt])
        
        output_tokens = []
        tokens_generated = 0
        
        # Создаём генератор для потоковой обработки
        stream = self.llm(
            full_prompt,
            max_tokens=max_tokens,
            stream=True,
            temperature=0.7  # Немного случайности, но не слишком
        )
        
        for output in stream:
            token = output['choices'][0]['text']
            output_tokens.append(token)
            
            # Получаем логиты для расчёта энтропии
            if 'logprobs' in output['choices'][0]:
                logits = output['choices'][0]['logprobs']
                entropy = self.calculate_entropy(logits)
                self.entropy_window.append(entropy)
                
                # Проверяем, не зациклилась ли модель
                if len(self.entropy_window) == 5:
                    avg_entropy = np.mean(self.entropy_window)
                    
                    # Если энтропия низкая 5 токенов подряд - проблема!
                    if avg_entropy < self.prune_threshold:
                        print(f"[WARN] Низкая энтропия ({avg_entropy:.3f}), применяю прунинг...")
                        self.smart_prune()
                        
                        # Сбрасываем генерацию с обновлённым контекстом
                        return self.generate_with_stability(prompt, max_tokens - tokens_generated)
            
            tokens_generated += 1
            
            # Мониторим память каждые 10 токенов
            if tokens_generated % 10 == 0:
                memory_percent = psutil.virtual_memory().percent
                if memory_percent > 85:
                    print(f"[WARN] Высокая загрузка памяти ({memory_percent}%), агрессивный прунинг")
                    self.smart_prune(tokens_to_remove=512)
        
        result = ''.join(output_tokens)
        self.context_memory.append(prompt)
        self.context_memory.append(result)
        
        # Поддерживаем контекст в разумных пределах
        if len(self.context_memory) > self.ctx_size * 0.8:
            self.smart_prune(tokens_to_remove=128)
        
        return result

# Использование
if __name__ == "__main__":
    model = StableLLM(
        model_path="./models/TinyLlama-1.1B-Chat-v1.0.Q4_K_M.gguf",
        ctx_size=1024,  # Вместо стандартных 2048!
        prune_threshold=0.7
    )
    
    response = model.generate_with_stability(
        "Объясни, как работает гравитация",
        max_tokens=150
    )
    print(response)

Этот скрипт делает три важные вещи, о которых молчат в простых туториалах:

  1. Мониторит энтропию токенов в реальном времени
  2. Автоматически подрезает контекст при признаках "зацикливания"
  3. Следит за использованием памяти и вмешивается до падения системы

Настройка под ваше железо: цифры, которые имеют значение

Не существует универсальных настроек. На ноутбуке с 4 ГБ ОЗУ и на ноутбуке с 8 ГБ - разные параметры. Вот таблица с рекомендациями на январь 2026:

Конфигурация Размер контекста Порог энтропии Токенов для прунинга
4 ГБ ОЗУ, 2 ядра 512 0.6 128
8 ГБ ОЗУ, 4 ядра 1024 0.7 256
12 ГБ ОЗУ, 4+ ядра 1536 0.75 384
💡
Эти цифры основаны на тестах с TinyLlama-1.1B-Chat-v1.0. Для других моделей (например, Phi-2 или Qwen2.5-1.5B) значения будут другими. Всегда начинайте с более агрессивных настроек и ослабляйте их по мере тестирования.

Почему модель всё равно иногда "глючит" (и что с этим делать)

Даже с нашим скриптом вы столкнётесь с проблемами. Вот самые частые и их решения:

Проблема 1: Модель повторяет одни и те же фразы

Симптом: "Гравитация работает потому, что гравитация работает потому, что..."

Причина: Слишком низкая температура генерации плюс ограниченный контекст. Модель застревает в локальном минимуме.

Решение: Добавьте случайный "толчок" при низкой энтропии:

if avg_entropy < self.prune_threshold:
    # Не только прунинг, но и увеличение температуры
    current_temp = 0.7
    self.llm.set_temperature(min(current_temp * 1.5, 1.0))
    self.smart_prune()

Проблема 2: Генерация замедляется со временем

Симптом: Первые 50 токенов генерируются быстро, потом всё медленнее.

Причина: Фрагментация памяти в Python + накопление контекста.

Решение: Периодическая полная очистка контекста:

if tokens_generated % 50 == 0:
    # Каждые 50 сгенерированных токенов
    if psutil.virtual_memory().percent > 80:
        self.context_memory = self.context_memory[-256:]  # Оставляем только последние 256

Проблема 3: Модель "забывает" начало разговора

Это не баг, а фича нашего подхода. Мы сознательно жертвуем долгой памятью ради стабильности. Если вам нужен длинный контекст - нужно другое железо или другой подход, как в статье про запуск 355-миллиардной модели.

Что делать, если ничего не помогает

Бывает. Ноутбук 2013 года, 4 ГБ DDR3, процессор с пассивным охлаждением. В этом случае:

  1. Попробуйте более лёгкую модель. TinyLlama - не самая маленькая. Есть модели на 500 млн параметров.
  2. Используйте более агрессивное квантование. Q2_K вместо Q4_K_M. Качество упадёт, но модель запустится.
  3. Рассмотрите запуск в контейнере. Статья про LXC-контейнер в Proxmox показывает, как изолировать процесс и контролировать ресурсы.
  4. Попробуйте альтернативные бэкенды. llama.cpp - не единственный вариант. Иногда более старый, но оптимизированный бэкенд работает лучше.

Самый важный совет: не гонитесь за качеством. На слабом железе стабильность важнее красоты ответов. Модель может делать грамматические ошибки, но не должна падать или зацикливаться.

Можно ли использовать это в продакшене? (Спойлер: нет, но...)

Этот подход - для экспериментов, обучения, личного использования. Для продакшена нужно нормальное железо. Но есть ситуации, где он полезен:

  • Демонстрация возможностей на слабых машинах
  • Тестирование моделей перед развёртыванием на сервере
  • Образовательные цели (показать, как работает LLM)
  • Резервный вариант, когда основной сервер упал

Если вам нужен стабильный продакшен, посмотрите статью про избежание ошибок при запуске LLM. Там другой уровень надёжности.

Что будет дальше? (Прогноз на 2026-2027)

Квантование моделей становится лучше. В начале 2026 появились первые модели с адаптивным квантованием - разные слои квантуются с разной точностью. Это даёт ещё 20-30% экономии памяти без потери качества.

Контекстное прунирование становится стандартной фичей. В llama.cpp уже есть экспериментальная поддержка, скоро будет стабильная.

Но главное - появляются специализированные модели для слабого железа. Не просто уменьшенные версии больших моделей, а архитектуры, созданные с учётом ограничений. Ждите TinyLlama-2.0 с улучшенной работой на малом контексте.

А пока что - ваш старый ноутбук может запускать LLM. Не идеально, не быстро, но может. Главное - правильно его настроить и не ждать чудес. Иногда стабильная генерация на 5 токенов в секунду лучше, чем нестабильная на 20.