Gemma 3n: установка, API и примеры кода для разработчиков | AiManual
AiManual Logo Ai / Manual.
11 Янв 2026 Гайд

Полное руководство по Gemma 3n: установка, API и примеры кода для разработчиков

Подробный гайд по работе с Gemma 3n: установка, настройка API, примеры кода и интеграция в проекты. Все для разработчиков.

Что такое Gemma 3n и почему она вам нужна

Gemma 3n - это не просто еще одна языковая модель от Google. Это инструмент, который превращает вашу локальную машину в полноценный ИИ-сервер. В отличие от облачных API вроде Gemini, Gemma работает там, где вы хотите: на вашем ноутбуке, сервере, даже на Raspberry Pi (если у вас хватит терпения ждать ответа несколько минут).

Gemma 3n - это open-source версия Gemini Nano от Google. Она оптимизирована для локального запуска и имеет значительно меньший размер по сравнению с полноценными моделями Gemini.

Зачем вам это нужно? Три причины:

  • Конфиденциальность - данные никуда не уходят из вашей сети
  • Экономия - нет платы за токены, только электричество
  • Кастомизация - можно дообучать под свои задачи

Установка Gemma 3n: от теории к боли

Официальная документация Google часто делает вид, что все работает из коробки. Это ложь. Вот что происходит на самом деле.

1 Подготовка системы: что Google не рассказывает

Первая проблема - зависимости. Если у вас Windows, сразу скажу: проще поставить WSL2. Почему? Потому что половина инструментов для работы с моделями написана под Linux, а порты для Windows работают через раз.

Минимальные требования: 8GB RAM для 2B-версии, 16GB для 7B. На деле добавьте еще 4GB сверху, потому что операционка тоже кушает память.

Устанавливаем базовые пакеты:

# Для Ubuntu/Debian
sudo apt update
sudo apt install -y python3-pip python3-venv git curl wget

# Проверяем версию Python - нужна 3.9+
python3 --version

# Если Python 3.8 или ниже - готовьтесь к боли
# Придется компилировать Python из исходников

2 Установка через Hugging Face: самый простой путь

Hugging Face - это ваш лучший друг и худший враг одновременно. С одной стороны, там все готово. С другой - иногда зависимости конфликтуют так, что хочется вернуться к каменному веку.

Создаем виртуальное окружение (это не опция, это необходимость):

python3 -m venv gemma_env
source gemma_env/bin/activate  # для Linux/Mac
# или gemma_env\Scripts\activate для Windows

Устанавливаем трансформеры и зависимости:

pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
# Если у вас есть CUDA, используйте соответствующую версию

pip install transformers accelerate sentencepiece protobuf
💡
Проблема с protobuf: если у вас уже установлен protobuf другой версии, будет конфликт. Удалите все версии и установите заново: pip uninstall protobuf && pip install protobuf

3 Загрузка модели: где брать веса и как не сломать интернет

Google размещает модели на Hugging Face Hub. Но есть нюанс: вам нужен аккаунт и доступ. Регистрируетесь, принимаете условия использования Gemma, получаете токен.

Как НЕ надо делать:

# Не делайте так
from transformers import AutoModelForCausalLM
model = AutoModelForCausalLM.from_pretrained("google/gemma-2b")
# Упадет с ошибкой, потому что нет доступа

Правильный способ:

from transformers import AutoTokenizer, AutoModelForCausalLM
import torch

# Сначала логинимся через huggingface-cli
# huggingface-cli login
# Вводите свой токен

tokenizer = AutoTokenizer.from_pretrained("google/gemma-2b")
model = AutoModelForCausalLM.from_pretrained(
    "google/gemma-2b",
    torch_dtype=torch.float16,
    device_map="auto"
)

API Gemma 3n: делаем из модели сервис

Запускать модель в интерактивном режиме - это для тестирования. В реальных проектах вам нужен API. Вот как превратить Gemma в веб-сервис.

