srlps/gemma4-poc

0

stars

3

commits

Python

primary language

Apr 30, 2026

updated

README

Gemma 4 PoC

Proof of concept para ejecutar el modelo Google Gemma 4 E2B localmente en CPU, con dos modos:

  • Modo completo (float16) via Hugging Face transformers — mayor fidelidad, mayor consumo de RAM.
  • Modo cuantizado (Q4_K_M GGUF) via llama-cpp-python — menor consumo, mayor velocidad en CPU.

Modelo base: google/gemma-4-E2B-it
Modelo GGUF: unsloth/gemma-4-E2B-it-GGUF


Scripts disponibles

ScriptDescripción
torch_test.pyDiagnóstico de instalación: versión de torch, CUDA y GPU
gpu_test.pyStress test de GPU usando GPT-2 (10 iteraciones de inferencia)
getting_started_gemma4.pyInferencia simple en CPU con Gemma 4 (greedy, una sola respuesta)
chat_model.pyChat interactivo en CPU con historial, streaming y log a fichero
chat_model_quantized.pyChat interactivo con modelo GGUF via llama-cpp-python y streaming
thinking.pyBenchmark de razonamiento: compara enable_thinking=True/False en CPU
thinking_quantized.pyMismo benchmark de razonamiento con modelo GGUF
multimodal_image.pyAnálisis de imágenes locales en CPU (OCR, gráficos, UI, fotos, diagramas)

Arquitectura de scripts

Hugging Face transformers (float16, CPU)      llama-cpp-python (GGUF Q4_K_M, CPU)
────────────────────────────────────          ──────────────────────────────────────
getting_started_gemma4.py                     chat_model_quantized.py
chat_model.py                                 thinking_quantized.py
thinking.py
multimodal_image.py

Instalación

Requisitos

  • Python 3.10, 3.11 o 3.12 (recomendado 3.12)
  • Python 3.13 no está soportado por PyTorch con CUDA

1. Crear y activar entorno virtual

py -3.12 -m venv .venv
.venv\Scripts\activate

2. Actualizar pip

python -m pip install --upgrade pip

3. Instalar PyTorch (PRIMERO, antes que el resto)

torch no está en requirements.txt porque el wheel correcto depende del sistema operativo, arquitectura, versión de Python y versión de CUDA instalada. Debe instalarse antes para evitar que pip instale la versión CPU automáticamente.

Los siguientes wheels corresponden a la configuración de este equipo:

  • OS: Windows (amd64)
  • Python: 3.12 (cp312)
  • CUDA: 12.1 (cu121)
  • torch: 2.5.1

Si tu configuración es diferente, busca el wheel adecuado en https://download.pytorch.org/whl/torch_stable.html.

pip install https://download-r2.pytorch.org/whl/cu121/torch-2.5.1%2Bcu121-cp312-cp312-win_amd64.whl
pip install https://download-r2.pytorch.org/whl/cu121/torchvision-0.20.1%2Bcu121-cp312-cp312-win_amd64.whl

4. Instalar el resto de dependencias

pip install -r requirements.txt

requirements.txt incluye:

bitsandbytes
transformers
accelerate
numpy
pillow
huggingface_hub
psutil
llama-cpp-python

Verificación de instalación

python torch_test.py

Salida esperada con GPU NVIDIA:

Torch version: 2.5.1+cu121
CUDA available: True
CUDA version (torch): 12.1
GPU: NVIDIA GeForce ...

Descripción detallada de scripts

getting_started_gemma4.py

Inferencia mínima en CPU. Carga el modelo en float16, procesa un único prompt con decodificación greedy y reporta tiempos y tokens/seg. Punto de entrada para verificar que el entorno funciona correctamente.

python getting_started_gemma4.py

chat_model.py

Chat interactivo multi-turno en CPU usando transformers con streaming via TextIteratorStreamer. Características:

  • Historial recortado a los últimos 6 turnos (MAX_HISTORY = 6)
  • Control de tokens de entrada (máx. 1024)
  • Log de conversación en chat_log.txt
  • Optimización de threads CPU (OMP_NUM_THREADS, MKL_NUM_THREADS)
  • Intento de compilación con torch.compile
  • System prompt configurable
python chat_model.py
# Type 'exit' para salir

chat_model_quantized.py

Misma funcionalidad de chat pero usando el modelo GGUF cuantizado (Q4_K_M) a través de llama-cpp-python. Más rápido y con menor consumo de RAM que el modo float16. Streaming nativo de llama-cpp.

