Durante los últimos meses han surgido numerosos modelos multimodales capaces de interpretar imágenes y generar descripciones de forma automática. Uno de los desarrollos más interesantes es FastVLM, presentado por Apple como una alternativa optimizada y rápida a las arquitecturas visuales tradicionales.
Este modelo destaca por su velocidad de inferencia y por funcionar correctamente sin necesidad de enviar datos a servicios externos, algo especialmente útil para quienes valoran un enfoque “local-first”, privacidad y control total sobre el ciclo de inferencia.
🔍 ¿Qué es FastVLM?
FastVLM forma parte de la familia de Vision Language Models, orientados a procesar contenido visual y generar texto en lenguaje natural. A diferencia de otros sistemas multimodales, su objetivo principal es ofrecer rapidez y eficiencia, incluso con recursos hardware limitados.
Entre sus mejoras destacan:
- FastViT HD: encoder visual optimizado con baja latencia.
- PagedAttention y FlashAttention: reducción de consumo de memoria y tiempo de acceso.
- Variantes ligeras: modelos desde 0.5B parámetros para uso en local.
⚙️ Ventajas principales
- Ejecución sin conexión
- Privacidad garantizada, las imágenes no salen del sistema
- Latencia reducida, adecuada para interfaces web en tiempo real
- Compatibilidad con Transformers
💻 Implementación en local con Streamlit y Docker
Una forma sencilla de probar FastVLM consiste en desarrollar una aplicación web mínima con Streamlit, y cargar el modelo desde un directorio local. Para ello es suficiente con descargar los pesos una única vez durante el build de Docker.
A continuación se presenta un ejemplo práctico dividido en bloques comentados.
Perfecto, gracias por compartir tus versiones definitivas. A continuación te dejo solo las dos secciones, reescritas con tu contenido real (sin inventar valores), y acompañadas de una explicación clara y breve para integrarlas en el post.
🐳 Docker Compose: orquestando el entorno
El siguiente docker-compose.yml levanta un servicio con Streamlit y FastVLM con soporte para GPU NVIDIA. Incluye variables de entorno relevantes para Streamlit y configuración necesaria para acceder al hardware acelerado desde dentro del contenedor.
services:
fastvlm-app:
build: .
container_name: fastvlm-streamlit
ports:
- "8501:8501"
environment:
- STREAMLIT_SERVER_ENABLECORS=false
- STREAMLIT_SERVER_ENABLEXsrfProtection=false
- CUDA_VISIBLE_DEVICES=0
- NVIDIA_VISIBLE_DEVICES=all
- NVIDIA_DRIVER_CAPABILITIES=compute,utility
deploy:
resources:
reservations:
devices:
- capabilities: ["gpu"]
runtime: nvidia
restart: unless-stopped🛠️ Dockerfile: instalando dependencias y descargando el modelo
Este Dockerfile está preparado para producción con descarga automática del modelo durante el build y con soporte CUDA integrado gracias a la imagen base de PyTorch con drivers y librerías NVIDIA incluidas.
# Imagen base con PyTorch y CUDA (GPU). Si usas CPU, cambia a pytorch/pytorch:2.2.2-cpu
FROM pytorch/pytorch:2.2.2-cuda12.1-cudnn8-runtime
# Evita prompts interactivos durante apt-get y warnings de HF
ENV DEBIAN_FRONTEND=noninteractive \
HF_HUB_DISABLE_SYMLINKS_WARNING=1
# Carpeta de trabajo
WORKDIR /app
# Instalamos dependencias de sistema
RUN apt-get update && apt-get install -y --no-install-recommends \
git \
&& rm -rf /var/lib/apt/lists/*
# Copiamos requirements primero, para cache de Docker
COPY requirements.txt .
# Instalamos dependencias Python (torch ya viene en esta imagen)
RUN pip install --no-cache-dir -r requirements.txt
# ======================================================
# DESCARGA DEL MODELO LOCAL DE HUGGING FACE
# ======================================================
# Se descargará en /app/models/FastVLM-0.5B
# y ya NO necesitaremos Internet durante ejecución
RUN mkdir -p /app/models/FastVLM-0.5B
RUN huggingface-cli download \
apple/FastVLM-0.5B \
--local-dir /app/models/FastVLM-0.5B \
--local-dir-use-symlinks False
# Copiamos la app completa
COPY app.py .
# Exponemos el puerto de streamlit
EXPOSE 8501
# Comando de ejecución del contenedor
CMD ["streamlit", "run", "app.py", "--server.address=0.0.0.0", "--server.port=8501"]
🧩 Ejemplo de código: app.py
Importaciones y configuración inicial
import torch
import streamlit as st
from PIL import Image
from transformers import AutoTokenizer, AutoModelForCausalLM
MODEL_PATH = "/app/models/FastVLM-0.5B" # Ruta local al modelo
IMAGE_TOKEN_INDEX = -200 # Token especial utilizado por FastVLM
En este bloque se importan las librerías necesarias y se definen las constantes básicas para la aplicación. MODEL_PATH indica la ubicación del modelo dentro del contenedor, mientras que IMAGE_TOKEN_INDEX representa el valor especial utilizado por FastVLM para identificar dónde debe insertarse la información visual dentro del prompt.
Carga del modelo y del procesador de imagen
@st.cache_resource
def load_model():
tokenizer = AutoTokenizer.from_pretrained(
MODEL_PATH,
trust_remote_code=True,
local_files_only=True
)
model = AutoModelForCausalLM.from_pretrained(
MODEL_PATH,
torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
device_map="auto",
trust_remote_code=True,
local_files_only=True
)
vision_tower = model.get_vision_tower()
image_processor = vision_tower.image_processor
device = model.device
return tokenizer, model, image_processor, device
tokenizer, model, image_processor, device = load_model()
Este fragmento define una función que carga el modelo y el tokenizador desde los archivos almacenados localmente. El parámetro local_files_only=True garantiza que durante la ejecución no se intente descargar nada desde Hugging Face. La instrucción get_vision_tower() permite acceder al componente responsable de procesar imágenes, y la anotación @st.cache_resource hace que la carga del modelo se realice una única vez, optimizando el rendimiento de la aplicación.
Construcción del prompt y generación
def describe_image(image: Image.Image) -> str:
pixel_values = image_processor(images=image, return_tensors="pt")["pixel_values"]
pixel_values = pixel_values.to(device, dtype=model.dtype)
messages = [{"role": "user", "content": "<image>\nDescribe esta imagen en español."}]
rendered = tokenizer.apply_chat_template(messages, add_generation_prompt=True, tokenize=False)
pre, post = rendered.split("<image>", 1)
pre_ids = tokenizer(pre, return_tensors="pt", add_special_tokens=False).input_ids
post_ids = tokenizer(post, return_tensors="pt", add_special_tokens=False).input_ids
img_tok = torch.tensor([[IMAGE_TOKEN_INDEX]], dtype=pre_ids.dtype)
input_ids = torch.cat([pre_ids, img_tok, post_ids], dim=1).to(device)
attention_mask = torch.ones_like(input_ids)
with torch.no_grad():
output = model.generate(
inputs=input_ids,
attention_mask=attention_mask,
images=pixel_values,
max_new_tokens=128,
)
return tokenizer.decode(output[0], skip_special_tokens=True)
En este bloque se prepara la imagen y el texto para que FastVLM pueda generar una descripción. El objeto image_processor convierte la imagen en tensores aptos para el modelo. El marcador <image> indica el punto exacto en el prompt donde debe integrarse la información visual, utilizando para ello el valor de IMAGE_TOKEN_INDEX. Las partes anterior y posterior al marcador se tokenizan y se fusionan con el token especial, formando una entrada única compuesta por texto e imagen. Finalmente, la llamada a model.generate() produce la salida en lenguaje natural; en este caso, una descripción en español de la imagen subida por el usuario.
Interfaz en Streamlit
st.title("FastVLM - Generador de descripciones de imágenes")
uploaded_file = st.file_uploader("Sube una imagen", type=["jpg", "jpeg", "png"])
if uploaded_file:
image = Image.open(uploaded_file).convert("RGB")
st.image(image, caption="Imagen cargada", use_column_width=True)
caption = describe_image(image)
st.subheader("Descripción generada:")
st.write(caption)
Se muestra un componente file_uploader para permitir al usuario subir una imagen.
Cuando la imagen se carga, se procesa automáticamente y se muestra la respuesta generada por FastVLM.
No se requiere infraestructura adicional ni una API externa.
🧠 ¿Por qué ejecutar IA en local?
Aunque la inferencia en la nube sigue siendo popular, existen numerosos escenarios donde ejecutar IA en local resulta ventajoso:
- Protección de información sensible
- Cumplimiento legal y normativo
- Autonomía frente a proveedores externos
- Uso en entornos sin conectividad
FastVLM facilita estos casos aportando un equilibrio razonable entre velocidad, calidad y consumo de recursos.
📈 Conclusión
FastVLM demuestra que es posible trabajar con modelos multimodales de forma eficiente sin depender de servicios externos. Su uso con Docker y Streamlit permite desarrollar aplicaciones sencillas y funcionales que aprovechan capacidades de IA visual en local.
Si más adelante se desea ampliar funcionalidades, existen variantes más grandes del modelo y numerosos recursos en Hugging Face y la comunidad open source que permiten seguir profundizando en el desarrollo multimodal.