everydaytok commited on
Commit
9feb5de
Β·
verified Β·
1 Parent(s): ae2bf63

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +105 -65
app.py CHANGED
@@ -10,7 +10,8 @@ Architecture:
10
  """
11
 
12
  import os, time, threading, json, re, textwrap, copy
13
- import traceback, html, itertools, math
 
14
  from collections import deque, defaultdict
15
  from typing import Dict, List, Tuple, Any, Optional, Set
16
  from dataclasses import dataclass, field
@@ -159,7 +160,6 @@ def build_core_problem(axl_def: AXLProblemDef) -> core.Problem:
159
  var_names = list(bounds.keys())
160
  compiled_constraints = []
161
 
162
- # Bug 2 Fix: Safe, mathematically accurate EQ/GEQ/LEQ kinds translation
163
  kind_map = {'EQ': 'equality', 'GEQ': 'inequality', 'LEQ': 'inequality'}
164
  dir_map = {'EQ': 'eq', 'GEQ': 'geq', 'LEQ': 'leq'}
165
 
@@ -176,20 +176,68 @@ def build_core_problem(axl_def: AXLProblemDef) -> core.Problem:
176
  return prob
177
 
178
  # ══════════════════════════════════════════════════════════════════════
179
- # SECTION 3: LLM BRIDGE
180
  # ══════════════════════════════════════════════════════════════════════
181
- def encode_problem(text: str, api_key: str) -> AXLProblemDef:
182
- client = genai.Client(api_key=api_key)
183
- config = types.GenerateContentConfig(
184
- system_instruction=[types.Part.from_text(text=oracle.ENCODER_PROMPT)],
185
- response_mime_type="application/json", temperature=0.1)
186
- resp = client.models.generate_content(
187
- model=GEMINI_MODEL,
188
- contents=[types.Content(role="user", parts=[types.Part.from_text(text=text)])],
189
- config=config)
190
-
191
- raw = resp.text.strip()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
  if raw.startswith("```json"): raw = raw[7:-3]
 
193
  d = json.loads(raw.strip())
194
 
195
  if "error" in d: raise ValueError(f"Isomorphism Invalid: {d['error']} - {d.get('reason', '')}")
@@ -204,36 +252,39 @@ def encode_problem(text: str, api_key: str) -> AXLProblemDef:
204
  scopes=[], anchors=anchors, observations=d.get("observations", {})
205
  )
206
 
207
- def collapse_solution(payload: dict, api_key: str) -> str:
208
- client = genai.Client(api_key=api_key)
209
- config = types.GenerateContentConfig(
210
- system_instruction=[types.Part.from_text(text=oracle.COLLAPSER_PROMPT)],
211
- temperature=0.2)
212
- resp = client.models.generate_content(
213
- model=GEMINI_MODEL,
214
- contents=[types.Content(role="user", parts=[types.Part.from_text(text=json.dumps(payload))])],
215
- config=config)
 
 
 
 
 
 
216
 
217
- raw = resp.text.strip()
218
  if raw.startswith("```json"): raw = raw[7:-3]
 
219
 
220
  try:
221
  data = json.loads(raw.strip())
222
  md = data.get("hypothesis_markdown", "No markdown generated.")
223
  return md
224
  except:
225
- return "JSON Decode Error from Collapser. Raw:\n" + resp.text
226
 
227
  # ══════════════════════════════════════════════════════════════════════
228
  # SECTION 4: THE ORCHESTRATOR LOOP
229
  # ══════════════════════════════════════════════════════════════════════
230
-
231
- # Bug 1 Fix: Explicit, exact integer-propagation solve callback
232
  def quick_solver_callback(axl_def: AXLProblemDef, N: int) -> Dict[str, float]:
233
  try:
234
  prob = build_core_problem(axl_def)
235
-
236
- # Pull integer vars bounded up to width 100
237
  int_vars = [v for v in prob.variables if v in prob.int_vars
238
  and math.isfinite(prob.bounds[v][0])
239
  and prob.bounds[v][1] - prob.bounds[v][0] <= 100]
@@ -245,13 +296,13 @@ def quick_solver_callback(axl_def: AXLProblemDef, N: int) -> Dict[str, float]:
245
  hi = int(math.floor(prob.bounds[v][1]))
246
  grids.append([(v, float(val)) for val in range(lo, hi+1)])
247
 
 
248
  for combo in itertools.product(*grids):
249
  pinned = dict(combo)
250
  resolved, _ = core.algebraic_propagate_pinned(prob, pinned)
251
  ok, msg = oracle.ground_truth_verify(resolved, N)
252
  if ok: return resolved
253
  else:
254
- # 1D single-parameter search (e.g. 1D Sine Snap)
255
  if 't' in prob.variables:
256
  lo, hi = prob.bounds['t']
257
  for t_val in range(max(2, int(lo)), min(100, int(hi)) + 1):
@@ -259,7 +310,6 @@ def quick_solver_callback(axl_def: AXLProblemDef, N: int) -> Dict[str, float]:
259
  resolved, _ = core.algebraic_propagate_pinned(prob, pinned)
260
  ok, msg = oracle.ground_truth_verify(resolved, N)
261
  if ok: return resolved
262
- # s, d Fermat grid search
263
  if 's' in prob.variables and 'd' in prob.variables:
264
  lo_s, hi_s = prob.bounds['s']
265
  lo_d, hi_d = prob.bounds['d']
@@ -274,7 +324,9 @@ def quick_solver_callback(axl_def: AXLProblemDef, N: int) -> Dict[str, float]:
274
  print(f"Quick solver callback error: {e}")
275
  return {}
276
 
277
- def global_solve_task(original_text: str, api_key: str, template_name: str = None):
 
 
278
  _update_state(
279
  is_running=True, phase="ENCODING", high_level_logs=[], answer="",
280
  best_ce=float('inf'), total_fired=0, best_ray="β€”",
@@ -288,8 +340,7 @@ def global_solve_task(original_text: str, api_key: str, template_name: str = Non
288
  template_text = oracle.STRUCTURAL_HYPOTHESIS_TEMPLATES[template_name]
289
  axl_def = parse_template_as_axl(template_text)
290
  else:
291
- _add_log("LLM Encoding Isomorphism...")
292
- axl_def = encode_problem(original_text, api_key)
293
 
294
  _add_log(f"`{axl_def.name}` | {len(axl_def.variables)} vars")
295
  if axl_def.minimize_var: _add_log(f" MINIMIZE: {axl_def.minimize_var}")
@@ -311,14 +362,11 @@ def global_solve_task(original_text: str, api_key: str, template_name: str = Non
311
  _update_state(phase="RAY TRACING")
312
  base_prob = build_core_problem(axl_def)
313
 
314
- # Setup initial seeds & execute exhaustive templates
315
  init_b, init_ce = axioms._mprt_sample(base_prob, 1000)
316
  _add_log("Searching continuous relaxation...")
317
 
318
  templates = axioms.generate_templates(base_prob, axioms.compute_sketch(base_prob))
319
- _add_log(f"Assembled {len(templates)} integer grid mappings.")
320
 
321
- # Restoring full 27.7 Ray Tracer engine with bandit feedback & batons
322
  tracer = axioms.SequenceRayTracer(
323
  log_callback=_add_log,
324
  update_state_callback=lambda **kwargs: _update_state(**kwargs)
@@ -351,7 +399,7 @@ def global_solve_task(original_text: str, api_key: str, template_name: str = Non
351
  "infeasibility_report": GLOBAL_SOLVE_STATE["infeasibility_report"]
352
  }
353
 
354
- ans = collapse_solution(payload, api_key)
355
  _update_state(answer=ans, raw_results_json=json.dumps(payload, indent=2), phase="DONE")
356
  _add_log("Pipeline Complete.")
357
 
@@ -367,15 +415,14 @@ def global_solve_task(original_text: str, api_key: str, template_name: str = Non
367
  finally:
368
  _update_state(is_running=False)
369
 
370
- def trigger_solve(problem_text, api_key):
371
  if GLOBAL_SOLVE_STATE["is_running"] or not problem_text.strip(): return
372
- threading.Thread(target=global_solve_task, args=(problem_text, api_key), daemon=True).start()
373
 
374
- def trigger_hyp_solve(template_name, api_key):
375
  if GLOBAL_SOLVE_STATE["is_running"]: return
376
- threading.Thread(target=global_solve_task, args=("", api_key, template_name), daemon=True).start()
377
 
378
- # Bug 3 Fix: Shors Demo imports directly from oracle without ModuleNotFoundError
379
  def run_quantum_demo():
380
  _update_state(is_running=True, phase="QUANTUM SIMULATION", answer="Running Physics Simulator...\nCheck console for output.", high_level_logs=[])
381
  def _run():
@@ -452,12 +499,12 @@ def _reset(c):
452
  c.update({"finalized": False, "ans": "", "raw": ""})
453
  return c
454
 
455
- def handle_solve(text, key, cache):
456
- trigger_solve(text, key)
457
  return _reset(cache)
458
 
459
- def handle_hyp_solve(name, key, cache):
460
- trigger_hyp_solve(name, key)
461
  return _reset(cache)
462
 
463
  def handle_q_run(cache):
@@ -472,7 +519,12 @@ with gr.Blocks(title="Practicality 28.0") as demo:
472
 
473
  with gr.Row():
474
  with gr.Column(scale=2):
475
- api_key_input = gr.Textbox(label="Gemini API Key", type="password", value=DEFAULT_GEMINI_API_KEY)
 
 
 
 
 
476
 
477
  gr.Markdown("### 1. Novel Discovery")
478
  prob_input = gr.Textbox(label="Target Description", lines=3)
@@ -490,26 +542,14 @@ with gr.Blocks(title="Practicality 28.0") as demo:
490
  ans_box = gr.Textbox(label="Grounded Hypothesis (LLM Output)", lines=12)
491
  raw_box = gr.Textbox(label="Raw JSON", lines=4)
492
 
493
- # NATIVE PY-SIDE TIMER:
494
- # Completely replaces JavaScript `setInterval` and invisible HTML button polling.
495
- # Runs over standard WebSockets; fully immune to Hugging Face Spaces iframe sandboxing.
496
  ui_timer = gr.Timer(1.0)
497
-
498
- ui_timer.tick(
499
- fn=fetch_dashboard,
500
- inputs=[dash_cache],
501
- outputs=[live_html, dash_cache]
502
- )
503
-
504
- ui_timer.tick(
505
- fn=fetch_answers,
506
- inputs=[ans_cache],
507
- outputs=[ans_box, raw_box, ans_cache]
508
- )
509
 
510
  # Event handlers routed cleanly
511
- solve_btn.click(fn=handle_solve, inputs=[prob_input, api_key_input, ans_cache], outputs=[ans_cache])
512
- hyp_solve_btn.click(fn=handle_hyp_solve, inputs=[hyp_dropdown, api_key_input, ans_cache], outputs=[ans_cache])
513
  q_btn.click(fn=handle_q_run, inputs=[ans_cache], outputs=[ans_cache])
514
 
515
  if __name__ == "__main__":
 
10
  """
