1yahoo commited on
Commit
492ea5a
·
verified ·
1 Parent(s): 46570d8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +82 -62
app.py CHANGED
@@ -7,17 +7,20 @@ from fastapi.middleware.cors import CORSMiddleware
7
  from openai import OpenAI
8
  from chromadb.utils import embedding_functions
9
 
10
- app = FastAPI(title="Neural OS - Deep Vault")
11
 
12
- # إعداد الذاكرة والعميل
13
  STORAGE_PATH = "/data/neural_memory" if os.path.exists("/data") else "./neural_memory"
14
  chroma_client = chromadb.PersistentClient(path=STORAGE_PATH)
15
  default_ef = embedding_functions.DefaultEmbeddingFunction()
16
- collection = chroma_client.get_or_create_collection(name="vault_v6", embedding_function=default_ef)
17
 
18
- client = OpenAI(base_url="https://router.huggingface.co/hf-inference/v1", api_key=os.getenv("HF_TOKEN"))
 
 
 
 
19
 
20
- # واجهة المستخدم الاحترافية (نسخة يوسف المفضلة)
21
  @app.get("/", response_class=HTMLResponse)
22
  async def get_ui():
23
  return """
@@ -26,30 +29,30 @@ async def get_ui():
26
  <head>
27
  <meta charset="UTF-8">
28
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
29
- <title>Deep Neural Vault | يوسف</title>
30
  <script src="https://cdn.tailwindcss.com"></script>
31
  <script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
32
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
33
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
34
  <link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans+Arabic:wght@300;400;600&display=swap" rel="stylesheet">
35
  <style>
36
- body { font-family: 'IBM Plex Sans Arabic', sans-serif; background: #020617; color: #f8fafc; overflow: hidden; }
37
- .neural-grid { background-image: radial-gradient(#1e293b 1px, transparent 1px); background-size: 30px 30px; }
38
- .glass-card { background: rgba(15, 23, 42, 0.7); backdrop-filter: blur(12px); border: 1px solid rgba(255,255,255,0.1); }
39
- @keyframes pulse { 0%, 100% { opacity: 0.5; } 50% { opacity: 1; transform: scale(1.1); } }
40
- .animate-neural { animation: pulse 2s infinite; }
41
  </style>
42
  </head>
43
- <body class="neural-grid">
44
  <div id="root"></div>
45
  <script type="text/babel">
46
- const { useState, useEffect, useRef } = React;
47
 
48
  function App() {
49
  const [messages, setMessages] = useState([]);
50
  const [input, setInput] = useState("");
51
- const [status, setStatus] = useState("idle"); // idle, thinking, memory
52
- const [files, setFiles] = useState([]);
 
53
 
54
  const sendMessage = async () => {
55
  if(!input.trim()) return;
@@ -62,7 +65,11 @@ async def get_ui():
62
  const response = await fetch('/v1/chat/completions', {
63
  method: 'POST',
64
  headers: {'Content-Type': 'application/json'},
65
- body: JSON.stringify({messages: [...messages, userMsg]})
 
 
 
 
66
  });
67
 
68
  const reader = response.body.getReader();
@@ -72,65 +79,76 @@ async def get_ui():
72
  while (true) {
73
  const {done, value} = await reader.read();
74
  if (done) break;
75
- const text = new TextDecoder().decode(value).replace(/data: /g, '').replace(/\\n\\n/g, '');
76
  if(text.includes("[DONE]")) break;
77
-
78
  botMsg.content += text;
79
  setMessages(prev => [...prev.slice(0, -1), {...botMsg}]);
80
- setStatus("memory");
81
  }
82
- } catch (e) { console.error(e); }
 
 
 
 
 
 
 
 
 
 
83
  setStatus("idle");
 
84
  };
85
 
86
  return (
87
- <div className="flex h-screen overflow-hidden">
88
- {/* القائمة الجانبية (خزنة المعرفة) */}
89
- <aside className="w-80 glass-card p-6 flex flex-col gap-6 hidden md:flex">
90
- <div className="flex items-center gap-3">
91
- <div className="p-2 bg-indigo-500/20 rounded-lg text-indigo-400">🧬</div>
92
- <h1 className="text-xl font-bold bg-gradient-to-r from-indigo-400 to-cyan-400 bg-clip-text text-transparent">Neural Vault</h1>
93
  </div>
94
 
95
- <div className="border-2 border-dashed border-slate-700 rounded-xl p-8 text-center hover:border-indigo-500 transition-colors cursor-pointer">
96
- <p className="text-sm text-slate-400">اسحب الملفات هنا (RAG)</p>
97
- </div>
98
-
99
- <div className="flex-1 overflow-y-auto space-y-2">
100
- <p className="text-xs text-slate-500 uppercase tracking-widest">المستندات المفهرسة</p>
101
- {files.length === 0 && <p className="text-sm text-slate-600 italic">الخزنة فارغة حالياً...</p>}
102
  </div>
103
  </aside>
104
 
105
- {/* منطقة الدردشة الرئيسية */}
106
- <main className="flex-1 flex flex-col relative">
107
- <header className="p-6 border-b border-white/5 flex justify-between items-center">
108
- <div className="flex items-center gap-4">
109
- <div className={`w-3 h-3 rounded-full ${status === 'thinking' ? 'bg-purple-500 animate-pulse' : status === 'memory' ? 'bg-cyan-500 animate-neural' : 'bg-slate-700'}`}></div>
110
- <span className="text-sm text-slate-400 font-mono">Status: {status}</span>
 
111
  </div>
112
  </header>
113
 
114
- <div className="flex-1 overflow-y-auto p-6 space-y-6 scroll-smooth">
115
  {messages.map((m, i) => (
116
- <div key={i} className={`flex ${m.role === 'user' ? 'justify-start' : 'justify-end animate-fade-in'}`}>
117
- <div className={`max-w-[80%] p-4 rounded-2xl ${m.role === 'user' ? 'bg-slate-800 text-slate-200' : 'bg-indigo-500/10 border border-indigo-500/20 text-indigo-100'}`}>
118
  {m.content}
119
  </div>
120
  </div>
121
  ))}
122
  </div>
123
 
124
- <div className="p-6 bg-slate-900/50 backdrop-blur-md">
125
- <div className="max-w-4xl mx-auto flex gap-4">
126
  <input
127
  value={input}
128
- onChange={(e) => setInput(e.target.value)}
129
- onKeyPress={(e) => e.key === 'Enter' && sendMessage()}
130
- placeholder="تحدث مع الوعي الاصطناعي..."
131
- className="flex-1 bg-slate-950/50 border border-white/10 rounded-xl px-6 py-4 focus:outline-none focus:border-indigo-500 transition-all shadow-2xl"
132
  />
133
- <button onClick={sendMessage} className="bg-indigo-600 hover:bg-indigo-500 px-8 rounded-xl font-bold transition-all shadow-lg shadow-indigo-500/20">إرسال</button>
 
 
134
  </div>
135
  </div>
136
  </main>
@@ -145,33 +163,35 @@ async def get_ui():
145
  </html>
146
  """
