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>
8.1 KiB
8.1 KiB
LLM Feature Manifest
Files that can be safely removed/reverted to fully remove LLM features. Updated with each implementation phase. Keep this current when making LLM-related changes.
How to Use This Manifest
- Quick disable: Set
llm_enabled = Falsein kitchen_settings — all LLM UI disappears, no API calls made. - Full removal: Follow the sections below to remove all LLM code and database objects.
- Code search: All LLM code is marked with
LLM FEATURE — see LLM-MANIFEST.mdcomments.
New Files (delete entirely)
| File | Purpose | Phase |
|---|---|---|
backend/services/llm_service.py |
Central LLM wrapper — client, caching, logging, rate limiting | 1 |
backend/models/llm.py |
LlmUsageLog + LlmAnalysisCache models |
1 |
backend/migrations/add_llm_infrastructure.py |
Migration for all LLM tables + settings columns | 1 |
Modified Files (sections to remove)
Phase 1 — Infrastructure
| File | What to Remove | Search Pattern |
|---|---|---|
backend/requirements.txt |
anthropic>=0.40.0 line |
anthropic |
backend/models/settings.py |
7 columns: llm_enabled, anthropic_api_key, llm_model, llm_confidence_threshold, llm_monthly_token_limit, llm_features_enabled |
llm_ or anthropic_ |
backend/api/settings.py |
LLM fields in SettingsResponse, SettingsUpdate, _build_settings_response(), LlmUsageStatsResponse, /llm-usage endpoint, /test-llm endpoint |
llm or LLM or anthropic |
backend/main.py |
Import + call of run_llm_infrastructure_migration |
llm_infrastructure |
Phase 2 — Label Parsing + Recipe Text (Features 1 + A)
| File | What to Remove | Search Pattern |
|---|---|---|
backend/services/llm_service.py |
analyse_product_label() function + LABEL_ANALYSIS_SYSTEM_MSG constant |
analyse_product_label |
backend/api/food_flags.py |
POST /analyse-label endpoint, LLM integration in recipe text scanning (GET /recipes/{id}/flags) — LLM call + merge block |
llm_service or analyse_product_label or llm_recipe_suggestions |
frontend/src/components/IngredientFlagEditor.tsx |
llmSuggestions + llmAnalysing props, LLM suggestion merge logic, AI spinner/indicator |
llmSuggestions or llmAnalysing or LLM FEATURE |
frontend/src/components/IngredientModal.tsx |
llmAnalysing + llmSuggestions + debouncedProductIngredients state, settings query for llm_enabled, /analyse-label useEffect, LLM props passed to IngredientFlagEditor |
llmAnalysing or llmSuggestions or analyse-label or LLM FEATURE |
frontend/src/pages/Settings.tsx |
'llm' in SettingsSection type, sidebar item, LLM fields in SettingsData interface, LLM state variables, LLM queries/mutations, handleSaveLlmSettings, entire activeSection === 'llm' block |
llm or LLM |
Phase 3 — Invoice OCR Assist + Reconciliation (Features 2 + E + H)
| File | What to Remove | Search Pattern |
|---|---|---|
backend/services/llm_service.py |
assist_invoice_ocr(), reconcile_line_items(), extract_invoice_fields_llm() functions |
assist_invoice_ocr or reconcile_line_items or extract_invoice_fields_llm |
backend/api/invoices.py |
POST /{invoice_id}/ai-assist endpoint |
ai-assist or ai_assist or LLM FEATURE |
backend/ocr/extractor.py |
LLM fallback block in process_invoice_image() — field extraction when Azure returns null |
extract_invoice_fields_llm or LLM FEATURE |
frontend/src/components/Review.tsx |
AiAssistSuggestions + AiReconciliationMatch interfaces, aiAssist* state variables, handleAiAssist + handleApplyAiCorrection + handleApplyAiSupplier functions, AI Assist button, AI suggestions panel, pack size suggestions panel + pre-fill in toggleCostBreakdown |
aiAssist or aiReconciliation or AiAssist or pack_size_suggestions or LLM FEATURE |
Phase 4 — Ingredient Matching + Supplier (Features 3 + D + F)
| File | What to Remove | Search Pattern |
|---|---|---|
backend/services/llm_service.py |
rank_ingredient_matches(), match_supplier_llm(), check_duplicate_ingredient_llm() functions |
rank_ingredient_matches or match_supplier_llm or check_duplicate_ingredient_llm |
backend/api/ingredients.py |
GET /ai-match endpoint, GET /ai-check-duplicate endpoint |
ai-match or ai-check-duplicate or LLM FEATURE |
backend/ocr/parser.py |
LLM fallback block at end of identify_supplier() |
match_supplier_llm or LLM FEATURE |
frontend/src/components/Review.tsx |
aiMatchLoading + aiMatchResults state, handleAiMatch function, AI Match button + results in cost breakdown modal |
aiMatch or ai-match or LLM FEATURE |
Phase 5 — Text Generation (Features B + C)
| File | What to Remove | Search Pattern |
|---|---|---|
backend/services/llm_service.py |
generate_menu_description(), draft_dispute_email() functions |
generate_menu_description or draft_dispute_email |
backend/api/menus.py |
GenerateDescriptionRequest model, POST /generate-description endpoint |
generate-description or generate_menu_description or LLM FEATURE |
backend/api/disputes.py |
POST /{dispute_id}/draft-email endpoint |
draft-email or draft_dispute_email or LLM FEATURE |
frontend/src/components/PublishToMenuModal.tsx |
aiDescLoading state, llmSettings query, handleGenerateDescription function, Generate button next to Description label |
aiDescLoading or handleGenerateDescription or LLM FEATURE |
frontend/src/components/DisputeDetailModal.tsx |
aiEmail* state variables, settings query, handleDraftEmail function, Draft Email section with subject/body/actions |
aiEmail or handleDraftEmail or LLM FEATURE |
Phase 6 — Polish + Yield (Feature G)
| File | What to Remove | Search Pattern |
|---|---|---|
backend/services/llm_service.py |
estimate_yield() function |
estimate_yield |
backend/api/ingredients.py |
GET /ai-estimate-yield endpoint |
ai-estimate-yield or estimate_yield or LLM FEATURE |
frontend/src/components/IngredientModal.tsx |
yieldHint + yieldHintLoading + debouncedFormName state, yield estimation useEffect, yield hint display below Yield % input |
yieldHint or yieldHintLoading or ai-estimate-yield or LLM FEATURE |
Database (migration to drop)
Tables
llm_usage_log— LLM API call trackingllm_analysis_cache— Response caching
Columns on kitchen_settings
llm_enabled(Boolean)anthropic_api_key(String)llm_model(String)llm_confidence_threshold(Numeric)llm_monthly_token_limit(Integer)llm_features_enabled(JSONB)
Removal SQL
DROP TABLE IF EXISTS llm_usage_log;
DROP TABLE IF EXISTS llm_analysis_cache;
ALTER TABLE kitchen_settings DROP COLUMN IF EXISTS llm_enabled;
ALTER TABLE kitchen_settings DROP COLUMN IF EXISTS anthropic_api_key;
ALTER TABLE kitchen_settings DROP COLUMN IF EXISTS llm_model;
ALTER TABLE kitchen_settings DROP COLUMN IF EXISTS llm_confidence_threshold;
ALTER TABLE kitchen_settings DROP COLUMN IF EXISTS llm_monthly_token_limit;
ALTER TABLE kitchen_settings DROP COLUMN IF EXISTS llm_features_enabled;
Design Principles for Clean Removal
- Conditional imports: All LLM imports use
from services.llm_service import Xonly inside functions, not at module top level (except main.py migration import). - Kill switch: All LLM UI elements gated behind
if (!llmEnabled)— removing the settings column and defaulting to False effectively removes all UI. - No existing signatures changed: LLM features are additive (new endpoints, new UI elements), never modify existing function behaviour.
- Existing logic untouched: Regex/trigram logic untouched — LLM runs alongside, not instead of.
- Breadcrumb comments: Every LLM-related function and component includes
LLM FEATURE — see LLM-MANIFEST.md for removal instructions.