python chat_model_quantized.py
# Type 'exit' para salir

thinking.py

Benchmark de razonamiento con 5 prompts de prueba. Ejecuta cada prompt dos veces: con enable_thinking=True y enable_thinking=False, usando streaming para mostrar la respuesta en tiempo real. Permite comparar la calidad y velocidad de ambos modos.

python thinking.py

Prompts de prueba incluidos:

  • Velocidad media de un tren
  • Problema de las ovejas del granjero
  • Debug de código Python
  • Silogismo lógico (Bloops/Razzies/Lazzies)
  • Operación aritmética con razonamiento

thinking_quantized.py

Mismo benchmark de razonamiento pero con el modelo GGUF. En modo thinking usa max_tokens=512 y un system prompt que indica razonamiento paso a paso; en modo normal usa max_tokens=256 y pide solo la respuesta final.

python thinking_quantized.py

multimodal_image.py

Análisis multimodal de imágenes locales en CPU. Prueba 5 casos predefinidos con imágenes en la carpeta images/:

Archivo esperadoTarea
images/document.jpgOCR — extraer texto
images/chart.pngAnálisis de gráfico
images/screenshot.pngInterpretación de UI
images/photo.jpgDescripción detallada
images/diagram.jpgExplicación de diagrama

Cada imagen se prueba con tres resoluciones de visual tokens: 70 (224×224), 280 (448×448) y 1120 (896×896).

python multimodal_image.py

Añade las imágenes en la carpeta images/ antes de ejecutar.

gpu_test.py

Stress test de GPU usando GPT-2 (modelo ligero). Carga el modelo en GPU si está disponible (si no, en CPU) y ejecuta 10 iteraciones de inferencia. Útil para verificar que la GPU responde correctamente antes de ejecutar modelos más grandes.

python gpu_test.py

Estructura de carpetas

gemma4-poc/
├── images/                        # Imágenes para multimodal_image.py
├── getting_started_gemma4.py      # Inferencia simple (transformers)
├── chat_model.py                  # Chat interactivo (transformers)
├── chat_model_quantized.py        # Chat interactivo (GGUF)
├── thinking.py                    # Benchmark razonamiento (transformers)
├── thinking_quantized.py          # Benchmark razonamiento (GGUF)
├── multimodal_image.py            # Análisis imágenes locales (transformers)
├── gpu_test.py                    # Stress test GPU con GPT-2
├── torch_test.py                  # Diagnóstico torch/CUDA
├── chat_log.txt                   # Log generado automáticamente por chat
└── requirements.txt

Resultado esperado:

  • CUDA disponible: True
  • GPU detectada correctamente

🔥 Verificación de uso REAL de GPU

No basta con detectar la GPU — este test confirma que realmente se está usando para cómputo.


🧪 Test de inferencia en GPU

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM

# -----------------------------
# Verificar dispositivo
# -----------------------------
device = "cuda" if torch.cuda.is_available() else "cpu"
print("Using device:", device)

# -----------------------------
# Modelo (ligero para GPU de 4GB)
# -----------------------------
model_name = "gpt2"

tokenizer = AutoTokenizer.from_pretrained(model_name)

model = AutoModelForCausalLM.from_pretrained(model_name)
model.to(device)

# -----------------------------
# Input de prueba
# -----------------------------
prompt = "La inteligencia artificial en el futuro"
inputs = tokenizer(prompt, return_tensors="pt").to(device)

# Confirmación explícita
print("Input device:", inputs.input_ids.device)
print("Model device:", next(model.parameters()).device)

# -----------------------------
# Limpiar memoria (opcional)
# -----------------------------
if device == "cuda":
    torch.cuda.empty_cache()

# -----------------------------
# Inferencia (múltiples iteraciones para observar GPU)
# -----------------------------
print("\nRunning inference...")

for i in range(10):
    with torch.no_grad():
        output = model.generate(**inputs, max_new_tokens=100)

print("Inference done.")

# -----------------------------
# Decodificar resultado
# -----------------------------
result = tokenizer.decode(output[0])
print("\nOutput:")
print(result)

# -----------------------------
# Métricas GPU
# -----------------------------
if device == "cuda":
    print("\nGPU memory allocated:", torch.cuda.memory_allocated() / 1024**2, "MB")
    print("GPU memory reserved:", torch.cuda.memory_reserved() / 1024**2, "MB")