147
 
148
- # المسارات الخلفية (Backend)
 
 
 
 
 
 
 
149
  @app.post("/v1/chat/completions")
150
  async def chat_endpoint(request: Request):
151
  body = await request.json()
152
  messages = body.get("messages", [])
153
-
154
- # استرجاع المعرفة (RAG)
155
- user_query = messages[-1]["content"] if messages else ""
156
- results = collection.query(query_texts=[user_query], n_results=2)
157
- context = "\\n".join(results['documents'][0]) if results['documents'] else ""
158
-
159
- # حقن السياق
160
- full_messages = [{"role": "system", "content": f"Use this memory context: {context}"}] + messages
161
 
162
  def stream_gen():
 
163
  response = client.chat.completions.create(
164
  model="huihui-ai/Qwen2.5-72B-Instruct-abliterated",
165
- messages=full_messages,
 
166
  stream=True
167
  )
168
  for chunk in response:
169
  if chunk.choices[0].delta.content:
170
- yield f"data: {chunk.choices[0].delta.content}\\n\\n"
171
- yield "data: [DONE]\\n\\n"
172
 
173
  return StreamingResponse(stream_gen(), media_type="text/event-stream")
174
 
175
  if __name__ == "__main__":
176
  import uvicorn
177
- uvicorn.run(app, host="0.0.0.0", port=7860)
 
7
  from openai import OpenAI
8
  from chromadb.utils import embedding_functions
