Skip to content

Guía completa de instalación whisper.cpp para AMD A4-9125 #5

Description

@Charly-bite

Instalación paso a paso de whisper.cpp optimizado para AMD A4-9125

Hardware Target

  • CPU: AMD A4-9125 RADEON R3, 4 COMPUTE CORES 2C+2G
  • GPU: AMD Stoney [Radeon R2/R3/R4/R5 Graphics] integrada
  • RAM: 14.6 GB
  • Arquitectura: Excavator (btver2)

Proceso de Instalación

Paso 1: Preparar dependencias del sistema

#!/bin/bash
# setup_amd_dependencies.sh

echo "🔧 Preparando sistema para AMD A4-9125 + whisper.cpp"
echo "=================================================="

# Detectar distribución Linux
if [ -f /etc/os-release ]; then
    . /etc/os-release
    DISTRO=$NAME
    echo "🐧 Distribución detectada: $DISTRO"
fi

# Instalar dependencias según distribución
echo "📦 Instalando dependencias de compilación..."

if [[ "$DISTRO" == *"Ubuntu"* ]] || [[ "$DISTRO" == *"Debian"* ]] || [[ "$DISTRO" == *"Parrot"* ]]; then
    sudo apt update
    sudo apt install -y \
        build-essential \
        cmake \
        git \
        pkg-config \
        libopenblas-dev \
        libomp-dev \
        mesa-opencl-icd \
        opencl-headers \
        clinfo \
        wget \
        curl
    
    echo "✅ Dependencias Ubuntu/Debian instaladas"
    
elif [[ "$DISTRO" == *"Arch"* ]] || [[ "$DISTRO" == *"Manjaro"* ]]; then
    sudo pacman -S --noconfirm \
        base-devel \
        cmake \
        git \
        pkg-config \
        openblas \
        openmp \
        opencl-mesa \
        opencl-headers \
        clinfo \
        wget \
        curl
    
    echo "✅ Dependencias Arch/Manjaro instaladas"
    
elif [[ "$DISTRO" == *"Fedora"* ]]; then
    sudo dnf install -y \
        gcc-c++ \
        cmake \
        git \
        pkg-config \
        openblas-devel \
        libomp-devel \
        mesa-libOpenCL \
        opencl-headers \
        clinfo \
        wget \
        curl
    
    echo "✅ Dependencias Fedora instaladas"
else
    echo "⚠️ Distribución no reconocida: $DISTRO"
    echo "Por favor instala manualmente: build-essential, cmake, git, opencl"
fi

# Verificar OpenCL
echo "🔍 Verificando soporte OpenCL..."
if command -v clinfo &> /dev/null; then
    echo "📋 Información OpenCL:"
    clinfo -l 2>/dev/null || echo "⚠️ OpenCL detectado pero sin dispositivos"
else
    echo "❌ clinfo no disponible"
fi

echo "✅ Preparación de dependencias completada"

Paso 2: Compilar whisper.cpp optimizado

#!/bin/bash
# compile_whisper_amd_a4_9125.sh

echo "🔨 Compilando whisper.cpp para AMD A4-9125"
echo "=========================================="

# Crear directorio de trabajo
WORK_DIR="$HOME/whisper_amd_build"
mkdir -p "$WORK_DIR"
cd "$WORK_DIR"

# Clonar whisper.cpp si no existe
if [ ! -d "whisper.cpp" ]; then
    echo "📥 Clonando whisper.cpp..."
    git clone https://github.com/ggerganov/whisper.cpp.git
    cd whisper.cpp
else
    echo "📂 Usando whisper.cpp existente..."
    cd whisper.cpp
    git pull origin master
fi

# Crear directorio de build
mkdir -p build
cd build

echo "⚙️ Configurando CMake para AMD A4-9125..."

