ONYX-APP commited on
Commit
e9ef7a4
·
verified ·
1 Parent(s): 32f428b

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +98 -164
main.py CHANGED
@@ -2,222 +2,178 @@ import sys
2
  import os
3
  import types
4
  import logging
 
5
  from pathlib import Path
6
 
7
- import kagglehub
8
  import torch
9
  from fastapi import FastAPI
10
  from fastapi.responses import HTMLResponse
11
 
12
- # ── إعداد الـ Logging ─────────────────────────────────────
13
- logging.basicConfig(
14
- level=logging.INFO,
15
- format="%(asctime)s | %(levelname)s | %(message)s",
16
- )
17
  logger = logging.getLogger(__name__)
18
 
19
- # ── 0. تجهيز Kaggle Credentials (ضروري على HF Spaces) ─────
20
- # أضف KAGGLE_USERNAME و KAGGLE_KEY كـ Secrets في إعدادات الـ Space
 
 
 
 
 
 
 
 
 
 
21
  kaggle_username = os.environ.get("KAGGLE_USERNAME")
22
  kaggle_key = os.environ.get("KAGGLE_KEY")
23
 
24
  if kaggle_username and kaggle_key:
25
  os.environ["KAGGLE_USERNAME"] = kaggle_username
26
  os.environ["KAGGLE_KEY"] = kaggle_key
27
- logger.info("✅ Kaggle credentials configured from environment")
 
 
 
 
 
 
28
  else:
29
- logger.warning("⚠️ KAGGLE_USERNAME/KAGGLE_KEY not found. Public download may fail on HF Spaces.")
30
 
31
- # ── 1. تحميل النموذج من Kaggle ────────────────────────────
32
- MODEL_HANDLE = "ruicompany/onyx-code-figma/keras/default"
33
  model_path = None
34
 
 
35
  try:
36
- logger.info(f"⬇️ جاري تحميل النموذج: {MODEL_HANDLE}")
37
- model_path = kagglehub.model_download(MODEL_HANDLE, force_download=False)
38
- logger.info(f"✅ النموذج محمل في: {model_path}")
39
  except Exception as e:
40
- logger.error(f"❌ فشل تحميل النموذج من Kaggle: {e}")
41
-
42
- # Fallback: جرب مسارات محلية شائعة
43
- fallback_paths = [
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  "/kaggle/working/onyx-code-figma-bundle",
45
  "./onyx-code-figma-bundle",
46
- "./model",
47
- "/app/model",
48
- "/tmp/onyx-code-figma-bundle",
49
  ]
50
- for p in fallback_paths:
51
  if os.path.exists(p) and any(Path(p).rglob("*.safetensors")):
52
  model_path = p
53
- logger.info(f"✅ استخدام مسار محلي: {model_path}")
54
  break
55
 
56
- # ── 2. فحص محتويات المجلد ─────────────────────────────────
57
- def inspect_model_dir(path: str):
58
- """يفحص الملفات الموجودة في مجلد النموذج"""
59
- if not path or not os.path.exists(path):
60
- return []
61
- items = []
62
- for root, dirs, files in os.walk(path):
63
- level = root.replace(path, '').count(os.sep)
64
- indent = ' ' * 2 * level
65
- items.append(f"{indent}{os.path.basename(root)}/")
66
- subindent = ' ' * 2 * (level + 1)
67
- for file in files:
68
- items.append(f"{subindent}{file}")
69
- return items
70
 
 
71
  if model_path:
72
- logger.info("📁 محتويات مجلد النموذج:")
73
- for line in inspect_model_dir(model_path):
74
- logger.info(line)
75
 
76
- # ── 3. البحث عن onyx_code.py داخل المجلد ──────────────────
77
  onyx_code_dir = None
78
  if model_path:
79
  for py_file in Path(model_path).rglob("onyx_code.py"):
80
  onyx_code_dir = py_file.parent
81
- logger.info(f"🔍 Found onyx_code.py at: {py_file}")
82
  break
83
 
