Запуск GPT OSS и Qwen VL на 6 ГБ VRAM с MCP-сервером | AiManual
AiManual Logo Ai / Manual.
10 Янв 2026 Гайд

Как запустить GPT OSS и Qwen VL на 6 ГБ VRAM: создание кастомного MCP-сервера

Пошаговый гайд по созданию кастомного MCP-сервера для запуска двух больших моделей на ограниченной видеопамяти. Оптимизация памяти, настройка llama.cpp, решение

Зачем пытаться запихнуть слона в холодильник?

Вам знакома эта ситуация: есть две крутые модели - GPT OSS для текста и Qwen VL для анализа изображений. И есть ваш скромный GPU с 6 ГБ памяти. В теории каждая модель требует 8-10 ГБ, но на практике вы хотите обе. Прямо сейчас. Без покупки новой видеокарты.

Стандартный подход "скачал-запустил" здесь не работает. Одна модель займет всю память, вторая не запустится. Можно переключаться между ними, но это медленно и неудобно. А что если нужно обработать текст и изображение в одном диалоге?

Попытка запустить обе модели одновременно стандартными методами закончится ошибкой CUDA out of memory. Это не баг - это физика. Но физику можно обмануть.

Что такое MCP-сервер и зачем он нам?

Model Context Protocol (MCP) - относительно новый стандарт от Anthropic для взаимодействия с моделями. По сути, это HTTP-сервер, который умеет управлять несколькими моделями, распределять запросы и память. Кастомный MCP-сервер - наш ключ к решению проблемы.

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

💡
Если вы уже читали мою статью про локальную LLM-инфраструктуру, то знаете: главное - не железо, а архитектура. Здесь тот же принцип.

Подготовка: что нужно перед началом

Прежде чем прыгать в код, убедитесь что у вас есть:

  • NVIDIA GPU с 6 ГБ VRAM (RTX 2060, 3050, 3060 и подобные)
  • Python 3.10 или новее
  • CUDA 11.8 или 12.x (совместимая с вашим драйвером)
  • Не менее 16 ГБ оперативной памяти
  • 30 ГБ свободного места на диске для моделей

Проверьте установку CUDA:

nvidia-smi

Если видите версию драйвера и свободную память - все хорошо. Если нет - сначала установите драйверы.

1Шаг 1: Выбор правильных версий моделей

Это самый критичный момент. Нельзя просто взять любые версии GPT OSS и Qwen VL. Нужны специально квантованные GGUF-версии.

Для GPT OSS ищем модель в формате GGUF с квантованием Q4_K_M или Q5_K_M. Почему именно эти?

  • Q4_K_M дает хороший баланс качества и размера (~4-5 ГБ)
  • Q5_K_M немного лучше по качеству, но больше (~5-6 ГБ)
  • Q8 и выше не влезут вместе с Qwen VL

Для Qwen VL ситуация сложнее. Мультимодальные модели всегда больше. Ищем Qwen2-VL-7B-Instruct-GGUF с квантованием Q4_K_M. Да, только Q4. И только 7B версию. 14B или 32B не влезут даже поодиночке.

МодельРекомендуемая версияРазмерГде искать
GPT OSSgpt-oss-7b-q4_k_m.gguf~4.2 ГБHugging Face
Qwen VLQwen2-VL-7B-Instruct-q4_k_m.gguf~4.8 ГБHugging Face

Скачиваем обе модели в папку ~/.cache/gguf/ или другую удобную.

2Шаг 2: Установка llama.cpp с правильными флагами

Не устанавливайте llama.cpp из pip. Соберите из исходников с CUDA поддержкой:

git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
make clean
LLAMA_CUDA=1 make -j$(nproc)

Проверяем что CUDA работает:

./main -m ~/.cache/gguf/gpt-oss-7b-q4_k_m.gguf -p "Hello" -n 10 --gpu-layers 20

Если видите ответ и нет ошибок CUDA - все окей. Если получаете ошибку - проверьте переменные окружения:

export CUDA_VISIBLE_DEVICES=0
export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH

Теперь главный трюк: определяем сколько слоев грузить на GPU. Для 6 ГБ и двух моделей:

