ibrahimlasfar commited on
Commit
431e7f9
·
1 Parent(s): 625c5f1

update for cache

Browse files
Files changed (4) hide show
  1. Dockerfile +22 -21
  2. Dockerfiley +33 -0
  3. app.py +43 -30
  4. setup.sh +8 -7
Dockerfile CHANGED
@@ -1,32 +1,33 @@
1
- # -------------------------------------------------
2
- # Dockerfile – Python 3.10‑slim + build tools
3
- # -------------------------------------------------
4
  FROM python:3.10-slim
5
 
6
- # تثبيت الأدوات الأساسية + git & wget
7
- RUN apt-get update && \
8
- apt-get install -y git wget build-essential && \
9
- rm -rf /var/lib/apt/lists/*
 
 
 
 
 
10
 
11
- # مجلد العمل داخل الحاوية
12
  WORKDIR /app
13
 
14
- # ---------- المتطلبات ----------
15
  COPY requirements.txt .
16
- # تحديث pip ثم تثبيت الحزم
17
- RUN pip install --upgrade pip && \
18
- pip install --no-cache-dir -r requirements.txt
19
 
20
- # ---------- الكود ----------
21
  COPY app.py .
22
  COPY setup.sh .
23
- COPY entrypoint.sh .
24
- RUN chmod +x setup.sh entrypoint.sh
25
 
26
- # ---------- إعدادات الـ cache ----------
27
- ENV HF_HOME=/root/.cache/huggingface
28
- ENV TRANSFORMERS_CACHE=${HF_HOME}
29
- ENV HF_HUB_CACHE=${HF_HOME}
30
 
31
- # ---------- نقطة الدخول ----------
32
- ENTRYPOINT ["./entrypoint.sh"]
 
 
 
 
 
 
 
 
1
  FROM python:3.10-slim
2
 
3
+ # تثبيت المتطلبات الأساسية، بما في ذلك أدوات التطوير
4
+ RUN apt-get update && apt-get install -y \
5
+ git \
6
+ wget \
7
+ gcc \
8
+ g++ \
9
+ cmake \
10
+ make \
11
+ && rm -rf /var/lib/apt/lists/*
12
 
13
+ # إعداد مجلد العمل
14
  WORKDIR /app
15
 
16
+ # نسخ ملفات التطبيق
17
  COPY requirements.txt .
18
+ RUN pip install --no-cache-dir -r requirements.txt
 
 
19
 
20
+ # نسخ السكريبتات والملفات
21
  COPY app.py .
22
  COPY setup.sh .
23
+ RUN chmod +x setup.sh
 
24
 
25
+ # تحميل النموذج
26
+ RUN ./setup.sh
 
 
27
 
28
+ # تعيين المتغيّر لتجنب التحذير
29
+ ENV HF_HOME=/app/.cache/huggingface
30
+ ENV TRANSFORMERS_CACHE=/app/.cache/huggingface
31
+
32
+ # تشغيل التطبيق
33
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8080"]
Dockerfiley ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10-slim
2
+
3
+ # تثبيت المتطلبات الأساسية، بما في ذلك أدوات التطوير
4
+ RUN apt-get update && apt-get install -y \
5
+ git \
6
+ wget \
7
+ gcc \
8
+ g++ \
9
+ cmake \
10
+ make \
11
+ && rm -rf /var/lib/apt/lists/*
12
+
13
+ # إعداد مجلد العمل
14
+ WORKDIR /app
15
+
16
+ # نسخ ملفات التطبيق
17
+ COPY requirements.txt .
18
+ RUN pip install --no-cache-dir -r requirements.txt
19
+
20
+ # نسخ السكريبتات والملفات
21
+ COPY app.py .
22
+ COPY setup.sh .
23
+ RUN chmod +x setup.sh
24
+
25
+ # تحميل النموذج
26
+ RUN ./setup.sh
27
+
28
+ # تعيين المتغيّر لتجنب التحذير
29
+ ENV HF_HOME=/app/.cache/huggingface
30
+ ENV TRANSFORMERS_CACHE=/app/.cache/huggingface
31
+
32
+ # تشغيل التطبيق
33
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8080"]
app.py CHANGED
@@ -5,11 +5,14 @@ from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
5
  from llama_cpp import Llama
6
 
7
  # -------------------------------------------------
8
- # إعداد مسار الـ cache (يُستَخدم للـ transformers & huggingface)
9
  # -------------------------------------------------
10
- CACHE_DIR = os.getenv("HF_HOME", "/root/.cache/huggingface")
11
  os.makedirs(CACHE_DIR, exist_ok=True)
12
- os.environ.setdefault("TRANSFORMERS_CACHE", CACHE_DIR)
 
 
 
13
 
14
  # -------------------------------------------------
15
  # إنشاء التطبيق
@@ -23,51 +26,61 @@ app = FastAPI(
23
  # 1️⃣ تحميل نموذج T5 المدرب من Hub
24
  # -------------------------------------------------
25
  T5_REPO = "MGZON/mgzon-flan-t5-base"
26
- t5_tokenizer = AutoTokenizer.from_pretrained(T5_REPO, cache_dir=CACHE_DIR)
27
- t5_model = AutoModelForSeq2SeqLM.from_pretrained(T5_REPO, cache_dir=CACHE_DIR)
 
 
 
28
 
29
  # -------------------------------------------------
30
- # 2️⃣ تحميل ملف Mistral .gguf (قد تم تنزيله runtime)
31
  # -------------------------------------------------
32
- gguf_path = os.path.abspath(os.path.join("models", "mistral-7b-instruct-v0.1.Q4_K_M.gguf"))
33
  if not os.path.exists(gguf_path):
34
- # إذا لم يُحمَّل (مثلاً بسبب حذف الـ volume) نُعيد تحميله الآن
35
  raise RuntimeError(
36
  f"ملف Mistral .gguf غير موجود في {gguf_path}. "
37
- "تأكد من أن ملف setup.sh تم تنفيذه (يتم تشغيله تلقائيًا عند بدء الحاوية)."
38
  )
39
 
40
- mistral = Llama(
41
- model_path=gguf_path,
42
- n_ctx=2048,
43
- n_threads=8,
44
- # إذا كان لديك GPU داخل Space يمكنك إضافة n_gpu_layers=35
45
- )
 
 
 
46
 
47
  # -------------------------------------------------
48
- # طلبات الـ API
49
  # -------------------------------------------------
50
  class AskRequest(BaseModel):
51
  question: str
52
  max_new_tokens: int = 150
53
 
 
 
 
54
  @app.post("/ask")
55
  def ask(req: AskRequest):
56
  q = req.question.strip()
57
  if not q:
58
  raise HTTPException(status_code=400, detail="Empty question")
59
 
60
- # اختيار النموذج بناءً على الكلمات المفتاحية
61
- if any(tok in q.lower() for tok in ["mgzon", "flan", "t5"]):
62
- # ---------- نموذج T5 ----------
63
- inputs = t5_tokenizer(q, return_tensors="pt", truncation=True, max_length=256)
64
- out_ids = t5_model.generate(**inputs, max_length=req.max_new_tokens)
65
- answer = t5_tokenizer.decode(out_ids[0], skip_special_tokens=True)
66
- model_name = "MGZON‑FLAN‑T5"
67
- else:
68
- # ---------- نموذج Mistral ----------
69
- out = mistral(prompt=q, max_tokens=req.max_new_tokens)
70
- answer = out["choices"][0]["text"].strip()
71
- model_name = "Mistral‑7B‑GGUF"
72
-
73
- return {"model": model_name, "response": answer}
 
 
 
5
  from llama_cpp import Llama
6
 
7
  # -------------------------------------------------
8
+ # إعداد مسار الـ cache
9
  # -------------------------------------------------
10
+ CACHE_DIR = "/app/.cache/huggingface" # مسار موحد لـ Hugging Face Spaces
11
  os.makedirs(CACHE_DIR, exist_ok=True)
12
+
13
+ # تأكد من أن المكتبتين تقرأ المتغيّرات البيئية
14
+ os.environ["TRANSFORMERS_CACHE"] = CACHE_DIR
15
+ os.environ["HF_HOME"] = CACHE_DIR
16
 
17
  # -------------------------------------------------
18
  # إنشاء التطبيق
 
26
  # 1️⃣ تحميل نموذج T5 المدرب من Hub
27
  # -------------------------------------------------
28
  T5_REPO = "MGZON/mgzon-flan-t5-base"
29
+ try:
30
+ t5_tokenizer = AutoTokenizer.from_pretrained(T5_REPO, cache_dir=CACHE_DIR)
31
+ t5_model = AutoModelForSeq2SeqLM.from_pretrained(T5_REPO, cache_dir=CACHE_DIR)
32
+ except Exception as e:
33
+ raise RuntimeError(f"فشل تحميل نموذج T5 من {T5_REPO}: {str(e)}")
34
 
35
  # -------------------------------------------------
36
+ # 2️⃣ تحميل ملف Mistral .gguf
37
  # -------------------------------------------------
38
+ gguf_path = os.path.abspath("models/mistral-7b-instruct-v0.1.Q4_K_M.gguf")
39
  if not os.path.exists(gguf_path):
 
40
  raise RuntimeError(
41
  f"ملف Mistral .gguf غير موجود في {gguf_path}. "
42
+ "تأكد من أن ملف setup.sh تم تنفيذه أثناء الـ build."
43
  )
44
 
45
+ try:
46
+ mistral = Llama(
47
+ model_path=gguf_path,
48
+ n_ctx=2048,
49
+ n_threads=8,
50
+ # إذا كان لديك GPU، يمكنك إضافة: n_gpu_layers=35
51
+ )
52
+ except Exception as e:
53
+ raise RuntimeError(f"فشل تحميل نموذج Mistral من {gguf_path}: {str(e)}")
54
 
55
  # -------------------------------------------------
56
+ # تعريف شكل الطلب (JSON)
57
  # -------------------------------------------------
58
  class AskRequest(BaseModel):
59
  question: str
60
  max_new_tokens: int = 150
61
 
62
+ # -------------------------------------------------
63
+ # نقطة النهاية /ask
64
+ # -------------------------------------------------
65
  @app.post("/ask")
66
  def ask(req: AskRequest):
67
  q = req.question.strip()
68
  if not q:
69
  raise HTTPException(status_code=400, detail="Empty question")
70
 
71
+ # منطق اختيار النموذج
72
+ try:
73
+ if any(tok in q.lower() for tok in ["mgzon", "flan", "t5"]):
74
+ # نموذج T5
75
+ inputs = t5_tokenizer(q, return_tensors="pt", truncation=True, max_length=256)
76
+ out_ids = t5_model.generate(**inputs, max_length=req.max_new_tokens)
77
+ answer = t5_tokenizer.decode(out_ids[0], skip_special_tokens=True)
78
+ model_name = "MGZON-FLAN-T5"
79
+ else:
80
+ # نموذج Mistral
81
+ out = mistral(prompt=q, max_tokens=req.max_new_tokens)
82
+ answer = out["choices"][0]["text"].strip()
83
+ model_name = "Mistral-7B-GGUF"
84
+ return {"model": model_name, "response": answer}
85
+ except Exception as e:
86
+ raise HTTPException(status_code=500, detail=f"خطأ أثناء معالجة الطلب: {str(e)}")
setup.sh CHANGED
@@ -1,28 +1,29 @@
1
  #!/usr/bin/env bash
2
  set -e
3
 
4
- # إنشاء مجلد للنماذج
 
 
 
 
 
5
  mkdir -p models
6
 
7
  # تحميل ملف .gguf إذا لم يكن موجودًا مسبقًا
8
  python - <<PY
9
  from huggingface_hub import hf_hub_download
10
  import os
11
-
12
  repo_id = "TheBloke/Mistral-7B-Instruct-v0.1-GGUF"
13
  filename = "mistral-7b-instruct-v0.1.Q4_K_M.gguf"
14
  local_dir = "models"
15
-
16
- dest_path = os.path.join(local_dir, filename)
17
-
18
- if not os.path.exists(dest_path):
19
- # المتغيّر السري HF_TOKEN يُستَخدم تلقائيًا داخل huggingface_hub
20
  hf_hub_download(
21
  repo_id=repo_id,
22
  filename=filename,
23
  local_dir=local_dir,
24
  local_dir_use_symlinks=False,
25
  force_download=False,
 
26
  )
27
  print("✅ تم تحميل Mistral .gguf")
28
  else:
 
1
  #!/usr/bin/env bash
2
  set -e
3
 
4
+ # التحقق من وجود HF_TOKEN
5
+ if [ -z "$HF_TOKEN" ]; then
6
+ echo "⚠️ متغير HF_TOKEN غير معرف. قد يتسبب هذا في فشل تحميل النموذج."
7
+ fi
8
+
9
+ # إنشاء مجلد لتخزين النموذج
10
  mkdir -p models
11
 
12
  # تحميل ملف .gguf إذا لم يكن موجودًا مسبقًا
13
  python - <<PY
14
  from huggingface_hub import hf_hub_download
15
  import os
 
16
  repo_id = "TheBloke/Mistral-7B-Instruct-v0.1-GGUF"
17
  filename = "mistral-7b-instruct-v0.1.Q4_K_M.gguf"
18
  local_dir = "models"
19
+ if not os.path.exists(os.path.join(local_dir, filename)):
 
 
 
 
20
  hf_hub_download(
21
  repo_id=repo_id,
22
  filename=filename,
23
  local_dir=local_dir,
24
  local_dir_use_symlinks=False,
25
  force_download=False,
26
+ token=os.environ.get("HF_TOKEN")
27
  )
28
  print("✅ تم تحميل Mistral .gguf")
29
  else: