Derr11 commited on
Commit
02a5a58
·
verified ·
1 Parent(s): fbc8aaf

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +82 -387
app.py CHANGED
@@ -1,406 +1,101 @@
1
- """
2
- نسخة محسّنة من app.py مع دعم Quantization و Memory Optimization
3
- للنماذج الكبيرة على ZeroGPU
4
-
5
- Optimized version of app.py with Quantization and Memory Optimization
6
- for large models on ZeroGPU
7
- """
8
-
9
  import gradio as gr
10
  import torch
11
- import spaces
12
- from PIL import Image
13
  import os
14
- import tempfile
15
- import gc
16
- from typing import Optional, Union
17
-
18
- # استيراد المكتبات الضرورية
19
- try:
20
- from uni_moe.model.processing_qwen2_vl import Qwen2VLProcessor
21
- from uni_moe.model.modeling_out import GrinQwen2VLOutForConditionalGeneration
22
- from uni_moe.qwen_vl_utils import process_mm_info
23
- from transformers import BitsAndBytesConfig
24
- except ImportError as e:
25
- print(f"⚠️ Warning: Import error - {e}")
26
- print("Some features may not work properly.")
27
-
28
 
29
- # ==================== الإعدادات / Configuration ====================
 
 
 
30
 
31
- # اختر النموذج المناسب
32
- # Choose appropriate model
33
- MODEL_NAME = "HIT-TMG/Uni-MoE-2.0-Omni" # النموذج الكامل / Full model
34
- # MODEL_NAME = "HIT-TMG/Uni-MoE-2.0-Base" # البديل الأصغر / Smaller alternative
35
 
36
- # إعدادات التحسين / Optimization settings
37
- USE_4BIT = True # استخدام 4-bit quantization لتوفير الذاكرة
38
- USE_8BIT = False # بديل: استخدام 8-bit quantization
39
- USE_FLASH_ATTENTION = True # استخدام Flash Attention للسرعة
40
- MAX_MEMORY = "20GB" # الحد الأقصى للذاكرة المستخدمة
41
 
42
- device = "cuda" if torch.cuda.is_available() else "cpu"
 
 
 
 
 
43
 
44
- # ==================== تحميل النموذج / Model Loading ====================
45
 
46
- print("="*60)
47
- print(f"🚀 Loading Uni-MoE 2.0 Model")
48
- print(f"📍 Model: {MODEL_NAME}")
49
- print(f"🖥️ Device: {device}")
50
- print(f"⚙️ 4-bit Quantization: {USE_4BIT}")
51
- print(f"⚙️ 8-bit Quantization: {USE_8BIT}")
52
- print("="*60)
53
-
54
-
55
- def load_model_optimized():
56
- """تحميل النموذج بطريقة محسّنة"""
57
- global processor, model
58
 
