ChatGPT на вашем ноутбуке: бесплатно, анонимно, навсегда
ChatGPT на вашем ноутбуке: бесплатно, анонимно, навсегда

Полная версия

Настройки чтения
Размер шрифта
Высота строк
Поля
На страницу:
3 из 9

На уровне Q5_K_M и выше качество стабилизируется: дальнейшее повышение битности даёт всё меньший прирост. Это аналог «порога насыщения» — как в музыке, где битрейт 320 кбит/с уже неотличим от lossless для большинства слушателей.

Практический совет: как выбрать квантование под своё железо

1. Определите доступную память. Сколько свободной ОЗУ или VRAM вы готовы выделить под модель? Не забывайте, что операционная система, среда разработки и прочие программы тоже потребляют память. Ориентируйтесь на доступные гигабайты, а не на общий объём.

2. Выберите битность. Найдите в таблице выше квантование, чьё потребление памяти укладывается в ваш лимит с запасом хотя бы 1–2 ГБ.

3. Всегда предпочитайте K-quant. Суффиксы с буквой K (Q4_K_M, Q5_K_M) почти всегда лучше старых форматов без K (например, Q4_0), потому что используют неравномерное распределение битов по слоям.

4. Начните с Q4_K_M. Если вы не знаете, с чего начать, — начните с Q4_K_M. Это универсальный выбор, который работает на большинстве устройств. Позже вы всегда сможете скачать более качественную или более лёгкую версию и просто подменить файл — код не изменится.

Что мы будем использовать в книге

Для основного проекта мы скачаем Llama 3.1 8B Instruct, формат GGUF, квантование Q4_K_M. Файл будет весить около 5 ГБ. Это даст нам:

· Отличное качество ответов, неотличимое от онлайн-аналогов в большинстве задач,

· Запуск на ноутбуке с 8 ГБ ОЗУ или 6 ГБ VRAM,

· Скорость генерации 15–30 токенов/с на процессоре и до 60 токенов/с на видеокарте,

· Запас по памяти для RAG и других компонентов.

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

Теперь, когда мы понимаем, что за файл нам нужен, пора его скачать. В следующей главе мы напишем код, который сделает это одной командой.

Глава 2.3. Практикум: скачиваем модель одной командой

Мы выбрали модель, разобрались с квантованием и теперь знаем, какой файл нам нужен: llama-3.1-8b-instruct-Q4_K_M.gguf. Пришло время получить его на свой диск. Конечно, можно открыть Hugging Face в браузере, найти страницу модели, кликнуть по ссылке и ждать, пока браузер скачает 5 ГБ. Но мы — разработчики, и пойдём другим путём: напишем Python-функцию, которая сделает это одной командой.

Почему это важно? Потому что в будущем наш ИИ-помощник должен уметь сам загружать модель при первом запуске. Пользователь просто запускает программу, а она, обнаружив отсутствие файла, сама скачивает его из интернета. Никаких инструкций «зайдите на сайт, нажмите...» — всё автоматизировано. Наша «одна кнопка» начинается уже здесь.

Предварительные требования

Нам понадобится Python (у вас он уже установлен, версия 3.10 или выше) и библиотека huggingface_hub. Она умеет взаимодействовать с Hugging Face — крупнейшим хранилищем моделей и датасетов. Установим её:

bash

pip install huggingface_hub

Пошаговая инструкция

Вся магия будет заключена в одной функции download_model(). Вот что она должна делать:

1. Принимать имя модели (например, "unsloth/Llama-3.1-8B-Instruct") и имя файла ("Llama-3.1-8B-Instruct-Q4_K_M.gguf").

2. Проверять, существует ли уже такой файл локально. Если да — пропускать скачивание.

3. Если файла нет — загружать его, показывая прогресс и скорость.

4. Возвращать путь к скачанному файлу, чтобы остальной код мог его открыть.

Создайте в вашем проекте файл model_loader.py и напишите следующий код:

python# model_loader.pyimport osimport sysfrom pathlib import Pathfrom huggingface_hub import hf_hub_downloaddef download_model( repo_id: str = "unsloth/Llama-3.1-8B-Instruct", filename: str = "Llama-3.1-8B-Instruct-Q4_K_M.gguf", model_dir: str = "./models") -> str: """ Скачивает файл модели GGUF с Hugging Face, если его ещё нет локально. Аргументы: repo_id: идентификатор репозитория на Hugging Face (например, "unsloth/Llama-3.1-8B-Instruct") filename: имя файла модели в репозитории model_dir: локальная папка для сохранения моделей Возвращает: Абсолютный путь к файлу модели на диске """ # Создаём папку, если её нет Path(model_dir).mkdir(parents=True, exist_ok=True) # Полный путь, где должен лежать файл local_path = Path(model_dir) / filename # Если файл уже есть — просто возвращаем путь if local_path.exists(): print(f" Модель уже загружена: {local_path}") return str(local_path.resolve()) # Иначе — скачиваем print(f" Загрузка модели {filename} из {repo_id}...") print(" Размер файла ~5 ГБ. Первая загрузка может занять несколько минут.") try: # Основная функция загрузки downloaded_path = hf_hub_download( repo_id=repo_id, filename=filename, local_dir=model_dir, resume_download=True, # Можно продолжить при обрыве связи ) print(f" Модель загружена в: {downloaded_path}") return downloaded_path except KeyboardInterrupt: print("\n Загрузка прервана пользователем. При повторном запуске она продолжится с того же места.") sys.exit(1) except Exception as e: print(f" Ошибка при загрузке: {e}") print(" Проверьте интернет-соединение и правильность repo_id/filename.") sys.exit(1)if __name__ == "__main__": # Для теста: просто запустите этот файл, и модель начнёт качаться path = download_model() print(f"\nГотово! Путь к модели: {path}")

Объяснение кода

· from huggingface_hub import hf_hub_download — это функция, которая делает всю тяжёлую работу: находит файл в репозитории, скачивает его, проверяет контрольные суммы, умеет продолжать прерванную загрузку.

· Проверка if local_path.exists() — ключевая оптимизация. Модель весит 5 ГБ, и мы не хотим качать её заново при каждом запуске. Функция сначала смотрит, есть ли файл на диске. Если есть — мгновенно возвращает путь.

· resume_download=True — спасение для медленного интернета. Если соединение оборвётся, при следующем запуске загрузка начнётся не с нуля, а с того же места. huggingface_hub сохраняет временный файл и автоматически докачивает недостающие байты.

· Обработка KeyboardInterrupt — вежливость к пользователю, который нажал Ctrl+C. Мы сообщаем ему, что прогресс не потерян и при повторном запуске всё продолжится.

Тестирование

Откройте терминал в папке проекта и выполните:

bashpython model_loader.pyВы увидите примерно такой вывод:text Загрузка модели Llama-3.1-8B-Instruct-Q4_K_M.gguf из unsloth/Llama-3.1-8B-Instruct... Размер файла ~5 ГБ. Первая загрузка может занять несколько минут. Downloading: 100%|| 5.12G/5.12G [05:30<00:00, 15.5MB/s] Модель загружена в: models/Llama-3.1-8B-Instruct-Q4_K_M.ggufГотово! Путь к модели: models/Llama-3.1-8B-Instruct-Q4_K_M.ggufПри повторном запуске:text Модель уже загружена: models/Llama-3.1-8B-Instruct-Q4_K_M.ggufГотово! Путь к модели: models/Llama-3.1-8B-Instruct-Q4_K_M.gguf

Что мы получили

В папке models/ нашего проекта теперь лежит файл модели. Это полностью автономный, самодостаточный «мозг» нашего будущего ИИ. Его можно скопировать на флешку, перенести на другой компьютер, и он будет работать без каких-либо дополнительных манипуляций.

Возможные проблемы и ихрешение

Ошибка «Repo not found». Возникает, когда вы указали неверный идентификатор репозитория. Проверьте название на сайте huggingface.co — возможно, вы ошиблись в имени пользователя или названии модели. Для квантованных моделей часто используются репозитории сообщества: unsloth, bartowski, TheBloke, mradermacher. Именно там лежат готовые GGUF-файлы, а не в официальных репозиториях разработчиков.

Ошибка «Entry not found». Означает, что запрошенный файл не найден в репозитории. Либо вы опечатались в имени файла, либо модель удалили или переименовали. Откройте страницу репозитория в браузере и проверьте актуальный список файлов — имена могли измениться с выходом новой версии.

Очень медленная загрузка. Скорость может падать из-за ограничений вашего провайдера или загруженности серверов Hugging Face. Для пользователей из некоторых регионов помогает переключение на зеркало: установите переменную окружения HF_ENDPOINT=https://hf-mirror.com. Это особенно актуально для Китая, Ирана и некоторых других стран.

Не хватает места на диске. Квантованная модель Llama 3.1 8B весит около 5 ГБ, но при загрузке через hf_hub_download создаются временные файлы. Суммарно может потребоваться до 6 ГБ свободного места. Перед загрузкой проверьте диск и при необходимости освободите место.

