AhmedBenElsayedBenAhmed commited on
Commit
ff7f00d
·
1 Parent(s): 4c4fd55

Merge branch 'Ai' into main

Browse files
Files changed (1) hide show
  1. app.py +15 -143
app.py CHANGED
@@ -1,18 +1,25 @@
1
  # ===============================
2
  # 1️⃣ استيراد المكتبات
3
  # ===============================
4
- from transformers import AutoModelForCausalLM, AutoTokenizer, Trainer, TrainingArguments
5
- from peft import LoraConfig, get_peft_model, TaskType, PeftModel
6
  from flask import Flask, request, jsonify
7
  from flask_cors import CORS
8
- import threading, torch
9
  from datasets import Dataset
10
- import os, json
 
 
 
 
 
 
 
11
 
12
  # ===============================
13
  # 2️⃣ إعداد المتغيرات
14
  # ===============================
15
  MODEL_NAME = "Qwen/Qwen2.5-0.5B-Instruct"
 
16
  SAVE_DIR = "./lora_model"
17
  DATASET_FILE = "dataset.json"
18
 
@@ -46,12 +53,12 @@ print("✅ LoRA model ready!")
46
  # ===============================
47
  if os.path.exists(SAVE_DIR):
48
  try:
49
- model = AutoModelForCausalLM.from_pretrained(
50
  MODEL_NAME,
51
  device_map="auto",
52
  torch_dtype=torch.float16
53
  )
54
- model = PeftModel.from_pretrained(model, SAVE_DIR)
55
  print("✅ LoRA weights auto-loaded from disk! [Fine-tuned model running]")
56
  except Exception as e:
57
  print("⚠️ Failed to auto-load LoRA weights:", str(e))
@@ -67,9 +74,7 @@ CORS(app)
67
  trainer = None
68
  current_dataset = None
69
 
70
- # ===============================
71
  # 🟢 تحميل الداتا من الملف عند البداية
72
- # ===============================
73
  def load_dataset():
74
  global current_dataset
75
  if os.path.exists(DATASET_FILE):
@@ -99,140 +104,7 @@ def load_dataset():
99
  load_dataset()
100
 
101
  # ===============================
102
- # 5a️⃣ توليد نصوص (generate)
103
- # ===============================
104
- @app.route("/generate", methods=["POST"])
105
- def generate():
106
- try:
107
- data = request.json
108
- prompt = data.get("prompt", "").strip()
109
-
110
- if current_dataset is None:
111
- return jsonify({
112
- "messages": [
113
- {"role": "assistant", "content": "⚖️ أنا زين، مساعد ذكي للاستشارات القانونية. برجاء طرح سؤال قانوني."}
114
- ]
115
- })
116
-
117
- # البحث في الداتا
118
- for item in current_dataset:
119
- lines = item["text"].split("\n")
120
- for line in lines:
121
- if line.lower().startswith("user:") and prompt in line:
122
- response_messages = []
123
- for l in lines:
124
- if ":" in l:
125
- role, content = l.split(":", 1)
126
- response_messages.append({
127
- "role": role.strip().lower(),
128
- "content": content.strip()
129
- })
130
- return jsonify({"messages": response_messages})
131
-
132
- # 🟡 لو مفيش تطابق
133
- return jsonify({
134
- "messages": [
135
- {"role": "assistant", "content": "⚖️ هذا السؤال ليس من ضمن اختصاصي. أنا زين مساعد قانوني مخصص للإجابة على الاستشارات القانونية فقط."}
136
- ]
137
- })
138
-
139
- except Exception as e:
140
- return jsonify({"messages": [{"role": "assistant", "content": f"خطأ: {str(e)}"}]})
141
-
142
- # ===============================
143
- # 5b️⃣ تدريب LoRA (Async) + حفظ
144
- # ===============================
145
- @app.route("/train", methods=["POST"])
146
- def train():
147
- global trainer, current_dataset, model
148
- try:
149
- data = []
150
- epochs = 1
151
- batch_size = 1
152
-
153
- # 📌 1) JSON request
154
- if request.is_json:
155
- body = request.get_json()
156
- data = body.get("data", [])
157
- epochs = int(body.get("epochs", 1))
158
- batch_size = int(body.get("batch_size", 1))
159
-
160
- # 📌 2) Form-data request
161
- else:
162
- epochs = int(request.form.get("epochs", 1))
163
- batch_size = int(request.form.get("batch_size", 1))
164
- file = request.files.get("file")
165
- if file:
166
- data = json.load(file)
167
- else:
168
- return jsonify({"error": "No file uploaded"}), 400
169
-
170
- # دمج وإزالة التكرارات
171
- old_data = []
172
- if os.path.exists(DATASET_FILE):
173
- with open(DATASET_FILE, "r", encoding="utf-8") as f:
174
- try:
175
- old_data = json.load(f)
176
- except:
177
- old_data = []
178
-
179
- combined = old_data + data
180
- unique_data, seen = [], set()
181
- for item in combined:
182
- key = json.dumps(item, ensure_ascii=False)
183
- if key not in seen:
184
- seen.add(key)
185
- unique_data.append(item)
186
-
187
- # الحفظ
188
- with open(DATASET_FILE, "w", encoding="utf-8") as f:
189
- json.dump(unique_data, f, ensure_ascii=False, indent=2)
190
-
191
- # تجهيز الداتا
192
- formatted = []
193
- for item in unique_data:
194
- if "messages" in item:
195
- conversation = ""
196
- for msg in item["messages"]:
197
- conversation += f"{msg['role'].capitalize()}: {msg['content']}\n"
198
- formatted.append({"text": conversation.strip()})
199
- elif "text" in item:
200
- formatted.append({"text": item["text"]})
201
-
202
- current_dataset = Dataset.from_list(formatted)
203
-
204
- def tokenize_function(examples):
205
- return tokenizer(examples["text"], truncation=True, padding="max_length", max_length=256)
206
-
207
- tokenized_dataset = current_dataset.map(tokenize_function, batched=True, remove_columns=["text"])
208
-
209
- training_args = TrainingArguments(
210
- output_dir=SAVE_DIR,
211
- per_device_train_batch_size=batch_size,
212
- num_train_epochs=epochs,
213
- logging_steps=2,
214
- save_strategy="epoch",
215
- fp16=True,
216
- report_to=None
217
- )
218
-
219
- trainer = Trainer(model=model, args=training_args, train_dataset=tokenized_dataset)
220
-
221
- def run_training():
222
- print("🔄 Training started...")
223
- trainer.train()
224
- trainer.save_model(SAVE_DIR)
225
- print("✅ Training completed & model saved!")
226
-
227
- threading.Thread(target=run_training, daemon=True).start()
228
-
229
- return jsonify({"status": "training started", "epochs": epochs, "batch_size": batch_size, "records": len(unique_data)})
230
-
231
- except Exception as e:
232
- return jsonify({"error": str(e)})
233
-
234
- # ===============================
235
- # 6️⃣ تشغيل Flask
236
  # ===============================
