Simulazione di un ristorante multi-agente utilizzando modelli linguistici di grandi dimensioni (LLM) in pratica, con Python e OpenAI

Ecco come ho utilizzato Large Language Model Agents per simulare l'attività end-to-end di un ristorante, utilizzando Python.

La scorsa settimana, OpenAI ha rilasciato un file PDFE tutti ne parlano. Questo file è una guida di 34 pagine che spiega cosa sono i Large Language Model Agents (LLM Agents) e come utilizzarli.

Il PDF è relativamente breve e facile da leggere (non è necessario essere un ingegnere informatico o un mentore per capirlo), ma in poche parole spiega tre cose:

.1. Agenti modello linguistico di grandi dimensioni (agenti LLM) “Si tratta di sistemi che completano autonomamente i compiti per tuo conto.”

Quindi, non si tratta semplicemente di semplici chiamate a modelli linguistici di grandi dimensioni (LLM) tramite un'API? Beh, sì e no. Stai utilizzando gli stessi moduli di completamento della conversazione, quindi è un po' come, Ma Lo scopo è creare un'azione specifica. Ciò che intendo dire è che l'output dei tuoi agenti Deve tradursi in un risultato praticabile. Nel tuo sistema. Ad esempio, se l'output del tuo LLM riporta "spaghetti", "spaghetti" verrà aggiunto al tuo percorso dati e prima o poi qualcuno lo vedrà e cucinerà spaghetti (avviso).

2. Gli agenti Large Language Model (agenti LLM) sono specificamente integrati con Funzioni (Strumenti)

Mi riferisco allo scenario in cui poni una domanda a ChatGPT e questo richiama il suo generatore di immagini/ricerca web/frammento di codice. Utilizza internamente una funzione chiamata widget, che viene attivata dal tuo prompt. Ora, il generatore di immagini è una funzione integrata, ma può anche essere chiamato Il tuo lavoro (il tuo strumento), che puoi specificare specificamente per il tuo compito. Questa capacità di integrare strumenti e funzionalità esterni è ciò che conferisce agli agenti LLM grande flessibilità e potenza nello svolgimento di una varietà di attività.

 

3. È possibile integrare più agenti modello linguistico di grandi dimensioni (agenti LLM). Consecutivo

È possibile integrare un singolo agente e dotarlo di più strumenti. أو Dividere gli strumenti in agenti specializzati è ciò che faremo in questo articolo (un altro suggerimento!).

I dettagli tecnici possono essere di interesse per gli ingegneri del software, ma perché questo argomento degli agenti è così importante per tutti gli altri?
Bene, perché questo rappresenta un cambio di paradigma che contribuisce a rendere utili i modelli di intelligenza artificiale aperta. Pensateci: ora i grandi modelli linguistici (LLM) forniscono Risultati attuabili. Quindi, non si tratta di utilizzare i prompt LLM nell'ultimo passaggio del flusso di lavoro per migliorare il risultato finale; Piuttosto, si tratta di Integrazione dell'intero flusso di lavoro con agenti Large Language Model (agenti LLM) Per migliorare la qualità dell'intero flusso di lavoro.

Anche se cerco di spiegarlo a parole, penso che sia più facile mostrarvelo in pratica. Diciamo che stiamo parlando di ristorante, Per esempio.

In genere, un ristorante segue uno svolgimento molto normale e chiaro: si fa la fila, si ordina il cibo, si aspetta che arrivi, si mangia e si va via. Ora, se traduciamo questo usando l’approccio “agente”, possiamo identificare almeno tre agenti:

  • agente Cliente Si tratta di un agente LLM (Large Language Model) che ordina cibo o chiede suggerimenti al cameriere.
  • agente cameriere Si tratta di un modello linguistico di grandi dimensioni (LLM) che raccoglie le richieste e, quando necessario, fornisce suggerimenti.
  • agente Divertimento Si tratta di un modello linguistico di grandi dimensioni (LLM) finalizzato alla gestione dei reclami dei clienti.

Ora, OpenAI ti spiega esattamente come costruire queste entità, ma questa è la parte relativamente semplice; C'è molto di più da scoprire, non è vero?

Dobbiamo implementare Ristorante, e dobbiamo creare Metodo della lista d'attesa, dove le persone si siedono in base a quanto è affollato il ristorante, e dobbiamo creare menu, simulazione وقت الانتظارe assicurati che tutto funzioni, Poi Solo allora Possiamo mettere in contatto gli agenti. come sempre:

 