# Configuración CMake específica para A4-9125
# btver2 es la arquitectura específica del A4-9125 (Excavator)
cmake -DCMAKE_BUILD_TYPE=Release \
      -DWHISPER_OPENBLAS=ON \
      -DWHISPER_OPENCL=ON \
      -DWHISPER_OPENMP=ON \
      -DCMAKE_C_FLAGS="-O2 -march=btver2 -mtune=btver2 -mfma -mavx -msse4.2" \
      -DCMAKE_CXX_FLAGS="-O2 -march=btver2 -mtune=btver2 -mfma -mavx -msse4.2" \
      -DCMAKE_INSTALL_PREFIX="/usr/local" \
      ..

if [ $? -ne 0 ]; then
    echo "❌ Error en configuración CMake"
    exit 1
fi

echo "🔨 Compilando con 2 threads (óptimo para A4-9125)..."
make -j2

if [ $? -ne 0 ]; then
    echo "❌ Error en compilación"
    exit 1
fi

echo "✅ Compilación exitosa!"

# Instalar binarios con nombres específicos para AMD
echo "📦 Instalando whisper-amd..."
sudo cp bin/whisper /usr/local/bin/whisper-amd
sudo cp bin/main /usr/local/bin/whisper-main-amd
sudo cp bin/bench /usr/local/bin/whisper-bench-amd 2>/dev/null || true

# Crear enlaces simbólicos para compatibilidad
sudo ln -sf /usr/local/bin/whisper-amd /usr/local/bin/whisper 2>/dev/null || true

# Verificar instalación
echo "🧪 Verificando instalación..."
if /usr/local/bin/whisper-amd --help >/dev/null 2>&1; then
    echo "✅ whisper-amd instalado correctamente"
    echo "📍 Ubicación: /usr/local/bin/whisper-amd"
    
    # Mostrar versión y características
    echo "📊 Información del binario:"
    /usr/local/bin/whisper-amd --help | head -10
else
    echo "❌ Error: whisper-amd no funciona correctamente"
    exit 1
fi

echo "🎉 Instalación de whisper-amd completada!"

Paso 3: Descargar modelos optimizados

#!/usr/bin/env python3
# download_models_amd_a4_9125.py

import os
import requests
import hashlib
from pathlib import Path
from urllib.parse import urlparse

def download_with_progress(url, filepath):
    """Descargar archivo con barra de progreso"""
    print(f"📥 Descargando: {filepath.name}")
    
    response = requests.get(url, stream=True)
    response.raise_for_status()
    
    total_size = int(response.headers.get('content-length', 0))
    downloaded = 0
    
    with open(filepath, 'wb') as f:
        for chunk in response.iter_content(chunk_size=8192):
            if chunk:
                f.write(chunk)
                downloaded += len(chunk)
                
                if total_size > 0:
                    progress = (downloaded / total_size) * 100
                    bars = int(progress / 2)
                    print(f"\r[{'='*bars}{' '*(50-bars)}] {progress:.1f}% ({downloaded/1024/1024:.1f}MB)", end='', flush=True)
    
    print(f"\n✅ Descarga completada: {filepath.name}")

def verify_model_integrity(filepath, expected_hash=None):
    """Verificar integridad del modelo descargado"""
    if not filepath.exists():
        return False
    
    # Verificación básica de tamaño
    size_mb = filepath.stat().st_size / (1024 * 1024)
    print(f"📊 Tamaño del modelo: {size_mb:.1f} MB")
    
    # Verificar que no esté corrupto (tamaño mínimo)
    if size_mb < 10:  # Modelos whisper son >100MB
        print("❌ Archivo demasiado pequeño, posiblemente corrupto")
        return False
    
    return True