FastAPI + Gemma: рецепт рабочего сервиса

FastAPI стал стандартом де-факто для ML-сервисов. Быстро, асинхронно, автоматическая документация.

Устанавливаем зависимости:

pip install fastapi uvicorn pydantic

Создаем файл app.py:

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from transformers import AutoTokenizer, AutoModelForCausalLM
import torch
import asyncio
from contextlib import asynccontextmanager

# Глобальные переменные для модели и токенайзера
model = None
tokenizer = None

@asynccontextmanager
async def lifespan(app: FastAPI):
    """Загружаем модель при старте приложения"""
    global model, tokenizer
    
    print("Загрузка модели Gemma 3n...")
    tokenizer = AutoTokenizer.from_pretrained("google/gemma-2b")
    model = AutoModelForCausalLM.from_pretrained(
        "google/gemma-2b",
        torch_dtype=torch.float16,
        device_map="auto",
        low_cpu_mem_usage=True
    )
    print("Модель загружена!")
    
    yield
    
    # Очистка при завершении
    if torch.cuda.is_available():
        torch.cuda.empty_cache()

app = FastAPI(lifespan=lifespan)

class PromptRequest(BaseModel):
    text: str
    max_length: int = 100
    temperature: float = 0.7
    top_p: float = 0.9

class CompletionResponse(BaseModel):
    generated_text: str
    processing_time: float

@app.post("/generate", response_model=CompletionResponse)
async def generate_text(request: PromptRequest):
    """Генерация текста через Gemma"""
    try:
        import time
        start_time = time.time()
        
        inputs = tokenizer(request.text, return_tensors="pt")
        
        if torch.cuda.is_available():
            inputs = inputs.to("cuda")
        
        with torch.no_grad():
            outputs = model.generate(
                **inputs,
                max_length=request.max_length,
                temperature=request.temperature,
                top_p=request.top_p,
                do_sample=True
            )
        
        generated_text = tokenizer.decode(outputs[0], skip_special_tokens=True)
        processing_time = time.time() - start_time
        
        return CompletionResponse(
            generated_text=generated_text,
            processing_time=round(processing_time, 2)
        )
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/health")
async def health_check():
    """Проверка работоспособности сервиса"""
    return {
        "status": "healthy",
        "model_loaded": model is not None,
        "device": str(model.device) if model else None
    }

Запускаем сервер:

uvicorn app:app --reload --host 0.0.0.0 --port 8000

Внимание: если у вас мало RAM, используйте параметр --workers 1. Каждый воркер загружает свою копию модели, что может привести к OOM killer.

Примеры кода: от простого к сложному

Теперь, когда у нас есть работающий API, посмотрим на практические кейсы. Вот что можно делать с Gemma 3n.

Классификация текстов без дообучения

Gemma умеет классифицировать тексты даже без fine-tuning. Используем few-shot prompting:

def classify_sentiment(text):
    """Классификация тональности текста"""
    prompt = f"""
Текст: "Я в восторге от этого продукта! Работает идеально."
Тональность: позитивная

Текст: "Это худшая покупка в моей жизни. Полный разочарование."
Тональность: негативная

Текст: "Доставка заняла 3 дня. Ничего особенного."
Тональность: нейтральная

Текст: "{text}"
Тональность:"""
    
    inputs = tokenizer(prompt, return_tensors="pt")
    
    if torch.cuda.is_available():
        inputs = inputs.to("cuda")
    
    outputs = model.generate(
        **inputs,
        max_new_tokens=10,
        temperature=0.1,  # Низкая температура для детерминированности
        do_sample=False
    )
    
    response = tokenizer.decode(outputs[0], skip_special_tokens=True)
    # Извлекаем последнюю строку с тональностью
    lines = response.strip().split('\n')
    return lines[-1].replace("Тональность:", "").strip()