L'intelligenza artificiale generativa è potente, ma solo se utilizzata nel contesto giusto.

Quindi, prima di passare alla parte interessante degli agenti, in questo articolo vedrai:

  1. Progettazione del sistema Per l'LLM come agente di ristorazione. Un'idea senza codice, solo uno schizzo del progetto fatto con carta e penna (o meglio, mouse e PowerPoint).
  2. Implementazione del ristorante senza agenti. Semplice e diretto, basta creare la struttura di base del codice.
  3. Implementazione dell'agente Restaurant. Oltre a un'interfaccia utente grafica semplice per visualizzarlo bene.
  4. Considerazioni e osservazioni finali.

Sembra che abbiamo molto da trattare. Al laboratorio! 🧪

1. Progettazione del sistema di ristorazione: una guida per esperti

Nota: se hai svolto alcune esercitazioni tecniche, troverai la progettazione di questo sistema molto semplice. L'obiettivo di questo progetto non è dimostrare in modo esaustivo ogni parte di un sistema di apprendimento automatico (come ti chiedono in un'intervista di 15 minuti 🙃), ma semplicemente fornire alcune indicazioni su cosa faremo in seguito.

Il modo in cui possiamo visualizzare il processo di ristorazione, integrato con un modello linguistico di grandi dimensioni (LLM), è riassunto in questa immagine:

Lasciatemi spiegare:

  • Ristorante() e Menu() Sono due classi. Li definiamo e tutte le tabelle, gli ordini e le informazioni di sistema all'interno delle classi verranno definiti e aggiornati dinamicamente.
  • dovrà Nuovo cliente Passare attraverso un meccanismo di seduta. Se possono sedersi (ci sono abbastanza tavoli liberi), va bene, possiamo lasciarli sedere; Altrimenti il ​​cliente dovrà attendere in coda.
  • Per il cliente il sedutoCi sarà un cameriere che permetterà loro di ordinare il cibo. Possono "lamentarsi" e chiedere quanto tempo ci vorrà per ricevere il cibo dopo averlo ordinato.
  • Le persone non possono in attesa in fila Fanno tante cose, ma possono anche "lamentarsi" e chiedere quanto tempo dovranno aspettare in fila prima di potersi sedere.

Ora, se ci pensi, non lo sei bisogno a un modello linguistico di grandi dimensioni (LLM) per questo scopo. Ad esempio, possiamo calcolare in anticipo il tempo di attesa e poi collegarlo a una stringa predefinita e formattata. Possiamo anche utilizzare un semplice menu per raccogliere gli ordini (come il chiosco automatico di McDonald's) e concludere l'ordine. Certo, possiamo farlo, ma pensiamoci.

Cosa succede se il cliente vuole chiedere informazioni sul menù? mentre si aspetta? E se lo fossero? esitante E riguardo al cibo? E se volessero saperlo? L'opzione vegetariana più deliziosa Nel menù? E se lo volessero? Buon vino a un prezzo ragionevole? Possiamo iniziare a definire metodi basati su regole per ciascuno di questi scenari, sprecando tempo e denaro, oppure possiamo iniziare a utilizzare l'intelligenza artificiale. Ecco di cosa parla questo articolo. Se utilizziamo agenti con modelli linguistici di grandi dimensioni (agenti LLM), abbiamo la possibilità di gestire tutti questi scenari in un'unica operazione.

Ora, se ho imparato qualcosa, è che bisogna fare ingegneria del software. Passo dopo passo. Faresti meglio ad avere Hiki Alami Quindi aggiungi decorazioni e accessori al tuo modello. Per questo motivo realizzeremo una versione senza agenti del prodotto sopra menzionato. Questa versione semplificata sarà dotata di un sistema di coda che calcola i tempi di attesa ed esegue il menu, in modo che tutto funzioni senza intoppi, senza bisogno di intelligenza artificiale. Dopo questo passaggio, possiamo posizionare gli agenti nei luoghi di cui abbiamo parlato e mostrato sopra (cliente, host e cameriere).

2. Implementazione senza agente

È sempre meglio semplificare il più possibile tutto nello script principale e lasciare le operazioni complesse in secondo piano. La nostra implementazione Agent Free può essere eseguita in questo codice.

importa casuale importa tempo importa matematica importa sys da utils importa * da costanti importa * da naive_models importa * se __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)

