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.
OpenAI heeft vorige week een bestand gepubliceerd PDFEn 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 u 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. Grote taalmodelagenten (LLM-agenten) “Het zijn systemen die zelfstandig taken voor u uitvoeren.”
Zijn dit dan niet gewoon eenvoudige aanroepen van grote taalmodellen (LLM's) via een API? Nou ja, ja en nee. Je gebruikt hetzelfde/dezelfde formulier(en) voor het voltooien van een gesprek, dus het is zoiets als: Maar Het is de bedoeling om een specifieke actie te creëren. Wat ik daarmee bedoel is dat de output van uw agenten Het moet vertaald worden in een uitvoerbaar resultaat. In jouw systeem. Als uw LLM-uitvoer bijvoorbeeld 'spaghetti' bevat, wordt 'spaghetti' toegevoegd aan uw gegevenspad. Uiteindelijk zal iemand dit zien en spaghetti koken (waarschuwing).
2. Grote taalmodelagenten (LLM-agenten) zijn specifiek geïntegreerd met Functies (Hulpmiddelen)
Ik heb het hier over een scenario waarin je ChatGPT een vraag stelt, en ChatGPT zijn eigen afbeeldingengenerator/webzoeker/codefragment aanroept. Intern wordt er een functie gebruikt die widget heet, die wordt geactiveerd door uw prompt. Nu is de beeldgenerator een ingebouwde functie, maar ze kunnen ook Jouw taak (jouw gereedschap), die u specifiek voor uw taak kunt opgeven. Het feit dat LLM-agenten externe hulpmiddelen en functionaliteiten kunnen integreren, geeft hen een grote flexibiliteit en kracht bij het uitvoeren van uiteenlopende taken.
3. Meerdere grote taalmodelagenten (LLM-agenten) kunnen worden geïntegreerd. Opeenvolgend
U kunt één enkele agent integreren en deze voorzien van meerdere tools. أو Verdeel de tools in gespecialiseerde agenten. Dat is precies wat we in dit artikel gaan doen (nog een tip!).
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 in de praktijk te laten zien. Laten we zeggen dat we het hebben over restaurant, Bijvoorbeeld.
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 implementeren Het restaurant, en we moeten creëren Wachtlijstmethodewaar mensen zitten op basis van hoe druk het restaurant is, en we moeten een ruimte creëren voedsel menusimulatie Wachttijden zorg ervoor dat alles werkt, Vervolgens Pas dan Wij kunnen agenten in contact brengen. 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 nu over nadenkt, ben je dat niet behoefte voor dit doel naar een groot taalmodel (LLM). We kunnen bijvoorbeeld de wachttijd vooraf berekenen en deze vervolgens koppelen aan een vooraf gedefinieerde, geformatteerde tekenreeks. We kunnen ook een eenvoudig menu gebruiken om bestellingen op te halen (zoals de geautomatiseerde kiosk van McDonald's) en klaar. Jazeker, dat kan, maar denk er eens over na.
Wat als de klant informatie wil opvragen over het menu? terwijl ik wacht? En wat nu als dat wel zo was? Aarzelend Over eten? Wat als ze het wilden weten? De lekkerste vegetarische optie Op het menu? En wat als ze dat zouden willen? Goede wijn voor een redelijke prijs? We kunnen voor elk van deze scenario's regelgebaseerde methoden gaan definiëren (wat tijd- en geldverspilling is) of we kunnen kunstmatige intelligentie gaan gebruiken. Daarover gaat dit artikel. Als we grote taalmodelagenten (LLM-agenten) gebruiken, kunnen we al deze scenario's in één keer afhandelen.
Als ik één ding heb geleerd, is het wel dat softwareontwikkeling een vak is. Stap voor stap. Je kunt maar beter skelet Voeg vervolgens decoraties en accessoires toe aan uw model. Om deze reden zullen we een agent-vrije versie van bovenstaand product bouwen. Deze vereenvoudigde versie beschikt over een wachtrijsysteem dat de wachttijden berekent en het menu uitvoert, zodat alles soepel verloopt zonder dat er AI aan te pas komt. Na deze stap kunnen we de agenten op de plekken plaatsen die we hierboven hebben besproken en getoond (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.
Nu wordt deze hele implementatie in een bestand uitgevoerd. naive_modellen.py, bestaande hier.
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 hele script draait op naive_sim met behulp van de opdracht .loop() 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 een definitie Cliënt, wat de klantoproep van OpenAI is, en newtools.py, die de lijst oproept, en call_agent die de individuele agent belt en deze bedient via loper. Deze componenten zijn essentieel voor het creëren van een effectief agentensysteem.
Dit is precies wat we in de inleiding bespraken. We identificeren verschillende Agenten Ze zullen verbonden zijn en ze gebruiken Hulpmiddelen Gedefinieerd door mijn code. Met deze hulpmiddelen en agents kunt u klantenservicetaken automatiseren en de gebruikerservaring verbeteren.
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 is geïntegreerd tafel و Restaurant Met agenten 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 de ober aan en zegt: "Ik wil graag beginnen met de bruschetta als voorgerecht. Daarna bestel ik de spaghetti carbonara als voorgerecht. Als dessert neem ik de tiramisu. Kunt u ook een bijpassende wijn aanbevelen?" [12:31:25] Het verwerkte antwoord van onze masterstudent is: {'eten': ['Bruschetta', 'Spaghetti Carbonara', 'Tiramisu', 'Chianti Classico'], 'status': 'succesvol'} [12:31:25] [0000M] ❓ Klant 1: Hoe lang duurt het om het eten te bereiden? [12:31:25] [0000M] ➡️ Verwachte wachttijd voor eten van klant 1:15 minuten [12:31:26] De LLM-student zorgde voor Emma's bestelling: Laatste klant: Agent(name=”Entertainer”, …) Eindresultaat (tekenreeks): Hoi Emma! Bedankt voor uw geduld. De wachttijd voor binnenkomst bedraagt ongeveer 15 minuten. We zijn er bijna: net genoeg tijd om te dromen van 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 zomaar een workflow simuleren, zoals we eerder deden; we hebben nu een workflow. Slim, aangedreven 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.
Ik wil op dit punt heel duidelijk zijn. Ik weet dat dit een beetje op Black Mirror lijkt. Klantensimulatie? Restaurant- en obersimulatie? Ja, het is raar, Maar Het probleem is nooit de AI-tool, maar altijd de manier waarop deze gebruikt wordt. 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.