# Тестируем
print(classify_sentiment("Обслуживание было на высшем уровне!"))
print(classify_sentiment("Ужасный сервис, никогда больше."))

Извлечение сущностей (NER)

Gemma может извлекать имена, компании, даты из текста:

def extract_entities(text):
    """Извлечение именованных сущностей"""
    prompt = f"""
Извлеки все имена людей, организаций и даты из текста:

Текст: "Иван Петров работает в Google с 2020 года."
Результат:
- Иван Петров (PERSON)
- Google (ORG)
- 2020 год (DATE)

Текст: "{text}"
Результат:"""
    
    inputs = tokenizer(prompt, return_tensors="pt")
    
    if torch.cuda.is_available():
        inputs = inputs.to("cuda")
    
    outputs = model.generate(
        **inputs,
        max_new_tokens=100,
        temperature=0.3,
        top_p=0.9
    )
    
    response = tokenizer.decode(outputs[0], skip_special_tokens=True)
    # Находим начало результата
    result_start = response.find("Результат:") + len("Результат:")
    return response[result_start:].strip()

# Пример использования
entities = extract_entities(
    "Мария Сидорова и Алексей Иванов встретились в Microsoft 15 марта 2023 года."
)
print(entities)

Генерация SQL-запросов

Один из самых полезных кейсов - преобразование естественного языка в SQL:

def natural_language_to_sql(nl_query, schema_definition):
    """Преобразование естественного языка в SQL"""
    prompt = f"""
Дана схема базы данных:
{schema_definition}

Преобразуй запрос на естественном языке в SQL:

Вход: "Покажи всех пользователей из Москвы"
SQL: SELECT * FROM users WHERE city = 'Москва';

Вход: "Найди заказы за последнюю неделю"
SQL: SELECT * FROM orders WHERE order_date >= DATE_SUB(NOW(), INTERVAL 7 DAY);

Вход: "{nl_query}"
SQL:"""
    
    inputs = tokenizer(prompt, return_tensors="pt")
    
    if torch.cuda.is_available():
        inputs = inputs.to("cuda")
    
    outputs = model.generate(
        **inputs,
        max_new_tokens=50,
        temperature=0.1,
        do_sample=False
    )
    
    response = tokenizer.decode(outputs[0], skip_special_tokens=True)
    # Извлекаем SQL запрос
    lines = response.strip().split('\n')
    sql_line = lines[-1].replace("SQL:", "").strip()
    return sql_line

# Пример схемы
schema = """
Таблица users:
- id INT PRIMARY KEY
- name VARCHAR(100)
- email VARCHAR(100)
- city VARCHAR(50)
- registration_date DATE

Таблица orders:
- order_id INT PRIMARY KEY
- user_id INT FOREIGN KEY REFERENCES users(id)
- amount DECIMAL(10,2)
- order_date DATETIME
- status VARCHAR(20)
"""

sql = natural_language_to_sql(
    "Покажи топ-10 пользователей по сумме заказов за 2023 год",
    schema
)
print(sql)

Оптимизация производительности: как не сжечь компьютер

Gemma 3n на локальной машине - это балансирование между качеством ответов и температурой процессора. Вот что реально работает.

Техника Эффект Сложность
Квантование 8-bit Память -50%, скорость +30% Средняя
Flash Attention 2 Скорость +40%, память -20% Высокая
Paged Attention Стабильность при длинных контекстах Низкая
Speculative Decoding Скорость генерации +2-3x Очень высокая

Квантование модели для экономии памяти

Если у вас мало RAM или вы хотите запустить модель на дешевом VPS, квантование - ваш выбор:

from transformers import BitsAndBytesConfig
import torch

bnb_config = BitsAndBytesConfig(
    load_in_8bit=True,
    llm_int8_threshold=6.0,
    llm_int8_has_fp16_weight=False,
    bnb_4bit_compute_dtype=torch.float16
)