👀 Qué deberías observar

En consola:

  • Using device: cuda
  • Input device: cuda:0
  • Model device: cuda:0

En GPU (usando nvidia-smi)

Ejecuta en otra terminal:

nvidia-smi -l 1

Durante la ejecución del script deberías ver:

  • 📈 Memory-Usage aumenta (ej: 200MB → 1000MB+)
  • GPU-Util sube (ej: 0% → 20–80%)

🧠 Interpretación

SeñalSignificado
VRAM subeEl modelo está cargado en GPU
GPU-Util subeSe está ejecutando cómputo real
Ambos✅ GPU funcionando correctamente

⚠️ Nota

Si el script es muy corto:

  • el uso de GPU puede aparecer solo por milisegundos
  • nvidia-smi puede mostrar solo picos breves (ej: 23%, 9%)

Esto es normal.


❌ Problemas comunes

GPU no se usa

  • Using device: cpu
  • GPU-Util = 0%
  • VRAM no cambia

👉 revisar instalación de torch


Solo sube VRAM pero no GPU-Util

👉 probablemente:

  • modelo muy pequeño
  • ejecución muy rápida

No es necesariamente un error.


⚙️ Recomendaciones para GPU (ej: GTX 1650 Ti)

  • VRAM limitada (~4GB)

  • Preferir:

    • modelos pequeños o medianos
    • device_map="auto"
    • torch_dtype="auto" o float16

🛠️ Troubleshooting

No matching distribution found for torch

  • Verificar versión de Python
  • En Python 3.12, usar instalación manual por wheel

torch.cuda.is_available() == False

  • Verificar drivers NVIDIA
  • Confirmar instalación correcta de torch con CUDA

❌ Error de memoria (OOM)

  • Usar modelos más pequeños
  • Reducir precisión (float16)
  • Cerrar apps que usen GPU

📌 Resumen

ComponenteRol
transformersModelos y API
torchEjecución (CPU/GPU)
accelerateGestión de dispositivos

Licencia

Este proyecto se distribuye bajo la licencia MIT.

Contributors

srlps

3 commits

srlps/gemma4-poc

0

stars

3

commits

Python

primary language

Apr 30, 2026

updated

README

Gemma 4 PoC

Proof of concept para ejecutar el modelo Google Gemma 4 E2B localmente en CPU, con dos modos:

  • Modo completo (float16) via Hugging Face transformers — mayor fidelidad, mayor consumo de RAM.
  • Modo cuantizado (Q4_K_M GGUF) via llama-cpp-python — menor consumo, mayor velocidad en CPU.

Modelo base: google/gemma-4-E2B-it
Modelo GGUF: unsloth/gemma-4-E2B-it-GGUF


Scripts disponibles

ScriptDescripción
torch_test.pyDiagnóstico de instalación: versión de torch, CUDA y GPU
gpu_test.pyStress test de GPU usando GPT-2 (10 iteraciones de inferencia)
getting_started_gemma4.pyInferencia simple en CPU con Gemma 4 (greedy, una sola respuesta)
chat_model.pyChat interactivo en CPU con historial, streaming y log a fichero
chat_model_quantized.pyChat interactivo con modelo GGUF via llama-cpp-python y streaming
thinking.pyBenchmark de razonamiento: compara enable_thinking=True/False en CPU
thinking_quantized.pyMismo benchmark de razonamiento con modelo GGUF
multimodal_image.pyAnálisis de imágenes locales en CPU (OCR, gráficos, UI, fotos, diagramas)

Arquitectura de scripts

Hugging Face transformers (float16, CPU)      llama-cpp-python (GGUF Q4_K_M, CPU)
────────────────────────────────────          ──────────────────────────────────────
getting_started_gemma4.py                     chat_model_quantized.py
chat_model.py                                 thinking_quantized.py
thinking.py
multimodal_image.py

Instalación

Requisitos

  • Python 3.10, 3.11 o 3.12 (recomendado 3.12)
  • Python 3.13 no está soportado por PyTorch con CUDA

1. Crear y activar entorno virtual

py -3.12 -m venv .venv
.venv\Scripts\activate

2. Actualizar pip

python -m pip install --upgrade pip

3. Instalar PyTorch (PRIMERO, antes que el resto)

