Simulación de restaurantes multiagente utilizando modelos de lenguaje grandes (LLM) en la práctica, con Python y OpenAI
Así es como utilicé agentes de modelos de lenguaje grandes para simular una operación de restaurante de extremo a extremo, utilizando Python.
La semana pasada, OpenAI publicó un archivo PDF del que todo el mundo habla. Este archivo es una guía de 34 páginas que explica qué son los agentes de modelos de lenguaje a gran escala (agentes LLM) y cómo utilizarlos.
El PDF es relativamente corto y fácil de leer también (no es necesario ser un ingeniero de software o mentor para entenderlo), pero en pocas palabras explica tres cosas:

1. Los agentes de modelos de lenguaje grandes (agentes LLM) “son sistemas que realizan tareas de forma independiente en su nombre”.
Entonces, ¿no son estas simples indicaciones del Modelo de Lenguaje Grande (LLM) llamadas a través de una API? Bueno, sí y no. Estás usando el mismo modelo de finalización de conversación, así que es algo parecido, pero la clave es crear una acción específica. Con esto quiero decir que la salida de tu proxy debe traducirse en una salida ejecutable en tu sistema. Por ejemplo, si la salida del LLM dice "espagueti", entonces "espagueti" se agregará a tu ruta de datos y, eventualmente, alguien lo verá y cocinará espagueti (alerta).
2. Los agentes del modelo de lenguaje grande (LLM) están particularmente integrados con funciones (herramientas).
Me refiero al escenario en el que le haces una pregunta a ChatGPT y este activa su generador de imágenes, buscador web o fragmento de código. Internamente, utiliza una función llamada widget, que se activa con tu pregunta. El generador de imágenes es una función integrada, pero también puede llamar a tu propio widget , que puedes especificar para tu tarea. Esta capacidad de integrar widgets y funciones externas es lo que otorga a los agentes de modelos de lenguaje grandes (agentes LLM) tanta flexibilidad y potencia para realizar una amplia variedad de tareas.
3. Muchos agentes de modelos de lenguaje grandes (agentes LLM) se pueden combinar secuencialmente.
Puedes combinar un único agente y equiparlo con varias herramientas , o bien dividir las herramientas en agentes especializados, que es lo que haremos en este artículo (¡otra pista!).
Los detalles técnicos pueden ser de interés para los ingenieros de software, pero ¿por qué este tema de los agentes es tan importante para todos los demás?
Bueno, porque esto representa un cambio de paradigma que ayuda a dar utilidad a los modelos de IA abierta. Piénselo: ahora los grandes modelos de lenguaje (LLM) proporcionan Resultados procesables. Por lo tanto, no se trata de utilizar indicaciones LLM en el último paso del flujo de trabajo para mejorar el resultado final; Más bien, se trata de Integración de todo el flujo de trabajo con agentes de modelos de lenguaje grandes (agentes LLM) Para mejorar la calidad de todo el flujo de trabajo.
Aunque intento explicarlo con palabras, creo que es más fácil ilustrarlo con un ejemplo práctico. Digamos que hablamos de un restaurante, por ejemplo.
Un restaurante típico tiene un proceso muy normal y claro: esperas en la cola, pides tu comida, esperas tu comida, comes y te vas. Ahora bien, si traducimos esto utilizando el enfoque del “agente”, podemos identificar al menos tres agentes:
- agente Cliente Es un agente de modelo de lenguaje grande (LLM) que ordena comida o pide sugerencias al camarero.
- agente النادل Es un modelo de lenguaje grande (LLM) que recoge solicitudes y hace sugerencias cuando es necesario.
- agente Entretenimiento Es un modelo de lenguaje grande (LLM) orientado a gestionar las quejas de los clientes.
Ahora, OpenAI te dice exactamente cómo construir estas entidades, pero esa es la parte relativamente fácil; Hay mucho más que eso, ¿no?
Necesitamos implementar el restaurante , crear un sistema de colas donde la gente se siente según la afluencia de clientes, crear el menú , simular los tiempos de espera y asegurarnos de que todo funcione. Solo entonces podremos conectar a los agentes. Como siempre:
La IA generativa es poderosa, pero solo cuando se utiliza en el contexto adecuado.
Entonces, antes de llegar a la parte emocionante sobre los agentes, en este artículo verás:
- Diseño de sistemas Para Agente de Restaurantes LLM. Una idea sin código, sólo un boceto del proyecto en lápiz y papel (o más bien, ratón y PowerPoint).
- Implementación de restaurante sin agente. Simple y directo, simplemente crea la estructura básica del código.
- Implementación del Agente Restaurante. Además de una interfaz gráfica de usuario sencilla para mostrarlo bien.
- Consideraciones y observaciones finales.
Parece que tenemos mucho que cubrir. ¡Al laboratorio! 🧪
1. Diseño de sistemas de restaurantes: una guía experta
Nota: Si ha realizado algunos recorridos técnicos, encontrará que el diseño de este sistema es muy fácil. El objetivo de este diseño no es demostrar exhaustivamente cada parte de un sistema de aprendizaje automático (como te piden en una entrevista de 15 minutos 🙃), sino simplemente brindar algo de orientación sobre lo que haremos a continuación.
La forma en que podemos visualizar el proceso del restaurante, integrado con un gran modelo de lenguaje (LLM), se resume en esta imagen:

