1yahoo commited on
Commit
db7c890
·
verified ·
1 Parent(s): e15631a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +33 -62
app.py CHANGED
@@ -13,10 +13,9 @@ chroma_client = chromadb.PersistentClient(path=CHROMA_DATA_PATH)
13
  ef = embedding_functions.DefaultEmbeddingFunction()
14
  collection = chroma_client.get_or_create_collection(name="yousef_vault", embedding_function=ef)
15
 
16
- # النموذج الأساسي الافتراضي (يمكنك تغييره من هنا)
17
  DEFAULT_MODEL = "huihui-ai/Qwen2.5-72B-Instruct-abliterated"
18
 
19
- # --- 2. دالة استخراج النصوص (يدعم PDF, DOCX, TXT) ---
20
  def process_document(file):
21
  if file is None: return "⚠️ لم يتم اختيار ملف."
22
  text = ""
@@ -34,95 +33,67 @@ def process_document(file):
34
  text = f.read()
35
 
36
  if not text.strip():
37
- return "❌ تعذر استخراج نص. تأكد أن الملف ليس صوراً فقط."
38
 
39
- # تقسيم النص لقطع وحقنها في الذاكرة
40
  chunks = [text[i:i+2000] for i in range(0, len(text), 2000)]
41
  ids = [str(uuid.uuid4()) for _ in chunks]
42
  collection.add(documents=chunks, ids=ids)
43
 
44
- return f"✅ تمت الأرشفة: {len(chunks)} شظية معرفية حُقنت في الذاكرة."
45
  except Exception as e:
46
- return f"❌ خطأ في المعالجة: {str(e)}"
47
 
48
- # --- 3. دالة الحوار (RAG) مع معالجة أخطاء الـ Stream ---
49
- def predict(message, history, system_prompt, temperature, custom_model, oauth_token: gr.OAuthToken | None):
50
- # استخدام توكن المستخدم المسجل (OAuth) لخصم الرصيد الشخصي
51
- api_key = oauth_token.token if oauth_token else os.getenv("HF_TOKEN")
 
52
 
53
  if not api_key:
54
- yield "⚠️ يرجى تسجيل الدخول عبر Hugging Face أولاً للوصول إلى رصيدك الشخصي."
55
  return
56
 
57
- client = OpenAI(
58
- base_url="https://router.huggingface.co/v1",
59
- api_key=api_key
60
- )
61
-
62
- # تحديد النموذج المستخدم
63
  active_model = custom_model.strip() if custom_model and custom_model.strip() else DEFAULT_MODEL
64
 
65
- # استرجاع سياق من الذاكرة
66
- results = collection.query(query_texts=[message], n_results=10)
67
  context = "\n".join(results['documents'][0]) if results['documents'] else ""
68
 
69
- # بناء قائمة الرسائل
70
  messages = [{"role": "system", "content": f"{system_prompt}\n\n[CONTEXT]:\n{context}"}]
71
-
72
  for msg in history:
73
- messages.append({"role": msg['role'], "content": msg['content']})
74
-
75
  messages.append({"role": "user", "content": message})
76
 
77
  try:
78
  response = client.chat.completions.create(
79
  model=active_model,
80
  messages=messages,
81
- temperature=temperature,
82
  stream=True
83
  )
84
 
85
  partial_message = ""
86
  for chunk in response:
87
- # حماية ضد خطأ list index out of range
88
- if hasattr(chunk, 'choices') and chunk.choices and len(chunk.choices) > 0:
89
- content = chunk.choices[0].delta.content
90
- if content:
91
- partial_message += content
92
- yield partial_message
93
- else:
94
- # تجاهل الإطارات الفارغة التي تظهر في نهاية البث
95
- continue
96
-
97
  except Exception as e:
98
- if partial_message:
99
- # إذا كان هناك نص تم توليده بالفعل، اعرضه ولا تظهر رسالة الخطأ
100
- yield partial_message
101
- else:
102
- yield f"❌ فشل الاتصال بالنموذج ({active_model}): {str(e)}"
103
 
104
- # --- 4. بناء الواجهة (بسيطة، داكنة، ومتجاوبة) ---
105
- with gr.Blocks(fill_height=True, theme=gr.themes.Soft(primary_hue="indigo")) as demo:
106
  with gr.Sidebar():
107
  gr.Markdown("# 🧬 دهليز يوسف")
108
- gr.LoginButton("Sign in")
109
 
110
- with gr.Accordion("⚙️ الضبط والوعي", open=True):
111
- model_input = gr.Textbox(
112
- label="المحرك المستهدف (Model ID)",
113
- placeholder="اتركه فارغاً للنموذج الأساسي",
114
- value="",
115
- lines=1
116
- )
117
- system_input = gr.Textbox(
118
- value="أنت رفيق حكيم يغوص في التيه مع المستخدم. أجب بصدق مستعيناً بالذاكرة.",
119
- label="البرومبت النظامي"
120
- )
121
- temp_slider = gr.Slider(0.1, 1.5, 0.8, label="درجة التشظي (Temperature)")
122
 
123
  gr.Markdown("---")
124
- gr.Markdown("### 📂 ملقم الذاكرة (PDF, DOCX, TXT)")
125
- file_box = gr.File(label="ارفع مسوداتك هنا", file_types=[".pdf", ".docx", ".txt"])
126
  status_msg = gr.Markdown("*الذاكرة بانتظار الملفات...*")
127
 
128
  file_box.change(process_document, inputs=file_box, outputs=status_msg)
@@ -130,17 +101,17 @@ with gr.Blocks(fill_height=True, theme=gr.themes.Soft(primary_hue="indigo")) as
130
  clear_btn = gr.Button("🗑 مسح الذاكرة")
131
  def clear_memory():
132
  all_data = collection.get()
133
- if all_data['ids']:
134
- collection.delete(ids=all_data['ids'])
135
- return "🗑 تم تصفير الذاكرة بالكامل."
136
  clear_btn.click(clear_memory, outputs=status_msg)
137
 
 
138
  gr.ChatInterface(
139
  predict,
140
  additional_inputs=[system_input, temp_slider, model_input],
141
- fill_height=True,
142
- type="messages"
143
  )
144
 
145
  if __name__ == "__main__":
146
- demo.launch()
 
 
13
  ef = embedding_functions.DefaultEmbeddingFunction()
14
  collection = chroma_client.get_or_create_collection(name="yousef_vault", embedding_function=ef)
15
 
 
16
  DEFAULT_MODEL = "huihui-ai/Qwen2.5-72B-Instruct-abliterated"
17
 
18
+ # --- 2. دالة استخراج النصوص ---
19
  def process_document(file):
20
  if file is None: return "⚠️ لم يتم اختيار ملف."
21
  text = ""
 
33
  text = f.read()
34
 
35
  if not text.strip():
36
+ return "❌ تعذر استخراج نص."
37
 
 
38
  chunks = [text[i:i+2000] for i in range(0, len(text), 2000)]
39
  ids = [str(uuid.uuid4()) for _ in chunks]
40
  collection.add(documents=chunks, ids=ids)
41
 
42
+ return f"✅ تمت الأرشفة: {len(chunks)} شظية معرفية."
43
  except Exception as e:
44
+ return f"❌ خطأ: {str(e)}"
45
 
46
+ # --- 3. دالة الحوار المصححة ---
47
+ def predict(message, history, system_prompt, temperature, custom_model):
48
+ # ملاحظة: تم إزالة oauth_token من هنا لتبسيط الاتصال بالـ API
49
+ # تأكد من وضع HF_TOKEN في Secrets إذا كنت ترفعه على Space
50
+ api_key = os.getenv("HF_TOKEN")
51
 
52
  if not api_key:
53
+ yield "⚠️ يرجى ضبط HF_TOKEN في الإعدادات."
54
  return
55
 
56
+ client = OpenAI(base_url="https://router.huggingface.co/v1", api_key=api_key)
 
 
 
 
 
57
  active_model = custom_model.strip() if custom_model and custom_model.strip() else DEFAULT_MODEL
58
 
59
+ # RAG: استرجاع السياق
60
+ results = collection.query(query_texts=[message], n_results=5)
61
  context = "\n".join(results['documents'][0]) if results['documents'] else ""
62
 
 
63
  messages = [{"role": "system", "content": f"{system_prompt}\n\n[CONTEXT]:\n{context}"}]
64
+ # تحويل التاريخ إلى صيغة OpenAI المتوافقة
65
  for msg in history:
66
+ messages.append({"role": msg["role"], "content": msg["content"]})
 
67
  messages.append({"role": "user", "content": message})
68
 
69
  try:
70
  response = client.chat.completions.create(
71
  model=active_model,
72
  messages=messages,
73
+ temperature=float(temperature),
74
  stream=True
75
  )
76
 
77
  partial_message = ""
78
  for chunk in response:
79
+ if chunk.choices and chunk.choices[0].delta.content:
80
+ partial_message += chunk.choices[0].delta.content
81
+ yield partial_message
 
 
 
 
 
 
 
82
  except Exception as e:
83
+ yield f"❌ فشل: {str(e)}"
 
 
 
 
84
 
85
+ # --- 4. بناء الواجهة (التحديث الجديد) ---
86
+ with gr.Blocks(fill_height=True) as demo:
87
  with gr.Sidebar():
88
  gr.Markdown("# 🧬 دهليز يوسف")
 
89
 
90
+ with gr.Accordion("⚙️ الضبط", open=True):
91
+ model_input = gr.Textbox(label="المحرك المستهدف", placeholder="Default Qwen", value="")
92
+ system_input = gr.Textbox(value="أنت رفيق حكيم.", label="البرومبت النظامي")
93
+ temp_slider = gr.Slider(0.1, 1.5, 0.8, label="Temperature")
 
 
 
 
 
 
 
 
94
 
95
  gr.Markdown("---")
96
+ file_box = gr.File(label="ارفع مسوداتك", file_types=[".pdf", ".docx", ".txt"])
 
97
  status_msg = gr.Markdown("*الذاكرة بانتظار الملفات...*")
98
 
99
  file_box.change(process_document, inputs=file_box, outputs=status_msg)
 
101
  clear_btn = gr.Button("🗑 مسح الذاكرة")
102
  def clear_memory():
103
  all_data = collection.get()
104
+ if all_data['ids']: collection.delete(ids=all_data['ids'])
105
+ return "🗑 تم تصفير الذاكرة."
 
106
  clear_btn.click(clear_memory, outputs=status_msg)
107
 
108
+ # التعديل هنا: حذف type="messages" لأنه أصبح افتراضياً أو غير مطلوب بهذا الشكل
109
  gr.ChatInterface(
110
  predict,
111
  additional_inputs=[system_input, temp_slider, model_input],
112
+ fill_height=True
 
113
  )
114
 
115
  if __name__ == "__main__":
116
+ # تم نقل theme إلى هنا حسب تحذير Gradio 6
117
+ demo.launch(theme=gr.themes.Soft(primary_hue="indigo"))