Skip to content

A robust RESTful API for digital restaurant menu management. Features include category organization, menu item CRUD operations, and real-time updates for pricing and descriptions.

Notifications You must be signed in to change notification settings

Suriok/menu-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Použité technologie

  • Jazyk: TypeScript / Node.js
  • Server: Express.js
  • AI Integrace: OpenAI SDK (připojeno na Perplexity API, model sonar)
  • HTTP Klient: Native Fetch
  • Databáze / Cache: SQLite
  • Testy: Jest + Supertest

Implementace požadavků a architektura

Web Content Retrieval (Varianta A + B Hybrid)

Pro získání obsahu stránky jsem zvolila hybridní přístup:

  • Používám HTTP request (fetch) pro stažení surového HTML textu stránky.
  • Důvod: Původně zamýšlená Varianta B (čistý LLM browsing) selhávala u některých českých webů (zejména těch s iframe menu, např. Menicka.cz). Přímé stažení textu a jeho následné předání do LLM se ukázalo jako nejspolehlivější metoda (RAG pattern).

LLM Integrace a Tool Calling

Jako LLM model je použit Perplexity Sonar.

  • Structured Output & Tool Calling:
    • Model sonar v současné době plně nepodporuje nativní parametr tools (při použití vrací chybu 400 Bad Request).
    • Místo toho jsem implementovala Simulated Tool Calling pomocí Structured System Prompting.
    • Důvod: Toto alternativní řešení plně nahrazuje funkcionalitu tool callingu:
      1. Struktura: Definice JSON schématu je vložena přímo do systémové instrukce (System Message).
      2. Validace: Prompt explicitně vynucuje datové typy (např. "Price must be integer"), čímž splňuje požadavek na normalizaci dat a strukturovaný výstup.

Caching (SQLite)

Pro ukládání dat využívám persistentní databázi SQLite (soubor menu.db).

  • Klíč: Kombinace URL + Datum.
  • Smart TTL Strategie (Invalidace):
    • Standardní: Úspěšně stáhnutá data jsou uložena na 24 hodin.
    • Short-lived: Pokud je menu prázdné nebo je restaurace zavřená, cache expiruje už za 30 minut (pro případ, že restaurace nahraje menu se zpožděním).
    • Invalidace: Staré záznamy jsou automaticky mazány při každém novém requestu.

Řešení chybových stavů (Edge Cases)

Aplikace ošetřuje nestandardní situace:

  • HTTP Chyby: Rozlišuje mezi nedostupnou stránkou (404), timeoutem serveru a interní chybou.
  • Zavřeno / Svátky: LLM detekuje fráze jako "Dnes zavřeno" nebo "Státní svátek" a vrací příznak is_closed: true s důvodem uzavření.

Instalace a spuštění

Instalace závislostí

Před prvním spuštěním je nutné nainstalovat potřebné balíčky:

npm install

Nastavení API klíče

Aby aplikace fungovala, musíte nastavit přístup k AI.

  1. Vytvorte soubor .env v kořenovém adresáři projektu.
  2. Vložte svůj API klíč:
PERPLEXITY_API_KEY=pplx-vas-klic-zde...
PORT=3000

Spuštění serveru

Otevřete terminál a spusťte:

npm start

Počkejte, dokud se neobjeví zpráva: Server running on http://localhost:3000.

Spouštění testů

Pro spuštění všech testů zadejte do terminálu:

npm test

Řešení chybových stavů a Edge Cases

Aplikace je navržena tak, aby byla odolná vůči nestandardním situacím:

  1. Nedostupnost stránky (404/Timeout):
  • API rozlišuje mezi chybou klienta (špatná URL) a výpadkem serveru restaurace. Vrací přesné HTTP status kódy.
  1. Nekonzistentní data:
  • Ceny: LLM normalizuje různé formáty ("145,-", "145 Kč") na čistý integer.
  • Alergeny: Pokud v textu chybí, vrací prázdné pole (prevence halucinací).
  1. Chybějící menu pro dnešní den:
  • Pokud restaurace menu ještě nenahrála, aplikace nastaví krátkou expiraci cache (30 min), aby se data brzy zkusila stáhnout znovu.
  1. Zavřeno / Svátky:
  • Model detekuje klíčová slova jako "Zavřeno" nebo "Státní svátek" a vrací příznak is_closed: true.
  1. Cache Invalidation:
  • Smart TTL: 24 hodin pro validní menu, 30 minut pro prázdné/chybné menu.
  • Manual Refresh: Parametr ?refresh=true vynutí okamžité smazání cache a nové stažení dat.
  1. Menu pouze jako obrázek:
  • Limitace: Aplikace zpracovává pouze textové HTML. Podpora pro obrázková menu (OCR / Vision LLM) je plánována jako budoucí rozšíření.

TTL cache 24 h a 30 min

1. Proč je 24 hodin příliš dlouhá doba?

Hlavní nevýhoda spočívá v zastaralosti dat po půlnoci. Menu, které bylo uloženo v pondělí dopoledne, by mělo být neplatné v úterý ráno. Pokud vyprší až v úterý v 11:00 (tj. 24 hodin od uložení), uživatelé vidí včerejší nabídku.

2. Kdy je i 30 minut problematických?

Plýtvání kredity: Pokud je restaurace o víkendu standardně zavřená (is_closed: true), API zbytečně každých 30 minut spouští novou drahou analýzu LLM, aby zjistilo, že je stále zavřeno.

Vysoké zatížení: Při vysoké návštěvnosti by každých 30 minut docházelo ke hromadnému zatížení backendu dotazy na všechny restaurace, i když se menu nezměnilo.

Ochrana proti SQL injection

Zajištěno použitím parametrizovaných dotazů (db.prepare().run(?)). Tím je efektivně zabráněno vkládání uživatelských dat přímo do SQL syntaxe

Izolace testů : Při spouštění testů se automaticky používá buď in-memory databáze, nebo oddělená testovací instance, aby se zabránilo kolizím dat a zaručila se izolace testů.

Separace prostředí : Konfigurace (API klíče) je striktně oddělena do souboru .env a načítána podle prostředí (Dev/Test/Prod).

Ochrana proti prompt injection

Oddělení rolí: Scraped data jsou vždy striktně oddělena do role user, zatímco kritické instrukce jsou v roli system (má vyšší prioritu).

Delimitery: Neprověřená data (pageText) jsou obalena jasnými, nestandardními oddělovači (např. trojitými uvozovkami """..."""). Tyto znaky modelovi signalizují, že text uvnitř je materiál ke zpracování (data), nikoliv příkaz k vykonání.

About

A robust RESTful API for digital restaurant menu management. Features include category organization, menu item CRUD operations, and real-time updates for pricing and descriptions.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published