
Este código permite cargar un modelo Phi-3 mini 4k instruct previamente fine-tuneado y realizar inferencias con él en una GPU utilizando cuantización en 4-bit para optimizar el uso de memoria VRAM.
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
from peft import PeftModel
# Rutas del modelo base y modelo fine-tuneado
base_model_path = r"D:/Phi-3-mini-4k-instruct" # Ruta del modelo base original
finetuned_model_path = r"D:/finetuned_phi3" # Ruta del modelo fine-tuneado
# Cargar el tokenizador
tokenizer = AutoTokenizer.from_pretrained(base_model_path)
# Configurar Offload para ahorrar VRAM si es necesario
offload_dir = "D:/finetuned_phi3/offload"
# Configuración de cuantización (para ejecutar en GPU con menos VRAM)
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_compute_dtype=torch.float16,
bnb_4bit_use_double_quant=True,
bnb_4bit_quant_type="nf4"
)
# Cargar el modelo base con cuantización
base_model = AutoModelForCausalLM.from_pretrained(
base_model_path,
torch_dtype=torch.float16,
device_map="auto",
quantization_config=bnb_config
)
# Cargar los pesos fine-tuneados
model = PeftModel.from_pretrained(
base_model,
finetuned_model_path,
device_map="auto",
offload_folder=offload_dir
)
# Loop interactivo para hacer preguntas
while True:
prompt = input(" Ingresa tu pregunta (o escribe 'salir' para terminar): ")
if prompt.lower() == "salir":
break
formatted_prompt = f"Pregunta: {prompt}\nRespuesta: "
inputs = tokenizer(formatted_prompt, return_tensors="pt").to("cuda")
output = model.generate(
**inputs,
max_length=100,
do_sample=False,
temperature=0.1,
top_p=0.1,
early_stopping=True,
num_beams=10
)
respuesta = tokenizer.decode(output[0], skip_special_tokens=True).strip()
print(f" Respuesta: {respuesta}\n")
1. Importación de Bibliotecas
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
from peft import PeftModel
Se importan las bibliotecas necesarias:
- torch: Biblioteca principal para operaciones con tensores y ejecución en GPU.
- transformers: Para cargar modelos de lenguaje preentrenados.
- BitsAndBytesConfig: Configuración para la cuantización del modelo.
- PeftModel: Permite cargar modelos ajustados con técnicas como LoRA.
2. Definición de Rutas
base_model_path = r"D:/Phi-3-mini-4k-instruct" # Ruta del modelo base original
finetuned_model_path = r"D:/finetuned_phi3" # Ruta del modelo fine-tuneado
Se especifican las rutas del modelo base (preentrenado) y el modelo fine-tuneado, que contiene los pesos ajustados tras el proceso de entrenamiento.
3. Carga del Tokenizador
tokenizer = AutoTokenizer.from_pretrained(base_model_path)
El tokenizador convierte el texto en tokens que el modelo puede procesar.
4. Configuración de Offload (Opcional)
offload_dir = "D:/finetuned_phi3/offload"
Este directorio se utiliza para descargar partes del modelo de la GPU cuando la memoria es insuficiente.
5. Configuración de Cuantización
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_compute_dtype=torch.float16,
bnb_4bit_use_double_quant=True,
bnb_4bit_quant_type="nf4"
)
Se configura el modelo para ejecutarse en una GPU con menos VRAM mediante cuantización en 4-bit (nf4). Se usa float16 para mejorar el rendimiento y se habilita la doble cuantización.
6. Carga del Modelo Base con Cuantización
base_model = AutoModelForCausalLM.from_pretrained(
base_model_path,
torch_dtype=torch.float16,
device_map="auto",
quantization_config=bnb_config
)
Aquí se carga el modelo base con las configuraciones de cuantización y se asigna automáticamente a la GPU.
7. Carga de los Pesos Fine-Tuneados
model = PeftModel.from_pretrained(
base_model,
finetuned_model_path,
device_map="auto",
offload_folder=offload_dir
)
Se aplica el modelo ajustado (fine-tuned) sobre el modelo base cargado.
8. Bucle de Interacción para Inferencia
while True:<br>
prompt = input(" Ingresa tu pregunta (o escribe 'salir' para terminar): ")
if prompt.lower() == "salir":
break
formatted_prompt = f"Pregunta: {prompt}\nRespuesta: "
inputs = tokenizer(formatted_prompt, return_tensors="pt").to("cuda")
output = model.generate(
**inputs,
max_length=100,
do_sample=False,
temperature=0.1,
top_p=0.1,
early_stopping=True,
num_beams=10
)
respuesta = tokenizer.decode(output[0], skip_special_tokens=True).strip()
print(f" Respuesta: {respuesta}\n")
Funcionamiento:
- Bucle Interactivo: Permite ingresar preguntas de forma continua.
- Salida Opcional: Si el usuario ingresa «salir», el programa termina.
- Preparación del Texto: Se formatea la entrada para que tenga la estructura: Pregunta: [texto del usuario] Respuesta:
- Tokenización y Envío a la GPU: Convierte el texto en tokens y los mueve a la GPU.
- Generación de Respuesta: El modelo genera una respuesta con parámetros como:
- max_length=100: Límite de longitud de la respuesta.
- do_sample=False: Se desactiva la muestreo aleatorio para respuestas más deterministas.
- temperature=0.1: Baja temperatura para respuestas más conservadoras.
- top_p=0.1: Se limita el rango de palabras posibles en la respuesta.
- num_beams=10: Se generan múltiples hipótesis y se selecciona la mejor.
- Decodificación y Visualización: Convierte la salida del modelo en texto y la muestra.
9. Conclusión
Este código permite cargar un modelo Phi-3 ajustado y utilizarlo para responder preguntas de manera eficiente en una GPU con VRAM limitada. La combinación de cuantización y optimización de memoria permite ejecutar el modelo incluso en hardware de gama media.