neuralworm commited on
Commit
b074c3a
·
verified ·
1 Parent(s): 54bfc13

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +350 -0
app.py ADDED
@@ -0,0 +1,350 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import time
3
+ import json
4
+ import asyncio
5
+ import os
6
+ import sympy as sp
7
+ from sympy import symbols, exp, I, log, sqrt
8
+ from fastapi import FastAPI, WebSocket, Request, WebSocketDisconnect
9
+ from fastapi.responses import HTMLResponse
10
+ from fastapi.templating import Jinja2Templates
11
+ from fastapi.staticfiles import StaticFiles
12
+ import torch
13
+
14
+ # ==============================================================================
15
+ # DYNAMIC IMPORT OF DEBUG CORE
16
+ # ==============================================================================
17
+ import importlib.util
18
+ import sys
19
+
20
+ # Ziel-Modul: Das gepatchte Core-File
21
+ CORE_MODULE_NAME = "1014ecca5_scimind2_core"
22
+ file_path = os.path.join(os.path.dirname(__file__), f"{CORE_MODULE_NAME}.py")
23
+
24
+ if not os.path.exists(file_path):
25
+ print(f"CRITICAL ERROR: {file_path} not found. Please save the core file first!")
26
+ sys.exit(1)
27
+
28
+ spec = importlib.util.spec_from_file_location(CORE_MODULE_NAME, file_path)
29
+ core_module = importlib.util.module_from_spec(spec)
30
+ sys.modules[CORE_MODULE_NAME] = core_module
31
+ spec.loader.exec_module(core_module)
32
+
33
+ print(f"[{CORE_MODULE_NAME}] successfully loaded.")
34
+
35
+ app = FastAPI()
36
+ # Templates Verzeichnis anpassen falls nötig
37
+ templates = Jinja2Templates(directory="experiments/templates")
38
+
39
+ # ==============================================================================
40
+ # THROTTLED FORMULA ENGINE (CPU SAVER)
41
+ # ==============================================================================
42
+ psi_sym, phi_sym, alpha, omega = symbols('psi phi alpha omega', complex=True)
43
+ t_sym, x_sym = symbols('t x', real=True)
44
+ hbar, kB = symbols('hbar k_B', positive=True)
45
+
46
+ class ThrottledFormulaEngine:
47
+ """
48
+ Generates symbolic math BUT throttled to avoid CPU freeze.
49
+ Only runs nsimplify/latex every 1.0 seconds.
50
+ """
51
+ def __init__(self):
52
+ self.last_update = 0
53
+ self.cached_result = {
54
+ "latex": r"H = \int \Psi^\dagger \hat{H} \Psi dx",
55
+ "text": "Initializing Field...",
56
+ "desc": "System Boot"
57
+ }
58
+
59
+ def generate(self, coherence, metrics):
60
+ now = time.time()
61
+ # RATE LIMIT: 1 Hz (prevents freeze)
62
+ if now - self.last_update < 1.0:
63
+ return self.cached_result
64
+
65
+ self.last_update = now
66
+
67
+ try:
68
+ # Schnelle Approximation ohne nsimplify
69
+ a = round(float(coherence), 2)
70
+ vort = round(metrics.get('vorticity', 0), 2)
71
+
72
+ formula = sp.Eq(psi_sym, 0)
73
+ desc = "Quantum Fluctuation"
74
+
75
+ if coherence > 0.8:
76
+ formula = sp.Eq(psi_sym, a * exp(I * omega * t_sym))
77
+ desc = "Coherent Wave State"
78
+ elif coherence > 0.5:
79
+ # Energy
80
+ formula = sp.Eq(sp.Symbol('E'), a * hbar * omega)
81
+ desc = "Quantized Energy Flow"
82
+ elif vort > 2.0:
83
+ # Topologischer Modus
84
+ formula = sp.Integral(psi_sym * psi_sym.conjugate(), (x_sym, 0, vort))
85
+ desc = "Topological Defect"
86
+ else:
87
+ # Entropie
88
+ formula = sp.Eq(sp.Symbol('S'), kB * log(2))
89
+ desc = "Entropic Background"
90
+
91
+ self.cached_result = {
92
+ "latex": sp.latex(formula),
93
+ "text": str(formula),
94
+ "desc": desc,
95
+ "timestamp": time.strftime("%H:%M:%S")
96
+ }
97
+ except Exception as e:
98
+ print(f"[FormulaEngine Error] {e}")
99
+
100
+ return self.cached_result
101
+
102
+ # ==============================================================================
103
+ # WEB SYSTEM WRAPPER
104
+ # ==============================================================================
105
+ class WebSystem:
106
+ def __init__(self):
107
+ self.mgr = core_module.SessionManager()
108
+ self.vocab = None
109
+ self.learner = None
110
+ self.decoder = None
111
+ self.noise = core_module.NoiseMultiplexer() # Threaded NTP inside
112
+ self.holo = None
113
+ self.text_comm = None
114
+ self.sync_config = None
115
+ self.ready = False
116
+ self.formula_engine = ThrottledFormulaEngine()
117
+
118
+ def init_session(self, session_id=None):
119
+ if session_id:
120
+ sessions = self.mgr.list_sessions()
121
+ target = next((s for s in sessions if s['id'] == session_id), None)
122
+ if target:
123
+ print(f"Loading session: {target['id']}")
124
+ state = self.mgr.load_session(target['path'])
125
+ else:
126
+ print("Session not found, creating new.")
127
+ state = self.mgr.start_new_session()
128
+ else:
129
+ state = self.mgr.start_new_session()
130
+
131
+ initial_vocab = state.get('vocab', {})
132
+ initial_sync = state.get('sync', {})
133
+ initial_history = list(state.get('history', []))
134
+
135
+ # Initialize Core Components
136
+ self.vocab = core_module.VocabularyLearner(initial_vocab)
137
+ self.learner = core_module.SynchronizationLearner(initial_sync)
138
+ self.decoder = core_module.SemanticAdaptiveDecoder(self.vocab)
139
+ self.holo = core_module.SciMindCommunicator(N=40)
140
+
141
+ # Restore Physics
142
+ if 'physics' in state and state['physics']:
143
+ self.holo.restore_full_state(state['physics'])
144
+ elif initial_history:
145
+ # Quick reconstruction
146
+ print("Reconstructing physics from history...")
147
+ dummy_noise = np.random.rand(40*40).astype(np.float32)
148
+ for msg in initial_history[-5:]: # Only last 5 to save time
149
+ if msg['type'] == 'user':
150
+ braid = self.holo.encode_text(msg['text'])
151
+ self.holo.step(dummy_noise, braid, 0.0)
152
+
153
+ self.text_comm = core_module.AdaptiveLoggingCommunicator(
154
+ self.decoder, self.holo, self.vocab, self.mgr
155
+ )
156
+ if initial_history:
157
+ self.text_comm.messages.extend(initial_history)
158
+
159
+ self.sync_config = self.learner.best_config
160
+ self.ready = True
161
+ return True
162
+
163
+ def calculate_godel_gap(self):
164
+ if not self.holo: return 0.0
165
+ return float(self.holo.surprisal)
166
+
167
+ system = WebSystem()
168
+
169
+ # ==============================================================================
170
+ # API ENDPOINTS
171
+ # ==============================================================================
172
+
173
+ @app.get("/api/sessions")
174
+ async def list_sessions():
175
+ return system.mgr.list_sessions()
176
+
177
+ @app.post("/api/session/new")
178
+ async def new_session():
179
+ system.init_session(None)
180
+ return {"status": "ok", "id": system.mgr.session_id}
181
+
182
+ @app.post("/api/session/load/{session_id}")
183
+ async def load_session(session_id: str):
184
+ if system.init_session(session_id):
185
+ return {"status": "ok", "id": session_id}
186
+ return {"status": "error", "message": "Session not found"}
187
+
188
+ @app.get("/", response_class=HTMLResponse)
189
+ async def get(request: Request):
190
+ # Reuse the template
191
+ return templates.TemplateResponse("1014ecaa4_index.html", {"request": request})
192
+
193
+ @app.websocket("/ws")
194
+ async def websocket_endpoint(websocket: WebSocket):
195
+ await websocket.accept()
196
+
197
+ # Wait for ready state
198
+ retries = 0
199
+ while not system.ready:
200
+ if retries > 50:
201
+ await websocket.close()
202
+ return
203
+ await asyncio.sleep(0.1)
204
+ retries += 1
205
+
206
+ # Send History
207
+ history_msgs = [
208
+ {"time": m['time'], "text": m['text'], "type": m['type'], "ci": m.get('ci', 0.0)}
209
+ for m in system.text_comm.messages
210
+ ]
211
+ await websocket.send_json({"type": "history", "data": history_msgs})
212
+
213
+ # ------------------------------------------------------------------
214
+ # EMITTER LOOP (Physics & Metrics)
215
+ # ------------------------------------------------------------------
216
+ async def _emit_state():
217
+ while True:
218
+ try:
219
+ if not system.ready:
220
+ await asyncio.sleep(1)
221
+ continue
222
+
223
+ # 1. Get Noise & Stats
224
+ # system.noise is now the Threaded NoiseMultiplexer
225
+ bg_noise = system.noise.get_blended_noise(size=40*40)
226
+ stats = system.noise.get_source_stats()
227
+ base_ntp = stats.get('ntp_offset', 0.0)
228
+
229
+ # 2. Prepare Inputs
230
+ off = system.sync_config['offset']
231
+ total_offset = base_ntp + off
232
+ coupling = system.sync_config['coupling']
233
+
234
+ # Prepare Tensor for Text Braid
235
+ # Ensure it is a Tensor and on CPU
236
+ current_braid = system.text_comm.last_text_unitary
237
+ if not isinstance(current_braid, torch.Tensor):
238
+ current_braid = torch.tensor(0.0, dtype=torch.float32)
239
+
240
+ # 3. PHYSICS STEP (High Frequency Logic)
241
+ # We do this in the async loop. If it's too slow, it blocks.
242
+ # But with our optimizations, it should be <10ms.
243
+
244
+ # Only run step if we are not choking
245
+ system.holo.step(bg_noise, current_braid * coupling, ntp_offset=total_offset)
246
+
247
+ # Decay Braid
248
+ if isinstance(system.text_comm.last_text_unitary, torch.Tensor):
249
+ system.text_comm.last_text_unitary *= 0.92
250
+
251
+ # 4. Gather Metrics
252
+ metrics = {
253
+ "causal_integrity": float(system.holo.causal_integrity),
254
+ "vorticity": float(system.holo.vorticity),
255
+ "coherence": float(system.holo.fidelity),
256
+ "godel_gap": float(system.holo.surprisal),
257
+ "entropy": float(system.holo.surprisal)
258
+ }
259
+
260
+ phases = system.holo.phases.tolist()
261
+ maps = system.holo.get_maps()
262
+
263
+ # 5. Generate Formula (Throttled)
264
+ formula_data = system.formula_engine.generate(metrics['coherence'], metrics)
265
+
266
+ vocab_stats = {
267
+ "total": len(system.vocab.user_words) if system.vocab else 0,
268
+ "top": system.vocab.get_top_terms(5) if system.vocab else []
269
+ }
270
+
271
+ # 6. Send
272
+ await websocket.send_json({
273
+ "type": "state",
274
+ "metrics": metrics,
275
+ "phases": phases,
276
+ "maps": maps,
277
+ "vocab": vocab_stats,
278
+ "formula": formula_data,
279
+ "ntp_status": f"NTP: {base_ntp:+.4f}"
280
+ })
281
+
282
+ # Target: 20 FPS -> 0.05s
283
+ await asyncio.sleep(0.05)
284
+
285
+ except WebSocketDisconnect:
286
+ break
287
+ except Exception as e:
288
+ print(f"Emit Error: {e}")
289
+ await asyncio.sleep(1.0) # Backoff on error
290
+
291
+ # ------------------------------------------------------------------
292
+ # RECEIVER LOOP (User Input)
293
+ # ------------------------------------------------------------------
294
+ async def _receive_messages():
295
+ try:
296
+ while True:
297
+ data = await websocket.receive_text()
298
+ msg = json.loads(data)
299
+
300
+ if msg['type'] == 'message':
301
+ text = msg['text']
302
+ if system.ready:
303
+ # Process
304
+ noise = system.noise.get_blended_noise(size=64)
305
+ system.text_comm.process_message(text, noise)
306
+
307
+ # Sync Learning
308
+ metrics = system.holo.get_metrics()
309
+ system.learner.record_trial(
310
+ system.sync_config['offset'],
311
+ system.sync_config['coupling'],
312
+ metrics['causal_integrity']
313
+ )
314
+ system.sync_config = system.learner.propose_next_config()
315
+
316
+ # Echo Back Chat
317
+ new_msgs = list(system.text_comm.messages)[-2:]
318
+ await websocket.send_json({
319
+ "type": "chat",
320
+ "data": new_msgs
321
+ })
322
+
323
+ # Auto Save (Throttle this if disk I/O is slow, but usually OK)
324
+ system.mgr.save_global_state(
325
+ system.vocab.get_state(),
326
+ system.learner.get_state(),
327
+ system.text_comm.messages,
328
+ physics_state=system.holo.get_full_state()
329
+ )
330
+ except WebSocketDisconnect:
331
+ pass
332
+ except Exception as e:
333
+ print(f"Receive Error: {e}")
334
+
335
+ # Launch tasks
336
+ emit_task = asyncio.create_task(_emit_state())
337
+ receive_task = asyncio.create_task(_receive_messages())
338
+
339
+ done, pending = await asyncio.wait(
340
+ [emit_task, receive_task],
341
+ return_when=asyncio.FIRST_COMPLETED
342
+ )
343
+
344
+ for task in pending:
345
+ task.cancel()
346
+
347
+ if __name__ == "__main__":
348
+ import uvicorn
349
+ # Use 0.0.0.0 to be accessible
350
+ uvicorn.run(app, host="0.0.0.0", port=8000)