def setup_models_for_amd_a4_9125():
    """Configurar modelos optimizados para AMD A4-9125"""
    
    print("🎯 Configurando modelos para AMD A4-9125")
    print("=" * 50)
    
    # Directorio de modelos
    models_dir = Path.home() / ".cache" / "whisper"
    models_dir.mkdir(parents=True, exist_ok=True)
    
    print(f"📁 Directorio de modelos: {models_dir}")
    
    # Modelos recomendados para A4-9125 (ordenados por prioridad)
    models = [
        {
            "name": "base",
            "filename": "ggml-base.bin",
            "url": "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-base.bin",
            "size_mb": 142,
            "description": "Modelo principal recomendado para A4-9125",
            "priority": 1
        },
        {
            "name": "small",
            "filename": "ggml-small.bin", 
            "url": "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-small.bin",
            "size_mb": 466,
            "description": "Mejor calidad (aprovecha 14.6GB RAM)",
            "priority": 2
        },
        {
            "name": "tiny",
            "filename": "ggml-tiny.bin",
            "url": "https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-tiny.bin", 
            "size_mb": 39,
            "description": "Respaldo ultra-rápido para emergencias",
            "priority": 3
        }
    ]
    
    downloaded_models = []
    
    for model in models:
        model_path = models_dir / model["filename"]
        
        print(f"\n🔍 Verificando modelo: {model['name']}")
        print(f"📝 {model['description']}")
        print(f"📊 Tamaño esperado: ~{model['size_mb']} MB")
        
        if model_path.exists():
            if verify_model_integrity(model_path):
                print(f"✅ Modelo {model['name']} ya existe y es válido")
                downloaded_models.append(model['name'])
                continue
            else:
                print(f"🗑️ Modelo corrupto, re-descargando...")
                model_path.unlink()
        
        try:
            download_with_progress(model['url'], model_path)
            
            if verify_model_integrity(model_path):
                downloaded_models.append(model['name'])
                print(f"✅ Modelo {model['name']} descargado y verificado")
            else:
                print(f"❌ Error en verificación del modelo {model['name']}")
                if model_path.exists():
                    model_path.unlink()
                    
        except Exception as e:
            print(f"❌ Error descargando {model['name']}: {e}")
            if model_path.exists():
                model_path.unlink()
    
    # Resumen final
    print(f"\n🎯 RESUMEN DE MODELOS INSTALADOS:")
    print("=" * 40)
    
    if downloaded_models:
        for model_name in downloaded_models:
            model_file = models_dir / f"ggml-{model_name}.bin"
            if model_file.exists():
                size_mb = model_file.stat().st_size / (1024 * 1024)
                print(f"✅ {model_name}: {size_mb:.1f} MB")
        
        print(f"\n🚀 CONFIGURACIÓN RECOMENDADA PARA A4-9125:")
        if "base" in downloaded_models:
            print("   🥇 Usar modelo 'base' para uso diario")
        if "small" in downloaded_models:
            print("   🥈 Usar modelo 'small' para máxima calidad")
        if "tiny" in downloaded_models:
            print("   🥉 Usar modelo 'tiny' para velocidad máxima")
    else:
        print("❌ No se descargaron modelos exitosamente")
        return False
    
    return len(downloaded_models) > 0

def test_whisper_amd_installation():
    """Probar la instalación de whisper-amd"""
    
    print(f"\n🧪 PROBANDO INSTALACIÓN")
    print("=" * 30)
    
    import subprocess
    
    # Verificar que whisper-amd esté disponible
    try:
        result = subprocess.run(["whisper-amd", "--help"], 
                              capture_output=True, text=True, timeout=10)
        if result.returncode == 0:
            print("✅ whisper-amd responde correctamente")
            return True
        else:
            print(f"❌ whisper-amd error: {result.stderr}")
            return False
    except FileNotFoundError:
        print("❌ whisper-amd no encontrado en PATH")
        print("💡 Ejecutar: sudo ln -sf /usr/local/bin/whisper-amd /usr/bin/whisper-amd")
        return False
    except subprocess.TimeoutExpired:
        print("⏰ whisper-amd no responde (timeout)")
        return False

if __name__ == "__main__":
    print("🎯 CONFIGURACIÓN DE MODELOS PARA AMD A4-9125")
    print("=" * 50)
    
    # Probar instalación primero
    if not test_whisper_amd_installation():
        print("\n❌ whisper-amd no está instalado correctamente")
        print("Por favor ejecutar primero: compile_whisper_amd_a4_9125.sh")
        exit(1)
    
    # Configurar modelos
    success = setup_models_for_amd_a4_9125()
    
    if success:
        print(f"\n🎉 ¡CONFIGURACIÓN COMPLETADA!")
        print("=" * 30)
        print("🔥 whisper-amd listo para usar")
        print("📊 Modelos descargados y verificados")
        print("⚡ Optimizado para AMD A4-9125")
        print("\n🚀 Próximo paso: Probar transcripción")
        print("python agents/processing_agent.py")
    else:
        print(f"\n❌ Error en configuración de modelos")
        exit(1)

Paso 4: Script de prueba completa

#!/usr/bin/env python3
# test_amd_a4_9125_transcription.py

import subprocess
import tempfile
import time
from pathlib import Path

def create_test_audio():
    """Crear audio de prueba específico para español"""
    
    print("🎵 Creando audio de prueba...")
    
    test_audio = Path("test_amd_a4_transcription.wav")
    
    if test_audio.exists():
        print("✅ Audio de prueba ya existe")
        return test_audio
    
    # Texto optimizado para probar transcripción en español
    test_text = """
    Hola, esta es una prueba de transcripción optimizada para el procesador AMD A4-9125 
    con gráficos Radeon R3 integrados. El sistema tiene catorce punto seis gigabytes de RAM 
    y está ejecutando whisper punto cpp compilado específicamente para la arquitectura Excavator.
    Esta prueba verificará la funcionalidad de transcripción de audio en tiempo real para 
    clases de ciberseguridad y toma de notas automática.
    """
    
    try:
        # Usar espeak-ng para generar audio de prueba
        subprocess.run([
            "espeak-ng", 
            "-s", "130",           # Velocidad moderada
            "-v", "es-es",         # Español de España
            "-w", str(test_audio), # Archivo de salida
            test_text
        ], check=True)
        
        print(f"✅ Audio de prueba creado: {test_audio}")
        return test_audio
        
    except subprocess.CalledProcessError as e:
        print(f"❌ Error creando audio: {e}")
        return None
    except FileNotFoundError:
        print("❌ espeak-ng no encontrado. Instalar con:")
        print("   sudo apt install espeak-ng")
        return None