model = AutoModelForCausalLM.from_pretrained(
    "google/gemma-2b",
    quantization_config=bnb_config,
    device_map="auto",
    low_cpu_mem_usage=True
)

Внимание: после квантования точность может снизиться на 1-3%. Для большинства задач это приемлемо, но для финансовых расчетов или медицинских диагнозов лучше использовать полную точность.

Оптимизация через vLLM

vLLM - это движок для эффективного обслуживания LLM. Он использует Paged Attention и дает прирост скорости до 24x.

# Установка vLLM
pip install vllm

# Запуск сервера
python -m vllm.entrypoints.openai.api_server \
    --model google/gemma-2b \
    --port 8000 \
    --max-model-len 4096 \
    --gpu-memory-utilization 0.9

Теперь у вас есть OpenAI-совместимый API:

import openai

openai.api_base = "http://localhost:8000/v1"
openai.api_key = "token-abc123"  # любая строка

response = openai.Completion.create(
    model="google/gemma-2b",
    prompt="Как оптимизировать SQL запрос?",
    max_tokens=100
)

print(response.choices[0].text)

Типичные ошибки и как их избежать

Я видел десятки проектов с Gemma. Вот самые частые ошибки, которые ломают все.

Ошибка 1: Неправильная обработка токенов

Как НЕ делать:

# Плохо: ручная обработка токенов
text = "Привет, мир!"
tokens = text.split()  # Это не токенизация!
inputs = torch.tensor([tokens])  # Ошибка!

Правильно:

# Хорошо: используем токенайзер модели
text = "Привет, мир!"
inputs = tokenizer(text, return_tensors="pt")  # Автоматическая токенизация

Ошибка 2: Игнорирование контекстного окна

Gemma 3n имеет ограниченное контекстное окно (обычно 8192 токена). Если вы подаете текст длиннее - он обрежется без предупреждения.

def safe_generate(text, max_context=8000):
    """Безопасная генерация с проверкой длины контекста"""
    # Токенизируем для подсчета длины
    tokens = tokenizer.encode(text)
    
    if len(tokens) > max_context:
        # Обрезаем или используем технику скользящего окна
        # Простой вариант: обрезаем начало
        truncated_tokens = tokens[-max_context:]
        text = tokenizer.decode(truncated_tokens)
        print(f"Предупреждение: текст обрезан с {len(tokens)} до {len(truncated_tokens)} токенов")
    
    # Теперь генерируем
    inputs = tokenizer(text, return_tensors="pt")
    # ... остальная часть генерации

Ошибка 3: Утечки памяти в долгоживущих процессах

После 1000 запросов ваш сервер может упасть из-за утечки памяти. Решение:

import gc
import torch

class SafeGenerator:
    def __init__(self, model, tokenizer):
        self.model = model
        self.tokenizer = tokenizer
        
    def generate_with_cleanup(self, text, **kwargs):
        """Генерация с очисткой памяти после каждого вызова"""
        try:
            inputs = self.tokenizer(text, return_tensors="pt")
            
            if torch.cuda.is_available():
                inputs = inputs.to("cuda")
            
            with torch.no_grad():
                outputs = self.model.generate(**inputs, **kwargs)
                
            result = self.tokenizer.decode(outputs[0], skip_special_tokens=True)
            
            return result
            
        finally:
            # Очистка
            if torch.cuda.is_available():
                torch.cuda.empty_cache()
            gc.collect()

Интеграция с реальными проектами

Теперь, когда мы разобрались с основами, посмотрим на реальные кейсы. Например, создание офлайн-помощников на Gemma 3n или построение гиперлокальных моделей для специфических задач.

Микросервис для обработки документов

Представьте, что вам нужно обрабатывать сотни документов в день. Вот архитектура:

import asyncio
from concurrent.futures import ThreadPoolExecutor
from typing import List
import aiofiles

