FECUOY commited on
Commit
a8ba3e2
·
verified ·
1 Parent(s): 171a056

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +48 -139
app.py CHANGED
@@ -1,168 +1,77 @@
1
  import gradio as gr
2
- from huggingface_hub import InferenceClient
3
  import zipfile
4
  import os
5
- import fitz # مكتبة PyMuPDF لقراءة ملفات PDF
6
- import docx # مكتبة لقراءة ملفات Word
7
 
8
- # --- إعدادات المعالجة ---
9
- MAX_CHAR_LIMIT = 50000 # أقصى عدد حروف يتم قراءته من الملفات لتجنب تجاوز ذاكرة النموذج
10
- MAX_ZIP_FILES_PREVIEW = 20 # عدد الملفات التي يتم قراءتها من داخل المجلد المضغوط
11
-
12
- def extract_text_from_file(file_path):
13
- """دالة شاملة لاستخراج النصوص بناءً على نوع الملف"""
14
- try:
15
- filename = os.path.basename(file_path)
16
- ext = filename.split('.')[-1].lower()
17
-
18
- # 1. معالجة PDF
19
- if ext == 'pdf':
20
- text = ""
21
- with fitz.open(file_path) as doc:
22
- for page in doc:
23
- text += page.get_text()
24
- return f"\n--- بداية ملف PDF: {filename} ---\n{text[:MAX_CHAR_LIMIT]}\n--- نهاية الملف ---\n"
25
-
26
- # 2. معالجة Word (DOCX)
27
- elif ext == 'docx':
28
- doc = docx.Document(file_path)
29
- text = "\n".join([para.text for para in doc.paragraphs])
30
- return f"\n--- بداية ملف Word: {filename} ---\n{text[:MAX_CHAR_LIMIT]}\n--- نهاية الملف ---\n"
31
-
32
- # 3. معالجة الملفات النصية والبرمجية (txt, py, md, json, html, csv)
33
- elif ext in ['txt', 'py', 'js', 'html', 'css', 'md', 'json', 'csv', 'xml']:
34
- with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
35
- content = f.read()
36
- return f"\n--- بداية ملف نصي: {filename} ---\n{content[:MAX_CHAR_LIMIT]}\n--- نهاية الملف ---\n"
37
-
38
- # 4. معالجة ملفات ZIP (الذكية)
39
- elif ext == 'zip':
40
- report = f"\n--- تحليل مجلد مضغوط: {filename} ---\n"
41
- with zipfile.ZipFile(file_path, 'r') as z:
42
- all_files = z.namelist()
43
- report += f"المجلد يحتوي على {len(all_files)} ملف/مجلد.\n"
44
- report += "قائمة الملفات (أول 50):\n" + "\n".join(all_files[:50]) + "\n"
45
-
46
- # قراءة محتوى عينة من الملفات داخل الـ ZIP
47
- read_count = 0
48
- for sub_file in all_files:
49
- if read_count >= MAX_ZIP_FILES_PREVIEW: break
50
- if sub_file.endswith(('/', '\\')): continue # تجاهل المجلدات الفارغة
51
-
52
- # محاولة قراءة الملفات النصية داخل الـ ZIP
53
- if sub_file.lower().endswith(('.txt', '.py', '.md', '.json', '.csv')):
54
- with z.open(sub_file) as f:
55
- content = f.read().decode('utf-8', errors='ignore')
56
- report += f"\n[محتوى ملف داخل ZIP: {sub_file}]\n{content[:2000]}...\n"
57
- read_count += 1
58
- return report + "\n--- نهاية المجلد المضغوط ---\n"
59
-
60
- else:
61
- return f"\n⚠️ تنبيه: الملف {filename} بصيغة غير مدعومة للقراءة النصية المباشرة.\n"
62
 
63
- except Exception as e:
64
- return f"\n⚠️ خطأ أثناء قراءة الملف {os.path.basename(file_path)}: {str(e)}\n"
65
 
