- BrainTools - https://www.braintools.ru -

Локальный ИИ на Windows в один клик: установщик Ollama с подбором модели под железо на Python и pywebview

Запустить нейросеть у себя дома сегодня несложно, но не с первого раза. Нужно найти и поставить Ollama, понять в терминале, какую из сотни моделей брать под свою видеокарту, не ошибиться с тегом, дождаться скачивания на несколько гигабайт, а потом ещё и добыть интерфейс. Родственникам и знакомым, которые просят «поставь мне такой же ИИ, как у тебя», всё это не объяснишь за пять минут. Поэтому я написал программу Local AI: она смотрит на железо, подбирает модель, ставит Ollama и модель одним кликом и открывает обычный чат. Ниже — как она устроена и какие грабли попались по пути.

Локальный ИИ на Windows в один клик: установщик Ollama с подбором модели под железо на Python и pywebview - 1

Что получилось

  • Один LocalAI.exe (около 42 МБ), ничего ставить заранее не нужно, Python тоже.

  • Определяет видеокарту, видеопамять, ОЗУ и свободное место на диске, рекомендует модель из каталога на 34 позиции (Qwen3, Gemma 3/3n, Llama 3.1/3.2, Mistral, Phi-4, DeepSeek-R1, Qwen2.5-Coder и -VL, LLaVA, gpt-oss).

  • Скачивает и ставит Ollama без прав администратора, скачивает модель с прогрессом.

  • Чат с потоковым ответом, режим «Рассуждать», вложения (текстовые файлы и картинки для моделей, которые их понимают), панель «О модели» и значки возможностей.

  • Выбор папок для Ollama и моделей, перенос моделей, обновление Ollama и моделей, удаление всего «без следов».

  • Интерфейс на русском и английском, две темы. Исходники открыты, MIT.

Диалоги не покидают ПК: чат разговаривает с Ollama на 127.0.0.1. Сеть нужна только для скачивания и проверки обновлений.

Локальный ИИ на Windows в один клик: установщик Ollama с подбором модели под железо на Python и pywebview - 2

Устройство

Выбор стека простой: нужно маленькое окно с интерфейсом и логика [1], которая лезет в систему (реестр, процессы, установщики). Это Python, а интерфейс — обычный HTML/CSS/JS без сборщиков.

  • main.py поднимает локальный HTTP-сервер на 127.0.0.1 и открывает окно pywebview [2] (WebView2). Если окно не открылось, запасной путь — Edge или Chrome с ключом --app.

  • server.py — API для интерфейса: состояние, установка, чат, обновления, пути. Запросы защищены токеном сессии (заголовок X-Token) и проверкой Host, чтобы страница из браузера не могла дёргать локальный сервер.

  • hw.py — определение железа, catalog.py — каталог моделей и рекомендация, engine.py — всё про Ollama (поиск, установка, запуск, скачивание моделей, обновление, удаление).

  • ui/ — страница, стили и app.js с мини-Markdown, чатами и модальными окнами. Строки интерфейса лежат в i18n.js на двух языках.

Железо без WMI

Первым делом хотелось спросить у Windows про видеокарту через WMI. На моём ПК он оказался сломан, а на чужих такое тоже бывает, поэтому железо определяется без него:

  • NVIDIA — nvidia-smi --query-gpu=name,memory.total [3];

  • остальные видеокарты — ключ реестра класса дисплея (DriverDesc, HardwareInformation.qwMemorySize); у значения бывает отрицательное число из 32-битного переполнения, его надо поправить;

  • ОЗУ — GlobalMemoryStatusEx через ctypes.

Дискретной считается NVIDIA и AMD с заметным объёмом видеопамяти; встроенная графика равна режиму «только процессор». Свободное место считается по диску папки моделей, а не по диску C:, потому что папку пользователь может перенести.

Как подбирается модель

В каталоге у каждой модели размер в ГиБ (сверен с registry.ollama.ai [4]) и возможности. Модели нужно больше места, чем её файл: контекст и буферы. Грубая оценка и три режима:

OVERHEAD = 1.2   # множитель на контекст и буферы
EXTRA = 0.6      # ГБ запаса

def _need(size):
    return size * OVERHEAD + EXTRA