# Для GPT OSS (4.2 ГБ модель)
./main -m gpt-oss-7b-q4_k_m.gguf -p "test" -n 5 --gpu-layers 18 --ctx-size 2048

# Для Qwen VL (4.8 ГБ модель) 
./main -m Qwen2-VL-7B-Instruct-q4_k_m.gguf -p "test" -n 5 --gpu-layers 15 --ctx-size 1024

Почему такие цифры? --gpu-layers определяет сколько слоев модели будут в VRAM. Остальные - в RAM. Меньше слоев на GPU = меньше потребление VRAM, но медленнее инференс. Экспериментируйте. Начните с 15-18 слоев для каждой модели.

Запустите каждую модель отдельно с разным количеством --gpu-layers и смотрите потребление VRAM через nvidia-smi. Цель - чтобы каждая модель занимала не более 3.5 ГБ VRAM в рабочем состоянии.

3Шаг 3: Создаем кастомный MCP-сервер

Теперь напишем сервер на Python, который будет управлять обеими моделями. Установите зависимости:

pip install fastapi uvicorn pydantic python-multipart

Создайте файл mcp_server.py:

import subprocess
import threading
import time
import json
import os
from typing import Optional
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import signal

app = FastAPI(title="Dual Model MCP Server")

class ModelManager:
    def __init__(self):
        self.current_model = None
        self.process = None
        self.models = {
            "gpt_oss": {
                "path": "/home/user/.cache/gguf/gpt-oss-7b-q4_k_m.gguf",
                "gpu_layers": 18,
                "ctx_size": 2048
            },
            "qwen_vl": {
                "path": "/home/user/.cache/gguf/Qwen2-VL-7B-Instruct-q4_k_m.gguf",
                "gpu_layers": 15,
                "ctx_size": 1024
            }
        }
    
    def switch_model(self, model_name: str):
        """Выгружаем текущую модель, загружаем новую"""
        if self.current_model == model_name:
            return True
        
        # Останавливаем текущий процесс
        if self.process:
            self.process.terminate()
            self.process.wait(timeout=5)
        
        # Запускаем новую модель
        model_config = self.models[model_name]
        cmd = [
            "./main",
            "-m", model_config["path"],
            "--gpu-layers", str(model_config["gpu_layers"]),
            "--ctx-size", str(model_config["ctx_size"]),
            "--simple-io",
            "--n-predict", "512",
            "--temp", "0.7"
        ]
        
        self.process = subprocess.Popen(
            cmd,
            stdin=subprocess.PIPE,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True
        )
        self.current_model = model_name
        
        # Даем модели время на инициализацию
        time.sleep(3)
        return True
    
    def generate(self, model_name: str, prompt: str) -> str:
        self.switch_model(model_name)
        
        if not self.process:
            raise RuntimeError("Model not loaded")
        
        # Отправляем промпт
        self.process.stdin.write(prompt + "\n")
        self.process.stdin.flush()
        
        # Читаем ответ
        output = []
        while True:
            line = self.process.stdout.readline()
            if not line:
                break
            output.append(line.strip())
            if "" in line or len(output) > 50:
                break
        
        return "\n".join(output)

manager = ModelManager()

class ChatRequest(BaseModel):
    model: str
    prompt: str
    max_tokens: Optional[int] = 512

@app.post("/chat")
async def chat(request: ChatRequest):
    try:
        if request.model not in ["gpt_oss", "qwen_vl"]:
            raise HTTPException(status_code=400, detail="Unknown model")
        
        response = manager.generate(request.model, request.prompt)
        return {"response": response, "model": request.model}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/health")
async def health():
    return {"status": "ok", "current_model": manager.current_model}

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

Это упрощенная версия. В реальном проекте добавьте обработку изображений для Qwen VL (она требует base64 кодирование), кэширование, таймауты и логирование.

4Шаг 4: Запуск и тестирование

Сначала запустите сервер:

cd llama.cpp
python mcp_server.py

В другом терминале проверьте работу:

# Проверка здоровья
curl http://localhost:8000/health

# Запрос к GPT OSS
curl -X POST http://localhost:8000/chat \
  -H "Content-Type: application/json" \
  -d '{"model": "gpt_oss", "prompt": "Explain quantum computing"}'

