AnesKAM commited on
Commit
a5f1ff9
·
verified ·
1 Parent(s): 48d7a15

Update server.js

Browse files
Files changed (1) hide show
  1. server.js +302 -227
server.js CHANGED
@@ -1,279 +1,354 @@
1
  const express = require('express');
2
- const cors = require('cors');
3
- const dotenv = require('dotenv');
4
-
5
- dotenv.config();
6
-
7
  const app = express();
8
- const PORT = process.env.PORT || 3000;
9
 
10
- app.use(cors());
11
- app.use(express.json());
12
  app.use(express.static('public'));
 
13
 
14
- // إعدادات النموذج
15
- const MODEL_CONFIGS = {
16
- flash: {
17
- temperature: 1.0,
18
- top_p: 0.95,
19
- max_tokens: 2048,
20
- system_message: "أنت مساعد ودود وسريع. اسمك MiniMax-M2.5. قدم إجابات مباشرة وواضحة. عندما تريد التفكير في مشكلة معقدة، استخدم علامة 'genisi thought' ثم اكتب تفكيرك، ثم 'genisi thought' للإغلاق.",
21
- },
22
- pro: {
23
- temperature: 0.7,
24
- top_p: 0.9,
25
- max_tokens: 4096,
26
- system_message: "أنت مساعد خبير ومحلل عميق. اسمك MiniMax-M2.5-Pro. استخدم علامة 'genisi thought' لتحليل المشكلات بعمق قبل الإجابة. اكتب 'genisi thought' ثم تفكيرك المفصل، ثم 'genisi thought' مرة أخرى.",
27
- }
28
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
 
30
- let currentMode = 'flash';
 
 
 
 
 
 
 
31
 
32
- // دالة لاستدعاء Gradio Space عبر REST API
33
- async function callGradioSpace(message, mode) {
34
- const SPACE_URL = "https://ostarling-minimax-m2-5-chat.hf.space";
35
- const config = MODEL_CONFIGS[mode];
36
-
37
- try {
38
- // الخطوة 1: إرسال الطلب والحصول على event_id
39
- const submitResponse = await fetch(`${SPACE_URL}/gradio_api/call/respond`, {
40
- method: 'POST',
41
- headers: {
42
- 'Content-Type': 'application/json',
43
- },
44
- body: JSON.stringify({
45
- data: [
46
- message,
47
- config.system_message,
48
- config.max_tokens,
49
- config.temperature,
50
- config.top_p
51
- ]
52
- })
53
- });
54
-
55
- if (!submitResponse.ok) {
56
- throw new Error(`فشل الإرسال: ${submitResponse.status}`);
57
- }
58
-
59
- const submitResult = await submitResponse.json();
60
- const eventId = submitResult.event_id;
61
-
62
- if (!eventId) {
63
- throw new Error('لم يتم استلام event_id');
64
- }
65
-
66
- // الخطوة 2: انتظار النتيجة
67
- let result = null;
68
- let attempts = 0;
69
- const maxAttempts = 30; // 30 ثانية كحد أقصى
70
-
71
- while (attempts < maxAttempts) {
72
- await new Promise(resolve => setTimeout(resolve, 1000)); // انتظر ثانية
73
-
74
- const resultResponse = await fetch(`${SPACE_URL}/gradio_api/call/respond/${eventId}`, {
75
- headers: {
76
- 'Accept': 'text/event-stream',
77
- }
78
- });
79
-
80
- const text = await resultResponse.text();
81
-
82
- // تحليل Server-Sent Events
83
- const lines = text.split('\n');
84
- for (const line of lines) {
85
- if (line.startsWith('data: ')) {
86
- try {
87
- const data = JSON.parse(line.slice(6));
88
- if (data.event === 'complete') {
89
- result = data.data;
90
- break;
91
  }
92
- } catch (e) {
93
- // تجاهل أخطاء التحليل
94
- }
95
  }
 
 
 
 
96
  }
97
-
98
- if (result) break;
99
- attempts++;
100
- }
101
-
102
- if (result && result[0]) {
103
- return result[0];
104
- } else {
105
- throw new Error('لم يتم استلام رد من النموذج');
106
- }
107
-
108
- } catch (error) {
109
- console.error('خطأ في الاتصال بـ Hugging Face:', error.message);
110
- // في حالة الفشل، استخدم ردود محاكاة
111
- return getMockResponse(message, mode);
112
- }
113
- }
114
-
115
- // ردود محاكاة للاختبار (في حالة عدم وجود اتصال)
116
- function getMockResponse(message, mode) {
117
- if (mode === 'pro') {
118
- return `genisi thought
119
- 📊 تحليل عميق للسؤال: "${message}"
120
-
121
- 🔍 الخطوة 1: فهم المتطلبات
122
- السؤال يتطلب تفكيراً استراتيجياً وتحليلاً متعدد الأبعاد.
123
-
124
- 💡 الخطوة 2: تقييم الخيارات
125
- هناك عدة جوانب يجب مراعاتها قبل الإجابة.
126
 
127
- 🎯 الخطوة 3: صياغة الحل الأمثل
128
- بناءً على التحليل، سأقدم لك إجابة شاملة.
129
-
130
- genisi thought
131
-
132
- الإجابة النهائية (وضع البرو):
133
-
134
- شكراً على سؤالك الممتاز! "${message}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
 
136
- هذه إجابة تفصيلية وشاملة مع تحليل عميق للموضوع. في وضع البرو، أركز على تقديم حلول متقدمة مع شرح وافي لكل خطوة.`;
137
- } else {
138
- return `⚡ رد سريع (وضع الفلاش):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
 
140
- بالنسبة لسؤالك: "${message}"
 
 
 
 
 
 
 
 
 
 
 
 
 
141
 
142
- هذه إجابة مباشرة وواضحة دون تفكير مطول. وضع الفلاش مناسب للمحادثات السريعة.`;
143
- }
144
- }
145
 
146
- // دالة لتحليل نص الرد واستخراج أجزاء التفكير
147
  function parseResponse(text) {
148
  const parts = [];
149
-
150
- // البحث عن علامات genisi thought
151
  const thoughtRegex = /genisi thought\s*([\s\S]*?)\s*genisi thought/gi;
152
  let lastIndex = 0;
153
  let match;
154
 
155
- let tempText = text;
156
-
157
- while ((match = thoughtRegex.exec(tempText)) !== null) {
158
- // النص قبل التفكير
159
  if (match.index > lastIndex) {
160
- const beforeText = tempText.substring(lastIndex, match.index).trim();
161
- if (beforeText) {
162
- parts.push({
163
- type: 'text',
164
- content: beforeText
165
- });
166
- }
167
  }
168
-
169
- // محتوى التفكير
170
  const thoughtContent = match[1].trim();
171
- if (thoughtContent) {
172
- parts.push({
173
- type: 'thought',
174
- content: thoughtContent
175
- });
176
- }
177
-
178
  lastIndex = match.index + match[0].length;
179
  }
180
 
181
- // باقي النص بعد آخر تفكير
182
- if (lastIndex < tempText.length) {
183
- const afterText = tempText.substring(lastIndex).trim();
184
- if (afterText) {
185
- parts.push({
186
- type: 'text',
187
- content: afterText
188
- });
189
- }
190
- }
191
-
192
- // إذا لم يتم العثور على أي تفكير
193
- if (parts.length === 0 && tempText) {
194
- parts.push({
195
- type: 'text',
196
- content: tempText
197
- });
198
  }
199
 
 
200
  return parts;
201
  }
202
 
203
- // API endpoint للدردشة
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
  app.post('/api/chat', async (req, res) => {
205
  const { message, mode } = req.body;
206
-
207
- if (!message) {
208
- return res.status(400).json({ error: 'الرسالة مطلوبة' });
209
- }
210
-
211
  const activeMode = mode || currentMode;
212
-
213
- try {
214
- // محاولة الاتصال بـ Hugging Face Space
215
- let modelResponse;
216
- try {
217
- modelResponse = await callGradioSpace(message, activeMode);
218
- console.log('تم الاتصال بـ Hugging Face بنجاح');
219
- } catch (apiError) {
220
- console.log('استخدام الردود المحاكاة بسبب خطأ:', apiError.message);
221
- modelResponse = getMockResponse(message, activeMode);
222
- }
223
-
224
- // تحليل الرد لاستخراج أجزاء التفكير
225
- const parsedResponse = parseResponse(modelResponse);
226
-
227
- res.json({
228
- success: true,
229
- response: parsedResponse,
230
- mode: activeMode,
231
- rawResponse: modelResponse
232
- });
233
- } catch (error) {
234
- console.error('خطأ:', error);
235
- res.status(500).json({
236
- success: false,
237
- error: error.message
238
- });
239
- }
240
  });
241
 
242
- // API endpoint لتغيير الوضع
243
  app.post('/api/mode', (req, res) => {
244
  const { mode } = req.body;
245
  if (mode === 'flash' || mode === 'pro') {
246
  currentMode = mode;
247
- res.json({
248
- success: true,
249
- mode: currentMode,
250
- config: MODEL_CONFIGS[mode]
251
- });
252
  } else {
253
  res.status(400).json({ error: 'وضع غير صالح' });
254
  }
255
  });
256
 
257
- // API endpoint للحصول على الوضع الحالي
258
  app.get('/api/mode', (req, res) => {
259
- res.json({
260
- mode: currentMode,
261
- config: MODEL_CONFIGS[currentMode]
262
- });
263
- });
264
-
265
- // API endpoint للصحة
266
- app.get('/api/health', (req, res) => {
267
- res.json({
268
- status: 'running',
269
- mode: currentMode,
270
- timestamp: new Date().toISOString()
271
- });
272
  });
273
 
274
- // بدء الخادم
275
  app.listen(PORT, '0.0.0.0', () => {
276
  console.log(`🚀 الخادم يعمل على http://localhost:${PORT}`);
277
- console.log(`📌 الوضع الحالي: ${currentMode}`);
278
- console.log(`✅ جاهز للاستخدام!`);
279
  });
 
1
  const express = require('express');
2
+ const path = require('path');
 
 
 
 
3
  const app = express();
4
+ const PORT = process.env.PORT || 7860;
5
 
6
+ // خدمة الملفات الثابتة
 
7
  app.use(express.static('public'));
8
+ app.use(express.json());
9
 
10
+ // صفحة HTML بسيطة مدمجة
11
+ app.get('/', (req, res) => {
12
+ res.send(`
13
+ <!DOCTYPE html>
14
+ <html dir="rtl">
15
+ <head>
16
+ <meta charset="UTF-8">
17
+ <title>MiniMax Chat</title>
18
+ <style>
19
+ * { margin: 0; padding: 0; box-sizing: border-box; }
20
+ body {
21
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
22
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
23
+ min-height: 100vh;
24
+ display: flex;
25
+ justify-content: center;
26
+ align-items: center;
27
+ padding: 20px;
28
+ }
29
+ .container {
30
+ background: white;
31
+ border-radius: 20px;
32
+ width: 100%;
33
+ max-width: 800px;
34
+ height: 90vh;
35
+ display: flex;
36
+ flex-direction: column;
37
+ overflow: hidden;
38
+ box-shadow: 0 20px 60px rgba(0,0,0,0.3);
39
+ }
40
+ .header {
41
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
42
+ color: white;
43
+ padding: 20px;
44
+ text-align: center;
45
+ }
46
+ .mode-buttons {
47
+ display: flex;
48
+ gap: 10px;
49
+ padding: 10px 20px;
50
+ background: #f8f9fa;
51
+ }
52
+ .mode-btn {
53
+ flex: 1;
54
+ padding: 10px;
55
+ border: none;
56
+ border-radius: 10px;
57
+ cursor: pointer;
58
+ font-weight: bold;
59
+ transition: all 0.3s;
60
+ }
61
+ .mode-btn.flash {
62
+ background: #ffd93d;
63
+ color: #8b6b00;
64
+ }
65
+ .mode-btn.pro {
66
+ background: #4a90e2;
67
+ color: white;
68
+ }
69
+ .mode-btn.active {
70
+ transform: scale(0.95);
71
+ box-shadow: 0 2px 8px rgba(0,0,0,0.2);
72
+ }
73
+ .chat-messages {
74
+ flex: 1;
75
+ overflow-y: auto;
76
+ padding: 20px;
77
+ background: #f0f2f5;
78
+ }
79
+ .message {
80
+ display: flex;
81
+ margin-bottom: 15px;
82
+ animation: slideIn 0.3s ease;
83
+ }
84
+ @keyframes slideIn {
85
+ from { opacity: 0; transform: translateY(20px); }
86
+ to { opacity: 1; transform: translateY(0); }
87
+ }
88
+ .message.user {
89
+ flex-direction: row-reverse;
90
+ }
91
+ .message-content {
92
+ max-width: 70%;
93
+ padding: 10px 15px;
94
+ border-radius: 15px;
95
+ background: white;
96
+ box-shadow: 0 1px 2px rgba(0,0,0,0.1);
97
+ }
98
+ .message.user .message-content {
99
+ background: #4a90e2;
100
+ color: white;
101
+ }
102
+ .thought-container {
103
+ background: #fff3e0;
104
+ border-right: 4px solid #ff9800;
105
+ padding: 12px;
106
+ margin: 10px 0;
107
+ border-radius: 10px;
108
+ }
109
+ .thought-header {
110
+ display: flex;
111
+ align-items: center;
112
+ gap: 8px;
113
+ color: #ff9800;
114
+ font-weight: bold;
115
+ margin-bottom: 8px;
116
+ }
117
+ .input-area {
118
+ padding: 20px;
119
+ border-top: 1px solid #e0e0e0;
120
+ display: flex;
121
+ gap: 10px;
122
+ background: white;
123
+ }
124
+ textarea {
125
+ flex: 1;
126
+ padding: 10px;
127
+ border: 2px solid #e0e0e0;
128
+ border-radius: 10px;
129
+ resize: none;
130
+ font-family: inherit;
131
+ }
132
+ button {
133
+ padding: 10px 20px;
134
+ background: #4a90e2;
135
+ color: white;
136
+ border: none;
137
+ border-radius: 10px;
138
+ cursor: pointer;
139
+ font-weight: bold;
140
+ }
141
+ .status {
142
+ padding: 8px 20px;
143
+ font-size: 12px;
144
+ color: #6c757d;
145
+ background: #f8f9fa;
146
+ text-align: center;
147
+ }
148
+ </style>
149
+ </head>
150
+ <body>
151
+ <div class="container">
152
+ <div class="header">
153
+ <h2>🤖 MiniMax M2.5</h2>
154
+ <p>شات بوت مع تفكير متقدم</p>
155
+ </div>
156
+ <div class="mode-buttons">
157
+ <button id="flashBtn" class="mode-btn flash active">⚡ وضع الفلاش</button>
158
+ <button id="proBtn" class="mode-btn pro">🚀 وضع البرو</button>
159
+ </div>
160
+ <div class="chat-messages" id="chatMessages">
161
+ <div class="message bot">
162
+ <div class="message-content">مرحباً! كيف يمكنني مساعدتك؟</div>
163
+ </div>
164
+ </div>
165
+ <div class="input-area">
166
+ <textarea id="userInput" placeholder="اكتب رسالتك هنا..." rows="2"></textarea>
167
+ <button id="sendBtn">إرسال 📤</button>
168
+ </div>
169
+ <div class="status" id="status">✅ جاهز للحديث | الوضع الحالي: فلاش</div>
170
+ </div>
171
 
172
+ <script>
173
+ let currentMode = 'flash';
174
+ const chatMessages = document.getElementById('chatMessages');
175
+ const userInput = document.getElementById('userInput');
176
+ const sendBtn = document.getElementById('sendBtn');
177
+ const flashBtn = document.getElementById('flashBtn');
178
+ const proBtn = document.getElementById('proBtn');
179
+ const statusDiv = document.getElementById('status');
180
 
181
+ function addMessage(text, isUser = false, parts = null) {
182
+ const messageDiv = document.createElement('div');
183
+ messageDiv.className = 'message ' + (isUser ? 'user' : 'bot');
184
+ const contentDiv = document.createElement('div');
185
+ contentDiv.className = 'message-content';
186
+
187
+ if (isUser) {
188
+ contentDiv.textContent = text;
189
+ } else if (parts && Array.isArray(parts)) {
190
+ parts.forEach(part => {
191
+ if (part.type === 'thought') {
192
+ const thoughtDiv = document.createElement('div');
193
+ thoughtDiv.className = 'thought-container';
194
+ thoughtDiv.innerHTML = '<div class="thought-header">🧠 تفكير النموذج (genisi thought)</div>' +
195
+ '<div>' + part.content + '</div>';
196
+ contentDiv.appendChild(thoughtDiv);
197
+ } else if (part.type === 'text' && part.content) {
198
+ const textDiv = document.createElement('div');
199
+ textDiv.textContent = part.content;
200
+ contentDiv.appendChild(textDiv);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
  }
202
+ });
203
+ } else {
204
+ contentDiv.textContent = text;
205
  }
206
+
207
+ messageDiv.appendChild(contentDiv);
208
+ chatMessages.appendChild(messageDiv);
209
+ chatMessages.scrollTop = chatMessages.scrollHeight;
210
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
211
 
212
+ async function sendMessage() {
213
+ const message = userInput.value.trim();
214
+ if (!message) return;
215
+
216
+ addMessage(message, true);
217
+ userInput.value = '';
218
+ statusDiv.textContent = '🤔 جاري المعالجة...';
219
+
220
+ try {
221
+ const response = await fetch('/api/chat', {
222
+ method: 'POST',
223
+ headers: { 'Content-Type': 'application/json' },
224
+ body: JSON.stringify({ message, mode: currentMode })
225
+ });
226
+
227
+ const data = await response.json();
228
+ if (data.success) {
229
+ addMessage('', false, data.response);
230
+ statusDiv.textContent = '✅ تم الرد | الوضع: ' + (data.mode === 'flash' ? 'فلاش' : 'برو');
231
+ } else {
232
+ addMessage('عذراً، حدث خطأ. حاول مرة أخرى.', false);
233
+ statusDiv.textContent = '❌ خطأ في الاستجابة';
234
+ }
235
+ } catch (error) {
236
+ addMessage('خطأ في الاتصال بالخادم.', false);
237
+ statusDiv.textContent = '❌ فشل الاتصال';
238
+ }
239
+ }
240
 
241
+ async function setMode(mode) {
242
+ try {
243
+ const response = await fetch('/api/mode', {
244
+ method: 'POST',
245
+ headers: { 'Content-Type': 'application/json' },
246
+ body: JSON.stringify({ mode })
247
+ });
248
+ if (response.ok) {
249
+ currentMode = mode;
250
+ if (mode === 'flash') {
251
+ flashBtn.classList.add('active');
252
+ proBtn.classList.remove('active');
253
+ statusDiv.textContent = '✅ تم التبديل إلى وضع الفلاش - ردود سريعة';
254
+ } else {
255
+ proBtn.classList.add('active');
256
+ flashBtn.classList.remove('active');
257
+ statusDiv.textContent = '✅ تم التبديل إلى وضع البرو - تفكير عميق';
258
+ }
259
+ }
260
+ } catch (error) {
261
+ console.error('خطأ في تغيير الوضع:', error);
262
+ }
263
+ }
264
 
265
+ sendBtn.addEventListener('click', sendMessage);
266
+ flashBtn.addEventListener('click', () => setMode('flash'));
267
+ proBtn.addEventListener('click', () => setMode('pro'));
268
+ userInput.addEventListener('keypress', (e) => {
269
+ if (e.key === 'Enter' && !e.shiftKey) {
270
+ e.preventDefault();
271
+ sendMessage();
272
+ }
273
+ });
274
+ </script>
275
+ </body>
276
+ </html>
277
+ `);
278
+ });
279
 
280
+ // API endpoints
281
+ let currentMode = 'flash';
 
282
 
 
283
  function parseResponse(text) {
284
  const parts = [];
 
 
285
  const thoughtRegex = /genisi thought\s*([\s\S]*?)\s*genisi thought/gi;
286
  let lastIndex = 0;
287
  let match;
288
 
289
+ while ((match = thoughtRegex.exec(text)) !== null) {
 
 
 
290
  if (match.index > lastIndex) {
291
+ const beforeText = text.substring(lastIndex, match.index).trim();
292
+ if (beforeText) parts.push({ type: 'text', content: beforeText });
 
 
 
 
 
293
  }
 
 
294
  const thoughtContent = match[1].trim();
295
+ if (thoughtContent) parts.push({ type: 'thought', content: thoughtContent });
 
 
 
 
 
 
296
  lastIndex = match.index + match[0].length;
297
  }
298
 
299
+ if (lastIndex < text.length) {
300
+ const afterText = text.substring(lastIndex).trim();
301
+ if (afterText) parts.push({ type: 'text', content: afterText });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
302
  }
303
 
304
+ if (parts.length === 0 && text) parts.push({ type: 'text', content: text });
305
  return parts;
306
  }
307
 
308
+ function generateResponse(message, mode) {
309
+ if (mode === 'pro') {
310
+ return `genisi thought
311
+ 🧠 تحليل لسؤالك: "${message}"
312
+
313
+ أفكر في:
314
+ 1. فهم المشكلة
315
+ 2. تحليل الحلول
316
+ 3. تقديم الإجابة المثلى
317
+ genisi thought
318
+
319
+ ✨ إجابة وضع البرو:
320
+ شكراً لسؤالك! "${message}" هو سؤال ممتاز. هذه إجابة مفصلة وشاملة.`;
321
+ } else {
322
+ return `⚡ رد سريع من وضع الفلاش:
323
+ سؤالك: "${message}" - هذه إجابة مباشرة وواضحة.`;
324
+ }
325
+ }
326
+
327
  app.post('/api/chat', async (req, res) => {
328
  const { message, mode } = req.body;
329
+ if (!message) return res.status(400).json({ error: 'الرسالة مطلوبة' });
 
 
 
 
330
  const activeMode = mode || currentMode;
331
+ await new Promise(resolve => setTimeout(resolve, 200));
332
+ const response = generateResponse(message, activeMode);
333
+ const parsed = parseResponse(response);
334
+ res.json({ success: true, response: parsed, mode: activeMode });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
335
  });
336
 
 
337
  app.post('/api/mode', (req, res) => {
338
  const { mode } = req.body;
339
  if (mode === 'flash' || mode === 'pro') {
340
  currentMode = mode;
341
+ res.json({ success: true, mode: currentMode });
 
 
 
 
342
  } else {
343
  res.status(400).json({ error: 'وضع غير صالح' });
344
  }
345
  });
346
 
 
347
  app.get('/api/mode', (req, res) => {
348
+ res.json({ mode: currentMode });
 
 
 
 
 
 
 
 
 
 
 
 
349
  });
350
 
 
351
  app.listen(PORT, '0.0.0.0', () => {
352
  console.log(`🚀 الخادم يعمل على http://localhost:${PORT}`);
353
+ console.log(` افتح المتصفح على هذا الرابط: http://localhost:${PORT}`);
 
354
  });