def rate(model, hw):
    need = _need(model["size"])
    vram, ram = hw["vram_gb"], hw["ram_gb"]
    if vram and need <= vram * 0.95:
        return "gpu"        # целиком в видеопамяти — быстро
    if need <= ram * 0.7:
        return "mixed" if vram else "cpu"
    return "no"             # не влезает

Рекомендуется самая крупная из подходящих «основных» моделей (Qwen3 и Gemma 3), которая целиком влезает в видеопамять. Без видеокарты — лёгкая модель, не больше 5 ГБ: плотные модели побольше на процессоре слишком медленные. В окне выбора показываются только те модели, что подходят этому ПК (и по памяти [5], и по диску), так что неподходящую не выберешь случайно. Любое изменение модели идёт через окно подтверждения.

Локальный ИИ на Windows в один клик: установщик Ollama с подбором модели под железо на Python и pywebview - 3

Установка Ollama

Установщик OllamaSetup.exe весит около 1,6 ГБ, поэтому качать его нужно с докачкой: файл лежит в %TEMP%LocalAI как .part, и после обрыва или отмены загрузка продолжается заголовком Range:

done = os.path.getsize(part) if os.path.exists(part) else 0
headers = dict(UA, **({"Range": f"bytes={done}-"} if done else {}))
resp = urllib.request.urlopen(urllib.request.Request(SETUP_URL, headers=headers), timeout=30)
if resp.status != 206:   # сервер Range не поддержал — качаем заново
    done = 0

Перед запуском проверяется цифровая подпись: статус Valid и подписант O=Ollama, иначе файл удаляется:

sig = subprocess.run(
    ["powershell", "-NoProfile", "-Command",
     f"$s = Get-AuthenticodeSignature -LiteralPath '{path}'; "
     ""$($s.Status)|$($s.SignerCertificate.Subject)""],
    capture_output=True, text=True, creationflags=NO_WINDOW).stdout.strip()

Установка тихая (/VERYSILENT /NORESTART /SUPPRESSMSGBOXES), с нужной папкой через /DIR="…"; ставится в профиль пользователя, права администратора не нужны. Дальше /api/pull скачивает модель, и прогресс идёт в интерфейс. У /api/pull длинный таймаут чтения: на этапе проверки sha256 Ollama долго молчит.

Подводные камни

Окно Ollama поверх нашего. Установщик сам запускает ollama app.exe, и он открывает своё окно прямо поверх нашего. Программа находит это окно и шлёт ему WM_CLOSE: приложение уходит в трей, а движок продолжает работать.

Чёрные консольные окна. ollama serve нужно запускать с одним CREATE_NO_WINDOW и без DETACHED_PROCESS. У процесса без консоли каждый дочерний ollama.exe и llama-server.exe (раннер, он появляется при загрузке модели) открывает свою чёрную консоль. Проверял наблюдателем окон: EnumWindows каждые 10 мс. После правки новых окон, кроме «Local AI», нет.

Быстрая проверка порта. Если Ollama не запущена, обычный connect на 127.0.0.1:11434 на Windows возвращает отказ только через пару секунд из-за повторов SYN. /api/state из-за этого тормозил на 3–5 секунд. Теперь сначала быстрый socket.create_connection с таймаутом 0,3 с, а HTTP-запрос только если порт открыт.

Ollama гасится при выходе. Закрыли окно — модель выгружается из видеопамяти, трей не висит. Из-за этого первый ответ после запуска ждёт загрузки модели в память (у меня около 3 секунд на RTX 3070, у других дольше), и со стороны это выглядит как «ответ появился сразу целиком»: загрузка, потом ответ за секунду. Поэтому до первого токена в пузыре показывается «Загрузка модели в память…», а сервер первой строкой потока отдаёт {"status":"loading"}, если модели нет в /api/ps. При старте программа сама поднимает Ollama.

Перенос моделей. Папка моделей задаётся переменной OLLAMA_MODELS в HKCUEnvironment с рассылкой WM_SETTINGCHANGE. В Ollama 0.40 модели лежат не только в blobs и manifests, а ещё в manifests-v2 и metadata; перенести надо всё, иначе в новой папке модель не видна. На одном диске перенос — rename, на другом — копирование с прогрессом; отмена или ошибка [6] откатывают всё назад.