torch no está en requirements.txt porque el wheel correcto depende del sistema operativo, arquitectura, versión de Python y versión de CUDA instalada. Debe instalarse antes para evitar que pip instale la versión CPU automáticamente.

Los siguientes wheels corresponden a la configuración de este equipo:

  • OS: Windows (amd64)
  • Python: 3.12 (cp312)
  • CUDA: 12.1 (cu121)
  • torch: 2.5.1

Si tu configuración es diferente, busca el wheel adecuado en https://download.pytorch.org/whl/torch_stable.html.

pip install https://download-r2.pytorch.org/whl/cu121/torch-2.5.1%2Bcu121-cp312-cp312-win_amd64.whl
pip install https://download-r2.pytorch.org/whl/cu121/torchvision-0.20.1%2Bcu121-cp312-cp312-win_amd64.whl

4. Instalar el resto de dependencias

pip install -r requirements.txt

requirements.txt incluye:

bitsandbytes
transformers
accelerate
numpy
pillow
huggingface_hub
psutil
llama-cpp-python

Verificación de instalación

python torch_test.py

Salida esperada con GPU NVIDIA:

Torch version: 2.5.1+cu121
CUDA available: True
CUDA version (torch): 12.1
GPU: NVIDIA GeForce ...

Descripción detallada de scripts

getting_started_gemma4.py

Inferencia mínima en CPU. Carga el modelo en float16, procesa un único prompt con decodificación greedy y reporta tiempos y tokens/seg. Punto de entrada para verificar que el entorno funciona correctamente.

python getting_started_gemma4.py

chat_model.py

Chat interactivo multi-turno en CPU usando transformers con streaming via TextIteratorStreamer. Características:

  • Historial recortado a los últimos 6 turnos (MAX_HISTORY = 6)
  • Control de tokens de entrada (máx. 1024)
  • Log de conversación en chat_log.txt
  • Optimización de threads CPU (OMP_NUM_THREADS, MKL_NUM_THREADS)
  • Intento de compilación con torch.compile
  • System prompt configurable
python chat_model.py
# Type 'exit' para salir

chat_model_quantized.py

Misma funcionalidad de chat pero usando el modelo GGUF cuantizado (Q4_K_M) a través de llama-cpp-python. Más rápido y con menor consumo de RAM que el modo float16. Streaming nativo de llama-cpp.

python chat_model_quantized.py
# Type 'exit' para salir

thinking.py

Benchmark de razonamiento con 5 prompts de prueba. Ejecuta cada prompt dos veces: con enable_thinking=True y enable_thinking=False, usando streaming para mostrar la respuesta en tiempo real. Permite comparar la calidad y velocidad de ambos modos.

python thinking.py

Prompts de prueba incluidos:

  • Velocidad media de un tren
  • Problema de las ovejas del granjero
  • Debug de código Python
  • Silogismo lógico (Bloops/Razzies/Lazzies)
  • Operación aritmética con razonamiento

thinking_quantized.py

Mismo benchmark de razonamiento pero con el modelo GGUF. En modo thinking usa max_tokens=512 y un system prompt que indica razonamiento paso a paso; en modo normal usa max_tokens=256 y pide solo la respuesta final.

python thinking_quantized.py

multimodal_image.py

Análisis multimodal de imágenes locales en CPU. Prueba 5 casos predefinidos con imágenes en la carpeta images/:

Archivo esperadoTarea
images/document.jpgOCR — extraer texto
images/chart.pngAnálisis de gráfico
images/screenshot.pngInterpretación de UI
images/photo.jpgDescripción detallada
images/diagram.jpgExplicación de diagrama

Cada imagen se prueba con tres resoluciones de visual tokens: 70 (224×224), 280 (448×448) y 1120 (896×896).

python multimodal_image.py

Añade las imágenes en la carpeta images/ antes de ejecutar.

gpu_test.py

Stress test de GPU usando GPT-2 (modelo ligero). Carga el modelo en GPU si está disponible (si no, en CPU) y ejecuta 10 iteraciones de inferencia. Útil para verificar que la GPU responde correctamente antes de ejecutar modelos más grandes.

python gpu_test.py

Estructura de carpetas

