Symulacja restauracji wieloagentowej z wykorzystaniem dużych modeli językowych (LLM) w praktyce, z Pythonem i OpenAI
Oto w jaki sposób wykorzystałem agentów dużego modelu językowego do symulacji kompleksowego działania restauracji za pomocą Pythona.
W zeszłym tygodniu OpenAI opublikowało plik PDF , o którym wszyscy mówią. Ten 34-stronicowy przewodnik wyjaśnia, czym są agenci LLM (Large Language Model Agents) i jak ich używać.
Plik PDF jest stosunkowo krótki i łatwy do odczytania (nie musisz być inżynierem oprogramowania ani mentorem, żeby go zrozumieć), ale w kilku słowach wyjaśnia trzy rzeczy:

1. Agenci dużego modelu językowego (agenci LLM) „to systemy, które niezależnie wykonują zadania w Twoim imieniu”.
Czy to nie są po prostu proste monity Big Language Model (LLM) wywoływane przez API? Cóż, i tak, i nie. Używasz tych samych modeli uzupełniania konwersacji, więc to trochę tak, ale chodzi o stworzenie konkretnej akcji. Mam na myśli to, że dane wyjściowe proxy muszą zostać przetłumaczone na dane wyjściowe wykonywalne w systemie. Na przykład, jeśli dane wyjściowe LLM zawierają słowo „spaghetti”, to „spaghetti” zostanie dodane do ścieżki danych i w końcu ktoś je zobaczy i ugotuje spaghetti (alert).
2. Agenci Dużego Modelu Językowego (LLM) są szczególnie zintegrowani z funkcjami (narzędziami).
Mam tu na myśli scenariusz, w którym zadajesz pytanie ChatGPT, a on wywołuje swój generator obrazów/wyszukiwarkę stron/fragment kodu. Wewnętrznie używa funkcji zwanej widgetem, która jest uruchamiana przez monit. Generator obrazów jest funkcją wbudowaną, ale może również wywołać własny widget , który możesz określić dla swojego zadania. Ta możliwość integracji zewnętrznych widgetów i funkcji zapewnia agentom LLM (Large Language Model Agents) tak dużą elastyczność i moc w wykonywaniu szerokiej gamy zadań.
3. Wiele agentów dużego modelu językowego (agentów LLM) można łączyć sekwencyjnie.
Możesz połączyć pojedynczego agenta i wyposażyć go w wiele narzędzi lub podzielić narzędzia na wyspecjalizowanych agentów, co zrobimy w tym artykule (kolejna wskazówka!).
Szczegóły techniczne mogą zainteresować inżynierów oprogramowania, ale dlaczego temat agentów jest tak ważny dla wszystkich innych?
Ponieważ stanowi to zmianę paradygmatu, która pomaga wnieść wartość do modeli otwartej sztucznej inteligencji. Pomyśl o tym: duże modele językowe (LLM) zapewniają teraz Wyniki możliwe do podjęcia. Nie chodzi więc o wykorzystanie podpowiedzi LLM na ostatnim etapie przepływu pracy w celu poprawy końcowego wyniku, ale o Integracja całego przepływu pracy z agentami dużego modelu językowego (agentami LLM) Aby poprawić jakość całego przepływu pracy.
Chociaż próbuję to wyjaśnić słowami, myślę, że łatwiej będzie zilustrować to w praktyce. Załóżmy na przykład , że mówimy o restauracji .
Typowa restauracja ma bardzo naturalny i prosty schemat działania: czekasz w kolejce, zamawiasz jedzenie, czekasz na nie, jesz i wychodzisz. Jeśli przełożymy to na podejście „agenta”, możemy zidentyfikować co najmniej trzech agentów:
- agent Klient To agent o dużym modelu językowym (LLM), który zamawia jedzenie lub prosi kelnera o sugestie.
- agent kelner Jest to duży model językowy (LLM), który zbiera prośby i w razie potrzeby zgłasza sugestie.
- agent Zabawa Jest to duży model językowy (LLM) mający na celu obsługę skarg klientów.
OpenAI dokładnie wyjaśnia, jak tworzyć te byty, ale to stosunkowo łatwa część; jest w tym o wiele więcej, prawda?
Musimy wdrożyć restaurację , stworzyć system kolejkowy, w którym ludzie będą siadać w zależności od liczby gości w restauracji, stworzyć menu , symulować czas oczekiwania i upewnić się, że wszystko działa. Dopiero wtedy możemy połączyć agentów. Jak zawsze:
Sztuczna inteligencja generatywna jest potężna, ale tylko wtedy, gdy jest używana w odpowiednim kontekście.
Zanim przejdziemy do ekscytującej części o agentach, w tym artykule dowiesz się:
- Projektowanie systemów Dla agenta restauracyjnego z tytułem LLM. Pomysł bez kodu, tylko szkic projektu na papierze (a raczej na myszce i w programie PowerPoint).
- Wdrożenie restauracji bez agentów. Proste i przejrzyste, wystarczy stworzyć podstawową strukturę kodu.
- Wdrożenie Agent Restaurant. A także prosty graficzny interfejs użytkownika, który dobrze to prezentuje.
- Uwagi i spostrzeżenia końcowe.
Wygląda na to, że mamy dużo do omówienia. Czas na laboratorium! 🧪
1. Projektowanie systemu restauracyjnego: poradnik eksperta
Uwaga: Jeśli zapoznałeś się z kilkoma technicznymi przewodnikami, projekt tego systemu okaże się dość prosty. Celem tego projektu nie jest kompleksowe zaprezentowanie każdej części systemu uczenia maszynowego (jak można by się spodziewać po 15-minutowej rozmowie 🙃), ale raczej udzielenie wskazówek, co robić dalej.
Sposób wizualizacji procesu restauracyjnego, zintegrowanego z dużym modelem językowym (LLM), przedstawiono na poniższym rysunku:

