Salon Fryzjerski Szymon — system rezerwacji z asystentem AI
Pełna aplikacja webowa dla salonu fryzjerskiego: rezerwacja online, panel administracyjny, powiadomienia e-mail i inteligentny chatbot, który prowadzi klienta przez proces rezerwacji w naturalnej rozmowie. Zbudowana na FastAPI, React 19 i OpenAI Agents SDK z wektorową bazą wiedzy (RAG).
Celem projektu było zbudowanie rzeczywistego, wdrożeniowego systemu rezerwacji dla lokalnego salonu fryzjerskiego — nie demo, lecz aplikacji, która radzi sobie z prawdziwymi wymaganiami: grafik pracy pracowników z wyjątkami (urlopy, zmiany godzin), konflikty terminów, powiadomienia mailowe, czarna lista numerów i e-maili, oraz asystent AI, który faktycznie potrafi zarezerwować wizytę w rozmowie z klientem.
Aplikacja składa się z trzech warstw: frontend w React 19 z TypeScriptem, backend w FastAPI ze SQLAlchemy 2.0 w trybie async, oraz warstwa AI oparta na OpenAI Agents SDK z 10 function tools i własną bazą wiedzy RAG (pgvector + embeddingi OpenAI).
01Funkcjonalności
Asystent konwersacyjny
Agent AI prowadzi klienta przez rezerwację krok po kroku, pamięta kontekst rozmowy i weryfikuje dostępność w czasie rzeczywistym.
System rezerwacji
Rezerwacja online z kodem potwierdzenia, walidacja konfliktów, anulowanie kodem, integracja z grafikiem.
Zarządzanie zespołem
Profile pracowników ze zdjęciami, specjalizacjami (JSON), indywidualnym grafikiem i wyjątkami.
Panel administracyjny
Autentykacja HMAC + HTTP-only cookies, zarządzanie usługami, grafikiem, bazą wiedzy i czarną listą.
Baza wiedzy (RAG)
Wektorowa baza pgvector, automatyczne chunkowanie, embeddingi OpenAI, wyszukiwanie semantyczne (cosine similarity).
Powiadomienia e-mail
Integracja z Brevo API — potwierdzenia, anulowania, wysyłane asynchronicznie w background tasks.
02Architektura systemu
Aplikacja jest podzielona na cztery niezależne warstwy. Frontend komunikuje się z backendem wyłącznie przez REST API, backend korzysta z PostgreSQL z rozszerzeniem pgvector do przechowywania zarówno danych relacyjnych (rezerwacje, usługi, grafik), jak i wektorów embeddingów dla bazy wiedzy. Agent AI jest izolowanym modułem, który komunikuje się z OpenAI API i wywołuje wewnętrzne serwisy przez function tools.
03Stack technologiczny
Frontend
- React 19najnowsza wersja, nowy compiler, Hooks API
- TypeScriptpełne typowanie, zero any
- Vite 7szybki dev server i build
- Tailwind CSS 3utility-first styling
- shadcn/ui + Radix40+ dostępnych komponentów UI
- React Router 7routing po stronie klienta
- React Hook Form + Zodwalidacja formularzy
- GSAPanimacje scrollowe i przejścia
- Rechartswykresy w dashboardzie admina
Backend
- FastAPIasync framework, auto-generowane OpenAPI
- SQLAlchemy 2.0async ORM z typed Mapped[]
- PostgreSQL + pgvectorbaza relacyjna z wektorami
- OpenAI Agents SDKagent z function tools
- langchain-text-splitterschunking dokumentów dla RAG
- Pydantic v2walidacja i schematy
- httpxasync klient HTTP (Brevo)
- tiktokentokenizacja tekstu
- Docker Composekonteneryzacja środowiska dev
04Serce aplikacji — Agent AI
Najciekawszy technicznie element projektu. Agent zbudowany na OpenAI Agents SDK otrzymuje
10 function tools, które pozwalają mu wykonać realne operacje na bazie danych — od sprawdzania dostępności
po utworzenie rezerwacji. Prompt systemowy wymusza anty-halucynacyjne zasady (m.in. agent NIGDY nie potwierdzi
rezerwacji bez faktycznego wywołania create_booking), a stan sesji jest persystowany w PostgreSQL.
Przepływ rezerwacji przez chat
Przykład function tool
Każde narzędzie agenta jest zwykłą async funkcją z dekoratorem @function_tool. SDK automatycznie generuje schematy JSON dla OpenAI na podstawie typowania argumentów:
@function_tool
async def get_available_slots(
ctx: RunContextWrapper[BookingContext],
date_str: str,
service_id: Optional[str] = None,
team_member_id: Optional[str] = None,
) -> str:
# pobierz kontekst z sesji — agent pamięta co już wybrano
state = ctx.context.session_state
service_id = service_id or state.get("service_id")
team_member_id = team_member_id or state.get("team_member_id")
if not service_id:
return json.dumps({"error": "Brak usługi — najpierw save_service"})
booking_date = _parse_date(date_str)
if booking_date < date.today():
return json.dumps({"error": "Data w przeszłości"})
# faktyczne sprawdzenie w bazie, z uwzględnieniem grafiku i innych rezerwacji
availability = await ctx.context.booking_service.get_availability(
booking_date=booking_date,
service_id=UUID(service_id),
team_member_id=UUID(team_member_id)
)
slots = sorted(availability.keys())
return json.dumps({"date": booking_date.isoformat(), "slots": slots})
Anty-halucynacyjne zabezpieczenia w prompcie agenta: NIGDY nie mów, że rezerwacja została potwierdzona bez wywołania create_booking. NIGDY nie wymyślaj kodów rezerwacji — kod pochodzi wyłącznie z wyniku narzędzia. Rezerwacja jest potwierdzona TYLKO gdy tool zwróci {"success": true}.
05RAG — wektorowa baza wiedzy
Drugi filar systemu AI. Pliki markdown z bazą wiedzy salonu (cennik, godziny, poradniki fryzjerskie, informacje o zespole)
są automatycznie chunkowane, zamieniane na wektory embeddingów przez OpenAI i zapisywane w PostgreSQL
w kolumnie typu Vector(1536) dzięki rozszerzeniu pgvector. Podczas rozmowy agent wywołuje narzędzie search_knowledge,
które liczy embedding zapytania i robi wyszukiwanie po cosine similarity.
Dzięki temu chatbot nie opiera się na ogólnej wiedzy modelu — wszystkie fakty o salonie pochodzą wyłącznie z kontrolowanej bazy wiedzy, którą administrator edytuje w panelu.
# Model SQLAlchemy z kolumną wektorową
class KnowledgeChunk(Base):
__tablename__ = "knowledge_chunks"
id: Mapped[uuid.UUID] = mapped_column(primary_key=True, default=uuid.uuid4)
category: Mapped[str] = mapped_column(String(50), index=True)
title: Mapped[str] = mapped_column(String(200))
content: Mapped[str] = mapped_column(Text)
embedding: Mapped[Any] = mapped_column(Vector(1536)) # ← pgvector
source: Mapped[str] = mapped_column(String(100))
06Struktura projektu
Projekt podzielony jest na frontend (app/) i backend (backend/) z jasnym rozdzieleniem warstw: endpointy → serwisy → repozytoria → modele.
Wzorce architektoniczne
- Repository Pattern — każda encja ma swoje repozytorium (
BookingRepository,ServiceRepository…), które hermetyzuje dostęp do bazy - Service Layer — logika biznesowa oddzielona od endpointów i dostępu do danych
- Dependency Injection — FastAPI
Depends()+ własny kontener dla agenta - Domain Exceptions — własna hierarchia wyjątków mapowana na kody HTTP w globalnym handlerze
- Lifespan events — auto-ingest bazy wiedzy przy starcie aplikacji z inteligentną detekcją zmian
07REST API — wybrane endpointy
Backend udostępnia ponad 40 endpointów w /api/v1. Dokumentacja auto-generowana przez FastAPI dostępna jest pod /docs (Swagger) i /redoc.
08Panel administracyjny
Osobna sekcja aplikacji z autoryzacją HMAC i HTTP-only cookies (zabezpieczenie przed XSS). Umożliwia pełne zarządzanie salonem z poziomu przeglądarki:
- Dashboard z metrykami i wykresami (Recharts)
- Rezerwacje z filtrowaniem, zmianą statusów i usuwaniem
- Usługi — CRUD cennika, kategorii, kolejności wyświetlania
- Zespół z uploadem zdjęć (serwowanym przez StaticFiles)
- Grafik pracy — tygodniowy grafik salonu + wyjątki indywidualne (urlopy)
- Baza wiedzy — edytor plików markdown z re-ingestem po zapisie
- Czarna lista — blokowanie numerów telefonów i e-maili
09Dokumentacja — 9 faz rozwoju
Projekt zawiera kompletną dokumentację w postaci poradników Faza 0–8, które prowadzą przez cały proces budowy aplikacji od pustego repozytorium do wdrożenia. Każda faza dodaje konkretną warstwę funkcjonalności, z uzasadnieniem decyzji projektowych i przykładami kodu.
- Faza 0 — Setup projektu, Docker, FastAPI Hello World
- Faza 1 — CRUD usług (model, repo, schema, endpoint)
- Faza 2 — Zespół, JSON column, upload zdjęć
- Faza 3 — Godziny otwarcia i grafik z wyjątkami
- Faza 4 — System rezerwacji, konflikty, BackgroundTasks
- Faza 5 — E-mail (Brevo) i czarna lista
- Faza 6 — RAG: pgvector, embeddingi, cosine similarity
- Faza 7 — AI Agent: OpenAI Agents SDK, function tools
- Faza 8 — Panel admin: HMAC auth, HTTP-only cookies
10Czego dowodzi ten projekt
Poza samą aplikacją, projekt pokazuje konkretne kompetencje istotne z perspektywy pracodawcy:
Full-stack
Od modelu SQLAlchemy po animację GSAP — samodzielnie wyprowadzony produkt end-to-end.
Nowoczesny AI
Praktyczna integracja LLM: function calling, RAG, embeddingi, kontrola halucynacji, persystencja sesji.
Async Python
FastAPI + async SQLAlchemy 2.0 + httpx — wszystkie operacje I/O w pełni asynchroniczne.
Czysta architektura
Repository Pattern, Service Layer, Dependency Injection, domain exceptions — nie jeden plik z wszystkim.
TypeScript + React 19
Typed API client, custom hooks, formularze z Zod, komponenty shadcn/ui.
DevOps basics
Docker Compose, zmienne środowiskowe, lifespan events, auto-ingest przy starcie.
Bezpieczeństwo
HMAC auth, HTTP-only cookies, CORS, walidacja Pydantic, ochrona przed prompt injection.
Dokumentacja
9 faz poradników krok po kroku — umiejętność przekazywania wiedzy, nie tylko pisania kodu.
Zobacz pełny kod na GitHubie
Repozytorium zawiera frontend, backend, konfigurację Dockera, schematy bazy danych, poradniki 0–8 i wszystkie szczegóły implementacji.
Zobacz kod na GitHub11Aplikacja w akcji
Poniżej filmik pokazujący system w działaniu — od strony klienta (rezerwacja przez chatbota) po panel administracyjny.