gemma4-poc/
├── images/                        # Imágenes para multimodal_image.py
├── getting_started_gemma4.py      # Inferencia simple (transformers)
├── chat_model.py                  # Chat interactivo (transformers)
├── chat_model_quantized.py        # Chat interactivo (GGUF)
├── thinking.py                    # Benchmark razonamiento (transformers)
├── thinking_quantized.py          # Benchmark razonamiento (GGUF)
├── multimodal_image.py            # Análisis imágenes locales (transformers)
├── gpu_test.py                    # Stress test GPU con GPT-2
├── torch_test.py                  # Diagnóstico torch/CUDA
├── chat_log.txt                   # Log generado automáticamente por chat
└── requirements.txt

Resultado esperado:

  • CUDA disponible: True
  • GPU detectada correctamente

🔥 Verificación de uso REAL de GPU

No basta con detectar la GPU — este test confirma que realmente se está usando para cómputo.


🧪 Test de inferencia en GPU

import torch
from transformers import AutoTokenizer, AutoModelForCausalLM

# -----------------------------
# Verificar dispositivo
# -----------------------------
device = "cuda" if torch.cuda.is_available() else "cpu"
print("Using device:", device)

# -----------------------------
# Modelo (ligero para GPU de 4GB)
# -----------------------------
model_name = "gpt2"

tokenizer = AutoTokenizer.from_pretrained(model_name)

model = AutoModelForCausalLM.from_pretrained(model_name)
model.to(device)

# -----------------------------
# Input de prueba
# -----------------------------
prompt = "La inteligencia artificial en el futuro"
inputs = tokenizer(prompt, return_tensors="pt").to(device)

# Confirmación explícita
print("Input device:", inputs.input_ids.device)
print("Model device:", next(model.parameters()).device)

# -----------------------------
# Limpiar memoria (opcional)
# -----------------------------
if device == "cuda":
    torch.cuda.empty_cache()

# -----------------------------
# Inferencia (múltiples iteraciones para observar GPU)
# -----------------------------
print("\nRunning inference...")

for i in range(10):
    with torch.no_grad():
        output = model.generate(**inputs, max_new_tokens=100)

print("Inference done.")

# -----------------------------
# Decodificar resultado
# -----------------------------
result = tokenizer.decode(output[0])
print("\nOutput:")
print(result)

# -----------------------------
# Métricas GPU
# -----------------------------
if device == "cuda":
    print("\nGPU memory allocated:", torch.cuda.memory_allocated() / 1024**2, "MB")
    print("GPU memory reserved:", torch.cuda.memory_reserved() / 1024**2, "MB")

👀 Qué deberías observar

En consola:

  • Using device: cuda
  • Input device: cuda:0
  • Model device: cuda:0

En GPU (usando nvidia-smi)

Ejecuta en otra terminal:

nvidia-smi -l 1

Durante la ejecución del script deberías ver:

  • 📈 Memory-Usage aumenta (ej: 200MB → 1000MB+)
  • GPU-Util sube (ej: 0% → 20–80%)

🧠 Interpretación

SeñalSignificado
VRAM subeEl modelo está cargado en GPU
GPU-Util subeSe está ejecutando cómputo real
Ambos✅ GPU funcionando correctamente

⚠️ Nota

Si el script es muy corto:

  • el uso de GPU puede aparecer solo por milisegundos
  • nvidia-smi puede mostrar solo picos breves (ej: 23%, 9%)

Esto es normal.


❌ Problemas comunes

GPU no se usa

  • Using device: cpu
  • GPU-Util = 0%
  • VRAM no cambia

👉 revisar instalación de torch


Solo sube VRAM pero no GPU-Util

👉 probablemente:

  • modelo muy pequeño
  • ejecución muy rápida

No es necesariamente un error.


⚙️ Recomendaciones para GPU (ej: GTX 1650 Ti)

  • VRAM limitada (~4GB)

  • Preferir:

    • modelos pequeños o medianos
    • device_map="auto"
    • torch_dtype="auto" o float16

🛠️ Troubleshooting

No matching distribution found for torch

  • Verificar versión de Python
  • En Python 3.12, usar instalación manual por wheel

torch.cuda.is_available() == False

  • Verificar drivers NVIDIA
  • Confirmar instalación correcta de torch con CUDA

❌ Error de memoria (OOM)

  • Usar modelos más pequeños
  • Reducir precisión (float16)
  • Cerrar apps que usen GPU

📌 Resumen

ComponenteRol
transformersModelos y API
torchEjecución (CPU/GPU)
accelerateGestión de dispositivos

Licencia

Este proyecto se distribuye bajo la licencia MIT.

Contributors

srlps

3 commits

Languages

Python

100.0%