Multi-agent restaurantsimulatie met behulp van grote taalmodellen (LLM) in de praktijk, met Python en OpenAI
Hier ziet u hoe ik Large Language Model Agents heb gebruikt om een end-to-end restaurantoperatie te simuleren met behulp van Python.
Vorige week publiceerde OpenAI een PDF- bestand , en iedereen heeft het erover. Dit bestand is een handleiding van 34 pagina's waarin wordt uitgelegd wat Large Language Model Agents (LLM Agents) zijn en hoe je ze kunt gebruiken.
De PDF is relatief kort en gemakkelijk te lezen (je hoeft geen software-engineer/mentor te zijn om het te begrijpen), maar het legt in een paar woorden drie dingen uit:

1. Large Language Model Agents (LLM Agents) zijn systemen die taken zelfstandig namens u uitvoeren.
Zijn dit dan niet gewoon simpele Big Language Model (LLM) prompts die via een API worden aangeroepen? Nou, ja en nee. Je gebruikt dezelfde modellen voor het aanvullen van gesprekken, dus het is er wel een beetje mee te vergelijken, maar het gaat erom een specifieke actie te creëren. Wat ik daarmee bedoel, is dat je proxy-output moet worden vertaald naar een uitvoerbare output in je systeem. Als de LLM-output bijvoorbeeld "spaghetti" zegt, wordt "spaghetti" toegevoegd aan je datapad, en uiteindelijk zal iemand het zien en spaghetti koken (alert).
2. Agenten met een groot taalmodel (LLM) zijn in het bijzonder geïntegreerd met functies (hulpmiddelen).
Ik doel hier op het scenario waarin je ChatGPT een vraag stelt en het de afbeeldingsgenerator/webzoeker/codefragmentfunctie aanroept. Intern gebruikt het een functie die een widget wordt genoemd en die wordt geactiveerd door je prompt. De afbeeldingsgenerator is een ingebouwde functie, maar ze kunnen ook je eigen widget aanroepen , die je voor jouw taak kunt specificeren. Deze mogelijkheid om externe widgets en functies te integreren, geeft Large Language Model Agents (LLM Agents) zoveel flexibiliteit en kracht bij het uitvoeren van een breed scala aan taken.
3. Veel grote taalmodelagenten (LLM-agenten) kunnen sequentieel worden gecombineerd.
Je kunt één agent combineren en deze uitrusten met meerdere tools , of de tools verdelen over gespecialiseerde agenten, wat we in dit artikel gaan doen (nog een hint!).
De technische details zijn misschien interessant voor software-engineers, maar waarom is het onderwerp van agents zo belangrijk voor anderen?
Omdat dit een paradigmaverschuiving vertegenwoordigt die de bruikbaarheid van Open AI-modellen vergroot. Denk er eens over na: tegenwoordig bieden grote taalmodellen (LLM's) Bruikbare uitkomsten. Het gaat dus niet om het gebruiken van LLM-prompts in de laatste stap van de workflow om het uiteindelijke resultaat te verbeteren; Het gaat er eerder om Integratie van de gehele workflow met Large Language Model Agents (LLM Agents) Om de kwaliteit van de volledige workflow te verbeteren.
Hoewel ik het in woorden probeer uit te leggen, denk ik dat het makkelijker is om het praktisch te illustreren. Laten we bijvoorbeeld zeggen dat we het over een restaurant hebben.
In een typisch restaurant is het proces heel normaal en duidelijk: je wacht in de rij, bestelt je eten, wacht op je eten, eet het op en gaat weer weg. Als we dit nu vertalen met behulp van de ‘agent’-benadering, kunnen we minstens drie agenten identificeren:
- tussenpersoon Cliënt Het is een Large Language Model (LLM) Agent die eten bestelt of de ober om suggesties vraagt.
- tussenpersoon bediende Het is een groot taalmodel (LLM) dat verzoeken verzamelt en indien nodig suggesties doet.
- tussenpersoon Vermaak Het is een groot taalmodel (LLM) dat gericht is op het omgaan met klachten van klanten.
OpenAI vertelt je precies hoe je deze entiteiten bouwt, maar dat is het relatief eenvoudige gedeelte; Er zit nog veel meer achter, toch?
We moeten het restaurant implementeren , een wachtrijsysteem creëren waarbij mensen plaatsnemen op basis van de drukte in het restaurant, het menu samenstellen , wachttijden simuleren en ervoor zorgen dat alles werkt. Pas dan kunnen we de agents koppelen. Zoals altijd:
Generatieve AI is krachtig, maar alleen als het in de juiste context wordt gebruikt.
Voordat we naar het interessante gedeelte over agenten gaan, leest u in dit artikel:
- Systeemontwerp Voor Restaurant Agent LLM. Een idee zonder code, alleen een schets van het project met pen en papier (of liever gezegd met muis en PowerPoint).
- Implementatie van restaurant zonder agenten. Eenvoudig en duidelijk: maak gewoon de basisstructuur van de code.
- Implementatie van Agent Restaurant. En een eenvoudige grafische gebruikersinterface om het goed weer te geven.
- Slotoverwegingen en opmerkingen.
Het lijkt erop dat we veel te bespreken hebben. Naar het lab! 🧪
1. Restaurantsysteemontwerp: een gids voor experts
Let op: als u bekend bent met technische rondleidingen, zult u dit systeemontwerp heel eenvoudig vinden. Het doel van dit ontwerp is niet om elk onderdeel van een machine learning-systeem uitgebreid te demonstreren (zoals ze je in een kwartiertje vragen 🙃), maar gewoon om wat richtlijnen te geven voor wat we vervolgens gaan doen.
De manier waarop we het restaurantproces kunnen visualiseren, geïntegreerd met een groot taalmodel (LLM), wordt samengevat in deze afbeelding:

Laat ik het uitleggen:
- Restaurant() و Menu() Er zijn twee klassen. Wij definiëren ze, en alle tabellen, orders en systeemgegevens binnen de klassen worden dynamisch gedefinieerd en bijgewerkt.
- zal moeten Nieuwe klant Passeer een zitmechanisme. Als ze kunnen zitten (voldoende vrije tafels), is dat geweldig, dan kunnen we ze laten zitten; Anders zal de klant in de rij gaan staan.
- Voor de klant ZittendEr zal een ober aanwezig zijn die hen helpt met het bestellen van eten. Ze kunnen ‘klagen’ en vragen hoe lang het duurt voordat het eten geserveerd wordt na de bestelling.
- Mensen kunnen niet in de rij staan Ze doen veel, maar ze kunnen ook ‘klagen’ en vragen hoe lang ze in de rij moeten wachten voordat ze mogen zitten.
Als je er even over nadenkt, heb je hiervoor geen groot taalmodel (LLM) nodig . We zouden bijvoorbeeld de wachttijd van tevoren kunnen berekenen en die vervolgens koppelen aan een vooraf gedefinieerde, gestructureerde tekenreeks. We zouden ook een eenvoudige bestellijst kunnen gebruiken (zoals een geautomatiseerde kiosk van McDonald's) en daarmee klaar zijn. Natuurlijk, dat zou kunnen, maar denk er eens over na.
Wat als een klant tijdens het wachten naar het menu wil vragen ? Wat als ze nog niet weten wat ze willen eten? Wat als ze willen weten wat de beste vegetarische optie op de menukaart is? Wat als ze een goede wijn willen voor een redelijke prijs ? We kunnen ofwel voor elk van deze scenario's op regels gebaseerde methoden gaan definiëren, wat tijd en geld kost, of we kunnen kunstmatige intelligentie gaan gebruiken. Daar gaat dit artikel over. Als we Large Language Model Agents (LLM Agents) gebruiken, krijgen we de mogelijkheid om al deze scenario's in één keer af te handelen.
Als je iets hebt geleerd, is het wel dat softwareontwikkeling stap voor stap moet gebeuren . Het is het beste om eerst de basisstructuur van je model te hebben en daarna de puntjes op de i te zetten en verbeteringen aan te brengen. Daarom bouwen we een agentloze versie van het bovenstaande product. Deze vereenvoudigde versie heeft een wachtrijsysteem dat de wachttijden berekent en het menu afhandelt, zodat alles soepel verloopt zonder kunstmatige intelligentie. Na deze stap kunnen we agents plaatsen op de posities die we hierboven hebben besproken en gedemonstreerd (klant, gastheer en ober).
2. Agentvrije implementatie
Het is altijd beter om alles in het hoofdscript zo veel mogelijk te vereenvoudigen en de complexere handelingen op de achtergrond te laten. Onze Agent Free Implementation kan in deze code worden uitgevoerd.
importeer willekeurig importeer tijd importeer wiskunde importeer sys van utils importeer * van constanten importeer * van naive_models importeer * als __naam__ == "__hoofd__": random.seed(42) menu = preprocess_menu(MENU_FILE, eet_tijd_factor=0.5) R = Restaurant( num_tables=2, aankomst_kans=0.7, tick_lengte=1, real_pause=5.0, query_kans=0.4, menu=menu ) R.run(totale_tijd=60)
Zoals we kunnen zien, kunnen we het volgende veranderen:
- aantal_tabellen; Aantal tafels in ons restaurant.
- aankomst_probleem; Het is de waarschijnlijkheid dat er bij elke tijdstap een klant arriveert.
- teek; Het is de tijdstap van onze simulatie.
- pauze; Het implementeert de time.sleep()-functie, die wordt gebruikt om de workflow van een echt restaurant te simuleren.
Deze implementatie vindt volledig plaats in het bestand naive_models.py , dat zich hier bevindt.
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)
Dit is een lang verhaal. Ik zal u enkele stappen uitleggen.
Het volledige script wordt uitgevoerd op naive_sim met behulp van de .run() opdracht met de volgende functies:
- aankomen, die de aankomst en het verzoek van klanten weergeeft, of hun aankomst en plaatsing in een wachtrij.
- proces_koken, die het koken van elke tafel simuleert.
- proces_vertrekken, wat een vertrek van de klant simuleert.
- stoel_van_wachtrij, die klanten simuleert die in de rij zitten.
- willekeurige_query afhandelen, die willekeurig wordt aangeroepen, waar een klant die in de rij staat of op zijn eten wacht, kan vragen naar de wachttijd.
Als we naive_sim.py uitvoeren, krijgen we dit via de terminal.

Dit is op zichzelf al een data science-product. Je kunt hiermee een keten in Monte Carlo runnen, je ziet de kans dat er een lange wachtrij ontstaat, restaurants kunnen deze ‘digitale tweeling’ van hun restaurant gebruiken en zien wanneer er kritieke situaties kunnen ontstaan. Nu we een werkend product hebben, kunnen we het mooier en krachtiger maken met behulp van kunstmatige intelligentie (AI).
3. Implementatie van agentrestaurants
Zoals u hierboven kunt zien, kunnen klanten al vragen stellen en hebben wij het antwoord in de vorm van een getal. De klant kiest ook willekeurig een gerecht uit ons systeem. Laten we nu proberen agenten aan dit systeem toe te voegen. Het activeren van een restaurantagentsysteem is een geavanceerde stap in het automatiseren van klantenservice en het verbeteren van de gebruikerservaring. Getrainde agenten kunnen efficiënt antwoord geven op de vragen van klanten en gepersonaliseerde aanbevelingen doen.
3.1 Implementatie van toegewijde agenten
U moet de module ‘Agenten’ installeren:
Hieronder ziet u de implementatie van de functies klantenservicemedewerker, entertainmentmedewerker en klachtenbehandelaar.
# custom_agents.py import os, json van openai import OpenAI van agents import Agent van newtools import * client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"), default_headers={"OpenAI-Beta":"assistants=v2"}) menu_agent = Agent(name = "Chef_suggester", instructions = "Je bent een behulpzame ober die alles weet over ons restaurant en klanten helpt bij het kiezen van hun eten. Je begint met jezelf beleefd voor te stellen als virtuele assistent voor eten en de klant beleefd te begroeten. De naam van de klant is te vinden in het msg json-bestand. Je leest het menu voor en, op basis van wat de klant je vraagt, in de request key van het json-bestand. Als de klant je ongepaste vragen stelt, voer je gewoon 'unsuccessfull' in de json-indeling '{food:' in. , status: }'", tools = [get_menu]) entertainer_agent = Agent(name = "Entertainer", instructions = ("U bent een behulpzame ober die de klanten bezig houdt terwijl ze wachten." "U kunt geen korting of aanbieding geven, maar ze kunnen vragen stellen over het menu, die u kunt krijgen via de" "get_menu-functies. Ze kunnen u ook vragen hoe lang de rij gaat zijn om binnen te komen. Hun informatie staat in de waiting_time" "Als de user_status 'queue' is, geef dan gewoon de tijd met vriendelijkheid, gebaseerd op de wachttijd. Anders, " "als de user_status 'food' is, betekent dit dat ze wachten op eten. Vink 'order' aan en geef een grappige verwijzing naar" "hun wachttijd. Bijvoorbeeld: 'uw wachttijd voor pasta is 1 minuten, het lijkt alsof de kok er saus op doet!'", tools = [get_menu]) customer_agent = Agent(name = "Klant", instructions = ("U bent een klant en u eet in een Italiaans restaurant. Bekijk het menu met de get_menu-functie. Als u al Weet u wat u wilt? Vertel het dan gewoon aan de ober. "Anders kunt u ze een algemene indicatie geven of om begeleiding vragen op basis van uw algemene voorkeuren, en zij zullen het beste voor u kiezen."), 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, '')
We hebben de clientdefinitie , oftewel de OpenAI-clientaanroep, newtools.py , dat de lijst ophaalt, en call_agent , dat de individuele agent aanroept en uitvoert via een runner . Deze componenten zijn essentieel voor het creëren van een effectief agentsysteem.
Dit is precies wat we in de inleiding hebben besproken. We definiëren verschillende agents die met elkaar verbonden moeten worden, en zij gebruiken tools die in mijn code zijn gespecificeerd. Deze tools en agents maken de automatisering van klantenservicetaken en een verbeterde gebruikerservaring mogelijk.
van agenten import function_tool van constanten import * import pandas als pd @function_tool def get_menu(): df = pd.read_csv(MENU_FILE) # converteren naar lijst met dicts (of JSON-serialiseerbare structuur) return df.to_dict(orient="records")
3.2 Implementatie van toegewijde agenten
De implementatie van Table en Restaurant, inclusief de agents, is geïntegreerd in de volgende code:
importeer willekeurig importeer tijd importeer wiskunde importeer sys van utils importeer * van constanten importeer * importeer tijd, willekeurig, json van custom_agents importeer * van utils importeer * van constanten importeer * van agents importeer Runner # lijst met voornamen van uw NAMES constante # neem aan dat NAMES = [ ... ] 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] ➡️ Geschatte wachttijd voor klant {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"Onze LLM heeft {cname} hiermee afgehandeld: {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 voor t in self.tables als t.cust_id == cid) food = table.plate cname = self.names[cid] msg = f"[{self.clock:04}m] ❓ Klant {cid}: Hoe lang duurt het voordat ik het eten krijg?
print(msg) self.log_to_msg(msg) als wait None is: msg = f"[{self.clock:04}m] ➡️ Nu klaar!"
print(msg) self.log_to_msg(msg) anders: msg = f"[{self.clock:04}m] ➡️ Geschatte wachttijd voor klant {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"Onze LLM heeft {cname} hiermee afgehandeld: {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() als self.query_prob en 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() vrij = som(t.is_vrij voor t in self.tables) msg = f"n--- EINDE VAN DE SHIFT ---n{vrij}/{len(self.tables)} tabellen vrij om {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 Implementatie van een grafische gebruikersinterface (GUI) voor een restaurant met behulp van een groot taalmodel (LLM)
Om de prestaties van het restaurant weer te geven met een LLM-applicatie (Large Language Model) gebruiken we een eenvoudige grafische gebruikersinterface (GUI).
van llm_models_gui import RestaurantGUI van utils import * import random van llm_models import Restaurant als __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, # smoother voor GUI query_prob=0.8, menu=menu ) app = RestaurantGUI(R)

De grafische gebruikersinterface (GUI) geeft u informatie over de persoon (Emma), de tabel, de tijd en de uitvoer van het grote taalmodel (LLM). Er wordt ook automatisch een .txt-record aangemaakt.
Ik wil u graag een voorbeeld van de uitvoer laten zien:
[12:31:23] Klant Emma spreekt met de ober en zegt: "Ik wil graag beginnen met de bruschetta als voorgerecht. Daarna bestel ik spaghetti carbonara als eerste gang. Als dessert neem ik tiramisu. Kunt u ook een wijn aanbevelen die goed bij deze maaltijd past?" [12:31:25] Het verwerkte antwoord van onze masterstudent is: {'food': ['Bruschetta', 'Spaghetti Carbonara', 'Tiramisu', 'Chianti Classico'], 'status': 'successful'} [12:31:25] [0000m] ❓ Klant 1: Hoe lang duurt het om het eten klaar te maken? [12:31:25] [00:00] ➡️ Verwachte wachttijd voor eten per klant: 1:15 minuten [12:31:26] De MBA-student nam Emma's zaak over met het volgende: Laatste klant: Agent(naam=”Entertainer”, …) Eindresultaat (keten): Hallo Emma! Bedankt voor je geduld. De wachttijd om binnen te komen is ongeveer 15 minuten. Bijna klaar – net genoeg tijd voor mij om te dromen over die heerlijke bruschetta! 🍽️
Wij kunnen bieden:
- De klant stelt via de agent zijn eigen menu samen.en vraagt om een aanbeveling van de agent van de ober.
- De ober raadt een Chianti-wijn aan en zet deze op de kaart.
- De klachtenbehandelaar informeert de klant over de wachttijd.
Nu kunnen we niet alleen de workflow simuleren, zoals we voorheen deden, maar we hebben een intelligente workflow , verbeterd door dezelfde ChatGPT-technologie. Is dat niet geweldig?
4. Conclusie
Hartelijk dank dat je gekomen bent, het betekent veel voor mij ❤️.
Laten we eens teruggaan en kijken wat we in dit artikel hebben gedaan.
- Ontwerp van restaurantsystemen:
We hebben een snel ontwerp gemaakt voor een restaurantsysteem met behulp van PowerPoint en de toevoeging van AI-agents. - Agent-vrije basis:
Eerst bouwden we een deterministische simulatie, zodat we de logica voor de wachtrij, kooktijden en tafelrotatie konden coderen. Dit is ons skelet voordat we met AI aan de slag gaan. - Restaurant met agentschap:
In deze fase hebben we AI-agenten ingezet om onze klacht- en actiedossiers te vullen met agenten. We hebben ook een grafische gebruikersinterface gemaakt om de resultaten duidelijk weer te geven.
Nu wil ik op dit punt heel duidelijk zijn. Ik weet dat dit een beetje klinkt als een Black Mirror-scenario. Klantensimulatie? Restaurant- en obersimulatie? Ja, het is vreemd, maar het probleem zit hem nooit in de AI-tool zelf, maar altijd in hoe deze wordt gebruikt. Ik denk dat het vervangen van menselijke obers door AI een verloren zaak is.
Werken als ober betekent niet alleen dat je bestellingen opneemt en wijnnummer N aanbeveelt op basis van de N-1 wijnen die eerder zijn besteld. Het gaat erom dat je warm genoeg bent om een gast zich welkom te laten voelen, maar ook afstandelijk genoeg om zijn of haar gesprek niet te verstoren. Zacht genoeg om ze zich thuis te laten voelen, maar sterk genoeg om ervoor te zorgen dat ze jouw grenzen respecteren. Het is een combinatie van eigenschappen waarvoor volgens mij een menselijke aanpak, geduld en empathie nodig zijn.
Ik geloof echter dat het juiste gebruik van deze technologie tweeledig is:
- Echte mensen helpen die op de wachtlijst staan. De obers binnen zijn erg druk en in restaurants kun je al een menukaart bekijken terwijl je wacht op je tafel. Het is dan ook niet realistisch om te denken dat andere obers mensen vermaken die zonder tafel in de rij staan te wachten. Op dit punt kan het handig zijn om een AI-partner te hebben waarmee je kunt chatten.
- Restaurant simulatie. Het scenario dat ik schreef simuleert Gedrag Klanten Ook. Dit betekent dat u simulaties potentieel kunt gebruiken om verschillende scenario's te testen, te zien wanneer er wachtrijen ontstaan, verschillende reacties van mensen te veronderstellen, verschillende antwoorden van obers te verwachten, enz. Met andere woorden, dit kan uw 'digitale tweeling' zijn waarop u tests uitvoert.
Reacties zijn gesloten.