11
 
12
  import os, time, threading, json, re, textwrap, copy
13
+ import traceback, html
14
+ import requests
15
  from collections import deque, defaultdict
16
  from typing import Dict, List, Tuple, Any, Optional, Set
17
  from dataclasses import dataclass, field
 
160
  var_names = list(bounds.keys())
161
  compiled_constraints = []
162
 
 
163
  kind_map = {'EQ': 'equality', 'GEQ': 'inequality', 'LEQ': 'inequality'}
164
  dir_map = {'EQ': 'eq', 'GEQ': 'geq', 'LEQ': 'leq'}
165
 
 
176
  return prob
177
 
178
  # ══════════════════════════════════════════════════════════════════════
179
+ # SECTION 3: EXTERNAL / INTERNAL LLM BRIDGE
180
  # ══════════════════════════════════════════════════════════════════════
181
+
182
+ def call_external_ai(url: str, model: str, system_prompt: str, prompt: str) -> str:
183
+ """Interfaces with the external Express.js server."""
184
+ url = url.rstrip("/")
185
+ try:
186
+ # 1. Create chat
187
+ res = requests.post(f"{url}/api/chats", timeout=10)
188
+ res.raise_for_status()
189
+ chat_id = res.json()["id"]
190
+
191
+ # 2. Trigger stream & wait for completion
192
+ payload = {"model": model, "prompt": prompt, "system_prompt": system_prompt}
193
+ stream_res = requests.post(f"{url}/api/chats/{chat_id}/stream", json=payload, stream=True, timeout=180)
194
+ stream_res.raise_for_status()
195
+ for _ in stream_res.iter_content(chunk_size=8192):
196
+ pass # Exhaust stream
197
+
198
+ # 3. Fetch clean chat object from DB
199
+ chat_res = requests.get(f"{url}/api/chats/{chat_id}", timeout=10)
200
+ chat_res.raise_for_status()
201
+ chat_data = chat_res.json()
202
+
203
+ # 4. Clean up (delete chat politely)
204
+ try:
205
+ requests.delete(f"{url}/api/chats/{chat_id}", timeout=10)
206
+ except:
207
+ pass
208
+
209
+ # 5. Extract final message content
210
+ messages = chat_data.get("messages", [])
211
+ if not messages: raise ValueError("No messages returned from external AI")
212
+
213
+ last_msg = messages[-1]
214
+ if last_msg.get("role") != "assistant": raise ValueError("Last message is not from assistant")
215
+
216
+ return last_msg.get("content", "")
217
+
218
+ except Exception as e:
219
+ raise RuntimeError(f"External AI Call Failed: {str(e)}")
220
+
221
+
222
+ def encode_problem(text: str, api_key: str, use_ext: bool, ext_url: str, ext_model: str) -> AXLProblemDef:
223
+ if use_ext:
224
+ _add_log(f"Calling External AI Encoder ({ext_model})...")
225
+ raw = call_external_ai(ext_url, ext_model, oracle.ENCODER_PROMPT, text)
226
+ else:
227
+ _add_log("Calling Internal Gemini Encoder...")
228
+ client = genai.Client(api_key=api_key)
229
+ config = types.GenerateContentConfig(
230
+ system_instruction=[types.Part.from_text(text=oracle.ENCODER_PROMPT)],
231
+ response_mime_type="application/json", temperature=0.1)
232
+ resp = client.models.generate_content(
233
+ model=GEMINI_MODEL,
234
+ contents=[types.Content(role="user", parts=[types.Part.from_text(text=text)])],
235
+ config=config)
236
+ raw = resp.text
237
+
238
+ raw = raw.strip()
239
  if raw.startswith("```json"): raw = raw[7:-3]