84
- # ── 4. فخ IPython (Monkey-patch) محسّن ───────────────────
85
  captured_html = []
86
 
87
  class MockHTML:
88
- def __init__(self, data=None, url=None, filename=None, **kwargs):
89
  self.data = data or ""
90
- for k, v in kwargs.items():
91
- setattr(self, k, v)
92
 
93
  def mock_display(*objs, **kwargs):
94
- """يلتقط أي كائن HTML يُعرض عبر IPython"""
95
  for obj in objs:
96
  if hasattr(obj, 'data') and isinstance(obj.data, str):
97
  captured_html.append(obj.data)
98
- logger.info(f"📄 تم التقاط HTML: {len(obj.data)} حرف")
99
  elif isinstance(obj, str):
100
  captured_html.append(obj)
101
- logger.info(f"📄 تم التقاط نص: {len(obj)} حرف")
102
-
103
- def mock_display_html(*objs, **kwargs):
104
- """بديل لـ display_html"""
105
- mock_display(*objs, **kwargs)
106
 
107
- # إنشاء modules وهمية
108
  ipython_pkg = types.ModuleType("IPython")
109
  ipython_display = types.ModuleType("IPython.display")
110
  ipython_display.HTML = MockHTML
111
  ipython_display.display = mock_display
112
- ipython_display.display_html = mock_display_html
113
  ipython_display.clear_output = lambda *a, **k: None
114
  ipython_display.Javascript = lambda *a, **k: MockHTML()
115
- ipython_display.JSON = lambda *a, **k: MockHTML()
116
 
117
  ipython_pkg.display = ipython_display
118
  sys.modules["IPython"] = ipython_pkg
119
  sys.modules["IPython.display"] = ipython_display
120
 
121
- # ── 5. استيراد onyx_code والتقاط HTML ─────────────────────
122
- html_content = "<h2>⚠️ لم يتم التقاط HTML</h2>"
123
- onyx_code_module = None
124
 
125
  if onyx_code_dir:
126
  sys.path.insert(0, str(onyx_code_dir))
127
  try:
128
  import onyx_code
129
- onyx_code_module = onyx_code
130
- logger.info("✅ تم استيراد onyx_code بنجاح")
131
-
132
  if hasattr(onyx_code, 'launch_designer'):
133
- logger.info("🎨 تشغيل launch_designer()...")
134
  onyx_code.launch_designer()
135
- if captured_html:
136
- html_content = captured_html[-1]
137
- logger.info(f"📄 HTML captured: {len(html_content)} chars")
138
- else:
139
- logger.warning("⚠️ launch_designer() اشتغلت بس ما التقطتش HTML")
140
- else:
141
- logger.warning("⚠️ onyx_code.launch_designer() غير موجودة")
142
- public_funcs = [f for f in dir(onyx_code) if not f.startswith('_')]
143
- logger.info(f"🔍 الدوال المتاحة: {public_funcs}")
144
-
145
- except ImportError as e:
146
- logger.error(f"❌ فشل استيراد onyx_code: {e}")
147
  except Exception as e:
148
- logger.error(f"❌ خطأ أثناء تشغيل launch_designer(): {e}")
149
  import traceback
150
  logger.error(traceback.format_exc())
151
- elif model_path:
152
- # جرب الاستيراد من المسار الرئيسي مباشرة
153
- sys.path.insert(0, model_path)
154
- try:
155
- import onyx_code
156
- onyx_code_module = onyx_code
157
- logger.info("✅ تم استيراد onyx_code من model_path")
158
- if hasattr(onyx_code, 'launch_designer'):
159
- onyx_code.launch_designer()
160
- html_content = captured_html[-1] if captured_html else html_content
161
- except Exception as e:
162
- logger.error(f"❌ فشل استيراد onyx_code من model_path: {e}")
163
 
164
- # ── 6. محاولة تحميل النموذج (Transformers) ────────────────
165
  model = None
166
  tokenizer = None
167
 
168
- if model_path:
169
- has_pytorch = any(
170
- f.suffix in ['.bin', '.safetensors'] or f.name == 'pytorch_model.bin'
171
- for f in Path(model_path).rglob('*')
172
- )
173
- has_keras = any(
174
- f.suffix in ['.keras', '.h5'] or f.name == 'saved_model.pb'
175
- for f in Path(model_path).rglob('*')
176
- )
177
-
178
- logger.info(f"🔍 PyTorch weights found: {has_pytorch}")
179
- logger.info(f"🔍 Keras weights found: {has_keras}")
180
-
181
- if has_pytorch:
182
- try:
183
- from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
184
-
185
- quantization_config = BitsAndBytesConfig(
186
- load_in_8bit=True,
187
- llm_int8_enable_fp32_cpu_offload=True,
188
- )
189
-
190
- model = AutoModelForCausalLM.from_pretrained(
191
- model_path,
192
- quantization_config=quantization_config,
193
- device_map="auto",
194
- max_memory={0: "0GB", "cpu": "6GB"},
195
- offload_buffers=True,
196
- offload_folder="offload",
197
- offload_state_dict=True,
198
- torch_dtype=torch.float32,
199
- trust_remote_code=True,
200
- )
201
- tokenizer = AutoTokenizer.from_pretrained(
202
- model_path,
203
- trust_remote_code=True
204
- )
205
- logger.info("✅ تم تحميل النموذج بـ PyTorch/Transformers")
206
- except Exception as e:
207
- logger.error(f"❌ فشل تحميل النموذج بـ Transformers: {e}")
208
- model = None
209
-
210
- elif has_keras:
211
- logger.warning("⚠️ النموذج بصيغة Keras. AutoModelForCausalLM لا يدعم Keras مباشرة.")
212
- logger.info("💡 استخدم tensorflow.keras.models.load_model() بدلاً من ذلك.")
213
- try:
214
- import tensorflow as tf
215
- model = tf.keras.models.load_model(model_path)
216
- logger.info("✅ تم تحميل النموذج بـ TensorFlow/Keras")
217
- except Exception as e:
218
- logger.error(f"❌ فشل تحميل Keras model: {e}")
219
 
220
- # ── 7. FastAPI ────────────────────────────────────────────
221
  app = FastAPI(title="Onyx Code Figma API")
222
 
223
  @app.get("/", response_class=HTMLResponse)
@@ -229,31 +185,9 @@ def health_check():
229
  return {
230
  "model_loaded": model is not None,
231
  "model_path": model_path,
232
- "html_captured": len(captured_html) > 0,
233
  "html_length": len(html_content),
234
- "onyx_code_loaded": onyx_code_module is not None,
235
- }
236
-
237
- @app.get("/model-info")
238
- def model_info():
239
- """يعرض معلومات عن النموذج المحمل"""
240
- if not model_path:
241
- return {"error": "Model not downloaded"}
242
-
243
- files = []
244
- for f in Path(model_path).rglob('*'):
245
- if f.is_file():
246
- files.append(str(f.relative_to(model_path)))
247
-
248
- return {
249
- "model_path": model_path,
250
- "has_pytorch": has_pytorch if 'has_pytorch' in dir() else None,
251
- "has_keras": has_keras if 'has_keras' in dir() else None,
252
- "python_files": [str(f.relative_to(model_path)) for f in Path(model_path).rglob("*.py")][:20],
253
- "all_files": files[:50],
254
  }
255
 
256
  if __name__ == "__main__":
257
  import uvicorn
258
- logger.info("🚀 تشغيل FastAPI على http://0.0.0.0:7860")
259
  uvicorn.run(app, host="0.0.0.0", port=7860)
 
2
  import os
3
  import types
4
  import logging
5
+ import subprocess
6
  from pathlib import Path
7
 
 
8
  import torch
9
  from fastapi import FastAPI
10
  from fastapi.responses import HTMLResponse
11
 
12
+ logging.basicConfig(level=logging.INFO, format="%(asctime)s | %(levelname)s | %(message)s")
 
 
 
 
13
  logger = logging.getLogger(__name__)
14
 
15
+ # ── 0. تحديث kagglehub (مهم جداً!) ────────────────────────
16
+ try:
17
+ subprocess.check_call([
18
+ sys.executable, "-m", "pip", "install", "-q", "--upgrade", "kagglehub>=1.0.2"
19
+ ])
20
+ logger.info("✅ kagglehub upgraded")
21
+ except Exception as e:
22
+ logger.warning(f"⚠️ upgrade failed: {e}")
23
+
24
+ import kagglehub
25
+
26
+ # ── 1. Kaggle Credentials ─────────────────────────────────
27
  kaggle_username = os.environ.get("KAGGLE_USERNAME")
28
  kaggle_key = os.environ.get("KAGGLE_KEY")
29
 
30
  if kaggle_username and kaggle_key:
31
  os.environ["KAGGLE_USERNAME"] = kaggle_username
32
  os.environ["KAGGLE_KEY"] = kaggle_key
33
+ # اكتب kaggle.json يدوياً (بعض الإصدارات بتقرأ من الملف)
34
+ kaggle_dir = Path.home() / ".kaggle"
35
+ kaggle_dir.mkdir(parents=True, exist_ok=True)
36
+ kaggle_json = kaggle_dir / "kaggle.json"
37
+ kaggle_json.write_text(f'{{"username":"{kaggle_username}","key":"{kaggle_key}"}}')
38
+ os.chmod(kaggle_json, 0o600)
39
+ logger.info("✅ Kaggle credentials configured")
40
  else:
41
+ logger.warning("⚠️ KAGGLE_USERNAME/KAGGLE_KEY not set")
42
 
43
+ # ── 2. تحميل النموذج (محاولات متعددة) ─────────────────────
 
44
  model_path = None
45
 
46
+ # محاولة 1: transformers framework (الصحيح للـ .safetensors)
47
  try:
48
+ logger.info("⬇️ [Attempt 1] transformers/default")
49
+ model_path = kagglehub.model_download("ruicompany/onyx-code-figma/transformers/default")
50
+ logger.info(f"✅ Success: {model_path}")
51
  except Exception as e:
52
+ logger.error(f"❌ Attempt 1 failed: {e}")
53
+
54
+ # محاولة 2: keras/default (القديم - إذا ما غيّرته)
55
+ if not model_path:
56
+ try:
57
+ logger.info("⬇️ [Attempt 2] keras/default")
58
+ model_path = kagglehub.model_download("ruicompany/onyx-code-figma/keras/default")
59
+ logger.info(f"✅ Success: {model_path}")
60
+ except Exception as e:
61
+ logger.error(f"❌ Attempt 2 failed: {e}")
62
+
63
+ # محاولة 3: dataset_download (أكتر استقراراً)
64
+ if not model_path:
65
+ try:
66
+ logger.info("⬇️ [Attempt 3] dataset_download")
67
+ model_path = kagglehub.dataset_download("ruicompany/onyx-code-figma")
68
+ logger.info(f"✅ Success: {model_path}")
69
+ except Exception as e:
70
+ logger.error(f"❌ Attempt 3 failed: {e}")
71
+
72
+ # محاولة 4: مسار محلي (إذا ضمّنت المودل بالـ Docker)
73
+ if not model_path:
74
+ local_paths = [
75
+ "/app/model",
76
+ "./model",
77
  "/kaggle/working/onyx-code-figma-bundle",
78
  "./onyx-code-figma-bundle",
 
 
 
79
  ]
80
+ for p in local_paths:
81
  if os.path.exists(p) and any(Path(p).rglob("*.safetensors")):
82
  model_path = p
83
+ logger.info(f"✅ [Fallback] Local path: {p}")
84
  break
85
 
86
+ if not model_path:
87
+ logger.error("🚨 All download attempts failed!")
88
+ model_path = None
 
 
 
 
 
 
 
 
 
 
 
89
 
90
+ # ── 3. فحص الملفات ────────────────────────────────────────
91
  if model_path:
92
+ logger.info("📁 Files in model path:")
93
+ for f in sorted(Path(model_path).rglob("*"))[:30]:
94
+ logger.info(f" {f.relative_to(model_path)}")
95
 
96
+ # ── 4. البحث عن onyx_code.py ──────────────────────────────
97
  onyx_code_dir = None
98
  if model_path:
99
  for py_file in Path(model_path).rglob("onyx_code.py"):
100
  onyx_code_dir = py_file.parent
101
+ logger.info(f"🔍 Found onyx_code.py: {py_file}")
102
  break
103
 
104
+ # ── 5. Monkey-patch IPython ────────────────────────────────
105
  captured_html = []
106
 
107
  class MockHTML:
108
+ def __init__(self, data=None, **kwargs):
109
  self.data = data or ""
 
 
110
 
111
  def mock_display(*objs, **kwargs):
 
112
  for obj in objs:
113
  if hasattr(obj, 'data') and isinstance(obj.data, str):
114
  captured_html.append(obj.data)
 
115
  elif isinstance(obj, str):
116
  captured_html.append(obj)
 
 
 
 
 
117
 
 
118
  ipython_pkg = types.ModuleType("IPython")
119
  ipython_display = types.ModuleType("IPython.display")
120
  ipython_display.HTML = MockHTML
121
  ipython_display.display = mock_display
122
+ ipython_display.display_html = mock_display
123
  ipython_display.clear_output = lambda *a, **k: None
124
  ipython_display.Javascript = lambda *a, **k: MockHTML()
 
125
 
126
  ipython_pkg.display = ipython_display
127
  sys.modules["IPython"] = ipython_pkg
128
  sys.modules["IPython.display"] = ipython_display
129
 
130
+ # ── 6. استيراد onyx_code ──────────────────────────────────
131
+ html_content = "<h2>⚠️ Onyx Designer not loaded</h2>"
 
132
 
133
  if onyx_code_dir:
134
  sys.path.insert(0, str(onyx_code_dir))
135
  try:
136
  import onyx_code
137
+ logger.info("✅ onyx_code imported")
 
 
138
  if hasattr(onyx_code, 'launch_designer'):
 
139
  onyx_code.launch_designer()
140
+ html_content = captured_html[-1] if captured_html else html_content
141
+ logger.info(f"📄 HTML: {len(html_content)} chars")
 
 
 
 
 
 
 
 
 
 
142
  except Exception as e:
143
+ logger.error(f"❌ Error: {e}")
144
  import traceback
145
  logger.error(traceback.format_exc())
 
 
 
 
 
 
 
 
 
 
 
 
146
 
147
+ # ── 7. تحميل Transformers Model ───────────────────────────
148
  model = None
149
  tokenizer = None
150
 
151
+ if model_path and any(Path(model_path).rglob("*.safetensors")):
152
+ try:
153
+ from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
154
+
155
+ quantization_config = BitsAndBytesConfig(
156
+ load_in_8bit=True,
157
+ llm_int8_enable_fp32_cpu_offload=True,
158
+ )
159
+
160
+ model = AutoModelForCausalLM.from_pretrained(
161
+ model_path,
162
+ quantization_config=quantization_config,
163
+ device_map="auto",
164
+ max_memory={0: "0GB", "cpu": "6GB"},
165
+ offload_buffers=True,
166
+ offload_folder="offload",
167
+ offload_state_dict=True,
168
+ torch_dtype=torch.float32,
169
+ trust_remote_code=True,
170
+ )
171
+ tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
172
+ logger.info("✅ Model loaded")
173
+ except Exception as e:
174
+ logger.error(f"❌ Model load failed: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
175
 
176
+ # ── 8. FastAPI ────────────────────────────────────────────
177
  app = FastAPI(title="Onyx Code Figma API")
178
 
179
  @app.get("/", response_class=HTMLResponse)
 
185
  return {
186
  "model_loaded": model is not None,
187
  "model_path": model_path,
 
188
  "html_length": len(html_content),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
189
  }
190
 
191
  if __name__ == "__main__":
192
  import uvicorn
 
193
  uvicorn.run(app, host="0.0.0.0", port=7860)