class DocumentProcessor:
    def __init__(self, model_path="google/gemma-2b", max_workers=2):
        self.tokenizer = AutoTokenizer.from_pretrained(model_path)
        self.model = AutoModelForCausalLM.from_pretrained(
            model_path,
            torch_dtype=torch.float16,
            device_map="auto"
        )
        self.executor = ThreadPoolExecutor(max_workers=max_workers)
        
    async def process_document(self, filepath: str) -> dict:
        """Обработка одного документа"""
        # Чтение файла
        async with aiofiles.open(filepath, 'r', encoding='utf-8') as f:
            content = await f.read()
        
        # Асинхронная генерация в отдельном потоке
        loop = asyncio.get_event_loop()
        summary = await loop.run_in_executor(
            self.executor,
            self._generate_summary,
            content
        )
        
        # Извлечение ключевых слов
        keywords = await loop.run_in_executor(
            self.executor,
            self._extract_keywords,
            content
        )
        
        return {
            "file": filepath,
            "summary": summary,
            "keywords": keywords,
            "length": len(content)
        }
    
    def _generate_summary(self, text: str) -> str:
        """Генерация краткого содержания"""
        prompt = f"Сократи текст до 3 предложений:\n\n{text[:2000]}"
        inputs = self.tokenizer(prompt, return_tensors="pt")
        
        if torch.cuda.is_available():
            inputs = inputs.to("cuda")
        
        outputs = self.model.generate(
            **inputs,
            max_new_tokens=100,
            temperature=0.7
        )
        
        return self.tokenizer.decode(outputs[0], skip_special_tokens=True)
    
    def _extract_keywords(self, text: str) -> List[str]:
        """Извлечение ключевых слов"""
        prompt = f"Извлеки 5 ключевых слов из текста:\n\n{text[:1500]}"
        inputs = self.tokenizer(prompt, return_tensors="pt")
        
        if torch.cuda.is_available():
            inputs = inputs.to("cuda")
        
        outputs = self.model.generate(
            **inputs,
            max_new_tokens=50,
            temperature=0.3
        )
        
        result = self.tokenizer.decode(outputs[0], skip_special_tokens=True)
        # Парсим результат (например: "Ключевые слова: ИИ, машинное обучение, данные")
        if ":" in result:
            keywords_part = result.split(":", 1)[1].strip()
            return [kw.strip() for kw in keywords_part.split(",")]
        return []

# Использование
async def main():
    processor = DocumentProcessor()
    documents = ["doc1.txt", "doc2.txt", "doc3.txt"]
    
    tasks = [processor.process_document(doc) for doc in documents]
    results = await asyncio.gather(*tasks)
    
    for result in results:
        print(f"Файл: {result['file']}")
        print(f"Краткое содержание: {result['summary'][:200]}...")
        print(f"Ключевые слова: {result['keywords']}")
        print("-" * 50)

Что дальше? От локальной модели к production

Вы запустили Gemma локально. Поздравляю. Но это только начало. Дальше нужно думать о масштабировании, мониторинге, отказоустойчивости.

Если вам нужна более мощная модель для production, посмотрите на Gemini 3 Flash API. Для сложных задач reasoning изучите различия между Gemini 3 и 2.5.

💡
Помните: локальная модель - это не панацея. Для high-load проектов с тысячами запросов в минуту облачные решения вроде Gemini API могут быть дешевле, чем аренда GPU-серверов. Считайте TCO (Total Cost of Ownership).

Мой совет: начните с локальной Gemma для прототипирования и тестирования идей. Когда поймете, что ваш продукт работает и нуждается в масштабировании - переходите на облачные решения или разворачивайте кластер GPU-серверов.

И последнее: не пытайтесь заставить Gemma делать то, для чего она не создана. Если вам нужна мультимодальность - смотрите в сторону Gemini. Если нужен сложный reasoning - возможно, вам нужна Gemini 2.5 Computer Use. Каждый инструмент хорош для своей задачи.

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