Come possiamo vedere, possiamo modificare:

  • num_tabelle; Numero di tavoli nel nostro ristorante.
  • arrivo_probabile; Rappresenta la probabilità che un cliente arrivi a ogni intervallo temporale.
  • zecca; È il passo temporale della nostra simulazione.
  • pausa; Implementa la funzione time.sleep(), che viene utilizzata per simulare il flusso di lavoro di un vero ristorante.

Ora, tutta questa implementazione viene eseguita in un file. modelli_naive.py, esistente qui.

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)

Bene, è un discorso lungo, lasciatemi spiegarvi alcuni passaggi.

L'intero script viene eseguito su naive_sim utilizzando il comando .correre() Con le seguenti funzioni:

  • arrivare, che rappresenta l'arrivo e la richiesta dei clienti, oppure il loro arrivo e il loro posizionamento in una coda.
  • processo_di_cottura, che simula la cottura di ogni tavolo.
  • processi_partenze, che simula la partenza del cliente.
  • posto_dalla_coda, che simula i clienti seduti in coda.
  • gestire_query_casuale, che viene chiamato in modo casuale, dove un cliente in coda o in attesa del suo cibo può chiedere informazioni sul tempo di attesa.

Se eseguiamo naive_sim.py, otterremo questo dal terminale.

Ora, questo è di per sé un prodotto di scienza dei dati. Con questo si può gestire una catena di ristoranti di Monte Carlo, si può vedere il potenziale per la creazione di una lunga coda, i ristoranti possono usare questo "gemello digitale" del loro ristorante e vedere quando potrebbero verificarsi situazioni critiche. Ora che abbiamo un prodotto funzionante, rendiamolo più bello e potente utilizzando l'intelligenza artificiale (IA).

3. Implementazione del ristorante dell'agente

Come possiamo vedere sopra, i clienti sono già in grado di porre domande e noi abbiamo la risposta sotto forma di numero. Il cliente sceglie anche un alimento casuale nel nostro sistema. Ora proviamo ad aggiungere agenti a questo sistema. L'attivazione di un sistema di agenti di ristorazione è un passo avanti nell'automazione del servizio clienti e nel miglioramento dell'esperienza utente. Gli agenti qualificati sanno rispondere in modo efficiente alle richieste dei clienti e fornire consigli personalizzati.

3.1 Implementazione di agenti dedicati

Sarà necessario installare il modulo “Agenti”:

Di seguito è riportata l'implementazione dell'agente del servizio clienti, dell'agente di intrattenimento e del gestore dei reclami.

# custom_agents.py import os, json da openai import OpenAI da agents import Agent da newtools import * client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"), default_headers={"OpenAI-Beta":"assistants=v2"}) menu_agent = Agent(name = "Chef_suggester", instructions = "Sei un cameriere disponibile che conosce tutto del nostro ristorante e aiuta i clienti a scegliere il cibo. Inizierai presentandoti educatamente come assistente virtuale per il cibo e salutando educatamente il cliente. Il nome del cliente si trova nel file json msg" "Leggerai il menu e, in base a ciò che il cliente ti chiede, nella chiave di richiesta del file json, fornirai il miglior consiglio dal menu." "Se il cliente ti pone domande inappropriate, invia semplicemente un messaggio in formato json 'unsuccessfull' '{food: , stato: }'", tools = [get_menu]) entertainer_agent = Agent(name = "Entertainer", instructions = ("Sei un cameriere disponibile che tiene occupati i clienti mentre aspettano." "Non puoi offrire sconti o offerte, ma possono fare domande sul menu, che puoi ottenere dalle" "funzioni get_menu. Possono anche chiederti quanto tempo ci sarà per entrare. Le loro informazioni sono in waiting_time" "Se user_status è 'queue', fornisci semplicemente l'orario con gentilezza, in base alla durata dell'attesa. Altrimenti, se user_status è 'food', significa che stanno aspettando il cibo. Seleziona 'order' e fornisci un riferimento divertente al loro tempo di attesa. Ad esempio 'il tuo tempo di attesa per la pasta è di 1 minuti, sembra che lo chef ci stia mettendo il sugo!'", tools = [get_menu]) customer_agent = Agent(name = "Customer", instructions = ("Sei un cliente e stai mangiando in un ristorante italiano. Guarda il menu utilizzando Funzione get_menu. Se sai già cosa vuoi, dillo al cameriere. " "In caso contrario, fornisci loro un'indicazione generale o chiedi una guida in base ai tuoi gusti generali e sceglieranno il meglio per te."), tools = [get_menu]) def call_agent(runner, msg, class_agent = "wait"): if class_agent == "entertainer": return runner.run_sync(entertainer_agent, msg) elif class_agent == "waiter": return runner.run_sync(menu_agent, msg) elif class_agent == "customer": return runner.run_sync(customer_agent, '')