59
- try:
60
- # تحميل المعالج
61
- print("📥 Loading processor...")
62
- processor = Qwen2VLProcessor.from_pretrained(MODEL_NAME)
63
-
64
- # إعداد Quantization Config
65
- quantization_config = None
66
- if USE_4BIT:
67
- print("⚙️ Setting up 4-bit quantization...")
68
- quantization_config = BitsAndBytesConfig(
69
- load_in_4bit=True,
70
- bnb_4bit_compute_dtype=torch.float16,
71
- bnb_4bit_use_double_quant=True,
72
- bnb_4bit_quant_type="nf4"
73
- )
74
- elif USE_8BIT:
75
- print("⚙️ Setting up 8-bit quantization...")
76
- quantization_config = BitsAndBytesConfig(
77
- load_in_8bit=True,
78
- )
79
-
80
- # تحميل النموذج
81
- print("📥 Loading model (this may take a few minutes)...")
82
- load_kwargs = {
83
- "device_map": "auto",
84
- "torch_dtype": torch.float16 if not USE_4BIT else None,
85
- "trust_remote_code": True,
86
- }
87
-
88
- if quantization_config:
89
- load_kwargs["quantization_config"] = quantization_config
90
-
91
- if device == "cuda" and not USE_4BIT and not USE_8BIT:
92
- load_kwargs["max_memory"] = {0: MAX_MEMORY}
93
-
94
- model = GrinQwen2VLOutForConditionalGeneration.from_pretrained(
95
- MODEL_NAME,
96
- **load_kwargs
97
- )
98
-
99
- # تعيين data_args
100
- processor.data_args = model.config
101
-
102
- print("✅ Model loaded successfully!")
103
- print(f"💾 Model size: {sum(p.numel() for p in model.parameters()) / 1e9:.2f}B parameters")
104
-
105
- return True
106
-
107
- except Exception as e:
108
- print(f"❌ Error loading model: {str(e)}")
109
- return False
110
-
111
-
112
- # تحميل النموذج
113
- model_loaded = load_model_optimized()
114
- if not model_loaded:
115
- processor = None
116
- model = None
117
-
118
-
119
- # ==================== دوال مساعدة / Helper Functions ====================
120
-
121
- def clear_gpu_memory():
122
- """تنظيف ذاكرة GPU"""
123
- if torch.cuda.is_available():
124
- torch.cuda.empty_cache()
125
- gc.collect()
126
-
127
-
128
- def estimate_tokens(text: str) -> int:
129
- """تقدير عدد التوكنات"""
130
- return len(text.split()) * 1.3
131
-
132
-
133
- # ==================== دالة التوليد الرئيسية / Main Generation Function ====================
134
-
135
- @spaces.GPU(duration=120)
136
- def generate_response(
137
- text_input: str,
138
- image_input: Optional[Image.Image] = None,
139
- audio_input: Optional[str] = None,
140
- temperature: float = 1.0,
141
- max_new_tokens: int = 512,
142
- top_p: float = 0.9,
143
- repetition_penalty: float = 1.1
144
- ) -> str:
145
- """
146
- توليد استجابة من النموذج
147
- Generate response from the model
148
- """
149
-
150
- # التحقق من توفر النموذج
151
- if model is None or processor is None:
152
- return "❌ النموذج غير متاح. يرجى التحقق من السجلات.\n❌ Model not available. Please check logs."
153
-
154
- # تنظيف الذاكرة قبل البدء
155
- clear_gpu_memory()
156
 
157
- try:
158
- # التحقق من المدخلات
159
- if not text_input and image_input is None and audio_input is None:
160
- return "⚠️ يرجى إدخال نص أو صورة أو صوت على الأقل.\n⚠️ Please provide at least text, image, or audio input."
161
-
162
- # بناء محتوى الرسالة
163
- content = []
164
-
165
- # إضافة النص
166
- if text_input:
167
- content.append({"type": "text", "text": text_input})
168
-
169
- # إضافة الصورة
170
- temp_image_path = None
171
- if image_input is not None:
172
- temp_image_path = tempfile.NamedTemporaryFile(delete=False, suffix=".jpg").name
173
- image_input.save(temp_image_path)
174
- content.append({"type": "image", "image": temp_image_path})
175
 
176
- # إضافة الصوت
177
- if audio_input is not None:
178
- content.append({"type": "audio", "audio": audio_input})
179
 