237
  if __name__ == "__main__":
238
- app.run(host="0.0.0.0", port=7860, threaded=True)
 
1
  # ===============================
2
  # 1️⃣ استيراد المكتبات
3
  # ===============================
4
+ import os
5
+ import threading, torch, json
6
  from flask import Flask, request, jsonify
7
  from flask_cors import CORS
 
8
  from datasets import Dataset
9
+ from transformers import AutoModelForCausalLM, AutoTokenizer, Trainer, TrainingArguments
10
+ from peft import LoraConfig, get_peft_model, TaskType, PeftModel
11
+
12
+ # ===============================
13
+ # 🟢 إصلاح مشكلة الكاش في Hugging Face Spaces
14
+ # ===============================
15
+ os.environ["HF_HOME"] = "/app/cache"
16
+ os.environ["TRANSFORMERS_CACHE"] = "/app/cache"
17
 
18
  # ===============================
19
  # 2️⃣ إعداد المتغيرات
20
  # ===============================
21
  MODEL_NAME = "Qwen/Qwen2.5-0.5B-Instruct"
22
+ FLASK_PORT = 7860 # Spaces بيشتغل على 7860
23
  SAVE_DIR = "./lora_model"
24
  DATASET_FILE = "dataset.json"
25
 
 
53
  # ===============================
54
  if os.path.exists(SAVE_DIR):
55
  try:
56
+ base_model = AutoModelForCausalLM.from_pretrained(
57
  MODEL_NAME,
58
  device_map="auto",
59
  torch_dtype=torch.float16
60
  )
61
+ model = PeftModel.from_pretrained(base_model, SAVE_DIR)
62
  print("✅ LoRA weights auto-loaded from disk! [Fine-tuned model running]")
63
  except Exception as e:
64
  print("⚠️ Failed to auto-load LoRA weights:", str(e))
 
74
  trainer = None
75
  current_dataset = None
76
 
 
77
  # 🟢 تحميل الداتا من الملف عند البداية
 
78
  def load_dataset():
79
  global current_dataset
80
  if os.path.exists(DATASET_FILE):
 
104
  load_dataset()
105
 
106
  # ===============================
107
+ # 6️⃣ تشغيل Flask (بدون ngrok في Spaces)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  # ===============================
109
  if __name__ == "__main__":
110
+ app.run(host="0.0.0.0", port=FLASK_PORT, threaded=True)