Déjame explicarte:
- Restaurante()yMenú() Son dos clases. Los definimos y todas las tablas, órdenes e información del sistema dentro de las clases se definirán y actualizarán dinámicamente.
- tendrá que Nuevo cliente Pasar a través de un mecanismo de asiento. Si pueden sentarse (hay suficientes mesas libres), genial, podemos dejarlos sentarse; De lo contrario, el cliente tendrá que esperar en la cola.
- Para el cliente el sentadoHabrá un camarero que les permitirá pedir comida. Pueden “quejarse” y preguntar cuánto tiempo tardará la comida después de ordenarla.
- La gente no puede esperando en la fila Hacen muchas cosas, pero también pueden “quejarse” y preguntar cuánto tiempo tendrán que esperar en la fila antes de poder sentarse.
Ahora bien, si lo piensas bien, no necesitas un modelo de lenguaje complejo (LLM) para esto. Por ejemplo, podríamos calcular el tiempo de espera por adelantado y luego vincularlo a una cadena estructurada predefinida. También podríamos usar una lista simple de pedidos (como la de un quiosco automático de McDonald's) y listo. Claro que podríamos hacerlo, pero piénsalo.
¿Qué ocurre si un cliente quiere preguntar por el menú mientras espera ? ¿Y si no se decide por la comida? ¿Y si quiere saber cuál es la mejor opción vegetariana ? ¿Y si busca un buen vino a un precio razonable ? Podemos empezar a definir métodos basados en reglas para cada uno de estos casos, perdiendo tiempo y dinero, o podemos empezar a usar inteligencia artificial. De eso trata este artículo. Si utilizamos agentes de modelos de lenguaje a gran escala (agentes LLM), podremos gestionar todos estos casos de una sola vez.
Ahora bien, si algo has aprendido, es que la ingeniería de software debe realizarse paso a paso . Lo ideal es tener la estructura básica del modelo y luego añadir los toques finales y las mejoras. Por ello, construiremos una versión sin agentes del producto mencionado anteriormente. Esta versión simplificada contará con un sistema de colas que calcula los tiempos de espera y ejecuta el menú, de modo que todo funcionará sin problemas sin necesidad de inteligencia artificial. Tras este paso, podremos colocar agentes en los puestos que hemos descrito y demostrado anteriormente (cliente, anfitrión y camarero).
2. Implementación sin agente
Siempre es mejor simplificar todo lo posible en el script principal y dejar las operaciones complejas en segundo plano. Nuestra implementación sin agente se puede ejecutar en este código.
importar aleatorio importar tiempo importar matemáticas importar sistema desde utilidades importar * desde constantes importar * desde modelos_ingenuos importar * si __nombre__ == "__principal__": aleatorio.semilla(42) menú = preproceso_menú(ARCHIVO_MENÚ, factor_tiempo_comer=0.5) R = Restaurante( núm_mesas=2, probabilidad_llegada=0.7, duración_ticket=1, pausa_real=5.0, probabilidad_consulta=0.4, menú=menú ) R.ejecutar(tiempo_total=60)
Como podemos ver, podemos cambiar:
- num_tablas; Número de mesas en nuestro restaurante.
- probabilidad de llegada; Es la probabilidad de que un cliente llegue en cada paso de tiempo.
- garrapata; Es el paso de tiempo de nuestra simulación.
- pausa; Implementa la función time.sleep(), que se utiliza para simular el flujo de trabajo de un restaurante real.
Ahora bien, toda esta implementación se realiza en el archivo naive_models.py , ubicado aquí.
import random
import time
import math
import sys
from utils import *
from constants import *
class Table:
def __init__(self, id, capacity=1):
self.id = id
self.capacity = capacity
self.is_free = True
self.cust_id = None
self.plate = None
self.cooking_complete_at = None
self.leave_at = None
def seat(self, cust_id, clock, plate, cook_time, eat_time):
self.is_free = False
self.cust_id = cust_id
self.plate = plate
self.cooking_complete_at = clock + cook_time
self._scheduled_eat_time = eat_time
msg = (
f"[{clock:04}m] 🪑 Seated customer {cust_id} at T{self.id} "
f"ordering {plate!r} (cook {cook_time}m, eat {eat_time}m)"
)
print(msg); sys.stdout.flush()
def start_eating(self, clock):
self.leave_at = clock + self._scheduled_eat_time
msg = (
f"[{clock:04}m] 🍽️ Customer {self.cust_id} at T{self.id} "
f"starts eating their {self.plate!r} (leaves at {self.leave_at}m)"
)
print(msg); sys.stdout.flush()
def depart(self, clock):
msg = (
f"[{clock:04}m] 💸 Customer {self.cust_id} finished their "
f"{self.plate!r} and left T{self.id}"
)
print(msg); sys.stdout.flush()
self.is_free = True
self.cust_id = None
self.plate = None
self.cooking_complete_at = None
self.leave_at = None
class Restaurant:
def __init__(self, num_tables, arrival_prob=0.33,
tick_length=1, real_pause=0.5, menu=None,
query_prob=0.0):
self.tables = [Table(i) for i in range(num_tables)]
# queue holds only customer IDs
self.queue = []
self.clock = 0
self.next_cust_id = 1
self.arrival_prob = arrival_prob
self.tick = tick_length
self.pause = real_pause
self.menu = menu or [
("Burger", 2, 4),
("Pasta", 3, 5),
("Salad", 1, 2),
("Steak", 4, 6),
("Soup", 1, 3),
]
self.query_prob = query_prob
total = sum(c + e for _, c, e in self.menu)
self.avg_service_time = total / len(self.menu)
def open_tables(self):
return [t for t in self.tables if t.is_free]
def _pick_dish(self):
return random.choice(self.menu)
def arrive(self):
if random.random() < self.arrival_prob:
cid = self.next_cust_id
self.next_cust_id += 1
free = self.open_tables()
if free:
# pick dish only when seating immediately
plate, cook_time, eat_time = self._pick_dish()
table = min(free, key=lambda t: t.capacity)
table.seat(cid, self.clock, plate, cook_time, eat_time)
else:
self.queue.append(cid)
print(f"[{self.clock:04}m] ⏳ Queued customer {cid} (waiting)")
def process_cooking(self):
for t in self.tables:
if (not t.is_free
and t.cooking_complete_at is not None
and t.cooking_complete_at <= self.clock
and t.leave_at is None):
t.start_eating(self.clock)
def process_departures(self):
for t in self.tables:
if (not t.is_free
and t.leave_at is not None
and t.leave_at <= self.clock):
t.depart(self.clock)
def seat_from_queue(self):
while self.queue and self.open_tables():
cid = self.queue.pop(0)
# pick dish at seating time
plate, cook_time, eat_time = self._pick_dish()
table = min(self.open_tables(), key=lambda t: t.capacity)
table.seat(cid, self.clock, plate, cook_time, eat_time)
def estimate_queue_time(self, cid):
positions = list(self.queue)
idx = positions.index(cid)
raw_wait = (idx + 1) * self.avg_service_time / len(self.tables)
return math.ceil(raw_wait)
def estimate_food_time(self, cid):
for t in self.tables:
if t.cust_id == cid:
if t.cooking_complete_at > self.clock:
return t.cooking_complete_at - self.clock
return max(0, t.leave_at - self.clock)
return None
def handle_random_query(self):
queue_ids = list(self.queue)
seated_ids = [t.cust_id for t in self.tables if not t.is_free]
if queue_ids and (not seated_ids or random.random() < 0.7):
cid = random.choice(queue_ids)
wait = self.estimate_queue_time(cid)
print(f"[{self.clock:04}m] ❓ Customer {cid}: How long will I be in line?")
print(f"[{self.clock:04}m] ➡️ Estimated wait for customer {cid}: {wait}m")
elif seated_ids:
cid = random.choice(seated_ids)
wait = self.estimate_food_time(cid)
table = next(t for t in self.tables if t.cust_id == cid)
food = table.plate
print(f"[{self.clock:04}m] ❓ Customer {cid}: How long will the {food} take me?")
if wait is None:
print(f"[{self.clock:04}m] ➡️ Ready now!")
else:
print(f"[{self.clock:04}m] ➡️ Estimated food wait for customer {cid}: {wait}m")
def tick_once(self):
self.arrive()
self.process_cooking()
self.process_departures()
self.seat_from_queue()
if self.query_prob and random.random() < self.query_prob:
self.handle_random_query()
self.clock += self.tick
time.sleep(self.pause)
def run(self, total_time):
while self.clock < total_time:
self.tick_once()
print("n--- END OF SHIFT ---")
free = sum(t.is_free for t in self.tables)
print(f"{free}/{len(self.tables)} tables free at {self.clock}m.")
if __name__ == "__main__":
random.seed(42)
menu = preprocess_menu(MENU_FILE, eat_time_factor=0.5)
R = Restaurant(
num_tables=2,
arrival_prob=0.7,
tick_length=1,
real_pause=5.0,
query_prob=0.4,
menu=menu
)
R.run(total_time=60)
Bueno, esto es largo, déjame explicarte algunos pasos.
El script completo se ejecuta en naive_sim usando el comando .run() con las siguientes funciones:
- llegar, que representa la llegada y solicitud de clientes, o bien su llegada y colocación en una cola.
- proceso_cocción, que simula la cocción de cada mesa.
- proceso_salidas, que simula la salida del cliente.
- asiento_de_la_cola, que simula a los clientes sentados en la fila.
- manejar consulta aleatoria, que se llama de forma aleatoria, donde un cliente en la fila o esperando su comida puede preguntar sobre el tiempo de espera.
Si ejecutamos naive_sim.py, obtendremos esto desde la terminal.

Ahora bien, este es en sí mismo un producto de ciencia de datos. Puedes gestionar una cadena de Montecarlo con esto, puedes ver el potencial de que se cree una larga cola, los restaurantes pueden usar este “gemelo digital” de su restaurante y ver cuándo pueden suceder cosas críticas. Ahora que tenemos un producto funcional, hagámoslo más atractivo y potente utilizando inteligencia artificial (IA).
3. Implementación del restaurante del agente
Como podemos ver arriba, los clientes ya pueden hacer preguntas y tenemos la respuesta en forma de número. El cliente también elige una comida al azar en nuestro sistema. Ahora intentemos agregar agentes a este sistema. La activación de un sistema de agente de restaurante es un paso avanzado para automatizar el servicio al cliente y mejorar la experiencia del usuario. Los agentes capacitados pueden responder eficazmente las consultas de los clientes y brindar recomendaciones personalizadas.
3.1 Implementación de agentes dedicados
Necesitarás instalar el módulo “Agentes”:
A continuación se muestra la implementación del agente de servicio al cliente, el agente de entretenimiento y el manejador de quejas.
# custom_agents.py import os, json from openai import OpenAI from agents import Agent from newtools import * client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"), default_headers={"OpenAI-Beta":"assistants=v2"}) menu_agent = Agent(name = "Chef_suggester", instructions = "Eres un camarero servicial que conoce todo sobre nuestro restaurante y ayuda a los clientes a elegir su comida. Empezarás presentándote cortésmente como asistente virtual de cocina y saludando amablemente al cliente. El nombre del cliente se encuentra en el archivo json msg. Leerás el menú y, según las preguntas del cliente, en la clave de solicitud del archivo json, ofrecerás la mejor recomendación del menú. Si el cliente te hace preguntas inapropiadas, simplemente imprime 'unsuccessfull' en formato json '{food: , estado: }'", tools = [get_menu]) entertainer_agent = Agent(name = "Entertainer", instructions = ("Eres un camarero servicial que mantiene a los clientes ocupados mientras esperan." "No puedes ofrecer ningún descuento ni oferta, pero pueden hacer preguntas sobre el menú, que puedes obtener de las" "funciones get_menu. También pueden preguntarte cuánto tiempo va a durar la cola para entrar. Su información está en waiting_time" "Si el user_status es 'queue', simplemente proporciona el tiempo con amabilidad, en función de la duración de la espera. De lo contrario, " "si el user_status es 'food' significa que están esperando comida. Marca 'order' y proporciona una referencia divertida sobre" "su tiempo de espera. Por ejemplo, '¡tu tiempo de espera para la pasta es de 1 minutos, parece que el chef le está poniendo salsa!'", tools = [get_menu]) customer_agent = Agent(name = "Customer", instructions = ("Eres un cliente y estás comiendo en un restaurante italiano. Mira el menú usando La función get_menu. Si ya sabes lo que quieres, simplemente dile al camarero qué deseas. "De lo contrario, dales una indicación general o pídeles orientación según tus preferencias y elegirán lo mejor para ti.")
Tenemos la definición del cliente , que es la llamada al cliente de OpenAI, newtools.py , que obtiene la lista, y call_agent , que llama y ejecuta al agente individual a través de un ejecutor . Estos componentes son esenciales para crear un sistema de agentes eficaz.
Esto es precisamente lo que comentamos en la introducción. Definimos varios agentes que se conectarán entre sí y que utilizarán las herramientas especificadas en mi código. Estas herramientas y agentes permiten automatizar las tareas de atención al cliente y mejorar la experiencia del usuario.
de agentes importar function_tool de constantes importar * importar pandas como pd @function_tool def get_menu(): df = pd.read_csv(MENU_FILE) # convertir a lista de diccionarios (o estructura serializable en JSON) devolver df.to_dict(orient="records")
3.2 Implementación de agentes dedicados
La implementación de Table y Restaurant, junto con los agentes, está integrada en el siguiente código:
importar aleatorio importar tiempo importar matemáticas importar sistema desde utilidades importar * desde constantes importar * importar tiempo, aleatorio, json desde agentes_personalizados importar * desde utilidades importar * desde constantes importar * desde agentes importar Runner # lista de nombres de su constante NOMBRES # suponga que NOMBRES = [ ... ] is defined in constants.py
import logging
# Set up logging
def log(msg):
logging.info(msg)
class Table:
def __init__(self, id, capacity=1):
self.id = id
self.capacity = capacity
self.is_free = True
self.cust_id = None
self.orders = [] # list of (plate, cook_time, eat_time)
self.current_phase = None # "cooking" or "eating"
self.cooking_complete_at = None
self.leave_at = None
def seat(self, cust_id, cust_name, clock, orders):
self.is_free = False
self.cust_id = cust_id
self.orders = list(orders) # copy the list of tuples
# start first dish cooking immediately
plate, cook_time, eat_time = self.orders.pop(0)
self.current_phase = "cooking"
self._scheduled_eat_time = eat_time
self._remaining_orders = self.orders # save the tail
self.cooking_complete_at = clock + cook_time
self.leave_at = None
msg = (f"[{clock:04}m] 🪑 Seated {cust_name} (#{cust_id}) at T{self.id} "
f"ordering {len(orders)} dishes; first: {plate!r} "
f"(cook {cook_time}m, eat {eat_time}m)")
print(msg); sys.stdout.flush()
def start_eating(self, clock):
self.current_phase = "eating"
self.leave_at = clock + self._scheduled_eat_time
plate = self.plate if hasattr(self, 'plate') else "dish"
msg = (f"[{clock:04}m] 🍽️ {plate!r} ready for {self.cust_name} "
f"(#{self.cust_id}) at T{self.id}, eating until {self.leave_at}m")
print(msg); sys.stdout.flush()
def finish_phase(self, clock):
"""Called when eating of current dish finishes."""
if self._remaining_orders:
# move to next dish
plate, cook_time, eat_time = self._remaining_orders.pop(0)
self.current_phase = "cooking"
self._scheduled_eat_time = eat_time
self.cooking_complete_at = clock + cook_time
self.leave_at = None
self.plate = plate
msg = (f"[{clock:04}m] 🔄 Next dish for {self.cust_name} (#{self.cust_id}) "
f"at T{self.id}: {plate!r} (cook {cook_time}m, eat {eat_time}m)")
print(msg); sys.stdout.flush()
else:
# no more dishes: depart
msg = (f"[{clock:04}m] 💸 {self.cust_name} (#{self.cust_id}) "
f"finished all dishes and left T{self.id}")
print(msg); sys.stdout.flush()
self.is_free = True
self.cust_id = None
self.orders = []
self.current_phase = None
self.cooking_complete_at = None
self.leave_at = None
class Restaurant:
def __init__(self, num_tables, arrival_prob=0.33,
tick_length=1, real_pause=0.5, menu=None,
query_prob=0.0):
self.tables = [Table(i) for i in range(num_tables)]
self.queue = [] # just customer IDs
self.clock = 0
self.next_cust_id = 1
self.arrival_prob = arrival_prob
self.tick = tick_length
self.pause = real_pause
self.menu = menu or [
("Burger", 2, 4),
("Pasta", 3, 5),
("Salad", 1, 2),
("Steak", 4, 6),
("Soup", 1, 3),
]
self.runner = Runner()
self.query_prob = query_prob
self.names = {}
self.load_logging()
def load_logging(self):
logging.getLogger("httpx").setLevel(logging.WARNING)
logging.getLogger("openai").setLevel(logging.WARNING)
logging.getLogger("urllib3").setLevel(logging.WARNING)
logging.basicConfig(level=logging.INFO, format='[%(asctime)s] %(message)s',
datefmt='%H:%M:%S', handlers=[
logging.FileHandler("restaurant_log.txt", mode='w'),
logging.StreamHandler(sys.stdout)])
def log_to_msg(self,msg):
logging.info(msg)
def open_tables(self):
return [t for t in self.tables if t.is_free]
def _pick_orders(self, cname):
"""Choose between 1–3 random menu items as a list."""
#n = random.randint(1, 3)
#return random.sample(self.menu, n)
customer_text = call_agent(runner = self.runner, msg= '', class_agent="customer").final_output
msg = f'The customer {cname} is talking to the waiter, saying this {customer_text}'
print(msg)
self.log_to_msg(msg)
menu_asker_output = call_agent(runner = self.runner, msg = json.dumps(customer_text), class_agent="waiter").final_output
output = extract_json_dict(menu_asker_output)
msg = f'The processed response from our LLM is {output}'
print(msg)
self.log_to_msg(msg)
if output['status'] == 'successfull':
return filter_menu_items(output['food'])
else:
n = random.randint(1, 3)
return random.sample(self.menu, n)
def _assign_name(self, cid):
name = random.choice(NAMES)
self.names[cid] = name
return name
def arrive(self):
if random.random() < self.arrival_prob:
cid = self.next_cust_id
self.next_cust_id += 1
cname = self._assign_name(cid)
free = self.open_tables()
if free:
orders = self._pick_orders(cname)
table = min(free, key=lambda t: t.capacity)
table.cust_name = cname
plate, cook_time, eat_time = orders[0]
table.plate = plate
table.seat(cid, cname, self.clock, orders)
else:
self.queue.append(cid)
msg = f"[{self.clock:04}m] ⏳ Queued {cname} (#{cid}) – waiting"
print(msg)
self.log_to_msg(msg)
def process_cooking(self):
for t in self.tables:
if (not t.is_free and
t.current_phase=="cooking" and
t.cooking_complete_at <= self.clock):
# cooking done → start eating
t.cust_name = self.names[t.cust_id]
t.start_eating(self.clock)
def process_departures(self):
for t in self.tables:
if (not t.is_free and
t.current_phase=="eating" and
t.leave_at <= self.clock):
t.cust_name = self.names[t.cust_id]
t.finish_phase(self.clock)
def seat_from_queue(self):
while self.queue and self.open_tables():
cid = self.queue.pop(0)
cname = self.names[cid]
orders = self._pick_orders(cname=cname)
table = min(self.open_tables(), key=lambda t: t.capacity)
table.cust_name = cname
plate, cook_time, eat_time = orders[0]
table.plate = plate
table.seat(cid, cname, self.clock, orders)
def estimate_queue_time(self, cid):
# same logic as before: position in queue × avg service
avg = sum(c+e for _,c,e in self.menu) / len(self.menu)
idx = self.queue.index(cid)
return math.ceil((idx+1)*avg/len(self.tables))
def estimate_food_time(self, cid):
for t in self.tables:
if t.cust_id == cid:
# if they’re still cooking, time until cook‐done
if t.current_phase == "cooking":
return max(0, t.cooking_complete_at - self.clock)
# if they’re eating, time until they finish eating
if t.current_phase == "eating":
return max(0, t.leave_at - self.clock)
return None
def handle_random_query(self):
queue_ids = list(self.queue)
seated_ids = [t.cust_id for t in self.tables if not t.is_free]
if queue_ids and (not seated_ids or random.random() < 0.7):
cid = random.choice(queue_ids)
wait = self.estimate_queue_time(cid)
cname = self.names[cid]
msg = f"[{self.clock:04}m] ❓ Customer {cid}: How long will I be in line?"
print(msg) self.log_to_msg(msg) msg = f"[{self.clock:04}m] ➡️ Espera estimada para el cliente {cid}: {wait}m" print(msg) self.log_to_msg(msg) mensaje_de_espera = { "id_cliente": cid, "nombre_cliente": cname, "tipo": "línea", "min_espera": esperar, "siguiente_comida": Ninguno } output_llm = call_agent(class_agent="entertainer", runner = self.runner, msg = json.dumps(mensaje_de_espera)) msg = f"Nuestro LLM se encargó de {cname} con esto: {output_llm}" print(msg) self.log_to_msg(msg) elif ids_sentados: cid = random.choice(ids_sentados) esperar = self.estimate_food_time(cid) table = next(t for t in self.tables if t.cust_id == cid) comida = mesa.plato cname = self.names[cid] msg = f"[{self.clock:04}m] ❓ Cliente {cid}: ¿Cuánto tiempo me llevará la comida?”
print(msg) self.log_to_msg(msg) si la espera es Ninguna: msg = f"[{self.clock:04}m] ➡️ ¡Listo ahora!"
print(msg) self.log_to_msg(msg) else: msg = f"[{self.clock:04}m] ➡️ Tiempo estimado de espera de comida para el cliente {cid}: {wait}m" print(msg) self.log_to_msg(msg) mensaje_de_espera = { "id_cliente": cid, "nombre_cliente": cname, "tipo": "línea", "min_espera": esperar, "siguiente_comida": comida } output_llm = call_agent(class_agent="entertainer", runner = self.runner, msg = json.dumps(mensaje_de_espera)) msg = f"Nuestro LLM se encargó de {cname} con esto: {output_llm}" print(msg) self.log_to_msg(msg) def tick_once(self): self.arrive() self.process_cooking() self.process_departures() self.seat_from_queue() si self.query_prob y aleatorio.random() < self.query_prob: self.handle_random_query() self.clock += self.tick time.sleep(self.pause) def run(self, tiempo_total): mientras self.clock < tiempo_total: self.tick_once() libre = suma(t.está_libre para t en self.tablas) msg = f"n--- FIN DEL TURNO ---n{libre}/{len(self.tablas)} mesas libres a las {self.clock}m."
print(msg) self.log_to_msg(msg) if __name__ == "__main__": random.seed(42) menu = preprocess_menu(MENU_FILE, factor_tiempo_comida=0.5) R = Restaurant( núm_mesas=5, probabilidad_llegada=0.7, duración_ticket=1, pausa_real=5.0, probabilidad_consulta=0.8, menu=menu ) R.run(tiempo_total=60)
3.3 Implementación de una interfaz gráfica de usuario (GUI) para un restaurante utilizando un modelo de lenguaje grande (LLM)
Para mostrar el rendimiento del restaurante con una aplicación de modelo de lenguaje grande (LLM), utilizaremos una interfaz gráfica de usuario (GUI) simple.
de llm_models_gui importar RestaurantGUI de utils importar * importar aleatorio de llm_models importar Restaurant si __name__ == "__main__": random.seed(42) menú = preprocess_menu(MENU_FILE, eat_time_factor=0.5) R = Restaurant( num_tables=5, arrived_prob=0.7, tick_length=1, real_pause=1.0, # más suave para GUI query_prob=0.8, menu=menu ) aplicación = RestaurantGUI(R)

La interfaz gráfica de usuario (GUI) le proporciona información sobre la persona (Emma), la tabla, la hora y la salida del modelo de lenguaje grande (LLM). También se crea automáticamente un registro .txt.
Permítame mostrarle un ejemplo del resultado:
[12:31:23] La clienta Emma está hablando con el camarero y dice: “Me gustaría empezar con la bruschetta como aperitivo. Luego pediré espaguetis carbonara como primer plato. De postre, disfrutaré de un tiramisú. ¿Podría también sugerirme un vino para acompañar esta comida?” [12:31:25] La respuesta procesada de nuestro estudiante de máster es: {'food': ['Bruschetta', 'Spaghetti Carbonara', 'Tiramisu', 'Chianti Classico'], 'status': 'successful'} [12:31:25] [0000m] ❓ Cliente 1: ¿Cuánto tiempo tardaré en preparar la comida? [12:31:25] [00:00] ➡️ Tiempo de espera estimado para la comida por cliente: 1:15 minutos [12:31:26] El estudiante de MBA se hizo cargo del caso de Emma con esto: Último cliente: Agente (nombre=”Animador”, …) Resultado final (cadena): ¡Hola Emma! Gracias por tu paciencia. El tiempo de espera para entrar es de aproximadamente 15 minutos. ¡ Ya casi llegamos! ¡Justo el tiempo suficiente para que empiece a soñar con esa deliciosa bruschetta! 🍽️
Podemos ofrecer:
- El cliente crea su propio menú a través del agente.y solicita una recomendación del agente del camarero.
- El camarero recomienda un vino Chianti y lo añade a la lista.
- El agente de atención de reclamaciones informa al cliente del periodo de espera.
Ahora, no solo podemos simular el flujo de trabajo, como hacíamos antes, sino que contamos con un flujo de trabajo inteligente , mejorado por la misma tecnología ChatGPT. ¿No es asombroso?
4. Conclusión
Muchas gracias por venir, significa mucho para mí ❤️.
Volvamos atrás y veamos lo que hicimos en este artículo.
- Diseño de sistemas de restaurantes:
Creamos un diseño rápido para un sistema de restaurante usando PowerPoint con la incorporación de agentes de IA. - Base sin agente:
Primero construimos una simulación determinista para poder codificar la lógica de la cola, los tiempos de cocción y la rotación de las mesas. Este es nuestro esqueleto antes de hacer cualquier IA. - Restaurante basado en agentes:
En esta etapa, utilizamos agentes de IA para completar nuestro caso de queja + acción con agentes. También creamos una interfaz gráfica de usuario para mostrar claramente los resultados.
Ahora bien, quiero ser muy claro. Sé que suena un poco a película de ciencia ficción. ¿Simulación de clientes? ¿Simulación de restaurantes y camareros? Sí, es extraño, pero el problema nunca es la herramienta de IA en sí, sino cómo se usa. Creo que reemplazar a los camareros humanos con IA es una estrategia perdedora.
Ser camarero no consiste simplemente en tomar pedidos y recomendar el vino número N en función de los N-1 vinos que se han pedido anteriormente. Se trata de ser lo suficientemente cálido para hacer que un invitado se sienta bienvenido pero lo suficientemente distante para no interferir en su conversación, lo suficientemente amable para hacerlo sentir como en casa pero lo suficientemente fuerte para hacerlo respetar sus límites. Es una combinación de cualidades que creo que requieren un toque humano, paciencia y empatía.
Sin embargo, creo que el uso correcto de esta tecnología puede ser doble:
- Ayudando a personas reales que están en la lista de espera. Los camareros dentro están muy ocupados, y los restaurantes ya proporcionan un menú para que lo mires mientras esperas tu mesa, y no es realista pensar que otros camareros estén entreteniendo a personas que esperan sin mesa. En este punto, puede resultar útil contar con un compañero de IA para charlar.
- Simulación de restaurante. El escenario que escribí simula Comportamiento Cliente también. Esto significa que, potencialmente, puedes usar simulaciones para probar diferentes escenarios, ver cuándo se forman colas, asumir diferentes reacciones de las personas, diferentes respuestas de los camareros, etc. En otras palabras, este puede ser tu "gemelo digital" donde ejecutas pruebas.
Los comentarios están cerrados.