Abbiamo una definizione Cliente, che è la chiamata client di OpenAI, e nuovistrumenti.py, che richiama l'elenco e agente di chiamata che chiama l'agente individuale e lo gestisce tramite corridore. Questi componenti sono essenziali per creare un sistema di agenti efficace.

Questo è esattamente ciò di cui abbiamo parlato nell'introduzione. Ne identifichiamo diversi Agenti Saranno connessi e stanno usando Utensili Definito dal mio codice. Questi strumenti e agenti consentono di automatizzare le attività di assistenza clienti e migliorare l'esperienza utente.

da agenti importa function_tool da costanti importa * importa pandas come pd @function_tool def get_menu(): df = pd.read_csv(MENU_FILE) # converti in un elenco di dizionari (o struttura serializzabile JSON) restituisci df.to_dict(orient="records")

3.2 Implementazione di agenti dedicati

L'implementazione è integrata Table e Ristorante Con agenti nel seguente codice:

 

importa casuale importa tempo importa matematica importa sys da utilità importa * da costanti importa * importa tempo, casuale, json da agenti_personalizzati importa * da utilità importa * da costanti importa * da agenti importa Runner # elenco di nomi dalla tua costante NOMI # presumi che NOMI = [ ... ] 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] ➡️ Tempo di attesa stimato per il cliente {cid}: {wait}m" print(msg) self.log_to_msg(msg) waiting_message = { "customer_id": cid, "customer_name": cname, "type": "line", "wait_min": wait, "next_food": None } output_llm = call_agent(class_agent="entertainer", runner = self.runner, msg = json.dumps(waiting_message)) msg ​​​​= f"Il nostro LLM si è preso cura di {cname} con questo: {output_llm}" print(msg) self.log_to_msg(msg) 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 cname = self.names[cid] msg = f"[{self.clock:04}m] ❓ Cliente {cid}: Quanto tempo mi ci vorrà per ordinare il cibo?"
print(msg) self.log_to_msg(msg) se wait è None: msg = f"[{self.clock:04}m] ➡️ Pronto ora!"
print(msg) self.log_to_msg(msg) else: msg = f"[{self.clock:04}m] ➡️ Tempo di attesa stimato per il cibo per il cliente {cid}: {wait}m" print(msg) self.log_to_msg(msg) waiting_message = { "customer_id": cid, "customer_name": cname, "type": "line", "wait_min": wait, "next_food": food } output_llm = call_agent(class_agent="entertainer", runner = self.runner, msg = json.dumps(waiting_message)) msg = f"Il nostro LLM si è preso cura di {cname} con questo: {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() 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() free = sum(t.is_free for t in self.tables) msg = f"n--- FINE TURNO ---n{free}/{len(self.tables)} tavoli liberi a {self.clock}m."
print(msg) self.log_to_msg(msg) if __name__ == "__main__": random.seed(42) menu = preprocess_menu(MENU_FILE, eat_time_factor=0.5) R = Restaurant( num_tables=5, arrival_prob=0.7, tick_length=1, real_pause=5.0, query_prob=0.8, menu=menu ) R.run(total_time=60)

3.3 Implementazione di un'interfaccia utente grafica (GUI) per un ristorante utilizzando un modello linguistico di grandi dimensioni (LLM)

Per visualizzare le prestazioni del ristorante con un'applicazione LLM (Large Language Model), utilizzeremo una semplice interfaccia utente grafica (GUI).