240
+ if raw.startswith("```"): raw = raw[3:-3]
241
  d = json.loads(raw.strip())
242
 
243
  if "error" in d: raise ValueError(f"Isomorphism Invalid: {d['error']} - {d.get('reason', '')}")
 
252
  scopes=[], anchors=anchors, observations=d.get("observations", {})
253
  )
254
 
255
+ def collapse_solution(payload: dict, api_key: str, use_ext: bool, ext_url: str, ext_model: str) -> str:
256
+ if use_ext:
257
+ _add_log(f"Calling External AI Collapser ({ext_model})...")
258
+ raw = call_external_ai(ext_url, ext_model, oracle.COLLAPSER_PROMPT, json.dumps(payload))
259
+ else:
260
+ _add_log("Calling Internal Gemini Collapser...")
261
+ client = genai.Client(api_key=api_key)
262
+ config = types.GenerateContentConfig(
263
+ system_instruction=[types.Part.from_text(text=oracle.COLLAPSER_PROMPT)],
264
+ temperature=0.2)
265
+ resp = client.models.generate_content(
266
+ model=GEMINI_MODEL,
267
+ contents=[types.Content(role="user", parts=[types.Part.from_text(text=json.dumps(payload))])],
268
+ config=config)
269
+ raw = resp.text
270
 