# Запрос к Qwen VL (текстовый режим)
curl -X POST http://localhost:8000/chat \
  -H "Content-Type: application/json" \
  -d '{"model": "qwen_vl", "prompt": "Describe a sunset"}'

Откройте nvidia-smi в третьем терминале и наблюдайте как память освобождается и занимается при переключении моделей.

Где собака зарыта: самые частые ошибки

Я видел десятки попыток сделать подобное. Вот что ломается чаще всего:

Ошибка 1: CUDA out of memory после нескольких запросов. Почему? llama.cpp не всегда полностью освобождает память при завершении. Решение: добавить --no-mmap флаг при запуске main, но это замедлит загрузку модели.

Ошибка 2: Модель загружается вечно. Проверьте --ctx-size. Слишком большой контекст (8192+) может не влезть даже в RAM. Начните с 1024-2048.

Ошибка 3: Qwen VL не понимает промпты. Мультимодальные модели требуют специального форматирования. Для текстовых запросов используйте стандартный чатовый формат, для изображений - base64 в JSON.

Ошибка 4: Сервер падает при параллельных запросах. Наш простой сервер не потокобезопасен. В продакшене используйте очередь запросов или запускайте отдельный процесс llama.cpp для каждого запроса.

А можно еще оптимизировать?

Конечно. Вот что дает дополнительный прирост:

  • Используйте flash attention: соберите llama.cpp с LLAMA_FLASH_ATTN=1. Ускоряет инференс на 20-30%.
  • Экспериментируйте с кэшированием K/V: флаг --prompt-cache и --prompt-cache-all ускоряют повторные запросы.
  • Настройте swap: если не хватает RAM, добавьте swap файл 16-32 ГБ. Медленно, но лучше чем падение.
  • Рассмотрите EXL2 формат: вместо GGUF. Более эффективное квантование, но сложнее в настройке.

Если у вас совсем старый GPU или мало RAM, посмотрите мою статью про CPU+RAM инференс. Там другие подходы.

А что насчет 8 ГБ или 12 ГБ VRAM?

С 8 ГБ можно позволить себе более высокое квантование (Q6_K) или больше слоев на GPU. С 12 ГБ - можно попробовать запустить 13B версии моделей, но осторожно.

Главное правило: оставляйте 1-2 ГБ VRAM про запас. Не только для самой модели, но и для активаций, контекста, системных нужд CUDA. Если nvidia-smi показывает 5.8/6.0 ГБ - ждите падения при следующем запросе.

💡
Помните статью про минимальные требования VRAM? Там есть полезная таблица зависимости размера модели от квантования. Распечатайте ее и повесьте над монитором.

Что дальше? Куда развивать этот проект

Рабочий MCP-сервер - только начало. Вот что можно добавить:

  1. Поддержку OpenAI-совместимого API: чтобы подключать стандартные клиенты.
  2. Веб-интерфейс: простой чат с переключателем моделей.
  3. Автоматическое определение типа запроса: текст -> GPT OSS, упоминание изображений -> Qwen VL.
  4. Кэширование моделей в RAM: не выгружать полностью, а держать веса в оперативке для быстрого переключения.
  5. Интеграцию с RAG: добавить векторную базу для документов.

Самое интересное - когда вы понимаете что эта архитектура масштабируется. Добавить третью модель? Просто расширите словарь models в менеджере. Больше памяти? Увеличьте --gpu-layers. Нужно обслуживать несколько пользователей? Добавьте балансировщик нагрузки.

И главное - теперь у вас есть полный контроль. Никаких ограничений по токенам, никаких цензурных фильтров (если только вы сами их не добавите), никакой отправки данных в облако. Только ваше железо, ваши модели, ваши правила.

Кстати, если вы думаете "это слишком сложно для 6 ГБ, проще купить карту на 24 ГБ" - вы правы. Проще. Но где в этом кайф? Где вызов? Где тот момент когда вы смотрите на nvidia-smi и видите как две модели уместились там, где по спецификациям не должна поместиться ни одна?

Вот ради этого мы и занимаемся локальным AI. Не потому что это дешево или удобно. А потому что можем.