9
 
10
+ app = FastAPI()
11
 
12
+ # إعداد الذاكرة
13
  STORAGE_PATH = "/data/neural_memory" if os.path.exists("/data") else "./neural_memory"
14
  chroma_client = chromadb.PersistentClient(path=STORAGE_PATH)
15
  default_ef = embedding_functions.DefaultEmbeddingFunction()
16
+ collection = chroma_client.get_or_create_collection(name="vault_v7", embedding_function=default_ef)
17
 
18
+ # العميل - تم تصحيح المسار
19
+ client = OpenAI(
20
+ base_url="https://api-inference.huggingface.co/v1",
21
+ api_key=os.getenv("HF_TOKEN")
22
+ )
23
 
 
24
  @app.get("/", response_class=HTMLResponse)
25
  async def get_ui():
26
  return """
 
29
  <head>
30
  <meta charset="UTF-8">
31
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
32
+ <title>Deep Neural Vault</title>
33
  <script src="https://cdn.tailwindcss.com"></script>
34
  <script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
35
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
36
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
37
  <link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans+Arabic:wght@300;400;600&display=swap" rel="stylesheet">
38
  <style>
39
+ body { font-family: 'IBM Plex Sans Arabic', sans-serif; background: #020617; color: #f8fafc; }
40
+ .glass { background: rgba(15, 23, 42, 0.8); backdrop-filter: blur(10px); border: 1px solid rgba(255,255,255,0.05); }
41
+ .custom-scrollbar::-webkit-scrollbar { width: 4px; }
42
+ .custom-scrollbar::-webkit-scrollbar-thumb { background: #334155; border-radius: 10px; }
 
43
  </style>
44
  </head>
45
+ <body>
46
  <div id="root"></div>
47
  <script type="text/babel">
48
+ const { useState, useEffect } = React;
49
 
50
  function App() {
51
  const [messages, setMessages] = useState([]);
52
  const [input, setInput] = useState("");
53
+ const [status, setStatus] = useState("idle");
54
+ const [isSidebarOpen, setSidebarOpen] = useState(false);
55
+ const [settings, setSettings] = useState({ temp: 0.7, tokens: 2048 });
56
 
57
  const sendMessage = async () => {
58
  if(!input.trim()) return;
 
65
  const response = await fetch('/v1/chat/completions', {
66
  method: 'POST',
67
  headers: {'Content-Type': 'application/json'},
68
+ body: JSON.stringify({
69
+ messages: [...messages, userMsg],
70
+ temperature: settings.temp,
71
+ max_tokens: settings.tokens
72
+ })
73
  });
74
 
75
  const reader = response.body.getReader();
 
79
  while (true) {
80
  const {done, value} = await reader.read();
81
  if (done) break;
82
+ const text = new TextDecoder().decode(value).replace(/data: /g, '');
83
  if(text.includes("[DONE]")) break;
 
84
  botMsg.content += text;
85
  setMessages(prev => [...prev.slice(0, -1), {...botMsg}]);
 
86
  }
87
+ } catch (e) { console.error("Error:", e); }
88
+ setStatus("idle");
89
+ };
90
+
91
+ const uploadFile = async (e) => {
92
+ const file = e.target.files[0];
93
+ if(!file) return;
94
+ setStatus("thinking");
95
+ const fd = new FormData();
96
+ fd.append('file', file);
97
+ await fetch('/upload', { method: 'POST', body: fd });
98
  setStatus("idle");
99
+ alert("تمت الفهرسة");
100
  };
101
 
102
  return (
103
+ <div className="flex h-screen w-full overflow-hidden">
104
+ {/* القائمة الجانبية - متجاوبة */}
105
+ <aside className={`${isSidebarOpen ? 'translate-x-0' : 'translate-x-full'} fixed inset-y-0 right-0 z-50 w-72 glass p-6 transition-transform md:relative md:translate-x-0 flex flex-col gap-6`}>
106
+ <div className="flex justify-between items-center">
107
+ <h2 className="font-bold text-indigo-400">الإعدادات والذاكرة</h2>
108
+ <button className="md:hidden" onClick={() => setSidebarOpen(false)}>✕</button>
109
  </div>
110
 
111
+ <div className="space-y-4">
112
+ <label className="block text-xs text-slate-400 uppercase">الحرارة (الإبداع): {settings.temp}</label>
113
+ <input type="range" min="0" max="2" step="0.1" value={settings.temp} onChange={e => setSettings({...settings, temp: parseFloat(e.target.value)})} className="w-full h-1 bg-slate-700 rounded-lg appearance-none cursor-pointer" />
114
+
115
+ <label className="block text-xs text-slate-400 mt-4">رفع مستند (PDF/TXT)</label>
116
+ <input type="file" onChange={uploadFile} className="block w-full text-xs text-slate-400 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-xs file:bg-indigo-600 file:text-white hover:file:bg-indigo-500 cursor-pointer"/>
 
117
  </div>
118
  </aside>
119
 
120
+ {/* منطقة المحادثة */}
121
+ <main className="flex-1 flex flex-col w-full relative">
122
+ <header className="p-4 border-b border-white/5 flex justify-between items-center">
123
+ <button className="md:hidden p-2" onClick={() => setSidebarOpen(true)}>☰</button>
124
+ <div className="flex items-center gap-2">
125
+ <div className={`w-2 h-2 rounded-full ${status !== 'idle' ? 'bg-indigo-500 animate-pulse' : 'bg-slate-600'}`}></div>
126
+ <span className="text-xs font-mono">NEURAL_SYS: {status}</span>
127
  </div>
128
  </header>
129
 
130
+ <div className="flex-1 overflow-y-auto p-4 space-y-4 custom-scrollbar">
131
  {messages.map((m, i) => (
132
+ <div key={i} className={`flex ${m.role === 'user' ? 'justify-start' : 'justify-end'}`}>
133
+ <div className={`max-w-[90%] md:max-w-[70%] p-3 rounded-2xl text-sm ${m.role === 'user' ? 'bg-slate-800' : 'bg-indigo-900/30 border border-indigo-500/20'}`}>
134
  {m.content}
135
  </div>
136
  </div>
137
  ))}
138
  </div>
139
 
140
+ <div className="p-4 glass">
141
+ <div className="max-w-4xl mx-auto flex gap-2">
142
  <input
143
  value={input}
144
+ onChange={e => setInput(e.target.value)}
145
+ onKeyDown={e => e.key === 'Enter' && sendMessage()}
146
+ placeholder="اكتب شيئاً..."
147
+ className="flex-1 bg-slate-900 border border-white/10 rounded-xl px-4 py-3 text-sm focus:outline-none focus:border-indigo-500"
148
  />
149
+ <button onClick={sendMessage} className="bg-indigo-600 p-3 rounded-xl hover:bg-indigo-500 transition-colors">
150
+ <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path d="M5 12h14M12 5l7 7-7 7" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/></svg>
151
+ </button>
152
  </div>
153
  </div>
154
  </main>
 
163
  </html>
164
  """