271
+ raw = raw.strip()
272
  if raw.startswith("```json"): raw = raw[7:-3]
273
+ if raw.startswith("```"): raw = raw[3:-3]
274
 
275
  try:
276
  data = json.loads(raw.strip())
277
  md = data.get("hypothesis_markdown", "No markdown generated.")
278
  return md
279
  except:
280
+ return "JSON Decode Error from Collapser. Raw:\n" + raw
281
 
282
  # ══════════════════════════════════════════════════════════════════════
283
  # SECTION 4: THE ORCHESTRATOR LOOP
284
  # ══════════════════════════════════════════════════════════════════════
 
 
285
  def quick_solver_callback(axl_def: AXLProblemDef, N: int) -> Dict[str, float]:
286
  try:
287
  prob = build_core_problem(axl_def)
 
 
288
  int_vars = [v for v in prob.variables if v in prob.int_vars
289
  and math.isfinite(prob.bounds[v][0])
290
  and prob.bounds[v][1] - prob.bounds[v][0] <= 100]
 
296
  hi = int(math.floor(prob.bounds[v][1]))
297
  grids.append([(v, float(val)) for val in range(lo, hi+1)])
298
 
299
+ import itertools
300
  for combo in itertools.product(*grids):
301
  pinned = dict(combo)
302
  resolved, _ = core.algebraic_propagate_pinned(prob, pinned)
303
  ok, msg = oracle.ground_truth_verify(resolved, N)
304
  if ok: return resolved
305
  else:
 
306
  if 't' in prob.variables:
307
  lo, hi = prob.bounds['t']
308
  for t_val in range(max(2, int(lo)), min(100, int(hi)) + 1):
 
310
  resolved, _ = core.algebraic_propagate_pinned(prob, pinned)
311
  ok, msg = oracle.ground_truth_verify(resolved, N)
312
  if ok: return resolved
 
313
  if 's' in prob.variables and 'd' in prob.variables:
314
  lo_s, hi_s = prob.bounds['s']
315
  lo_d, hi_d = prob.bounds['d']
 
324
  print(f"Quick solver callback error: {e}")
325
  return {}
326
 
327
+
328
+ def global_solve_task(original_text: str, api_key: str, template_name: str = None,
329
+ use_ext: bool = False, ext_url: str = "", ext_model: str = ""):
330
  _update_state(
331
  is_running=True, phase="ENCODING", high_level_logs=[], answer="",
332
  best_ce=float('inf'), total_fired=0, best_ray="β€”",
 
340
  template_text = oracle.STRUCTURAL_HYPOTHESIS_TEMPLATES[template_name]
341
  axl_def = parse_template_as_axl(template_text)
342
  else:
343
+ axl_def = encode_problem(original_text, api_key, use_ext, ext_url, ext_model)
 
344
 
345
  _add_log(f"`{axl_def.name}` | {len(axl_def.variables)} vars")
346
  if axl_def.minimize_var: _add_log(f" MINIMIZE: {axl_def.minimize_var}")
 
362
  _update_state(phase="RAY TRACING")
363
  base_prob = build_core_problem(axl_def)
364
 
 
365
  init_b, init_ce = axioms._mprt_sample(base_prob, 1000)
366
  _add_log("Searching continuous relaxation...")
367
 
368
  templates = axioms.generate_templates(base_prob, axioms.compute_sketch(base_prob))
 
369
 
 
370
  tracer = axioms.SequenceRayTracer(
371
  log_callback=_add_log,
372
  update_state_callback=lambda **kwargs: _update_state(**kwargs)
 
399
  "infeasibility_report": GLOBAL_SOLVE_STATE["infeasibility_report"]
400
  }
401
 
402
+ ans = collapse_solution(payload, api_key, use_ext, ext_url, ext_model)
403
  _update_state(answer=ans, raw_results_json=json.dumps(payload, indent=2), phase="DONE")
404
  _add_log("Pipeline Complete.")
405
 
 
415
  finally:
416
  _update_state(is_running=False)
417
 
418
+ def trigger_solve(problem_text, api_key, template_name=None, use_ext=False, ext_url="", ext_model=""):
419
  if GLOBAL_SOLVE_STATE["is_running"] or not problem_text.strip(): return
420
+ threading.Thread(target=global_solve_task, args=(problem_text, api_key, template_name, use_ext, ext_url, ext_model), daemon=True).start()
421
 
422
+ def trigger_hyp_solve(template_name, api_key, use_ext=False, ext_url="", ext_model=""):
423
  if GLOBAL_SOLVE_STATE["is_running"]: return
424
+ threading.Thread(target=global_solve_task, args=("", api_key, template_name, use_ext, ext_url, ext_model), daemon=True).start()
425
 
 
426
  def run_quantum_demo():
427
  _update_state(is_running=True, phase="QUANTUM SIMULATION", answer="Running Physics Simulator...\nCheck console for output.", high_level_logs=[])
428
  def _run():
 
499
  c.update({"finalized": False, "ans": "", "raw": ""})
500
  return c
501
 
502
+ def handle_solve(text, key, use_ext, ext_url, ext_model, cache):
503
+ trigger_solve(text, key, template_name=None, use_ext=use_ext, ext_url=ext_url, ext_model=ext_model)
504
  return _reset(cache)
505
 
506
+ def handle_hyp_solve(name, key, use_ext, ext_url, ext_model, cache):
507
+ trigger_hyp_solve(name, key, use_ext=use_ext, ext_url=ext_url, ext_model=ext_model)
508
  return _reset(cache)
509
 
510
  def handle_q_run(cache):
 
519
 
520
  with gr.Row():
521
  with gr.Column(scale=2):
522
+ with gr.Group():
523
+ gr.Markdown("### βš™οΈ AI Backend Configuration")
524
+ api_key_input = gr.Textbox(label="Gemini API Key (Internal)", type="password", value=DEFAULT_GEMINI_API_KEY)
525
+ use_ext_toggle = gr.Checkbox(label="🌐 Use External AI Server", value=False)
526
+ ext_url_input = gr.Textbox(label="External Server URL", value="http://localhost:7860", placeholder="http://localhost:7860")
527
+ ext_model_dropdown = gr.Dropdown(choices=["claude", "haiku", "maverick"], value="claude", label="External Model")
528
 
529
  gr.Markdown("### 1. Novel Discovery")
530
  prob_input = gr.Textbox(label="Target Description", lines=3)
 
542
  ans_box = gr.Textbox(label="Grounded Hypothesis (LLM Output)", lines=12)
543
  raw_box = gr.Textbox(label="Raw JSON", lines=4)
544
 
545
+ # NATIVE PY-SIDE TIMER
 
 
546
  ui_timer = gr.Timer(1.0)
547
+ ui_timer.tick(fn=fetch_dashboard, inputs=[dash_cache], outputs=[live_html, dash_cache])
548
+ ui_timer.tick(fn=fetch_answers, inputs=[ans_cache], outputs=[ans_box, raw_box, ans_cache])
 
 
 
 
 
 
 
 
 
 
549
 
550
  # Event handlers routed cleanly
551
+ solve_btn.click(fn=handle_solve, inputs=[prob_input, api_key_input, use_ext_toggle, ext_url_input, ext_model_dropdown, ans_cache], outputs=[ans_cache])
552
+ hyp_solve_btn.click(fn=handle_hyp_solve, inputs=[hyp_dropdown, api_key_input, use_ext_toggle, ext_url_input, ext_model_dropdown, ans_cache], outputs=[ans_cache])
553
  q_btn.click(fn=handle_q_run, inputs=[ans_cache], outputs=[ans_cache])
554
 
555
  if __name__ == "__main__":