Pozwól, że wyjaśnię:
- Restauracja() و Menu() Są to dwie klasy. Definiujemy je, a wszystkie tabele, zamówienia i informacje systemowe w obrębie klas będą definiowane i aktualizowane dynamicznie.
- będzie musiał Nowy klient Przechodzimy przez mechanizm do obsługi miejsc siedzących. Jeśli mogą usiąść (wystarczająco dużo wolnych stolików), to świetnie, możemy im pozwolić usiąść; w przeciwnym razie klient będzie stał w kolejce.
- Dla klienta PosiedzenieBędzie tam kelner, który umożliwi im zamówienie jedzenia. Będą mogli „złożyć skargę” i zapytać, ile czasu zajmie dostarczenie jedzenia po złożeniu zamówienia.
- Ludzie nie mogą czekanie w kolejce Robią wiele, ale mogą też „poskarżyć się” i zapytać, jak długo będą musieli czekać w kolejce, zanim będą mogli usiąść.
Jeśli się nad tym zastanowić, nie potrzebujemy do tego dużego modelu języka (LLM). Na przykład moglibyśmy z góry obliczyć czas oczekiwania, a następnie połączyć go z predefiniowanym, ustrukturyzowanym ciągiem znaków. Moglibyśmy również użyć prostej listy zamówień (jak w automatycznym kiosku McDonald's) i mieć to z głowy. Oczywiście, moglibyśmy to zrobić, ale pomyślmy o tym.
Co jeśli klient będzie chciał zapytać o menu w trakcie oczekiwania ? Co jeśli nie będzie zdecydowany co do jedzenia? Co jeśli będzie chciał poznać najlepszą opcję wegetariańską w menu? Co jeśli będzie chciał dobrego wina w rozsądnej cenie ? Możemy albo zacząć definiować metody oparte na regułach dla każdego z tych scenariuszy, marnując czas i pieniądze, albo skorzystać ze sztucznej inteligencji. O tym właśnie jest ten artykuł. Jeśli użyjemy agentów LLM (Large Language Model Agents), będziemy mogli obsłużyć wszystkie te scenariusze za jednym razem.
Jeśli czegoś się nauczyłeś, to tego, że inżynieria oprogramowania powinna być realizowana krok po kroku . Najlepiej jest mieć podstawową strukturę modelu, a następnie dodawać ostatnie szlify i ulepszenia. Z tego powodu zbudujemy wersję produktu bez agentów. Ta uproszczona wersja będzie miała system kolejkowania, który oblicza czas oczekiwania i uruchamia menu, dzięki czemu wszystko będzie działać płynnie bez sztucznej inteligencji. Po tym kroku możemy umieścić agentów na stanowiskach, które omówiliśmy i zademonstrowaliśmy powyżej (klient, host i kelner).
2. Implementacja bez agenta
Zawsze najlepiej jest zachować wszystko tak proste, jak to możliwe w skrypcie głównym, pozostawiając złożone operacje w tle. Nasza implementacja bez agentów może zostać uruchomiona w tym kodzie.
import random import time import math import sys z utils import * z constants import * z naive_models import * jeśli __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)
Jak widać możemy zmienić:
- liczba_tabelLiczba stolików w naszej restauracji.
- prawdopodobieństwo_przybycia; jest prawdopodobieństwem przybycia klienta w każdym kroku czasowym.
- kleszcz; jest krokiem czasowym naszej symulacji.
- pauza; Implementuje funkcję time.sleep(), która służy do symulowania przepływu pracy w prawdziwej restauracji.
Cała ta implementacja znajduje się w pliku naive_models.py , znajdującym się tutaj.
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)
To już trochę za długo, ale pozwól, że przedstawię Ci kilka kroków.
Cały skrypt uruchamia się w naive_sim za pomocą polecenia .run() z następującymi funkcjami:
- przybyć, która przedstawia przybycie i prośbę klientów lub ich przybycie i ustawienie się w kolejce.
- proces_gotowania, która symuluje gotowanie na każdym stole.
- odejścia_procesu, który symuluje odejście klienta.
- miejsce_z_kolejki, która symuluje klientów siedzących w kolejce.
- obsługuj_losowe_zapytanie, która jest wywoływana losowo, gdzie klient stojący w kolejce lub czekający na jedzenie może zapytać o czas oczekiwania.
Jeśli uruchomimy naive_sim.py, otrzymamy ten kod z terminala.