165
 
166
+ @app.post("/upload")
167
+ async def upload_file(background_tasks: BackgroundTasks, file: UploadFile = File(...)):
168
+ content = await file.read()
169
+ # هنا يتم استدعاء وظيفة الـ Ingest التي كتبتها سابقاً
170
+ text = content.decode("utf-8", errors="ignore")
171
+ collection.add(documents=[text], ids=[str(uuid.uuid4())])
172
+ return {"status": "ok"}
173
+
174
  @app.post("/v1/chat/completions")
175
  async def chat_endpoint(request: Request):
176
  body = await request.json()
177
  messages = body.get("messages", [])
178
+ temp = body.get("temperature", 0.7)
 
 
 
 
 
 
 
179
 
180
  def stream_gen():
181
+ # استخدام موديل بديل إذا استمر الخطأ في Qwen
182
  response = client.chat.completions.create(
183
  model="huihui-ai/Qwen2.5-72B-Instruct-abliterated",
184
+ messages=messages,
185
+ temperature=temp,
186
  stream=True
187
  )
188
  for chunk in response:
189
  if chunk.choices[0].delta.content:
190
+ yield f"data: {chunk.choices[0].delta.content}\n\n"
191
+ yield "data: [DONE]\n\n"
192
 
193
  return StreamingResponse(stream_gen(), media_type="text/event-stream")
194
 
195
  if __name__ == "__main__":
196
  import uvicorn
197
+ uvicorn.run(app, host="0.0.0.0", port=7860)