Spaces:
Running on Zero
Running on Zero
update app
Browse files
app.py
CHANGED
|
@@ -19,6 +19,7 @@ from transformers import (
|
|
| 19 |
Qwen2_5_VLForConditionalGeneration,
|
| 20 |
Qwen3_5ForConditionalGeneration,
|
| 21 |
Qwen3VLForConditionalGeneration,
|
|
|
|
| 22 |
AutoProcessor,
|
| 23 |
AutoModelForImageTextToText,
|
| 24 |
TextIteratorStreamer,
|
|
@@ -42,6 +43,7 @@ LFM_450_MODEL_NAME = "LiquidAI/LFM2.5-VL-450M"
|
|
| 42 |
LFM_16_MODEL_NAME = "LiquidAI/LFM2.5-VL-1.6B"
|
| 43 |
QWEN_UNREDACTED_NAME = "prithivMLmods/Qwen3.5-2B-Unredacted-MAX"
|
| 44 |
QWEN25_VL_3B_NAME = "Qwen/Qwen2.5-VL-3B-Instruct"
|
|
|
|
| 45 |
|
| 46 |
# ββ Qwen3.5-4B ββββββββββββββββββββββββββββββββββββββββββ
|
| 47 |
print(f"Loading Qwen3.5-4B model: {QWEN_4B_MODEL_NAME} on {DEVICE}...")
|
|
@@ -144,6 +146,23 @@ except Exception as e:
|
|
| 144 |
qwen25_vl_3b_model = None
|
| 145 |
qwen25_vl_3b_processor = None
|
| 146 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 147 |
|
| 148 |
# --- Utility Functions ---
|
| 149 |
def safe_parse_json(text: str):
|
|
@@ -393,6 +412,40 @@ def generate_inference_stream(
|
|
| 393 |
yield f"data: {json.dumps({'chunk': tok})}\n\n"
|
| 394 |
thread.join()
|
| 395 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 396 |
yield "data: [DONE]\n\n"
|
| 397 |
|
| 398 |
|
|
@@ -745,6 +798,7 @@ async def homepage(request: Request):
|
|
| 745 |
.model-badge.lfm16 { background: rgba(107,203,119,0.15); color: #6bcb77; border: 1px solid rgba(107,203,119,0.35); }
|
| 746 |
.model-badge.qunred { background: rgba(255,80,160,0.15); color: #ff50a0; border: 1px solid rgba(255,80,160,0.35); }
|
| 747 |
.model-badge.q25vl3b { background: rgba(80,180,255,0.15); color: #50b4ff; border: 1px solid rgba(80,180,255,0.35); }
|
|
|
|
| 748 |
|
| 749 |
.model-info-box {
|
| 750 |
border-radius: 6px; padding: 9px;
|
|
@@ -761,7 +815,7 @@ async def homepage(request: Request):
|
|
| 761 |
<span class="logo">MULTIMODAL EDGE</span>
|
| 762 |
<span class="sep">|</span>
|
| 763 |
<span class="sub">Node-Based Inference Canvas</span>
|
| 764 |
-
<span class="badge">v2.
|
| 765 |
</div>
|
| 766 |
|
| 767 |
<div id="canvas">
|
|
@@ -836,6 +890,7 @@ async def homepage(request: Request):
|
|
| 836 |
<option value="lfm_16">LFM2.5-VL-1.6B (LiquidAI)</option>
|
| 837 |
<option value="qwen_unredacted">Qwen3.5-2B-Unredacted-MAX</option>
|
| 838 |
<option value="qwen25_vl_3b">Qwen2.5-VL-3B-Instruct</option>
|
|
|
|
| 839 |
</select>
|
| 840 |
</div>
|
| 841 |
<div id="modelInfoBox" class="model-info-box"
|
|
@@ -1091,6 +1146,13 @@ const MODEL_INFO = {
|
|
| 1091 |
bg: 'rgba(80,180,255,0.07)',
|
| 1092 |
border: 'rgba(80,180,255,0.25)',
|
| 1093 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1094 |
};
|
| 1095 |
|
| 1096 |
modelSelect.onchange = () => {
|
|
|
|
| 19 |
Qwen2_5_VLForConditionalGeneration,
|
| 20 |
Qwen3_5ForConditionalGeneration,
|
| 21 |
Qwen3VLForConditionalGeneration,
|
| 22 |
+
Gemma4ForConditionalGeneration,
|
| 23 |
AutoProcessor,
|
| 24 |
AutoModelForImageTextToText,
|
| 25 |
TextIteratorStreamer,
|
|
|
|
| 43 |
LFM_16_MODEL_NAME = "LiquidAI/LFM2.5-VL-1.6B"
|
| 44 |
QWEN_UNREDACTED_NAME = "prithivMLmods/Qwen3.5-2B-Unredacted-MAX"
|
| 45 |
QWEN25_VL_3B_NAME = "Qwen/Qwen2.5-VL-3B-Instruct"
|
| 46 |
+
GEMMA4_E2B_NAME = "google/gemma-4-E2B-it"
|
| 47 |
|
| 48 |
# ββ Qwen3.5-4B ββββββββββββββββββββββββββββββββββββββββββ
|
| 49 |
print(f"Loading Qwen3.5-4B model: {QWEN_4B_MODEL_NAME} on {DEVICE}...")
|
|
|
|
| 146 |
qwen25_vl_3b_model = None
|
| 147 |
qwen25_vl_3b_processor = None
|
| 148 |
|
| 149 |
+
# ββ Gemma4-E2B-it βββββββββββββββββββββββββββββββββββββββ
|
| 150 |
+
print(f"Loading Gemma4-E2B-it: {GEMMA4_E2B_NAME} on {DEVICE}...")
|
| 151 |
+
try:
|
| 152 |
+
gemma4_e2b_model = Gemma4ForConditionalGeneration.from_pretrained(
|
| 153 |
+
GEMMA4_E2B_NAME,
|
| 154 |
+
torch_dtype=torch.bfloat16,
|
| 155 |
+
device_map="auto" if torch.cuda.is_available() else None,
|
| 156 |
+
).eval()
|
| 157 |
+
if not torch.cuda.is_available():
|
| 158 |
+
gemma4_e2b_model = gemma4_e2b_model.to(DEVICE)
|
| 159 |
+
gemma4_e2b_processor = AutoProcessor.from_pretrained(GEMMA4_E2B_NAME)
|
| 160 |
+
print("Gemma4-E2B-it model loaded successfully.")
|
| 161 |
+
except Exception as e:
|
| 162 |
+
print(f"Warning: Gemma4-E2B-it model loading failed. Error: {e}")
|
| 163 |
+
gemma4_e2b_model = None
|
| 164 |
+
gemma4_e2b_processor = None
|
| 165 |
+
|
| 166 |
|
| 167 |
# --- Utility Functions ---
|
| 168 |
def safe_parse_json(text: str):
|
|
|
|
| 412 |
yield f"data: {json.dumps({'chunk': tok})}\n\n"
|
| 413 |
thread.join()
|
| 414 |
|
| 415 |
+
# ββ Gemma4-E2B-it βββββββββββββββββββββββββββββββββββ
|
| 416 |
+
elif model_id == "gemma4_e2b":
|
| 417 |
+
if gemma4_e2b_model is None or gemma4_e2b_processor is None:
|
| 418 |
+
yield f"data: {json.dumps({'chunk': '[Error] Gemma4-E2B-it model not loaded.'})}\n\n"
|
| 419 |
+
yield "data: [DONE]\n\n"
|
| 420 |
+
return
|
| 421 |
+
messages = [{"role": "user", "content": [
|
| 422 |
+
{"type": "image", "image": image},
|
| 423 |
+
{"type": "text", "text": full_prompt},
|
| 424 |
+
]}]
|
| 425 |
+
text_input = gemma4_e2b_processor.apply_chat_template(
|
| 426 |
+
messages, tokenize=False, add_generation_prompt=True
|
| 427 |
+
)
|
| 428 |
+
inputs = gemma4_e2b_processor(
|
| 429 |
+
text=[text_input],
|
| 430 |
+
images=[image],
|
| 431 |
+
return_tensors="pt",
|
| 432 |
+
padding=True,
|
| 433 |
+
).to(gemma4_e2b_model.device)
|
| 434 |
+
streamer = TextIteratorStreamer(
|
| 435 |
+
gemma4_e2b_processor.tokenizer,
|
| 436 |
+
skip_prompt=True, skip_special_tokens=True, timeout=120,
|
| 437 |
+
)
|
| 438 |
+
thread = threading.Thread(
|
| 439 |
+
target=gemma4_e2b_model.generate,
|
| 440 |
+
kwargs=dict(**inputs, streamer=streamer, max_new_tokens=1024,
|
| 441 |
+
use_cache=True, temperature=1.0, do_sample=True),
|
| 442 |
+
)
|
| 443 |
+
thread.start()
|
| 444 |
+
for tok in streamer:
|
| 445 |
+
if tok:
|
| 446 |
+
yield f"data: {json.dumps({'chunk': tok})}\n\n"
|
| 447 |
+
thread.join()
|
| 448 |
+
|
| 449 |
yield "data: [DONE]\n\n"
|
| 450 |
|
| 451 |
|
|
|
|
| 798 |
.model-badge.lfm16 { background: rgba(107,203,119,0.15); color: #6bcb77; border: 1px solid rgba(107,203,119,0.35); }
|
| 799 |
.model-badge.qunred { background: rgba(255,80,160,0.15); color: #ff50a0; border: 1px solid rgba(255,80,160,0.35); }
|
| 800 |
.model-badge.q25vl3b { background: rgba(80,180,255,0.15); color: #50b4ff; border: 1px solid rgba(80,180,255,0.35); }
|
| 801 |
+
.model-badge.g4e2b { background: rgba(66,197,107,0.15); color: #42c56b; border: 1px solid rgba(66,197,107,0.35); }
|
| 802 |
|
| 803 |
.model-info-box {
|
| 804 |
border-radius: 6px; padding: 9px;
|
|
|
|
| 815 |
<span class="logo">MULTIMODAL EDGE</span>
|
| 816 |
<span class="sep">|</span>
|
| 817 |
<span class="sub">Node-Based Inference Canvas</span>
|
| 818 |
+
<span class="badge">v2.6 β OCTA MODEL</span>
|
| 819 |
</div>
|
| 820 |
|
| 821 |
<div id="canvas">
|
|
|
|
| 890 |
<option value="lfm_16">LFM2.5-VL-1.6B (LiquidAI)</option>
|
| 891 |
<option value="qwen_unredacted">Qwen3.5-2B-Unredacted-MAX</option>
|
| 892 |
<option value="qwen25_vl_3b">Qwen2.5-VL-3B-Instruct</option>
|
| 893 |
+
<option value="gemma4_e2b">Gemma4-E2B-it (Google)</option>
|
| 894 |
</select>
|
| 895 |
</div>
|
| 896 |
<div id="modelInfoBox" class="model-info-box"
|
|
|
|
| 1146 |
bg: 'rgba(80,180,255,0.07)',
|
| 1147 |
border: 'rgba(80,180,255,0.25)',
|
| 1148 |
},
|
| 1149 |
+
gemma4_e2b: {
|
| 1150 |
+
html: `<span class="model-badge g4e2b">GEMMA 4 Β· E2B</span><br><br>
|
| 1151 |
+
Gemma4-E2B-it by Google DeepMind. Efficient 2B multimodal model
|
| 1152 |
+
with strong vision-language understanding & instruction-following.`,
|
| 1153 |
+
bg: 'rgba(66,197,107,0.07)',
|
| 1154 |
+
border: 'rgba(66,197,107,0.25)',
|
| 1155 |
+
},
|
| 1156 |
};
|
| 1157 |
|
| 1158 |
modelSelect.onchange = () => {
|