Удаление, которое стирает сам себя. Для кнопки «Удалить всё…» (модели, Ollama, программа — по галочкам, с двойным подтверждением) пришлось повозиться: деинсталлятор Ollama сам стирает ~/.ollama/models, поэтому папка моделей на время переименовывается, а потом возвращается. Inno-деинсталлятор перезапускает себя из %TEMP% и сразу отдаёт управление, так что ждать приходится исчезновения ollama.exe и записи в реестре. А exe программы удаляет скрытый PowerShell: он ждёт выхода наших процессов (и onefile-загрузчика PyInstaller, и потомка), потом стирает exe, %APPDATA%LocalAI, распакованную _MEI* и в конце себя.

localStorage и порт. Чаты хранятся в localStorage, а он привязан к origin вместе с портом. pywebview по умолчанию открывает окно в приватном режиме и ничего не сохраняет. Поэтому окно запускается с private_mode=False и своей папкой хранилища, а порт сервера постоянный (28765); если он занят, берётся любой свободный, но тогда у этого запуска будут свои чаты.

Анимация и requestAnimationFrame. Во время потока пузырь ответа перерисовывается по таймеру, а не в rAF: в перекрытом или скрытом окне кадры замирают, и ответ «приходил» бы сразу весь. Перерисовка меняет только innerHTML у .bubble, сам элемент сообщения не пересоздаётся, иначе анимация появления «мигала» бы всеми сообщениями.

Завершение процессов. taskkill /IM на моём ПК процессы не находил (тот же сломанный WMI), поэтому процессы завершаются через WinAPI: CreateToolhelp32Snapshot и TerminateProcess, сначала трей, потом сервер.

Что проверено

На RTX 3070 (8 ГБ), 32 ГБ ОЗУ:

  • реальная установка: Ollama 0.40.13, тихая установка около минуты, qwen3:8b в чате с think и без — поток работает; скорость ответа на gemma3:1b около 236 токенов в секунду (программа показывает её в боковой панели);

  • перенос моделей туда и обратно на одном диске, закрытие окна pywebview и режима Edge --app гасит Ollama;

  • удаление проверено в демо-режиме и на копии exe с подменёнными APPDATA и TEMP; настоящий деинсталлятор Ollama и удаление настоящих моделей я не запускал;

  • не проверено вживую: системный диалог выбора папки и переустановка Ollama в другую папку (только демо), а также реальное обновление Ollama (стоит последняя версия).

Для отладки интерфейса есть демо-режим: LOCALAI_DEMO=1 и python app/dev.py, он имитирует установку и чат без сети.

Ограничения

  • Только Windows 10 и 11.

  • Видеокарты: рекомендации рассчитаны на NVIDIA и AMD с заметным объёмом памяти; как именно Ollama использует вашу карту — вопрос к самой Ollama.

  • Генерации картинок и видео у моделей Ollama нет, поэтому в интерфейсе эти значки всегда серые.

  • Программа не подписана цифровой подписью: SmartScreen покажет предупреждение («Подробнее» → «Выполнить в любом случае»), а антивирусы иногда ругаются на exe от PyInstaller. Исходники открыты, собрать можно самому.

Где взять

Исходный код, README на русском и английском и готовый LocalAI.zip [7] — на GitHub: https://github.com/OlegChe77/local-ai [8] (MIT). Сборка: pip install -r requirements.txt, python app/main.py или build.ps [9]1.

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

Автор: OlegChe77

Источник [10]


Сайт-источник BrainTools: https://www.braintools.ru

Путь до страницы источника: https://www.braintools.ru/article/37946

URLs in this post:

[1] логика: http://www.braintools.ru/article/7640

[2] pywebview: https://pywebview.flowrl.com/

[3] memory.total: http://memory.total

[4] registry.ollama.ai: http://registry.ollama.ai

[5] памяти: http://www.braintools.ru/article/4140

[6] ошибка: http://www.braintools.ru/article/4192

[7] LocalAI.zip: http://LocalAI.zip

[8] https://github.com/OlegChe77/local-ai: https://github.com/OlegChe77/local-ai

[9] build.ps: http://build.ps

[10] Источник: https://habr.com/ru/articles/1102980/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1102980

www.BrainTools.ru

Rambler's Top100