da llm_models_gui importa RestaurantGUI da utils importa * importa casuale da llm_models importa Restaurant se __name__ == "__main__": random.seed(42) menu = preprocess_menu(MENU_FILE, eat_time_factor=0.5) R = Restaurant( num_tables=5, arrival_prob=0.7, tick_length=1, real_pause=1.0, # più fluido per GUI query_prob=0.8, menu=menu ) app = RestaurantGUI(R)

L'interfaccia utente grafica (GUI) fornisce informazioni sulla persona (Emma), sulla tabella, sull'ora e sull'output del modello linguistico completo (LLM). Viene creato automaticamente anche un record .txt.

Vi mostro un esempio dell'output:

[12:31:23] La cliente Emma si rivolge al cameriere dicendo: "Vorrei iniziare con la bruschetta come antipasto. Poi ordinerò gli spaghetti alla carbonara come primo. Per dessert, mi godrò il tiramisù. Puoi consigliarmi anche un vino da abbinare a questo piatto?" [12:31:25] La risposta elaborata dallo studente del nostro master è: {'food': ['Bruschetta', 'Spaghetti alla Carbonara', 'Tiramisù', 'Chianti Classico'], 'status': 'successful'} [12:31:25] [0000M] ❓ Cliente 1: Quanto tempo ci vorrà per preparare il cibo? [12:31:25] [0000M] ➡️ Tempo di attesa previsto per il cibo per il cliente 1:15 minuti [12:31:26] Lo studente LLM si è preso cura dell'ordine di Emma: Ultimo cliente: Agent(name=”Entertainer”, …) Risultato finale (stringa): Ciao Emma! Grazie per la pazienza. Il tempo di attesa per entrare è di circa 15 minuti. Ci siamo quasi, giusto il tempo di iniziare a sognare quella deliziosa bruschetta! ???? ️

Possiamo offrire:

  1. Il cliente crea il proprio menù tramite l'agente.e chiede una raccomandazione all'agente del cameriere.
  2. Il cameriere consiglia un vino Chianti e lo aggiunge alla lista.
  3. L'addetto alla gestione dei reclami informa il cliente del tempo di attesa.

Ora non possiamo semplicemente simulare un flusso di lavoro, come facevamo prima: abbiamo già un flusso di lavoro. Intelligente, basato sulla stessa tecnologia ChatGPT. Non è fantastico?

 

4. Conclusione

Grazie mille per essere venuti, significa molto per me ❤️.
Torniamo indietro e vediamo cosa abbiamo fatto in questo articolo.

  1. Progettazione del sistema di ristorazione:
    Abbiamo creato un progetto rapido per un sistema di ristorazione utilizzando PowerPoint con l'aggiunta di agenti di intelligenza artificiale.
  2. Senza agenti:
    Per prima cosa abbiamo realizzato una simulazione deterministica, in modo da poter codificare la logica della coda, dei tempi di cottura e della rotazione del tavolo. Questo è il nostro scheletro prima di realizzare qualsiasi IA.
  3. Ristorante basato su agente:
    In questa fase, abbiamo utilizzato agenti di intelligenza artificiale per popolare il nostro caso di reclamo + azione con gli agenti. Abbiamo anche creato un'interfaccia utente grafica per visualizzare chiaramente i risultati.

Ora, su questo punto, voglio essere molto chiaro. So che sembra un po' Black Mirror. Simulazione del cliente? Simulazione di ristorante e cameriere? Sì, è strano, Ma Il problema non è mai lo strumento di intelligenza artificiale, ma sempre il modo in cui viene utilizzato. Penso che sostituire i camerieri umani con l'intelligenza artificiale sia una partita persa.

Essere un cameriere non significa semplicemente prendere le ordinazioni e consigliare il vino numero N in base agli N-1 vini ordinati in precedenza. Si tratta di essere abbastanza cordiali da far sentire l'ospite benvenuto, ma abbastanza distanti da non interferire nella sua conversazione, abbastanza gentili da farlo sentire a casa, ma abbastanza forti da fargli rispettare i propri limiti. È una combinazione di qualità che, a mio avviso, richiedono tocco umano, pazienza ed empatia.

Tuttavia, ritengo che l'uso corretto di questa tecnologia possa essere duplice:

  1. Aiutare persone reali che sono in lista d'attesa. I camerieri all'interno sono molto impegnati e i ristoranti mettono già a disposizione un menù da consultare mentre si aspetta il tavolo; non è realistico pensare che altri camerieri intrattengano persone che aspettano senza tavolo. A questo punto, potrebbe essere utile avere un compagno AI con cui chattare.
  2. Simulazione di ristorante. Lo scenario che ho scritto simula Comportamento Clienti Anche. Ciò significa che, potenzialmente, puoi utilizzare le simulazioni per testare diversi scenari, vedere quando si formano le code, ipotizzare reazioni diverse da parte delle persone, risposte diverse da parte dei camerieri, ecc. In altre parole, questo può essere il tuo "gemello digitale" su cui eseguire i test.

 

 

I commenti sono chiusi.