File size: 3,742 Bytes
ec13f69
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
import React, { useState, useRef } from 'react';
import ChatMessage from './ChatMessage';

export default function App() {
  const [messages, setMessages] = useState([]);
  const [input, setInput] = useState('');
  const [model, setModel] = useState('glm-5.1');
  const [isLoading, setIsLoading] = useState(false);
  const messagesEndRef = useRef(null);

  const handleSend = async () => {
    if (!input.trim() || isLoading) return;

    const userMessage = { role: 'user', content: input };
    const newMessages = [...messages, userMessage];
    setMessages(newMessages);
    setInput('');
    setIsLoading(true);

    // إضافة رسالة بوت فارغة باش نبدأ نملأها
    setMessages(prev => [...prev, { role: 'assistant', content: '', thinking: '' }]);

    try {
      const response = await fetch('/api/chat', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ messages: newMessages, model })
      });

      const reader = response.body.getReader();
      const decoder = new TextDecoder();
      let fullText = '';
      let isThinking = false;
      let currentThinking = '';
      let currentContent = '';

      while (true) {
        const { done, value } = await reader.read();
        if (done) break;

        const chunk = decoder.decode(value, { stream: true });
        // تفكيك الـ Chunk (هذا يعتمد على كيفية إرسال HuggingFace للبيانات)
        // نفترض أن النموذج يرسل النص العادي أو بـ _XML tags للتفكير
        fullText += chunk; 

        // منطق استخراج التفكير (إذا استخدم النموذج <think)> أو <Scalars)
        if (fullText.includes("")) {
          const parts = fullText.split("");
          currentThinking = parts[0].replace("", "");
          currentContent = parts[1] || "";
        } else {
          currentContent = fullText;
        }

        // تحديث الرسالة الأخيرة في الواجهة
        setMessages(prev => {
          const updated = [...prev];
          updated[updated.length - 1] = { 
            role: 'assistant', 
            content: currentContent, 
            thinking: currentThinking 
          };
          return updated;
        });
      }
    } catch (error) {
      console.error('Error:', error);
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <div className="app-container">
      <div className="sidebar">
        <h1>AnesNT 🇩🇿</h1>
        <h3>Genisi AI</h3>
        <select value={model} onChange={(e) => setModel(e.target.value)}>
          <option value="gemma-4-31b">Gemma 4 31B (Flash)</option>
          <option value="glm-5.1">GLM 5.1 (Thinking)</option>
        </select>
        <button onClick={() => setMessages([])}>🗑️ مسح المحادثة</button>
      </div>
      
      <div className="chat-area">
        <div className="chat-header">
          <h2>Genisi AI - {model === 'glm-5.1' ? 'مفكر' : 'سريع'}</h2>
        </div>
        
        <div className="messages-container">
          {messages.map((msg, idx) => (
            <ChatMessage key={idx} message={msg} />
          ))}
          <div ref={messagesEndRef} />
        </div>

        <div className="input-area">
          <input 
            type="text" 
            value={input} 
            onChange={(e) => setInput(e.target.value)} 
            onKeyDown={(e) => e.key === 'Enter' && handleSend()}
            placeholder="اكتب رسالتك هنا..."
            disabled={isLoading}
          />
          <button onClick={handleSend} disabled={isLoading}>إرسال</button>
        </div>
      </div>
    </div>
  );
}