66
- def respond(
67
- message,
68
- history: list[dict[str, str]],
69
- system_message,
70
- max_tokens,
71
- temperature,
72
- top_p,
73
- hf_token: gr.OAuthToken,
74
- ):
75
- # 1. التحقق من التوكن
76
- if not hf_token or not hf_token.token:
77
- yield "⚠️ **خطأ:** يرجى تسجيل الدخول بحساب Hugging Face أولاً من الزر الموجود في الأعلى."
78
  return
79
 
80
- # إعداد العميل (Client)
81
- client = InferenceClient(
82
- model="moonshotai/Kimi-K2-Instruct",
83
- token=hf_token.token
84
- )
85
-
86
- # 2. استخراج البيانات من رسالة المستخدم
87
  user_text = message.get("text", "")
88
  files = message.get("files", [])
89
 
90
- # 3. معالجة الملفات (إن وجدت)
91
  extracted_knowledge = ""
92
  if files:
93
- yield "⏳ **جاري تحليل الملفات وقراءة محتوياتها...**"
94
  for file_obj in files:
95
- # Gradio يعيد مسار الملف في file_obj أو file_obj['path']
96
  path = file_obj if isinstance(file_obj, str) else file_obj.name
97
  extracted_knowledge += extract_text_from_file(path)
 
 
98
 
99
- # 4. بناء الرسالة النهائية للنموذج
100
- full_prompt = ""
101
- if extracted_knowledge:
102
- full_prompt = f"البيانات المستخرجة من الملفات المرفقة:\n{extracted_knowledge}\n\n"
103
-
104
- full_prompt += f"سؤال/طلب المستخدم: {user_text}"
105
-
106
- # 5. تجهيز سجل المحادثة
107
  messages = [{"role": "system", "content": system_message}]
108
- messages.extend(history)
 
109
  messages.append({"role": "user", "content": full_prompt})
110
 
111
- # 6. البث المباشر للإجابة (Streaming)
112
- response_text = ""
113
  try:
114
- for msg in client.chat_completion(
115
- messages,
 
 
116
  max_tokens=max_tokens,
117
  stream=True,
118
- temperature=temperature,
119
- top_p=top_p,
120
- ):
121
- if msg.choices:
122
- token = msg.choices[0].delta.content
123
- if token:
124
- response_text += token
125
- yield response_text
126
  except Exception as e:
127
- yield f"⚠️ **حدث خطأ من المصدر:** {str(e)}\n\nتأكد من أن الملفات ليست ضخمة جداً (أكبر من سياق النموذج) أو حاول تقليل عدد الملفات."
128
 
129
- # --- واجهة المستخدم (UI) ---
130
- with gr.Blocks(theme=gr.themes.Soft(), title="Advanced AI Assistant") as demo:
131
- gr.Markdown(
132
- """
133
- # 🤖 المساعد الذكي المتكامل (تحليل ملفات + دردشة)
134
- قم برفع ملفات PDF, Word, أو ZIP (حتى لو كانت كبيرة) واسأل عنها مباشرة.
135
- """
136
- )
137
 
138
- with gr.Row():
139
- with gr.Column(scale=1):
140
- gr.LoginButton(value="تسجيل دخول Hugging Face")
141
-
142
- with gr.Accordion("⚙️ إعدادات النموذج", open=False):
143
- system_msg = gr.Textbox(
144
- value="أنت مساعد ذكي ومحلل بيانات خبير. قم بالإجابة باللغة العربية بوضوح.",
145
- label="تعليمات النظام (System Prompt)",
146
- lines=3
147
- )
148
- max_tokens = gr.Slider(512, 8192, value=2048, step=64, label="طول الإجابة (Max Tokens)")
149
- temperature = gr.Slider(0.1, 2.0, value=0.6, step=0.1, label="الإبداع (Temperature)")
150
-
151
- # ... تكملة السطر الأخير الذي توقف عندك
152
- top_p = gr.Slider(0.1, 1.0, value=0.9, step=0.05, label="Top-p")
153
 
