import warnings warnings.filterwarnings("ignore", message="Can't initialize NVML") import datetime import requests import gradio as gr import torch from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline # Detectar si hay GPU disponible, de lo contrario usar CPU (-1) device = 0 if torch.cuda.is_available() else -1 # Cargar el modelo y el tokenizador (se usará CPU si no hay GPU) model_name = "microsoft/Phi-4-mini-instruct" tokenizer = AutoTokenizer.from_pretrained(model_name) model = AutoModelForCausalLM.from_pretrained(model_name) if device == 0: model.to("cuda") # Crear un pipeline de generación de texto utilizando el dispositivo adecuado generator = pipeline("text-generation", model=model, tokenizer=tokenizer, device=device) # Función para obtener las reservaciones de hotel filtradas por título def get_hotel_reservations(title_filter): url = "http://127.0.0.1:4000/api/accommodations" try: response = requests.get(url) if response.status_code == 200: data = response.json() # Se espera que 'data' sea una lista de reservaciones summary = "Reservaciones de Hotel:\n\n" found = False for reservation in data: hotel_title = reservation.get("title", "N/A") # Filtrar solo las reservaciones que contengan el filtro en el título if title_filter.lower() not in hotel_title.lower(): continue found = True hotel_id = reservation.get("id", "N/A") address = reservation.get("address", {}) street = address.get("street", "N/A") zip_code = address.get("zip_code", "N/A") latitude = address.get("latitude", "N/A") longitude = address.get("longitude", "N/A") guests = reservation.get("guests", {}) adult = guests.get("adult", "N/A") child = guests.get("child", "N/A") price = reservation.get("price", "N/A") summary += ( f"Reservación {hotel_id}:\n" f" - Hotel: {hotel_title}\n" f" - Dirección: {street}, Código Postal: {zip_code}\n" f" (Latitud: {latitude}, Longitud: {longitude})\n" f" - Huéspedes: {adult} adultos, {child} niños\n" f" - Precio: {price}\n\n" ) if not found: summary += f"No se encontraron reservaciones que coincidan con el filtro '{title_filter}'.\n" return summary else: return "Lo sentimos, no se pudieron obtener las reservaciones de hotel." except Exception as e: return f"Error al conectar con la API: {e}" # Diccionario que asocia nombres de funciones a sus implementaciones function_map = { "get_hotel_reservations": get_hotel_reservations, } # Definir la herramienta para function calling (útil para documentar la función) tools = [ { "type": "function", "function": { "name": "get_hotel_reservations", "description": "Obtiene una lista de reservaciones de hotel filtradas por un título. El parámetro 'title' permite especificar parte del nombre del hotel o región.", "parameters": { "type": "object", "properties": { "title": { "type": "string", "description": "Parte del nombre del hotel o región, e.g., Medellín, Bogotá, Cartagena" } }, "required": ["title"] } } } ] def process_instruction(instruction: str): """ Envía la instrucción al modelo y verifica si se debe llamar a una función. Se espera que el modelo devuelva una cadena que contenga un llamado a función en el siguiente formato: "Llamada a función: get_hotel_reservations(Bogotá)" """ output = "" result = generator(instruction, max_length=150)[0]['generated_text'] output += "Respuesta generada:\n" + result + "\n\n" if "Llamada a función:" in result: try: # Extraer la parte de la cadena que contiene el llamado a función start_index = result.find("Llamada a función:") + len("Llamada a función:") # Se asume que el llamado está en una única línea, por ejemplo: get_hotel_reservations(Bogotá) call_str = result[start_index:].strip().split()[0] func_name, params = call_str.split("(", 1) params = params.rstrip(")") func_name = func_name.strip() params = params.strip() if func_name in function_map: function_result = function_map[func_name](params) output += "Resultado de la función:\n" + str(function_result) else: output += "Función no encontrada: " + func_name except Exception as e: output += "Error al procesar la llamada a función: " + str(e) else: output += "No se encontró ninguna llamada a función en la respuesta." return output # Crear una interfaz Gradio para interactuar con el sistema iface = gr.Interface( fn=process_instruction, inputs=gr.Textbox(lines=5, placeholder="Escribe tu instrucción aquí...", label="Instrucción"), outputs="text", title="Demo de Function Calling con Phi-4-mini-instruct (CPU)" ) if __name__ == "__main__": iface.launch()