Update app.py to use Qwen VLM
Browse files
app.py
CHANGED
|
@@ -4,7 +4,7 @@ import pandas as pd
|
|
| 4 |
from pathlib import Path
|
| 5 |
from PIL import Image
|
| 6 |
import torch
|
| 7 |
-
from transformers import
|
| 8 |
import spaces
|
| 9 |
|
| 10 |
STORAGE_PATH = Path("state_manifest.csv")
|
|
@@ -35,18 +35,17 @@ def save_state_to_disk(dataframe_rows):
|
|
| 35 |
print(f"⚠️ Critical storage write failure: {e}")
|
| 36 |
|
| 37 |
# =====================================================================
|
| 38 |
-
# 🛰️ GLOBAL
|
| 39 |
# =====================================================================
|
| 40 |
-
print("🚀 Initializing
|
| 41 |
-
model_id = "
|
| 42 |
|
| 43 |
-
#
|
| 44 |
-
model =
|
| 45 |
-
model_id,
|
| 46 |
-
torch_dtype=torch.float16,
|
| 47 |
).eval()
|
| 48 |
processor = AutoProcessor.from_pretrained(model_id)
|
| 49 |
-
print("
|
| 50 |
|
| 51 |
# =====================================================================
|
| 52 |
# ⚡ ZERO-GPU INFERENCE PIPELINE
|
|
@@ -54,54 +53,64 @@ print("PaliGemma infrastructure successfully cached in memory.")
|
|
| 54 |
@spaces.GPU
|
| 55 |
def process_kitchen_operations(input_image, budget, days):
|
| 56 |
if input_image is None:
|
| 57 |
-
|
| 58 |
-
return df_rows, "⚠️ Please upload a fridge optical scan to map telemetry."
|
| 59 |
|
| 60 |
-
# Convert canvas profile and explicitly pin layers to active CUDA VRAM
|
| 61 |
image = input_image.convert("RGB")
|
| 62 |
model.to("cuda")
|
| 63 |
|
| 64 |
-
# 1. Structure
|
| 65 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
|
| 67 |
-
# 2.
|
| 68 |
-
|
|
|
|
| 69 |
|
| 70 |
with torch.no_grad():
|
| 71 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 72 |
|
| 73 |
-
|
| 74 |
-
generated_text = processor.decode(output[0], skip_special_tokens=True)[len(prompt):].strip()
|
| 75 |
-
print(f"🎯 PaliGemma Vision Output: {generated_text}")
|
| 76 |
|
| 77 |
-
# 3.
|
| 78 |
df_rows = []
|
| 79 |
-
raw_items = [item.strip() for item in
|
| 80 |
|
| 81 |
-
# Fallback default items to safely catch edge-case parsing drops
|
| 82 |
if not raw_items or raw_items == [""]:
|
| 83 |
raw_items = ["Salmon Fillet", "Fresh Broccoli", "Cherry Tomatoes"]
|
| 84 |
|
| 85 |
for raw_item in raw_items:
|
| 86 |
-
df_rows.append([raw_item.title(), "1 Unit", "Fresh (Nominal)", "$
|
| 87 |
|
| 88 |
-
# Commit changes permanently down to the local state file
|
| 89 |
save_state_to_disk(df_rows)
|
| 90 |
|
| 91 |
-
# 4. Process operational constraints math
|
| 92 |
daily_budget_allowance = budget / days
|
| 93 |
blueprint_md = (
|
| 94 |
-
f"### 🛠️ Logistics Routing Strategy Generated via
|
| 95 |
f"**Operational Horizon:** {days} Days | **Daily Financial Runway Ceiling:** ${daily_budget_allowance:.2f}/day\n\n"
|
| 96 |
f"📋 **Dynamic Cook Execution Pathway:**\n"
|
| 97 |
-
f"- **Day 1 Asset Recovery:** Prioritize routing
|
| 98 |
f"- **Day 2-3 Runway Balance:** Allocate remaining items under your strict financial boundary of ${daily_budget_allowance:.2f}/day."
|
| 99 |
)
|
| 100 |
|
| 101 |
return df_rows, blueprint_md
|
| 102 |
|
| 103 |
# =====================================================================
|
| 104 |
-
# 🎨 GRADIO INTERFACE DESIGN
|
| 105 |
# =====================================================================
|
| 106 |
with gr.Blocks() as demo:
|
| 107 |
gr.Markdown("# 🛰️ Parallel Plate: Kitchen Operations & Visual Logistics Engine")
|
|
|
|
| 4 |
from pathlib import Path
|
| 5 |
from PIL import Image
|
| 6 |
import torch
|
| 7 |
+
from transformers import Qwen2_5_VLForConditionalGeneration, AutoProcessor
|
| 8 |
import spaces
|
| 9 |
|
| 10 |
STORAGE_PATH = Path("state_manifest.csv")
|
|
|
|
| 35 |
print(f"⚠️ Critical storage write failure: {e}")
|
| 36 |
|
| 37 |
# =====================================================================
|
| 38 |
+
# 🛰️ GLOBAL OPEN VLM INITIALIZATION (Qwen2.5-VL)
|
| 39 |
# =====================================================================
|
| 40 |
+
print("🚀 Initializing Open Qwen2.5-VL Engine...")
|
| 41 |
+
model_id = "Qwen/Qwen2.5-VL-7B-Instruct"
|
| 42 |
|
| 43 |
+
# Native compilation path - No gating, completely open weight access
|
| 44 |
+
model = Qwen2_5_VLForConditionalGeneration.from_pretrained(
|
| 45 |
+
model_id, torch_dtype=torch.float16
|
|
|
|
| 46 |
).eval()
|
| 47 |
processor = AutoProcessor.from_pretrained(model_id)
|
| 48 |
+
print("Qwen2.5-VL layer matrix successfully loaded.")
|
| 49 |
|
| 50 |
# =====================================================================
|
| 51 |
# ⚡ ZERO-GPU INFERENCE PIPELINE
|
|
|
|
| 53 |
@spaces.GPU
|
| 54 |
def process_kitchen_operations(input_image, budget, days):
|
| 55 |
if input_image is None:
|
| 56 |
+
return load_persisted_state(), "⚠️ Please upload a fridge optical scan."
|
|
|
|
| 57 |
|
|
|
|
| 58 |
image = input_image.convert("RGB")
|
| 59 |
model.to("cuda")
|
| 60 |
|
| 61 |
+
# 1. Structure message payload using standard conversational schema
|
| 62 |
+
messages = [
|
| 63 |
+
{
|
| 64 |
+
"role": "user",
|
| 65 |
+
"content": [
|
| 66 |
+
{"type": "image", "image": image},
|
| 67 |
+
{"type": "text", "text": "List the food items visible inside this refrigerator, separated strictly by commas. Output only the comma-separated list."}
|
| 68 |
+
]
|
| 69 |
+
}
|
| 70 |
+
]
|
| 71 |
|
| 72 |
+
# 2. Process multi-modal chat templates natively
|
| 73 |
+
text = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
|
| 74 |
+
inputs = processor(text=[text], images=[image], padding=True, return_tensors="pt").to("cuda")
|
| 75 |
|
| 76 |
with torch.no_grad():
|
| 77 |
+
generated_ids = model.generate(**inputs, max_new_tokens=50)
|
| 78 |
+
|
| 79 |
+
# Trim prompt padding from generation token boundaries
|
| 80 |
+
generated_ids_trimmed = [
|
| 81 |
+
out_ids[len(in_ids):] for in_ids, out_ids in zip(inputs.input_ids, generated_ids)
|
| 82 |
+
]
|
| 83 |
+
detected_text = processor.batch_decode(
|
| 84 |
+
generated_ids_trimmed, skip_special_tokens=True, clean_up_tokenization_spaces=False
|
| 85 |
+
)[0].strip()
|
| 86 |
|
| 87 |
+
print(f"🎯 Qwen Vision Output: {detected_text}")
|
|
|
|
|
|
|
| 88 |
|
| 89 |
+
# 3. Dynamic array mapping to local state matrix
|
| 90 |
df_rows = []
|
| 91 |
+
raw_items = [item.strip() for item in detected_text.replace(".", ",").split(",") if item.strip()]
|
| 92 |
|
|
|
|
| 93 |
if not raw_items or raw_items == [""]:
|
| 94 |
raw_items = ["Salmon Fillet", "Fresh Broccoli", "Cherry Tomatoes"]
|
| 95 |
|
| 96 |
for raw_item in raw_items:
|
| 97 |
+
df_rows.append([raw_item.title(), "1 Unit", "Fresh (Nominal)", "$3.50"])
|
| 98 |
|
|
|
|
| 99 |
save_state_to_disk(df_rows)
|
| 100 |
|
|
|
|
| 101 |
daily_budget_allowance = budget / days
|
| 102 |
blueprint_md = (
|
| 103 |
+
f"### 🛠️ Logistics Routing Strategy Generated via Qwen2.5-VL\n\n"
|
| 104 |
f"**Operational Horizon:** {days} Days | **Daily Financial Runway Ceiling:** ${daily_budget_allowance:.2f}/day\n\n"
|
| 105 |
f"📋 **Dynamic Cook Execution Pathway:**\n"
|
| 106 |
+
f"- **Day 1 Asset Recovery:** Prioritize routing fresh profile (**{raw_items[0]}**) mapped by the edge sensor.\n"
|
| 107 |
f"- **Day 2-3 Runway Balance:** Allocate remaining items under your strict financial boundary of ${daily_budget_allowance:.2f}/day."
|
| 108 |
)
|
| 109 |
|
| 110 |
return df_rows, blueprint_md
|
| 111 |
|
| 112 |
# =====================================================================
|
| 113 |
+
# 🎨 GRADIO INTERFACE DESIGN
|
| 114 |
# =====================================================================
|
| 115 |
with gr.Blocks() as demo:
|
| 116 |
gr.Markdown("# 🛰️ Parallel Plate: Kitchen Operations & Visual Logistics Engine")
|