154
- with gr.Column(scale=4):
155
- # إعداد واجهة الدردشة
156
- gr.ChatInterface(
157
- respond,
158
- chatbot=gr.Chatbot(height=600, type="messages"), # تحديد الطول والنوع
159
- type="messages",
160
- multimodal=True, # ضروري لظهور زر رفع الملفات
161
- additional_inputs=[system_msg, max_tokens, temperature, top_p],
162
- title="Kimi-K2 File Analysis Bot",
163
- description="ارفع ملفاتك (ZIP, PDF, DOCX) وسأقوم بتحليلها والإجابة عن أسئلتك.",
164
- )
165
 
166
  if __name__ == "__main__":
167
- demo.queue().launch()
168
-
 
1
  import gradio as gr
2
+ from openai import OpenAI # مكتبة OpenAI متوافقة مع Kimi
3
  import zipfile
4
  import os
5
+ import fitz
6
+ import docx
7
 
8
+ # إعداد العميل ليتصل بسيرفرات Moonshot مباشرة
9
+ # استبدل MOONSHOT_API_KEY بمفتاحك الخاص أو اجعل المستخدم يدخله
10
+ def get_client(api_key):
11
+ return OpenAI(
12
+ api_key=api_key,
13
+ base_url="https://api.moonshot.cn/v1",
14
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
+ # ... (دالة extract_text_from_file تبقى كما هي في الكود السابق)
 
17
 
18
+ def respond(message, history, system_message, max_tokens, temperature, api_key):
19
+ if not api_key:
20
+ yield "⚠️ يرجى إدخال Moonshot API Key الخاص بك."
 
 
 
 
 
 
 
 
 
21
  return
22
 
23
+ client = get_client(api_key)
 
 
 
 
 
 
24
  user_text = message.get("text", "")
25
  files = message.get("files", [])
26
 
 
27
  extracted_knowledge = ""
28
  if files:
29
+ yield "⏳ جاري قراءة الملفات بعمق عبر سيرفرات Moonshot..."
30
  for file_obj in files:
 
31
  path = file_obj if isinstance(file_obj, str) else file_obj.name
32
  extracted_knowledge += extract_text_from_file(path)
33
+
34
+ full_prompt = f"{extracted_knowledge}\n\nسؤال المستخدم: {user_text}"
35
 
 
 
 
 
 
 
 
 
36
  messages = [{"role": "system", "content": system_message}]
37
+ for msg in history:
38
+ messages.append(msg)
39
  messages.append({"role": "user", "content": full_prompt})
40
 
 
 
41
  try:
42
+ completion = client.chat.completions.create(
43
+ model="moonshot-v1-128k", # أو 32k أو 8k حسب المتاح لك
44
+ messages=messages,
45
+ temperature=temperature,
46
  max_tokens=max_tokens,
47
  stream=True,
48
+ )
49
+
50
+ response_text = ""
51
+ for chunk in completion:
52
+ delta = chunk.choices[0].delta.content
53
+ if delta:
54
+ response_text += delta
55
+ yield response_text
56
  except Exception as e:
57
+ yield f"⚠️ خطأ من مزود Moonshot: {str(e)}"
58
 
59
+ # واجهة المستخدم مع خانة لإدخال الـ API Key الخاص بـ Moonshot
60
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
61
+ gr.Markdown("# 🚀 Kimi-K2 Ultra Memory Assistant")
 
 
 
 
 
62
 
63
+ with gr.Sidebar():
64
+ api_key_input = gr.Textbox(label="Moonshot API Key", type="password", placeholder="sk-...")
65
+ system_msg = gr.Textbox(value="أنت مساعد خبير في تحليل البيانات.", label="System Prompt")
66
+ max_t = gr.Slider(512, 128000, value=4096, label="Max Tokens")
67
+ temp = gr.Slider(0.1, 1.5, value=0.7, label="Temperature")
 
 
 
 
 
 
 
 
 
 
68
 
69
+ gr.ChatInterface(
70
+ respond,
71
+ additional_inputs=[system_msg, max_t, temp, api_key_input],
72
+ multimodal=True,
73
+ type="messages"
74
+ )
 
 
 
 
 
75
 
76
  if __name__ == "__main__":
77
+ demo.launch()