Update app.py moondream VLM
Browse files
app.py
CHANGED
|
@@ -1,27 +1,22 @@
|
|
| 1 |
-
import
|
| 2 |
import gradio as gr
|
| 3 |
import pandas as pd
|
| 4 |
from pathlib import Path
|
| 5 |
-
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 6 |
from PIL import Image
|
|
|
|
|
|
|
|
|
|
| 7 |
|
| 8 |
-
# =====================================================================
|
| 9 |
-
# 💾 STATE PERSISTENCE ENGINE (Local File System Checkpoints)
|
| 10 |
-
# =====================================================================
|
| 11 |
STORAGE_PATH = Path("state_manifest.csv")
|
| 12 |
|
| 13 |
def load_persisted_state():
|
| 14 |
-
"""Reads the asset manifest from the local disk partition upon boot."""
|
| 15 |
if STORAGE_PATH.exists():
|
| 16 |
try:
|
| 17 |
-
print("💾 Persistent storage record detected. Loading digital twin...")
|
| 18 |
df = pd.read_csv(STORAGE_PATH)
|
| 19 |
if list(df.columns) == ["Ingredient Asset", "Current Volume / Qty", "Telemetry Status", "Book Value (Est)"]:
|
| 20 |
return df.values.tolist()
|
| 21 |
except Exception as e:
|
| 22 |
print(f"⚠️ State reconstruction exception: {e}")
|
| 23 |
-
|
| 24 |
-
# Default baseline parameters if no checkpoint exists
|
| 25 |
return [
|
| 26 |
["Greek Yogurt", "0.5 Liters", "Fresh", "$2.50"],
|
| 27 |
["Baby Spinach", "1 Bag", "Wilting (Critical)", "$3.00"],
|
|
@@ -30,86 +25,93 @@ def load_persisted_state():
|
|
| 30 |
]
|
| 31 |
|
| 32 |
def save_state_to_disk(dataframe_rows):
|
| 33 |
-
"""Commits the current state machine rows permanently to the disk."""
|
| 34 |
try:
|
| 35 |
df = pd.DataFrame(
|
| 36 |
dataframe_rows,
|
| 37 |
columns=["Ingredient Asset", "Current Volume / Qty", "Telemetry Status", "Book Value (Est)"]
|
| 38 |
)
|
| 39 |
df.to_csv(STORAGE_PATH, index=False)
|
| 40 |
-
print("💾 Digital twin state successfully synced to disk partition.")
|
| 41 |
except Exception as e:
|
| 42 |
print(f"⚠️ Critical storage write failure: {e}")
|
| 43 |
|
| 44 |
# =====================================================================
|
| 45 |
-
#
|
| 46 |
# =====================================================================
|
| 47 |
-
print("🤖 Initializing
|
| 48 |
model_id = "vikhyatk/moondream2"
|
| 49 |
|
| 50 |
-
#
|
| 51 |
-
model = AutoModelForCausalLM.from_pretrained(
|
| 52 |
-
model_id,
|
| 53 |
-
trust_remote_code=True
|
| 54 |
-
)
|
| 55 |
tokenizer = AutoTokenizer.from_pretrained(model_id)
|
|
|
|
| 56 |
|
| 57 |
-
|
|
|
|
|
|
|
|
|
|
| 58 |
def process_kitchen_operations(input_image, budget, days):
|
| 59 |
if input_image is None:
|
| 60 |
-
# Fallback to your baseline if no image is uploaded
|
| 61 |
df_rows = load_persisted_state()
|
| 62 |
-
|
| 63 |
-
return df_rows, blueprint_md
|
| 64 |
|
| 65 |
-
#
|
| 66 |
image = input_image.convert("RGB")
|
|
|
|
| 67 |
|
| 68 |
-
#
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
print(f"Telemetried Inventory: {detected_text}")
|
| 74 |
|
| 75 |
-
#
|
| 76 |
-
|
|
|
|
|
|
|
|
|
|
| 77 |
df_rows = []
|
| 78 |
-
|
| 79 |
-
for item in
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 84 |
|
| 85 |
-
#
|
| 86 |
save_state_to_disk(df_rows)
|
| 87 |
|
| 88 |
-
#
|
| 89 |
daily_budget_allowance = budget / days
|
| 90 |
-
blueprint_md =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 91 |
|
| 92 |
return df_rows, blueprint_md
|
| 93 |
|
| 94 |
# =====================================================================
|
| 95 |
-
# 🎨 GRADIO
|
| 96 |
# =====================================================================
|
| 97 |
with gr.Blocks() as demo:
|
| 98 |
gr.Markdown("# 🛰️ Parallel Plate: Kitchen Operations & Visual Logistics Engine")
|
| 99 |
-
gr.Markdown("### *Physical-to-Digital Twin Asset Management Pipeline (Hardware Tier:
|
| 100 |
-
|
| 101 |
with gr.Row():
|
| 102 |
with gr.Column(scale=1):
|
| 103 |
gr.Markdown("### 📸 1. Physical Edge Ingestion")
|
| 104 |
image_input = gr.Image(label="Upload Fridge Optical Survey Scan", type="pil")
|
| 105 |
-
|
| 106 |
-
with gr.Row():
|
| 107 |
budget_slider = gr.Slider(minimum=5, maximum=100, value=25, step=5, label="Runway Budget ($ USD)")
|
| 108 |
days_slider = gr.Slider(minimum=1, maximum=7, value=3, step=1, label="Target Horizon (Days)")
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
with gr.Column(scale=1):
|
| 113 |
gr.Markdown("### 📊 2. Active Refrigerator Digital Twin")
|
| 114 |
inventory_df = gr.Dataframe(
|
| 115 |
headers=["Ingredient Asset", "Current Volume / Qty", "Telemetry Status", "Book Value (Est)"],
|
|
@@ -118,10 +120,9 @@ with gr.Blocks() as demo:
|
|
| 118 |
interactive=True,
|
| 119 |
wrap=True,
|
| 120 |
column_widths=["30%", "25%", "25%", "20%"],
|
| 121 |
-
value=load_persisted_state()
|
| 122 |
)
|
| 123 |
-
|
| 124 |
-
gr.Markdown("### 🔀 3. Resource Routing & Recipe Output")
|
| 125 |
output_text = gr.Markdown("*Awaiting asset telemetry mapping to generate optimal cooking execution paths...*")
|
| 126 |
|
| 127 |
scan_btn.click(
|
|
|
|
| 1 |
+
import os
|
| 2 |
import gradio as gr
|
| 3 |
import pandas as pd
|
| 4 |
from pathlib import Path
|
|
|
|
| 5 |
from PIL import Image
|
| 6 |
+
import torch
|
| 7 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 8 |
+
import spaces # <-- Crucial ZeroGPU orchestration engine
|
| 9 |
|
|
|
|
|
|
|
|
|
|
| 10 |
STORAGE_PATH = Path("state_manifest.csv")
|
| 11 |
|
| 12 |
def load_persisted_state():
|
|
|
|
| 13 |
if STORAGE_PATH.exists():
|
| 14 |
try:
|
|
|
|
| 15 |
df = pd.read_csv(STORAGE_PATH)
|
| 16 |
if list(df.columns) == ["Ingredient Asset", "Current Volume / Qty", "Telemetry Status", "Book Value (Est)"]:
|
| 17 |
return df.values.tolist()
|
| 18 |
except Exception as e:
|
| 19 |
print(f"⚠️ State reconstruction exception: {e}")
|
|
|
|
|
|
|
| 20 |
return [
|
| 21 |
["Greek Yogurt", "0.5 Liters", "Fresh", "$2.50"],
|
| 22 |
["Baby Spinach", "1 Bag", "Wilting (Critical)", "$3.00"],
|
|
|
|
| 25 |
]
|
| 26 |
|
| 27 |
def save_state_to_disk(dataframe_rows):
|
|
|
|
| 28 |
try:
|
| 29 |
df = pd.DataFrame(
|
| 30 |
dataframe_rows,
|
| 31 |
columns=["Ingredient Asset", "Current Volume / Qty", "Telemetry Status", "Book Value (Est)"]
|
| 32 |
)
|
| 33 |
df.to_csv(STORAGE_PATH, index=False)
|
|
|
|
| 34 |
except Exception as e:
|
| 35 |
print(f"⚠️ Critical storage write failure: {e}")
|
| 36 |
|
| 37 |
# =====================================================================
|
| 38 |
+
# 🛰️ GLOBAL VISION-LANGUAGE INITIALIZATION
|
| 39 |
# =====================================================================
|
| 40 |
+
print("🤖 Initializing Moondream VLM weights into memory pool...")
|
| 41 |
model_id = "vikhyatk/moondream2"
|
| 42 |
|
| 43 |
+
# Keep the model load global. On ZeroGPU, this registers it in container RAM.
|
| 44 |
+
model = AutoModelForCausalLM.from_pretrained(model_id, trust_remote_code=True)
|
|
|
|
|
|
|
|
|
|
| 45 |
tokenizer = AutoTokenizer.from_pretrained(model_id)
|
| 46 |
+
print("Model layers successfully loaded.")
|
| 47 |
|
| 48 |
+
# =====================================================================
|
| 49 |
+
# ⚡ ZERO-GPU INTERFERENCE PIPELINE
|
| 50 |
+
# =====================================================================
|
| 51 |
+
@spaces.GPU # <-- This moves the actual image-math onto the A10G GPU cluster dynamically!
|
| 52 |
def process_kitchen_operations(input_image, budget, days):
|
| 53 |
if input_image is None:
|
|
|
|
| 54 |
df_rows = load_persisted_state()
|
| 55 |
+
return df_rows, "⚠️ Please upload a fridge optical scan to map telemetry."
|
|
|
|
| 56 |
|
| 57 |
+
# 1. Capture spatial metadata and shift data to CUDA tensor space
|
| 58 |
image = input_image.convert("RGB")
|
| 59 |
+
width, height = image.size
|
| 60 |
|
| 61 |
+
# Move the model to GPU *inside* the decorated ZeroGPU environment
|
| 62 |
+
model.to("cuda")
|
| 63 |
+
|
| 64 |
+
# 2. Extract raw visual assets directly from your image text prompt
|
| 65 |
+
prompt = "List the specific fresh food items visible inside this refrigerator, separated by commas. Be accurate."
|
|
|
|
| 66 |
|
| 67 |
+
# Moondream's native GPU answer method
|
| 68 |
+
detected_text = model.answer_question(image, prompt, tokenizer)
|
| 69 |
+
print(f"🎯 Moondream Vision Output: {detected_text}")
|
| 70 |
+
|
| 71 |
+
# 3. Parse VLM output into the digital twin dataframe matrix
|
| 72 |
df_rows = []
|
| 73 |
+
# Splitting the string output into dynamic lines or comma elements
|
| 74 |
+
raw_items = [item.strip() for item in detected_text.replace(".", ",").split(",") if item.strip()]
|
| 75 |
+
|
| 76 |
+
if not raw_items:
|
| 77 |
+
raw_items = ["Detected Asset Cluster"]
|
| 78 |
+
|
| 79 |
+
# Loop through what Moondream ACTUALLY sees (Salmon, Broccoli, etc.)
|
| 80 |
+
for raw_item in raw_items:
|
| 81 |
+
# Dynamically append discovered assets to the dashboard UI table
|
| 82 |
+
df_rows.append([raw_item.title(), "1 Unit", "Fresh (Nominal)", "$3.50"])
|
| 83 |
|
| 84 |
+
# Sync this newly discovered dataset permanently to disk
|
| 85 |
save_state_to_disk(df_rows)
|
| 86 |
|
| 87 |
+
# 4. Generate Strategy Blueprint Text
|
| 88 |
daily_budget_allowance = budget / days
|
| 89 |
+
blueprint_md = (
|
| 90 |
+
f"### 🛠️ Logistics Routing Strategy Generated via Moondream VLM\n\n"
|
| 91 |
+
f"**Operational Horizon:** {days} Days | **Daily Financial Runway Ceiling:** ${daily_budget_allowance:.2f}/day\n\n"
|
| 92 |
+
f"📋 **Dynamic Cook Execution Pathway:**\n"
|
| 93 |
+
f"- **Day 1 Asset Recovery:** Prioritize routing the fresh profile (**{raw_items[0]}**) discovered by the optical scan sensor.\n"
|
| 94 |
+
f"- **Day 2-3 Runway Balance:** Allocate remaining items under your strict financial boundary of ${daily_budget_allowance:.2f}/day."
|
| 95 |
+
)
|
| 96 |
|
| 97 |
return df_rows, blueprint_md
|
| 98 |
|
| 99 |
# =====================================================================
|
| 100 |
+
# 🎨 GRADIO INTERFACE DESIGN
|
| 101 |
# =====================================================================
|
| 102 |
with gr.Blocks() as demo:
|
| 103 |
gr.Markdown("# 🛰️ Parallel Plate: Kitchen Operations & Visual Logistics Engine")
|
| 104 |
+
gr.Markdown("### *Physical-to-Digital Twin Asset Management Pipeline (Hardware Tier: ⚡ ZeroGPU Accelerated)*")
|
| 105 |
+
|
| 106 |
with gr.Row():
|
| 107 |
with gr.Column(scale=1):
|
| 108 |
gr.Markdown("### 📸 1. Physical Edge Ingestion")
|
| 109 |
image_input = gr.Image(label="Upload Fridge Optical Survey Scan", type="pil")
|
| 110 |
+
with gr.Row():
|
|
|
|
| 111 |
budget_slider = gr.Slider(minimum=5, maximum=100, value=25, step=5, label="Runway Budget ($ USD)")
|
| 112 |
days_slider = gr.Slider(minimum=1, maximum=7, value=3, step=1, label="Target Horizon (Days)")
|
| 113 |
+
scan_btn = gr.Button("🚀 Initialize Asset Optimization Scan", variant="primary")
|
| 114 |
+
with gr.Column(scale=1):
|
|
|
|
|
|
|
| 115 |
gr.Markdown("### 📊 2. Active Refrigerator Digital Twin")
|
| 116 |
inventory_df = gr.Dataframe(
|
| 117 |
headers=["Ingredient Asset", "Current Volume / Qty", "Telemetry Status", "Book Value (Est)"],
|
|
|
|
| 120 |
interactive=True,
|
| 121 |
wrap=True,
|
| 122 |
column_widths=["30%", "25%", "25%", "20%"],
|
| 123 |
+
value=load_persisted_state()
|
| 124 |
)
|
| 125 |
+
gr.Markdown("### 🔀 3. Resource Routing & Recipe Output")
|
|
|
|
| 126 |
output_text = gr.Markdown("*Awaiting asset telemetry mapping to generate optimal cooking execution paths...*")
|
| 127 |
|
| 128 |
scan_btn.click(
|