180
- # بناء الرسائل
181
- messages = [{"role": "user", "content": content}]
182
-
183
- # معالجة النص
184
- texts = processor.apply_chat_template(
185
- messages,
186
- tokenize=False,
187
- add_generation_prompt=True
188
- )
189
-
190
- # استبدال العلامات الخاصة
191
- texts = texts.replace(
192
- "<image>", "<|vision_start|><|image_pad|><|vision_end|>"
193
- ).replace(
194
- "<audio>", "<|audio_start|><|audio_pad|><|audio_end|>"
195
- ).replace(
196
- "<video>", "<|vision_start|><|video_pad|><|vision_end|>"
197
- )
198
-
199
- # معالجة الوسائط
200
- image_inputs, video_inputs, audio_inputs = process_mm_info(messages)
201
-
202
- # تجهيز المدخلات
203
- inputs = processor(
204
- text=texts,
205
- images=image_inputs,
206
- videos=video_inputs,
207
- audios=audio_inputs,
208
- padding=True,
209
- return_tensors="pt",
210
- )
211
-
212
- inputs["input_ids"] = inputs["input_ids"].unsqueeze(0)
213
- inputs = inputs.to(device=model.device)
214
-
215
- # التوليد
216
- with torch.inference_mode():
217
- output_ids = model.generate(
218
- **inputs,
219
- use_cache=True,
220
- pad_token_id=processor.tokenizer.eos_token_id,
221
- max_new_tokens=max_new_tokens,
222
- temperature=temperature,
223
- do_sample=True,
224
- top_p=top_p,
225
- repetition_penalty=repetition_penalty
226
- )
227
-
228
- # فك التشفير
229
- response = processor.batch_decode(
230
- output_ids[:, inputs["input_ids"].shape[-1]:],
231
- skip_special_tokens=True
232
- )[0]
233
-
234
- # تنظيف الملفات المؤقتة
235
- if temp_image_path and os.path.exists(temp_image_path):
236
- os.unlink(temp_image_path)
237
-
238
- # تنظيف الذاكرة
239
- clear_gpu_memory()
240
-
241
- return response
242
-
243
- except Exception as e:
244
- clear_gpu_memory()
245
- error_msg = f"❌ خطأ / Error: {str(e)}"
246
- print(error_msg)
247
- return error_msg
248
-
249
 
250
- # ==================== واجهة Gradio / Gradio Interface ====================
 
 
 
251
 
252
- css = """
253
- .rtl { direction: rtl; text-align: right; }
254
- .main-header {
255
- text-align: center;
256
- margin-bottom: 2rem;
257
- padding: 2rem;
258
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
259
- border-radius: 10px;
260
- color: white;
261
- }
262
- .note-box {
263
- padding: 1rem;
264
- background: #f0f9ff;
265
- border-left: 4px solid #3b82f6;
266
- border-radius: 4px;
267
- margin: 1rem 0;
268
- }
269
- """
270
-
271
- with gr.Blocks(title="Uni-MoE 2.0 Omni - Optimized", theme=gr.themes.Soft(), css=css) as demo:
272
-
273
- gr.HTML("""
274
- <div class="main-header">
275
- <h1>🚀 Uni-MoE 2.0 Omni Demo</h1>
276
- <p style="font-size: 1.1em; margin-top: 1rem;">
277
- نموذج متعدد الوسائط متقدم - Advanced Omnimodal Model
278
- </p>
279
- <p style="font-size: 0.9em; opacity: 0.9; margin-top: 0.5rem;">
280
- يدعم فهم وتوليد النصوص والصور والصوت<br>
281
- Supports understanding and generation of text, images, and audio
282
- </p>
283
- </div>
284
- """)
285
-
286
- with gr.Row():
287
- with gr.Column(scale=1):
288
- gr.Markdown("### 📝 المدخلات / Inputs")
289
-
290
- text_input = gr.Textbox(
291
- label="النص / Text",
292
- placeholder="اكتب سؤالك أو وصفك هنا...\nEnter your question or description here...",
293
- lines=4,
294
- rtl=True
295
- )
296
-
297
- with gr.Row():
298
- image_input = gr.Image(
299
- label="الصورة (اختياري) / Image (Optional)",
300
- type="pil",
301
- height=300
302
- )
303
-
304
- audio_input = gr.Audio(
305
- label="الصوت (اختياري) / Audio (Optional)",
306
- type="filepath"
307
- )
308
-
309
- with gr.Accordion("⚙️ إعدادات متقدمة / Advanced Settings", open=False):
310
- temperature = gr.Slider(
311
- minimum=0.1, maximum=2.0, value=0.7, step=0.1,
312
- label="Temperature (الإبداعية / Creativity)"
313
- )
314
- max_tokens = gr.Slider(
315
- minimum=64, maximum=2048, value=512, step=64,
316
- label="Max Tokens (الطول الأقصى / Max Length)"
317
- )
318
- top_p = gr.Slider(
319
- minimum=0.1, maximum=1.0, value=0.9, step=0.05,
320
- label="Top P (التنوع / Diversity)"
321
- )
322
- repetition_penalty = gr.Slider(
323
- minimum=1.0, maximum=2.0, value=1.1, step=0.1,
324
- label="Repetition Penalty (تجنب التكرار / Avoid Repetition)"
325
- )
326
-
327
- with gr.Row():
328
- submit_btn = gr.Button("🎯 توليد / Generate", variant="primary", size="lg")
329
- clear_btn = gr.Button("🗑️ مسح / Clear", size="lg")
330
-
331
- with gr.Column(scale=1):
332
- gr.Markdown("### 💬 النتيجة / Output")
333
-
334
- output = gr.Textbox(
335
- label="الاستجابة / Response",
336
- lines=20,
337
- show_copy_button=True,
338
- rtl=True
339
- )
340
 
341
- # ملاحظات مهمة
342
- gr.HTML("""
343
- <div class="note-box">
344
- <h3>📌 ملاحظات مهمة / Important Notes</h3>
345
- <ul>
346
- <li>⏱️ قد يستغرق التوليد 30-60 ثانية / Generation may take 30-60 seconds</li>
347
- <li>💾 يستخدم النموذج quantization لتوفير الذاكرة / Model uses quantization to save memory</li>
348
- <li>🔄 يتم تنظيف الذاكرة تلقائياً بعد كل استخدام / Memory is cleared automatically after each use</li>
349
- </ul>
350
- </div>
351
- """)
352
-
353
- # أمثلة
354
- gr.Markdown("### 📚 أمثلة / Examples")
355
- gr.Examples(
356
- examples=[
357
- ["ما هي عاصمة مصر؟ What is the capital of Egypt?", None, None],
358
- ["صف هذه الصورة بالتفصيل\nDescribe this image in detail", "https://picsum.photos/400/300", None],
359
- ["قارن بين Python و JavaScript\nCompare Python and JavaScript", None, None],
360
- ],
361
- inputs=[text_input, image_input, audio_input],
362
  )
363
 
364
- # معلومات ��ضافية
365
- gr.Markdown("""
366
- ---
367
- ### ℹ️ حول النموذج / About the Model
368
-
369
- **Uni-MoE 2.0 Omni** بني على:
370
- - 🧠 Mixture-of-Experts (MoE) architecture
371
- - 📊 Qwen2.5-7B base model (~33B parameters with experts)
372
- - 🌐 Omni-Modality 3D RoPE for cross-modal alignment
373
- - ⚡ Dynamic-Capacity routing mechanism
374
-
375
- **الأداء / Performance:**
376
- - +7% على فهم الفيديو / video understanding
377
- - ✅ +4% على الاستدلال السمعي-البصري / audio-visual reasoning
378
- - ✅ متفوق على Qwen2.5-Omni في 50+ معياراً / benchmarks
379
-
380
- 📄 [ورقة بحثية / Paper](https://arxiv.org/abs/2511.12609) |
381
- 💻 [GitHub](https://github.com/HITsz-TMG/Uni-MoE) |
382
- 🤗 [Model](https://huggingface.co/HIT-TMG/Uni-MoE-2.0-Omni)
383
- """)
384
-
385
- # ربط الأحداث
386
- submit_btn.click(
387
- fn=generate_response,
388
- inputs=[text_input, image_input, audio_input, temperature, max_tokens, top_p, repetition_penalty],
389
- outputs=output
390
- )
391
-
392
- clear_btn.click(
393
- fn=lambda: (None, None, None, None),
394
- outputs=[text_input, image_input, audio_input, output]
395
- )
396
-
397
 
398
- # تشغيل التطبيق
399
- if __name__ == "__main__":
400
- demo.queue(max_size=20, default_concurrency_limit=5)
401
- demo.launch(
402
- share=False,
403
- show_error=True,
404
- server_name="0.0.0.0",
405
- server_port=7860
406
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import gradio as gr
2
  import torch
 
 
3
  import os
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
+ # استيراد المكتبات الخاصة بالنموذج (تأكد أن مجلد uni_moe موجود بجانب هذا الملف)
6
+ from uni_moe.model.processing_qwen2_vl import Qwen2VLProcessor
7
+ from uni_moe.model.modeling_out import GrinQwen2VLOutForConditionalGeneration
8
+ from uni_moe.qwen_vl_utils import process_mm_info
9
 
10
+ # إعداد النموذج
11
+ MODEL_ID = "HIT-TMG/Uni-MoE-2.0-Omni"
12
+ DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
 
13
 
14
+ print(f"Loading model on {DEVICE}...")
 
 
 
 
15
 
16
+ # تحميل المعالج والنموذج
17
+ processor = Qwen2VLProcessor.from_pretrained(MODEL_ID)
18
+ model = GrinQwen2VLOutForConditionalGeneration.from_pretrained(
19
+ MODEL_ID,
20
+ torch_dtype=torch.bfloat16
21
+ ).to(DEVICE)
22
 
23
+ processor.data_args = model.config
24
 
25
+ def generate_response(text_input, image_path, audio_path):
26
+ # تجهيز محتوى الرسالة
27
+ content = []
 
 
 
 
 
 
 
 
 
28
 
29
+ # إضافة النص مع التاجات الخاصة إذا وجدت وسائط
30
+ prompt_text = text_input
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
 
32
+ if audio_path:
33
+ content.append({"type": "audio", "audio": audio_path})
34
+ prompt_text = "<audio>\n" + prompt_text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
+ if image_path:
37
+ content.append({"type": "image", "image": image_path})
38
+ prompt_text = "<image>\n" + prompt_text
39
 
40
+ content.append({"type": "text", "text": prompt_text})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
 
42
+ messages = [{
43
+ "role": "user",
44
+ "content": content
45
+ }]
46
 
47
+ # معالجة القوالب (Chat Template)
48
+ texts = processor.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
+ # استبدال التاجات الخاصة كما في المثال الأصلي
51
+ texts = texts.replace("<image>","<|vision_start|><|image_pad|><|vision_end|>") \
52
+ .replace("<audio>","<|audio_start|><|audio_pad|><|audio_end|>") \
53
+ .replace("<video>","<|vision_start|><|video_pad|><|vision_end|>")
54
+
55
+ # معالجة الوسائط
56
+ image_inputs, video_inputs, audio_inputs = process_mm_info(messages)
57
+
58
+ # تجهيز المدخلات للنموذج
59
+ inputs = processor(
60
+ text=texts,
61
+ images=image_inputs,
62
+ videos=video_inputs,
63
+ audios=audio_inputs,
64
+ padding=True,
65
+ return_tensors="pt",
 
 
 
 
 
66
  )
67
 
68
+ # إضافة بعد جديد للـ inputs ونقلها للـ GPU
69
+ if "input_ids" in inputs:
70
+ inputs["input_ids"] = inputs["input_ids"].unsqueeze(0) # Unsqueeze كما في المثال
71
+
72
+ inputs = inputs.to(device=model.device)
73
+
74
+ # التوليد
75
+ with torch.no_grad():
76
+ output_ids = model.generate(
77
+ **inputs,
78
+ use_cache=True,
79
+ pad_token_id=processor.tokenizer.eos_token_id,
80
+ max_new_tokens=2048, # تم التقليل قليلاً لتسريع الاستجابة في الويب
81
+ temperature=0.7,
82
+ do_sample=True
83
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
 
85
+ # فك التشفير واستخراج النص فقط
86
+ response = processor.batch_decode(output_ids[:, inputs["input_ids"].shape[-1]:], skip_special_tokens=True)[0]
87
+ return response
88
+
89
+ # بناء واجهة Gradio
90
+ with gr.Interface(
91
+ fn=generate_response,
92
+ inputs=[
93
+ gr.Textbox(label="Question/Prompt", placeholder="Describe the image or audio..."),
94
+ gr.Image(type="filepath", label="Upload Image (Optional)"),
95
+ gr.Audio(type="filepath", label="Upload Audio (Optional)")
96
+ ],
97
+ outputs=gr.Textbox(label="Uni-MoE Response"),
98
+ title="Uni-MoE 2.0 Omni Demo",
99
+ description="Upload an image or audio and ask questions about them using Uni-MoE 2.0."
100
+ ) as demo:
101
+ demo.launch()