To produkt z zakresu data science sam w sobie. Można nim zarządzać siecią restauracji Monte Carlo i dostrzegać potencjał długiej kolejki. Restauracje mogą korzystać z tego „cyfrowego bliźniaka” swojej restauracji i sprawdzać, kiedy mogą się wydarzyć krytyczne rzeczy. Skoro mamy już działający produkt, możemy go jeszcze bardziej upiększyć i udoskonalić, wykorzystując sztuczną inteligencję (AI).
3. Wdrożenie Agent Restaurant
Jak widać powyżej, klienci mogą już zadawać pytania, a my mamy odpowiedź w postaci liczby. Klient losowo wybiera również pozycję z menu. Spróbujmy teraz dodać agentów do tego systemu. Wdrożenie systemu agentów restauracyjnych to zaawansowany krok w automatyzacji obsługi klienta i poprawie doświadczenia użytkownika, ponieważ przeszkoleni agenci mogą sprawnie odpowiadać na pytania klientów i udzielać spersonalizowanych rekomendacji.
3.1 Implementacja dedykowanych agentów
Będziesz musiał zainstalować moduł „Agenci”:
Poniżej przedstawiono implementację agenta obsługi klienta, agenta rozrywki i osoby zajmującej się reklamacjami.
# custom_agents.py import os, json from openai import OpenAI from agents import Agent from newtools import * client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"), default_headers={"OpenAI-Beta":"assistants=v2"}) menu_agent = Agent(name = "Chef_suggester", instructions = "Jesteś pomocnym kelnerem, który wie wszystko o naszej restauracji i pomaga klientom w wyborze jedzenia. Na początek uprzejmie" "przedstawisz się jako wirtualny asystent kelnera i uprzejmie przywitasz się z klientem. Imię klienta można znaleźć w pliku json wiadomości" "Przeczytasz menu i, na podstawie pytania klienta, w kluczu żądania pliku json, przedstawisz najlepszą rekomendację z menu." "Jeśli klient zadaje Ci niewłaściwe pytania, po prostu wyświetl format json 'unsuccessfull' '{żywność: , stan: }'", tools = [get_menu]) entertainer_agent = Agent(name = "Artysta", instructions = ("Jesteś pomocnym kelnerem, który zajmuje klientów podczas oczekiwania." "Nie możesz udzielić żadnych rabatów ani ofert, ale mogą oni zadawać pytania dotyczące menu, które możesz uzyskać za pomocą funkcji get_menu. Mogą również zapytać Cię, jak długa będzie kolejka. Informacje na ten temat znajdują się w wait_time" "Jeśli user_status to 'queue', po prostu podaj czas z uprzejmością, w oparciu o długość oczekiwania. W przeciwnym razie, " "jeśli user_status to 'food', oznacza to, że czekają na jedzenie. Sprawdź 'order' i podaj zabawny odnośnik do ich czasu oczekiwania. Na przykład 'Twój czas oczekiwania na makaron wynosi 5 minut, wygląda na to, że kucharz dodaje do niego sos!'", tools = [get_menu]) customer_agent = Agent(name = "Customer", instructions = ("Jesteś klientem i jesz w włoskiej restauracji Restauracja. Spójrz na menu za pomocą funkcji get_menu. Jeśli wiesz już, czego chcesz, po prostu powiedz kelnerowi, czego chcesz. " "W przeciwnym razie daj im ogólne wskazówki lub poproś o wskazówki oparte na Twoich ogólnych upodobaniach, a oni wybiorą dla Ciebie najlepsze. "), 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, '')
Mamy definicję klienta , czyli wywołanie klienta OpenAI, plik newtools.py , który pobiera listę, oraz call_agent , który wywołuje i uruchamia pojedynczego agenta za pośrednictwem modułu uruchamiającego . Te komponenty są niezbędne do stworzenia efektywnego systemu agentów.
Dokładnie o tym mówiliśmy we wstępie. Definiujemy kilku agentów , którzy mają być połączeni, a oni korzystają z narzędzi określonych w moim kodzie. Te narzędzia i agenci pozwalają na automatyzację zadań związanych z obsługą klienta i poprawę doświadczenia użytkownika.
z agentów import function_tool ze stałych import * import pandas as pd @function_tool def get_menu(): df = pd.read_csv(MENU_FILE) # konwertuj na listę słowników (lub strukturę serializowalną w formacie JSON) return df.to_dict(orient="records")
3.2 Implementacja dedykowanych agentów
Implementacja Table i Restaurant, wraz z agentami, jest zintegrowana w następującym kodzie:
import random import time import math import sys from utils import * from constants import * import time, random, json from custom_agents import * from utils import * from constants import * from agents import Runner # lista imion z twojej stałej NAMES # załóż 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] ➡️ Szacowany czas oczekiwania klienta {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"Nasz LLM zajął się {cname} w ten sposób: {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] ❓ Klient {cid}: Jak długo zajmie mi otrzymanie jedzenia?”
print(msg) self.log_to_msg(msg) jeśli wait jest None: msg = f"[{self.clock:04}m] ➡️ Gotowe!"
print(msg) self.log_to_msg(msg) else: msg = f"[{self.clock:04}m] ➡️ Szacowany czas oczekiwania klienta na jedzenie {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"Nasz LLM zajął się {cname} w ten sposób: {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--- KONIEC PRZESUNIĘCIA ---n{free}/{len(self.tables)} tabele są wolne o {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 Implementacja graficznego interfejsu użytkownika (GUI) dla restauracji przy użyciu modelu dużego języka (LLM)
Aby przedstawić wydajność restauracji za pomocą aplikacji wykorzystującej duży model językowy (LLM), użyjemy prostego graficznego interfejsu użytkownika (GUI).
z llm_models_gui import RestaurantGUI z importu utils * import random z llm_models import Restaurant jeśli __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, # wygładzanie dla GUI query_prob=0.8, menu=menu ) app = RestaurantGUI(R)

Graficzny interfejs użytkownika (GUI) udostępnia informacje o osobie (Emma), tabeli, czasie oraz wynikach dużego modelu językowego (LLM). Rekord .txt jest również generowany automatycznie.
Pokażę Ci przykład wyniku:
[12:31:23] Klientka Emma rozmawia z kelnerem i mówi: „Chciałabym zacząć od bruschetty jako przystawki. Następnie zamówię spaghetti carbonara jako pierwsze danie. Na deser poproszę tiramisu. Czy mógłby Pan również zasugerować wino do tego posiłku?” [ 12:31:25] Przetworzona odpowiedź studenta naszego mistrza brzmi: {'jedzenie': ['Bruschetta', 'Spaghetti Carbonara', 'Tiramisu', 'Chianti Classico'], 'status': 'pomyślnie'} [12:31:25] [0000m] ❓ Klient 1: Ile czasu zajmie mi przygotowanie jedzenia? [12:31:25] [00:00] ➡️ Przewidywany czas oczekiwania na jedzenie dla każdego klienta: 1:15 minuty [12:31:26] Studentka MBA przejęła sprawę Emmy i przedstawiła ją w następujący sposób: Ostatni klient: Agent(name=”Entertainer”, …) Ostateczny wynik (sieć): Witaj Emmo! Dziękuję za cierpliwość. Czas oczekiwania na wejście wynosi około 15 minut. Już prawie koniec – akurat tyle, żebym zaczęła marzyć o tej pysznej bruschetcie! 🍽️
Możemy zaoferować:
- Klient za pośrednictwem agenta tworzy własne menu.i prosi o rekomendację agenta kelnera.
- Kelner poleca wino Chianti i dodaje je do listy.
- Pracownik rozpatrujący reklamacje informuje klienta o okresie oczekiwania.
Teraz możemy nie tylko symulować przepływ pracy, jak robiliśmy to wcześniej, ale mamy inteligentny przepływ pracy , wzbogacony o tę samą technologię ChatGPT. Czyż to nie niesamowite?
4. Wniosek
Dziękuję bardzo za przybycie, to dla mnie wiele znaczy ❤️.
Wróćmy i zobaczmy, co zrobiliśmy w tym artykule.
- Projekt systemu restauracyjnego:
Szybko stworzyliśmy projekt systemu restauracyjnego, korzystając z programu PowerPoint i dodając agentów AI. - Podstawa bez agenta:
Najpierw zbudowaliśmy symulację deterministyczną, aby móc zakodować logikę kolejki, czasu gotowania i rotacji stołów. To był nasz szkielet, zanim wdrożyliśmy jakąkolwiek sztuczną inteligencję. - Restauracja oparta na agencie:
Na tym etapie użyliśmy agentów AI do wypełnienia formularza skargi i zgłoszenia. Stworzyliśmy również graficzny interfejs użytkownika, aby przejrzyście wyświetlać wyniki.
W tym momencie chcę być bardzo jasny. Wiem, że brzmi to trochę jak czarne lustro. Symulacja obsługi klienta? Symulacja obsługi restauracji i kelnera? Tak, to dziwne, ale problem nigdy nie leży w samym narzędziu AI, a zawsze w sposobie jego wykorzystania. Myślę, że zastąpienie kelnerów sztuczną inteligencją to przegrana sprawa.
Bycie kelnerem to nie tylko przyjmowanie zamówień i rekomendowanie wina numer N na podstawie wcześniej zamówionych win numer 1. Chodzi o to, by być wystarczająco ciepłym, by gość poczuł się mile widziany, ale jednocześnie wystarczająco zdystansowanym, by nie wtrącać się w jego rozmowę, wystarczająco delikatnym, by gość poczuł się jak w domu, ale jednocześnie wystarczająco silnym, by uszanować twoje granice. To połączenie cech, które moim zdaniem wymaga ludzkiego podejścia, cierpliwości i empatii.
Uważam jednak, że właściwe wykorzystanie tej technologii może mieć dwojaki charakter:
- Pomaganie prawdziwym ludziom, którzy są na liście oczekujących. Kelnerzy w środku są niezwykle zajęci, a restauracje oferują już menu do przejrzenia w oczekiwaniu na stolik. Trudno uwierzyć, że inni kelnerzy zabawiają osoby czekające bez stolika. W tym momencie pomocny może okazać się towarzysz AI, z którym można porozmawiać.
- Symulacja restauracjiScenariusz, który napisałem, symuluje Zachowanie klienci Oznacza to również, że możesz potencjalnie wykorzystać symulację do testowania różnych scenariuszy, sprawdzania, kiedy tworzą się kolejki, zakładania różnych reakcji ludzi, różnych reakcji kelnerów itd. Innymi słowy, może ona stać się Twoim własnym „cyfrowym bliźniakiem”, w którym będziesz przeprowadzać testy.
Możliwość dodawania komentarzy nie jest dostępna.