def benchmark_amd_a4_9125():
    """Hacer benchmark específico para AMD A4-9125"""
    
    print("⚡ BENCHMARK AMD A4-9125")
    print("=" * 30)
    
    # Crear audio de prueba
    test_audio = create_test_audio()
    if not test_audio:
        return False
    
    # Configuraciones de prueba optimizadas para A4-9125
    test_configs = [
        {
            "name": "Conservador",
            "model": "tiny",
            "threads": 1,
            "description": "Máxima velocidad"
        },
        {
            "name": "Balanceado", 
            "model": "base",
            "threads": 2,
            "description": "Configuración recomendada"
        },
        {
            "name": "Calidad",
            "model": "small",
            "threads": 2, 
            "description": "Máxima calidad (si disponible)"
        }
    ]
    
    results = []
    
    for config in test_configs:
        print(f"\n🧪 Probando: {config['name']}")
        print(f"   📊 Modelo: {config['model']}")
        print(f"   🧵 Threads: {config['threads']}")
        print(f"   📝 {config['description']}")
        
        cmd = [
            "whisper-amd",
            str(test_audio),
            "--model", config["model"],
            "--language", "es",
            "--threads", str(config["threads"]),
            "--output_format", "txt",
            "--no_timestamps"  # Simplificar salida
        ]
        
        start_time = time.time()
        
        try:
            result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
            end_time = time.time()
            
            processing_time = end_time - start_time
            
            if result.returncode == 0:
                # Extraer texto transcrito
                transcript = result.stdout.strip()
                
                results.append({
                    "config": config,
                    "processing_time": processing_time,
                    "success": True,
                    "transcript": transcript[:100] + "..." if len(transcript) > 100 else transcript
                })
                
                print(f"   ⏱️ Tiempo: {processing_time:.2f}s")
                print(f"   ✅ Éxito")
                
            else:
                print(f"   ❌ Error: {result.stderr}")
                results.append({
                    "config": config,
                    "processing_time": None,
                    "success": False,
                    "error": result.stderr
                })
                
        except subprocess.TimeoutExpired:
            print(f"   ⏰ Timeout (>120s)")
            results.append({
                "config": config,
                "processing_time": None,
                "success": False,
                "error": "Timeout"
            })
    
    # Mostrar resultados
    print(f"\n📊 RESULTADOS BENCHMARK AMD A4-9125")
    print("=" * 45)
    
    successful_results = [r for r in results if r["success"]]
    
    if successful_results:
        # Ordenar por tiempo de procesamiento
        successful_results.sort(key=lambda x: x["processing_time"])
        
        print("🏆 CONFIGURACIONES EXITOSAS (ordenadas por velocidad):")
        for i, result in enumerate(successful_results, 1):
            config = result["config"]
            time_taken = result["processing_time"]
            
            emoji = "🥇" if i == 1 else "🥈" if i == 2 else "🥉"
            print(f"\n{emoji} #{i}: {config['name']}")
            print(f"     ⏱️ Tiempo: {time_taken:.2f}s")
            print(f"     📊 Modelo: {config['model']}")
            print(f"     🧵 Threads: {config['threads']}")
            print(f"     📝 Transcripción: {result['transcript']}")
        
        # Recomendar configuración óptima
        best_config = successful_results[0]["config"]
        print(f"\n🎯 CONFIGURACIÓN ÓPTIMA DETECTADA:")
        print(f"   Modelo: {best_config['model']}")
        print(f"   Threads: {best_config['threads']}")
        print(f"   Tiempo: {successful_results[0]['processing_time']:.2f}s")
        
        # Guardar configuración óptima
        optimal_config = {
            "amd_a4_9125_optimal": {
                "model": best_config['model'],
                "threads": best_config['threads'],
                "benchmark_time": successful_results[0]['processing_time'],
                "date_tested": "2025-06-14"
            }
        }
        
        import json
        with open("amd_a4_9125_optimal_config.json", "w") as f:
            json.dump(optimal_config, f, indent=2)
        
        print(f"💾 Configuración óptima guardada en: amd_a4_9125_optimal_config.json")
        
        return True
    else:
        print("❌ Ninguna configuración funcionó correctamente")
        print("\n🔧 POSIBLES SOLUCIONES:")
        print("1. Verificar que whisper-amd esté compilado correctamente")
        print("2. Verificar que los modelos estén descargados")
        print("3. Verificar dependencias OpenCL")
        
        return False

if __name__ == "__main__":
    print("🚀 PRUEBA COMPLETA AMD A4-9125 + whisper.cpp")
    print("=" * 50)
    
    success = benchmark_amd_a4_9125()
    
    if success:
        print(f"\n🎉 ¡PRUEBA COMPLETADA EXITOSAMENTE!")
        print("✅ whisper-amd funcionando correctamente") 
        print("⚡ Configuración óptima determinada")
        print("🔥 Listo para integrar con ProcessingAgent")
    else:
        print(f"\n❌ Prueba falló - revisar instalación")

Pasos de Ejecución

1. Preparar sistema (ejecutar primero)

chmod +x setup_amd_dependencies.sh
./setup_amd_dependencies.sh

2. Compilar whisper-amd

chmod +x compile_whisper_amd_a4_9125.sh
./compile_whisper_amd_a4_9125.sh

3. Descargar modelos

python download_models_amd_a4_9125.py

4. Probar y hacer benchmark

python test_amd_a4_9125_transcription.py

Resultados Esperados

Rendimiento estimado en tu A4-9125:

  • Modelo tiny: ~1-2x tiempo real
  • Modelo base: ~3-5x tiempo real
  • Modelo small: ~5-8x tiempo real

Uso de recursos:

  • CPU: 80-100% durante transcripción
  • RAM: 2-4 GB según modelo
  • GPU: 10-20% con OpenCL habilitado

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions