AnesKAM commited on
Commit
8426012
·
verified ·
1 Parent(s): c98121b

Update server.js

Browse files
Files changed (1) hide show
  1. server.js +146 -305
server.js CHANGED
@@ -1,354 +1,195 @@
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
  });
 
1
+ import express from 'express';
2
+ import { Client } from '@gradio/client';
3
+ import cors from 'cors';
4
+ import { fileURLToPath } from 'url';
5
+ import { dirname, join } from 'path';
6
+
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = dirname(__filename);
9
+
10
  const app = express();
11
  const PORT = process.env.PORT || 7860;
12
 
13
+ app.use(cors());
 
14
  app.use(express.json());
15
+ app.use(express.static('public'));
16
 
17
+ // إعدادات النموذج
18
+ const MODEL_CONFIGS = {
19
+ flash: {
20
+ temperature: 1.0,
21
+ top_p: 0.95,
22
+ max_tokens: 2048,
23
+ system_message: "أنت مساعد ودود وسريع. اسمك MiniMax-M2.5. قدم إجابات مباشرة وواضحة. عندما تريد التفكير في مشكلة معقدة، استخدم علامة 'genisi thought' ثم اكتب تفكيرك، ثم 'genisi thought' للإغلاق.",
24
+ },
25
+ pro: {
26
+ temperature: 0.7,
27
+ top_p: 0.9,
28
+ max_tokens: 4096,
29
+ system_message: "أنت مساعد خبير ومحلل عميق. اسمك MiniMax-M2.5-Pro. استخدم علامة 'genisi thought' لتحليل المشكلات بعمق قبل الإجابة. اكتب 'genisi thought' ثم تفكيرك المفصل، ثم 'genisi thought' مرة أخرى. قدم حلولاً متقدمة ومفصلة مع أمثلة عملية.",
30
+ }
31
+ };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
 
33
  let currentMode = 'flash';
34
+ let gradioClient = null;
35
+
36
+ // الاتصال بـ MiniMax Space
37
+ async function getGradioClient() {
38
+ if (!gradioClient) {
39
+ try {
40
+ console.log('🔄 جاري الاتصال بـ MiniMax Space...');
41
+ gradioClient = await Client.connect("ostarling/MiniMax-M2.5-Chat");
42
+ console.log('✅ تم الاتصال بـ MiniMax M2.5 بنجاح');
43
+ } catch (error) {
44
+ console.error('❌ فشل الاتصال:', error);
45
+ throw error;
46
+ }
47
+ }
48
+ return gradioClient;
49
+ }
50
+
51
+ // دالة لاستدعاء النموذج
52
+ async function callMiniMax(message, mode) {
53
+ const config = MODEL_CONFIGS[mode];
54
+ const client = await getGradioClient();
55
+
56
+ try {
57
+ console.log(`📤 إرسال إلى MiniMax (وضع ${mode}):`, message);
58
+
59
+ const result = await client.predict("/respond", {
60
+ message: message,
61
+ system_message: config.system_message,
62
+ max_tokens: config.max_tokens,
63
+ temperature: config.temperature,
64
+ top_p: config.top_p
65
+ });
66
+
67
+ console.log('📥 استلام رد من MiniMax');
68
+ return result.data;
69
+ } catch (error) {
70
+ console.error('خطأ في predict:', error);
71
+ throw error;
72
+ }
73
+ }
74
 
75
+ // دالة لتحليل الرد واستخراج أجزاء التفكير
76
  function parseResponse(text) {
77
  const parts = [];
78
  const thoughtRegex = /genisi thought\s*([\s\S]*?)\s*genisi thought/gi;
79
  let lastIndex = 0;
80
  let match;
81
 
82
+ // إذا كان النص نصياً عادياً
83
+ if (typeof text !== 'string') {
84
+ text = JSON.stringify(text);
85
+ }
86
+
87
  while ((match = thoughtRegex.exec(text)) !== null) {
88
+ // النص قبل التفكير
89
  if (match.index > lastIndex) {
90
  const beforeText = text.substring(lastIndex, match.index).trim();
91
+ if (beforeText) {
92
+ parts.push({ type: 'text', content: beforeText });
93
+ }
94
  }
95
+
96
+ // محتوى التفكير
97
  const thoughtContent = match[1].trim();
98
+ if (thoughtContent) {
99
+ parts.push({ type: 'thought', content: thoughtContent });
100
+ }
101
+
102
  lastIndex = match.index + match[0].length;
103
  }
104
 
105
+ // باقي النص بعد آخر تفكير
106
  if (lastIndex < text.length) {
107
  const afterText = text.substring(lastIndex).trim();
108
+ if (afterText) {
109
+ parts.push({ type: 'text', content: afterText });
110
+ }
111
  }
112
 
113
+ // إذا لم يتم العثور على أي تفكير
114
+ if (parts.length === 0 && text) {
115
+ parts.push({ type: 'text', content: text });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  }
117
+
118
+ return parts;
119
  }
120
 
121
+ // API endpoint للدردشة
122
  app.post('/api/chat', async (req, res) => {
123
  const { message, mode } = req.body;
124
+
125
+ if (!message) {
126
+ return res.status(400).json({ error: 'الرسالة مطلوبة' });
127
+ }
128
+
129
  const activeMode = mode || currentMode;
130
+
131
+ try {
132
+ // استدعاء النموذج الحقيقي
133
+ const responseData = await callMiniMax(message, activeMode);
134
+
135
+ // استخراج النص من الاستجابة
136
+ let modelResponse = '';
137
+ if (Array.isArray(responseData) && responseData.length > 0) {
138
+ modelResponse = responseData[0];
139
+ } else if (typeof responseData === 'string') {
140
+ modelResponse = responseData;
141
+ } else {
142
+ modelResponse = JSON.stringify(responseData);
143
+ }
144
+
145
+ // تحليل الرد
146
+ const parsedResponse = parseResponse(modelResponse);
147
+
148
+ res.json({
149
+ success: true,
150
+ response: parsedResponse,
151
+ mode: activeMode,
152
+ rawResponse: modelResponse
153
+ });
154
+ } catch (error) {
155
+ console.error('خطأ:', error);
156
+ res.status(500).json({
157
+ success: false,
158
+ error: error.message
159
+ });
160
+ }
161
  });
162
 
163
+ // API endpoint لتغيير الوضع
164
  app.post('/api/mode', (req, res) => {
165
  const { mode } = req.body;
166
  if (mode === 'flash' || mode === 'pro') {
167
  currentMode = mode;
168
+ res.json({
169
+ success: true,
170
+ mode: currentMode,
171
+ config: MODEL_CONFIGS[mode]
172
+ });
173
  } else {
174
  res.status(400).json({ error: 'وضع غير صالح' });
175
  }
176
  });
177
 
178
+ // API endpoint للحصول على الوضع الحالي
179
  app.get('/api/mode', (req, res) => {
180
+ res.json({
181
+ mode: currentMode,
182
+ config: MODEL_CONFIGS[currentMode]
183
+ });
184
+ });
185
+
186
+ // صفحة رئيسية
187
+ app.get('/', (req, res) => {
188
+ res.sendFile(join(__dirname, 'public', 'index.html'));
189
  });
190
 
191
+ // بدء الخادم
192
  app.listen(PORT, '0.0.0.0', () => {
193
  console.log(`🚀 الخادم يعمل على http://localhost:${PORT}`);
194
+ console.log(`✅ Space جاهز: https://your-space.hf.space`);
195
  });