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 PDFI wszyscy o tym mówią. Ten dokument to 34-stronicowy przewodnik wyjaśniający, czym są agenci modelu dużego języka (ang. Large Language Model Agents, LLM) i jak z nich korzystać.

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) „Są to systemy, które samodzielnie wykonują zadania w Twoim imieniu.”

Czy to nie są po prostu proste komunikaty LLM (Large Language Model) wywoływane przez API? Cóż, i tak, i nie. Używasz tego samego modelu (modeli) uzupełniania konwersacji, więc w pewnym sensie tak. Ale Ma to na celu stworzenie konkretnej akcji. Mam na myśli to, że dane wyjściowe Twoich agentów Musi zostać przełożone na wynik możliwy do podjęcia działań. W Twoim systemie. Na przykład, jeśli wynik Twojego modelu języka dużego (LLM) to „spaghetti”, „spaghetti” zostanie dodane do ścieżki danych i w końcu ktoś to zobaczy i ugotuje spaghetti (alert).

2. Agenci dużego modelu językowego (agenci LLM) są specjalnie zintegrowani z Funkcje (Narzędzia)

Mówię o scenariuszu, w którym zadajesz pytanie ChatGPT, a on wywołuje swój generator obrazów/wyszukiwarkę internetową/fragment kodu. Wewnętrznie używa funkcji zwanej narzędziem, która jest uruchamiana przez monit. Generator obrazów jest funkcją wbudowaną, ale może również wywołać… Twoja praca (Twoje narzędzie), które można dostosować specjalnie do swojego zadania. Ta możliwość integracji zewnętrznych narzędzi i funkcjonalności zapewnia agentom LLM dużą elastyczność i moc w realizacji różnorodnych zadań.

 

3. Możliwa jest integracja wielu agentów dużego modelu językowego (agentów LLM). Kolejny

Można zintegrować pojedynczego agenta i zapewnić mu wiele narzędzi. أو Podziel narzędzia na wyspecjalizowanych agentów, co właśnie 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 pokazać to w praktyce. Załóżmy, że mówimy o restauracja, Na przykład.

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ć Zachód słońcai musimy stworzyć Metoda listy oczekujących, gdzie ludzie siedzą w zależności od tego, jak zatłoczona jest restauracja, i musimy stworzyć menu, symulacja Czas oczekiwaniai upewnij się, że wszystko działa, Następnie 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ę:

  1. 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).
  2. Wdrożenie restauracji bez agentów. Proste i przejrzyste, wystarczy stworzyć podstawową strukturę kodu.
  3. Wdrożenie Agent Restaurant. A także prosty graficzny interfejs użytkownika, który dobrze to prezentuje.
  4. 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ąść.

Teraz, jeśli się nad tym zastanowisz, nie jesteś potrzebować Potrzebujemy do tego celu dużego modelu języka (LLM). Moglibyśmy na przykład obliczyć czas oczekiwania z wyprzedzeniem, a następnie połączyć go z predefiniowanym, sformatowanym ciągiem znaków. Moglibyśmy również użyć prostego menu do zbierania 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.

A co jeśli klient chce zapytać o informacje na temat menu? podczas oczekiwaniaA co jeśli tak? Niezdecydowany O jedzeniu? A co, jeśli będą chcieli wiedzieć? Najsmaczniejsza opcja wegetariańska W menu? A co, jeśli zechcą? Dobre wino w rozsądnej cenieMożemy zacząć definiować metody oparte na regułach dla każdego z tych scenariuszy, marnując czas i pieniądze, albo możemy zacząć korzystać ze sztucznej inteligencji. O tym właśnie jest ten artykuł. Jeśli użyjemy agentów dużego modelu językowego (agentów LLM), będziemy mieli szansę obsłużyć wszystkie te scenariusze za jednym razem.