Качает не тот файл. Если после загрузки модель не работает или ведёт себя странно, возможно, вы скачали не то квантование. Сравните имя файла с тем, что указано на странице репозитория. Лучше скопировать имя файла прямо с сайта, а не вводить вручную — это исключит опечатки.

Зачем мы написали это сами, а не использовали Ollama

Вы наверняка слышали про Ollama — удобный инструмент, где модель скачивается командой ollama pull llama3.1:8b. Почему мы не пошли этим путём?

Дело в том, что Ollama — это отдельный сервер, который работает в фоне и общается с нашим кодом через HTTP. Это добавляет лишнее звено, усложняет отладку и делает невозможным упаковку всего в один EXE-файл (нам пришлось бы таскать с собой ещё и Ollama). Мы же хотим максимального контроля: модель должна быть просто файлом, который наш Python-код загружает напрямую. Так мы сможем встроить её в любое приложение без внешних зависимостей.

В следующей главе мы возьмём скачанный файл и «оживим» его — напишем класс, который будет отправлять в модель запросы и получать ответы.

Резюме

· Мы установили huggingface_hub — мост между нашим кодом и миром открытых моделей.

· Написали функцию download_model(), которая качает файл один раз и повторно использует его.

· Функция умеет продолжать загрузку при обрыве связи и сообщать о прогрессе.

· Файл модели лежит в папке models/ и готов к использованию.

Теперь у нас есть «мозг». В Части 3 мы заставим его думать.

Часть 3. Сердце:запуск модели как локального сервера

Глава 3.1. Сравнениерантаймов: Ollama, llama.cpp, llama-cpp-python

У нас в руках файл модели — мозг будущего помощника. Теперь нужно выбрать «тело»: программу, которая загрузит этот файл в память, примет наш вопрос, пропустит его через нейросеть и вернёт ответ. В экосистеме локального ИИ сложились три основных способа это сделать. Они не исключают друг друга, но для нашей цели — создания единого компактного приложения — подходит только один. Давайте сравним претендентов.

Что такое «рантайм» для LLM

Рантайм (runtime) — это среда исполнения модели. Это программа или библиотека, которая берёт файл модели GGUF и «оживляет» его: распределяет вычисления между ядрами процессора или видеокарты, управляет памятью, обрабатывает входные токены и собирает выходные. Без рантайма файл модели — просто набор байтов. С рантаймом он становится собеседником.

Все современные рантаймы для локальных LLM так или иначе основаны на проекте llama.cpp — высокопроизводительном движке на C++, написанном специально для запуска квантованных моделей. Но формы, в которых этот движок доходит до нас, разработчиков на Python, различаются.

Вариант 1: Нативный llama.cpp (C++)

Это исходный проект: движок, написанный на C++, без каких-либо обёрток. Вы скачиваете исходники, компилируете их в исполняемый файл и запускаете модель из командной строки:

bash

./llama-cli -m models/Llama-3.1-8B-Instruct-Q4_K_M.gguf -p "Привет, мир!"

Как взаимодействовать из Python: только через запуск внешнего процесса (subprocess). Вы отправляете текст в stdin и читаете ответ из stdout.

Плюсы:

· Максимальная производительность (нативный C++ без прослоек).

· Первым получает все новые фичи (поддержка новых архитектур, квантований, бэкендов).

· Минимальное потребление памяти (нет накладных расходов на скриптовый язык).

Минусы:

· Необходимость компиляции под каждую платформу.

· Нет нормального API для Python: нужно парсить текстовый вывод, обрабатывать ошибки вручную.

· Неудобно встраивать в приложение: придётся таскать с собой скомпилированный бинарник.

· Сложность с потоковой генерацией (streaming).

Вердикт: Отличный инструмент для экспериментов и максимальной скорости, но для книги не подходит — нам нужна тесная интеграция с Python-кодом.

Вариант 2: Ollama

Ollama — это готовое приложение, которое устанавливается как обычная программа (есть версии для Windows, macOS, Linux). Оно запускает фоновый сервер, скачивает модели по запросу и предоставляет REST API, совместимое с OpenAI.

Работа с Ollama выглядит так:

bash

ollama pull llama3.1:8b

ollama run llama3.1:8b

А из Python мы обращаемся к ней через HTTP:

python

import requests

response = requests.post("http://localhost:11434/api/generate", json={

"model": "llama3.1:8b",

"prompt": "Привет, мир!"

})

Плюсы:

· Установка и запуск в одну команду — очень beginner-friendly.

· Автоматически скачивает модели (не нужен наш код из главы 2.3).

· Совместимость с OpenAI API: можно использовать библиотеки openai для Python, просто указав base_url на localhost.

