Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Suriok/menu-api

Open more actions menu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
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

 
 
 

Contributors

Morty Proxy This is a proxified and sanitized view of the page, visit original site.