FastAPI backend (Python 3.11, MSSQL ODBC for SambaPOS, Azure DI OCR),
kitchen_db on central PG. React/TS/Vite frontend with navy sidebar layout.
Backend: auth.py (APP_SLUG=kitchen, SimpleNamespace — archive routes use
.kitchen_id/.is_admin without modification), main.py (51 migrations, scheduler,
internal router for KDS bookings feed), api/internal.py, full archive API
(31 routers: invoices, recipes, menus, sambapos, resos, newbook, disputes,
purchase_orders, etc.), models, migrations, OCR pipeline.
kitchen_id pinned to 1 (B1 — single hotel).
Frontend: AuthGate (app=kitchen, token shim for archive compat — B5b pending),
Layout (navy sidebar, 6 sections, Lucide icons, teal --app-primary),
App.tsx (Outlet pattern, UploadApp outside Layout), index.css (full :root block).
strict: false — archive components have type issues; build clean.
Note: 45 archive components call fetch('/api/...') without /kitchen/ prefix
(B5b). Runtime 404s; deferred until after initial testing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
43 lines
2.2 KiB
Python
43 lines
2.2 KiB
Python
"""
|
|
LLM integration models — usage tracking and response caching.
|
|
LLM FEATURE — see LLM-MANIFEST.md for removal instructions
|
|
"""
|
|
from datetime import datetime
|
|
from typing import Optional
|
|
from sqlalchemy import String, DateTime, Integer, Text, Boolean, UniqueConstraint
|
|
from sqlalchemy.dialects.postgresql import JSONB
|
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
from database import Base
|
|
|
|
|
|
class LlmUsageLog(Base):
|
|
"""Log every LLM API call for cost tracking and debugging"""
|
|
__tablename__ = "llm_usage_log"
|
|
|
|
id: Mapped[int] = mapped_column(primary_key=True)
|
|
kitchen_id: Mapped[int] = mapped_column(Integer, nullable=False, index=True)
|
|
feature: Mapped[str] = mapped_column(String(50), nullable=False, index=True) # label_analysis, invoice_assist, etc.
|
|
model: Mapped[str] = mapped_column(String(100), nullable=False)
|
|
input_tokens: Mapped[int] = mapped_column(Integer, default=0)
|
|
output_tokens: Mapped[int] = mapped_column(Integer, default=0)
|
|
latency_ms: Mapped[int] = mapped_column(Integer, default=0)
|
|
success: Mapped[bool] = mapped_column(Boolean, default=True)
|
|
error_message: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, index=True)
|
|
|
|
|
|
class LlmAnalysisCache(Base):
|
|
"""Cache LLM responses to avoid redundant calls for identical inputs"""
|
|
__tablename__ = "llm_analysis_cache"
|
|
__table_args__ = (
|
|
UniqueConstraint("feature", "input_hash", "prompt_version", name="uq_llm_cache_feature_hash_version"),
|
|
)
|
|
|
|
id: Mapped[int] = mapped_column(primary_key=True)
|
|
kitchen_id: Mapped[int] = mapped_column(Integer, nullable=False, index=True)
|
|
feature: Mapped[str] = mapped_column(String(50), nullable=False) # label_analysis, ingredient_match, etc.
|
|
input_hash: Mapped[str] = mapped_column(String(64), nullable=False, index=True) # SHA-256 of input
|
|
result_json: Mapped[dict] = mapped_column(JSONB, nullable=False)
|
|
model_used: Mapped[str] = mapped_column(String(100), nullable=False)
|
|
prompt_version: Mapped[str] = mapped_column(String(10), nullable=False)
|
|
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|