· Удобный CLI и веб-интерфейс (через плагины).

Минусы:

· Это отдельный сервер, который должен быть запущен. Наше приложение без него не работает.

· Невозможно упаковать в один EXE вместе с нашим кодом. Пользователю придётся устанавливать и Ollama, и нашу программу.

· Меньше контроля: Ollama сама управляет памятью, кэшированием, выбором бэкенда. Мы не можем тонко настроить параметры инференса.

· Некоторые фичи (например, передача сырых токенов или доступ к логитам) недоступны через простой API.

Вердикт: Прекрасный инструмент для прототипирования и личного использования. Если вы просто хотите «поиграться с локальной моделью», возьмите Ollama. Но для книги, цель которой — создать автономное приложение с «одной кнопкой», он не годится из-за внешней зависимости.

Вариант 3: llama-cpp-python (наш выбор)

Это Python-биндинг к llama.cpp. По сути, llama.cpp скомпилирован как динамическая библиотека, а llama-cpp-python предоставляет Python-интерфейс ко всем его функциям. Установка проста:

bash

pip install llama-cpp-python

Использование — чистый Python:

python

from llama_cpp import Llama

model = Llama(model_path="models/Llama-3.1-8B-Instruct-Q4_K_M.gguf")

response = model.create_chat_completion(

messages=[{"role": "user", "content": "Привет, мир!"}]

)

print(response["choices"][0]["message"]["content"])

Плюсы:

· Всё в одном процессе. Модель загружается прямо в память Python-приложения. Нет отдельных серверов, HTTP-запросов, сетевых задержек.

· Полный контроль. Доступны все параметры llama.cpp: температура, top_p, частотные штрафы, контекстное окно, бэкенд (CPU/CUDA/Metal/Vulkan). Можно даже получать сырые логиты.

· Совместимость с OpenAI API. create_chat_completion принимает тот же формат сообщений, что и облачные сервисы. Меняется только одна строка — вместо openai.OpenAI(api_key=...) мы создаём Llama(model_path=...).

· Потоковая генерация. Встроенная поддержка streaming через generator.

· Упаковка в EXE. PyInstaller может включить llama-cpp-python и сам движок llama.cpp в один исполняемый файл. Никаких внешних бинарников не требуется.

· Активное сообщество. Библиотека обновляется практически синхронно с llama.cpp, поддерживает все новые архитектуры и квантования.

Минусы:

· Установка с поддержкой GPU требует указания дополнительных флагов (разберём в главе 3.2).

· Чуть больше потребление памяти, чем у нативного llama.cpp (разница в пределах 5–10%).

· При очень большом количестве запросов в секунду может уступать серверным решениям (но для персонального помощника это не важно).

Вердикт: Идеальный выбор для нашей книги. lloma-cpp-python даёт нам полный контроль над моделью из Python-кода, не требует внешних серверов и позволяет упаковать всё в один файл.

Сравнение рантаймов длязапуска моделей

llama.cpp (нативный)

Установка требует компиляции из исходников на C++ — не самый простой процесс для новичка. Интегрируется с Python через запуск внешнего процесса и парсинг вывода, что неудобно и ненадёжно. Не требует отдельного сервера, даёт полный контроль над параметрами, но потоковую генерацию организовать сложно. Совместимости с OpenAI API нет. При упаковке в EXE придётся таскать с собой скомпилированный бинарник. Поддержка GPU настраивается при компиляции. Лучше всего подходит для бенчмарков, кастомных клиентов и задач, где важна максимальная производительность.

Ollama

Устанавливается как обычная программа через готовый установщик — самый простой способ начать. Предоставляет HTTP API, к которому можно обращаться из любого языка программирования. Главный минус — требует постоянно запущенного фонового сервера, что делает невозможной упаковку в один EXE-файл. Контроль над параметрами модели ограничен — Ollama сама управляет памятью и кэшированием. Потоковая генерация встроена, совместимость с OpenAI API частичная. GPU поддерживается из коробки. Идеальный выбор для личного использования, прототипирования и экспериментов.

llama-cpp-python

Устанавливается одной командой pip install. Это нативные Python-биндинги к llama.cpp, которые работают в том же процессе, что и ваше приложение — никаких отдельных серверов. Даёт полный контроль над параметрами, поддерживает потоковую генерацию и совместимость с OpenAI API через метод create_chat_completion. Можно упаковать в EXE через PyInstaller без внешних зависимостей. Поддержка GPU включается флагами при установке. Это наш выбор для книги — идеальный баланс контроля, удобства и возможности распространения готового приложения.

Что мы выбираем и почему