Jeśli czegoś się nauczyłem, to tego, że inżynieria oprogramowania jest czymś, co trzeba robić. Krok po krokuLepiej mieć jedno. szkielet Dodaj dekoracje i akcesoria do swojego modelu. Z tego powodu stworzymy wersję produktu bez agentów. Ta uproszczona wersja będzie zawierać system kolejkowy, który oblicza czas oczekiwania i uruchamia menu, dzięki czemu wszystko będzie działać płynnie bez użycia sztucznej inteligencji. Po tym kroku możemy umieścić agentów na pozycjach, które omówiliśmy i zademonstrowaliśmy powyżej (klient, kelner 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.

Teraz cała ta implementacja odbywa się w pliku. naive_models.py, istniejący 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ę na naive_sim za pomocą polecenia .uruchomić() 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ę Klient, który jest wywołaniem klienta OpenAI i nowenarzędzia.py, który wyciąga listę i zadzwoń_do_agenta który dzwoni do indywidualnego agenta i obsługuje go za pośrednictwem biegaczKomponenty te są niezbędne do stworzenia efektywnego systemu agentowego.

To właśnie o tym mówiliśmy we wstępie. Wskazujemy kilka Agenci Będą połączone i będą korzystać Przybory Zdefiniowane przez mój kod. Te narzędzia i agenci pozwalają zautomatyzować zadania związane z obsługą klienta i poprawić 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

Wdrożenie jest zintegrowane Stół و restauracja Z agentami 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 zwraca się do kelnera: „Chciałabym zacząć od bruschetty jako przystawki. Następnie zamówię spaghetti carbonara jako pierwsze danie. Na deser poproszę tiramisu. Czy może mi Pani również polecić wino pasujące do tego dania?” [12:31:25] Przetworzona odpowiedź naszego studenta magistra brzmi: {'jedzenie': ['Bruschetta', 'Spaghetti Carbonara', 'Tiramisu', 'Chianti Classico'], 'status': 'pomyślne'} [12:31:25] [0000M] ❓ Klient 1: Ile czasu zajmie mi przygotowanie jedzenia? [12:31:25] [0000M] ➡️ Przewidywany czas oczekiwania klienta na jedzenie: 1:15 minuty [12:31:26] Studentka LLM zajęła się zamówieniem Emmy: Ostatni klient: Agent(name=”Entertainer”, …) Wynik końcowy (string): Cześć Emma! Dziękujemy za cierpliwość. Czas oczekiwania na wejście wynosi około 15 minut. Już prawie skończyliśmy – akurat tyle czasu, żebym zdążyła zacząć marzyć o tej pysznej bruschetcie! 🍽️.

Możemy zaoferować:

  1. Klient za pośrednictwem agenta tworzy własne menu.i prosi o rekomendację agenta kelnera.
  2. Kelner poleca wino Chianti i dodaje je do listy.
  3. Pracownik rozpatrujący reklamacje informuje klienta o okresie oczekiwania.

Teraz nie możemy po prostu symulować przepływu pracy, jak robiliśmy to wcześniej. Po prostu mamy przepływ pracy. Sprytny, oparty na tej samej technologii ChatGPT. Czy to nie wspaniałe?

 

4. Wniosek

Dziękuję bardzo za przybycie, to dla mnie wiele znaczy ❤️.
Wróćmy i zobaczmy, co zrobiliśmy w tym artykule.

  1. Projekt systemu restauracyjnego:
    Szybko stworzyliśmy projekt systemu restauracyjnego, korzystając z programu PowerPoint i dodając agentów AI.
  2. 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ę.
  3. 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 to brzmi trochę jak „Czarne lustro”. Odwzorowywanie klienta? Odwzorowywanie restauracji i kelnera? Tak, to dziwne. Ale Problemem nigdy nie jest narzędzie AI, ale zawsze sposób jego wykorzystania. Uważam, że zastąpienie kelnerów przez AI to przegrana gra.

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:

  1. 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ć.
  2. 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.