Proof of concept para ejecutar el modelo Google Gemma 4 E2B localmente en CPU, con dos modos:
float16) via Hugging Face transformers — mayor fidelidad, mayor consumo de RAM.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
| Script | Descripción |
|---|---|
torch_test.py | Diagnóstico de instalación: versión de torch, CUDA y GPU |
gpu_test.py | Stress test de GPU usando GPT-2 (10 iteraciones de inferencia) |
getting_started_gemma4.py | Inferencia simple en CPU con Gemma 4 (greedy, una sola respuesta) |
chat_model.py | Chat interactivo en CPU con historial, streaming y log a fichero |
chat_model_quantized.py | Chat interactivo con modelo GGUF via llama-cpp-python y streaming |
thinking.py | Benchmark de razonamiento: compara enable_thinking=True/False en CPU |
thinking_quantized.py | Mismo benchmark de razonamiento con modelo GGUF |
multimodal_image.py | Análisis de imágenes locales en CPU (OCR, gráficos, UI, fotos, diagramas) |
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
py -3.12 -m venv .venv
.venv\Scripts\activate
python -m pip install --upgrade pip
torchno está enrequirements.txtporque el wheel correcto depende del sistema operativo, arquitectura, versión de Python y versión de CUDA instalada. Debe instalarse antes para evitar quepipinstale la versión CPU automáticamente.
Los siguientes wheels corresponden a la configuración de este equipo:
cp312)cu121)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
pip install -r requirements.txt
requirements.txt incluye:
bitsandbytes
transformers
accelerate
numpy
pillow
huggingface_hub
psutil
llama-cpp-python
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 ...
getting_started_gemma4.pyInferencia 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.pyChat interactivo multi-turno en CPU usando transformers con streaming via TextIteratorStreamer. Características:
MAX_HISTORY = 6)chat_log.txtOMP_NUM_THREADS, MKL_NUM_THREADS)torch.compilepython chat_model.py
# Type 'exit' para salir
chat_model_quantized.pyMisma 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.pyBenchmark 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:
thinking_quantized.pyMismo 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.pyAnálisis multimodal de imágenes locales en CPU. Prueba 5 casos predefinidos con imágenes en la carpeta images/:
| Archivo esperado | Tarea |
|---|---|
images/document.jpg | OCR — extraer texto |
images/chart.png | Análisis de gráfico |
images/screenshot.png | Interpretación de UI |
images/photo.jpg | Descripción detallada |
images/diagram.jpg | Explicació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.pyStress 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
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: TrueNo basta con detectar la GPU — este test confirma que realmente se está usando para cómputo.
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")
Using device: cudaInput device: cuda:0Model device: cuda:0nvidia-smi)Ejecuta en otra terminal:
nvidia-smi -l 1
Durante la ejecución del script deberías ver:
| Señal | Significado |
|---|---|
| VRAM sube | El modelo está cargado en GPU |
| GPU-Util sube | Se está ejecutando cómputo real |
| Ambos | ✅ GPU funcionando correctamente |
Si el script es muy corto:
nvidia-smi puede mostrar solo picos breves (ej: 23%, 9%)Esto es normal.
Using device: cpuGPU-Util = 0%👉 revisar instalación de torch
👉 probablemente:
No es necesariamente un error.
VRAM limitada (~4GB)
Preferir:
device_map="auto"torch_dtype="auto" o float16No matching distribution found for torchtorch.cuda.is_available() == Falsetorch con CUDAfloat16)| Componente | Rol |
|---|---|
| transformers | Modelos y API |
| torch | Ejecución (CPU/GPU) |
| accelerate | Gestión de dispositivos |
Este proyecto se distribuye bajo la licencia MIT.
3 commits
Python
100.0%
Proof of concept para ejecutar el modelo Google Gemma 4 E2B localmente en CPU, con dos modos:
float16) via Hugging Face transformers — mayor fidelidad, mayor consumo de RAM.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
| Script | Descripción |
|---|---|
torch_test.py | Diagnóstico de instalación: versión de torch, CUDA y GPU |
gpu_test.py | Stress test de GPU usando GPT-2 (10 iteraciones de inferencia) |
getting_started_gemma4.py | Inferencia simple en CPU con Gemma 4 (greedy, una sola respuesta) |
chat_model.py | Chat interactivo en CPU con historial, streaming y log a fichero |
chat_model_quantized.py | Chat interactivo con modelo GGUF via llama-cpp-python y streaming |
thinking.py | Benchmark de razonamiento: compara enable_thinking=True/False en CPU |
thinking_quantized.py | Mismo benchmark de razonamiento con modelo GGUF |
multimodal_image.py | Análisis de imágenes locales en CPU (OCR, gráficos, UI, fotos, diagramas) |
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
py -3.12 -m venv .venv
.venv\Scripts\activate
python -m pip install --upgrade pip
torchno está enrequirements.txtporque el wheel correcto depende del sistema operativo, arquitectura, versión de Python y versión de CUDA instalada. Debe instalarse antes para evitar quepipinstale la versión CPU automáticamente.
Los siguientes wheels corresponden a la configuración de este equipo:
cp312)cu121)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
pip install -r requirements.txt
requirements.txt incluye:
bitsandbytes
transformers
accelerate
numpy
pillow
huggingface_hub
psutil
llama-cpp-python
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 ...
getting_started_gemma4.pyInferencia 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.pyChat interactivo multi-turno en CPU usando transformers con streaming via TextIteratorStreamer. Características:
MAX_HISTORY = 6)chat_log.txtOMP_NUM_THREADS, MKL_NUM_THREADS)torch.compilepython chat_model.py
# Type 'exit' para salir
chat_model_quantized.pyMisma 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.pyBenchmark 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:
thinking_quantized.pyMismo 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.pyAnálisis multimodal de imágenes locales en CPU. Prueba 5 casos predefinidos con imágenes en la carpeta images/:
| Archivo esperado | Tarea |
|---|---|
images/document.jpg | OCR — extraer texto |
images/chart.png | Análisis de gráfico |
images/screenshot.png | Interpretación de UI |
images/photo.jpg | Descripción detallada |
images/diagram.jpg | Explicació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.pyStress 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
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: TrueNo basta con detectar la GPU — este test confirma que realmente se está usando para cómputo.
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")
Using device: cudaInput device: cuda:0Model device: cuda:0nvidia-smi)Ejecuta en otra terminal:
nvidia-smi -l 1
Durante la ejecución del script deberías ver:
| Señal | Significado |
|---|---|
| VRAM sube | El modelo está cargado en GPU |
| GPU-Util sube | Se está ejecutando cómputo real |
| Ambos | ✅ GPU funcionando correctamente |
Si el script es muy corto:
nvidia-smi puede mostrar solo picos breves (ej: 23%, 9%)Esto es normal.
Using device: cpuGPU-Util = 0%👉 revisar instalación de torch
👉 probablemente:
No es necesariamente un error.
VRAM limitada (~4GB)
Preferir:
device_map="auto"torch_dtype="auto" o float16No matching distribution found for torchtorch.cuda.is_available() == Falsetorch con CUDAfloat16)| Componente | Rol |
|---|---|
| transformers | Modelos y API |
| torch | Ejecución (CPU/GPU) |
| accelerate | Gestión de dispositivos |
Este proyecto se distribuye bajo la licencia MIT.
3 commits
Python
100.0%