Для книги я выбираю llama-cpp-python. Вот главные причины:

1. Единый процесс. Модель — это просто объект Python. Никаких «запустите сервер Ollama перед использованием». Наше приложение самодостаточно.

2. Одна кнопка. Когда мы упакуем проект в EXE, пользователь не должен будет ничего устанавливать дополнительно. Двойной щелчок — и программа работает. С Ollama это невозможно, с нативным llama.cpp — крайне сложно.

3. Контроль. Мы сможем тонко настроить параметры инференса, управлять памятью, выбирать бэкенд (CPU или GPU) в зависимости от того, что доступно на машине пользователя. Ollama многие из этих решений принимает за нас, и не всегда удачно.

4. Привычный API. create_chat_completion с тем же форматом сообщений, что и у OpenAI. Если вы когда-нибудь писали код для ChatGPT, вы уже знаете, как работать с нашей локальной моделью.

Когда всё-таки стоит использовать Ollama

Я не хочу создавать впечатление, что Ollama — плохой инструмент. Для определённых сценариев он идеален:

· Вы экспериментируете с разными моделями и не хотите писать код для скачивания.

· Вы используете готовые приложения (Open WebUI, AnythingLLM), которые ожидают Ollama как бэкенд.

· Вам нужно быстро поднять API для команды разработчиков.

Но для создания автономного, упакованного в EXE ИИ-помощника — только llama-cpp-python.

Что дальше

В следующей главе мы установим llama-cpp-python, в том числе с поддержкой GPU, и напишем первый код, который «оживит» нашу модель. Мы создадим класс-обёртку LocalModel, который станет фундаментом всего дальнейшего проекта.

Глава 3.2. Установка инастройка llama-cpp-python

Мы выбрали инструмент. Теперь нужно установить его так, чтобы он работал быстро и без сюрпризов. Установка llama-cpp-python — это не просто pip install. Чтобы получить максимальную производительность (особенно если у вас есть видеокарта), нужно указать правильные флаги. В этой главе мы пройдём установку для всех основных платформ и проверим, что всё работает.

Что мы устанавливаем на самом деле

llama-cpp-python — это Python-обёртка. Под капотом она использует скомпилированную библиотеку llama.cpp. При установке через pip происходит компиляция этой библиотеки прямо на вашем компьютере. Поэтому процесс зависит от того, какие инструменты сборки у вас есть и какое железо вы хотите использовать.

Есть два основных варианта установки:

· Только CPU. Самый простой, работает везде. Модель будет использовать процессор и оперативную память.

· С поддержкой GPU. Требует драйверов и SDK от производителя видеокарты. Модель будет использовать видеопамять, что в разы быстрее.

Универсальный способ: установка только для CPU

Этот вариант подходит, если у вас нет мощной видеокарты или вы не хотите возиться с драйверами. Он работает на Windows, macOS и Linux.

bash

pip install llama-cpp-python

Всё. Библиотека скомпилируется с параметрами по умолчанию и будет использовать CPU. Никаких дополнительных действий не требуется. Если у вас macOS с Apple Silicon (M1/M2/M3/M4), этот способ автоматически задействует ускорение через Accelerate (Apple Neural Engine), что уже даст неплохую скорость.

Установка с поддержкой GPU: когда скорость важна

Если у вас есть дискретная видеокарта, вы можете задействовать её для инференса. Это даст прирост скорости в 3–10 раз.

Для видеокарт NVIDIA (CUDA)

Вам потребуются:

· Драйверы NVIDIA (любые современные, ставятся с сайта nvidia.com).

· CUDA Toolkit 12.x (скачивается с developer.nvidia.com/cuda-downloads).

Установите CUDA Toolkit, затем выполните:

bash

CMAKE_ARGS="-DGGML_CUDA=on" pip install llama-cpp-python

Переменная CMAKE_ARGS передаёт флаг -DGGML_CUDA=on компилятору. Он включает поддержку CUDA в llama.cpp. Компиляция займёт несколько минут.

Проверка: после установки запустите Python и выполните:

python

from llama_cpp import Llama

# Если модель загрузилась без ошибки "CUDA not available", всё работает.

Если вы видите предупреждение GGML_CUDA=off, значит, флаг не применился. Удалите библиотеку (pip uninstall llama-cpp-python) и повторите установку.

Для macOS с Apple Silicon (Metal)

На компьютерах Mac с чипами M1/M2/M3/M4 есть встроенное GPU-ускорение через Metal. В большинстве случаев CPU-установка уже использует Accelerate, но можно явно включить Metal для максимальной производительности:

На страницу:
3 из 9