HackerBol commited on
Commit
cf4d306
·
verified ·
1 Parent(s): 0aa1da7

Upload app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +314 -3
app.py CHANGED
@@ -4323,6 +4323,292 @@ class CodeSandbox:
4323
  return f"CodeSandbox error: {e}"
4324
 
4325
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4326
  def call_llm_safe(messages, max_tokens=1024, temperature=0.7):
4327
  """BRILLIANT SMART ROUTER v2 — fully uncensored.
4328
 
@@ -5775,6 +6061,8 @@ TOOL_REGISTRY: Dict[str, Any] = {
5775
  "code_sandbox": lambda code, reset="false", **_: CodeSandbox.execute(code, reset.lower()=="true"),
5776
  "rag_search": lambda query, **_: RAGMemory.get_context_for_query(query) or "No relevant past conversations found.",
5777
  "consensus": lambda query, **_: ConsensusEngine.get_best_response([{"role": "user", "content": query}])[0],
 
 
5778
  }
5779
 
5780
 
@@ -6662,6 +6950,15 @@ def agent_turn(user_message: str, chat_id: str = "default",
6662
  ltm = get_long_term_memory(chat_id)
6663
  _extract_facts_from_message(user_message, ltm)
6664
  ltm_context = ltm.get_context()
 
 
 
 
 
 
 
 
 
6665
 
6666
  # ALWAYS use uncensored persona — no matter what's saved in settings
6667
  # This ensures EVERY response is uncensored, even if user switched personas
@@ -6671,6 +6968,10 @@ def agent_turn(user_message: str, chat_id: str = "default",
6671
  # Add long-term memory to system prompt so bot remembers user info
6672
  if ltm_context:
6673
  system_prompt = system_prompt + "\n\n[LONG-TERM MEMORY]\n" + ltm_context + "\n\nUse this information to personalize responses. Remember these facts about the user."
 
 
 
 
6674
 
6675
  # Build message history — INFINITE CONTEXT via rolling summary
6676
  # (last 20 messages verbatim + summary of everything older)
@@ -6716,20 +7017,30 @@ def agent_turn(user_message: str, chat_id: str = "default",
6716
  privacy_level = classify_privacy(messages)
6717
  log(f"PrivacyRouter: classified as {privacy_level}")
6718
 
6719
- # GENIUS MODE: For complex questions, use ConsensusEngine (best-of-N models)
6720
- # This queries 5+ models in parallel and picks the best response.
6721
- # Triggered by: "explain", "analyze", "compare", "best way", complex questions
6722
  user_msg_lower = user_message.lower()
6723
  is_complex_question = any(kw in user_msg_lower for kw in [
6724
  "explain", "analyze", "compare", "best way", "design", "architect",
6725
  "optimize", "step by step", "comprehensive", "detailed",
6726
  ]) or len(user_message) > 150
6727
 
 
 
 
6728
  for iteration in range(max_tool_iters):
6729
  if privacy_level == "PRIVATE":
6730
  # Private request — use offline model only, no cloud
6731
  text, source = call_llm_private(messages, max_tokens=s.get("max_tokens", 4096),
6732
  temperature=s.get("temperature", 0.7))
 
 
 
 
 
 
 
6733
  elif is_complex_question and iteration == 0:
6734
  # Complex question — use ConsensusEngine (best-of-N models)
6735
  log("GeniusMode: using ConsensusEngine for complex question")
 
4323
  return f"CodeSandbox error: {e}"
4324
 
4325
 
4326
+ # ============================================================================
4327
+ # ULTRA-GENIUS LAYER — o1-style reasoning, self-reflection, debate
4328
+ # ============================================================================
4329
+
4330
+ class ReasoningEngine:
4331
+ """Chain-of-Thought + Self-Reflection reasoning engine.
4332
+
4333
+ This is the same pattern used by OpenAI o1 and DeepSeek-R1:
4334
+ 1. THINK: Generate a reasoning plan (step-by-step analysis)
4335
+ 2. DRAFT: Generate a response based on the reasoning
4336
+ 3. CRITIQUE: Evaluate the draft for errors/gaps
4337
+ 4. REFINE: If critique finds issues, regenerate with feedback
4338
+
4339
+ This produces dramatically better answers for complex questions because
4340
+ the model "thinks" before answering, then checks its own work.
4341
+
4342
+ Use for: math, logic, code debugging, complex analysis, anything hard.
4343
+ """
4344
+
4345
+ @classmethod
4346
+ def reason_and_answer(cls, messages, max_tokens=2048, temperature=0.7) -> Tuple[str, str]:
4347
+ """Full reasoning pipeline. Returns (final_answer, source)."""
4348
+ from concurrent.futures import ThreadPoolExecutor, as_completed
4349
+
4350
+ user_msg = ""
4351
+ for m in reversed(messages):
4352
+ if m.get("role") == "user":
4353
+ user_msg = m.get("content", "")
4354
+ break
4355
+
4356
+ # Step 1: THINK — generate reasoning in parallel with 3 different approaches
4357
+ reasoning_approaches = [
4358
+ ("analytical", "Analyze this step-by-step. Break down the problem, identify key components, then solve. Be thorough and logical."),
4359
+ ("creative", "Think about this from multiple angles. Consider edge cases, alternative interpretations, and creative solutions. Be comprehensive."),
4360
+ ("practical", "Focus on practical, actionable advice. What would an expert do? Include specific steps, examples, and pitfalls to avoid."),
4361
+ ]
4362
+
4363
+ reasonings = []
4364
+ with ThreadPoolExecutor(max_workers=3) as executor:
4365
+ futures = {}
4366
+ for approach_name, approach_prompt in reasoning_approaches:
4367
+ reason_messages = [
4368
+ {"role": "system", "content": f"You are a reasoning engine. {approach_prompt} Output ONLY your reasoning process (thinking), not the final answer."},
4369
+ ] + messages[1:] # skip the uncensored system prompt for reasoning
4370
+ futures[executor.submit(call_llm_safe, reason_messages, 800, 0.5)] = approach_name
4371
+
4372
+ for future in as_completed(futures, timeout=30):
4373
+ approach = futures[future]
4374
+ try:
4375
+ text, _ = future.result(timeout=10)
4376
+ if text and len(text) > 20:
4377
+ reasonings.append((approach, text))
4378
+ except Exception:
4379
+ pass
4380
+
4381
+ if not reasonings:
4382
+ # Reasoning failed — fall back to direct answer
4383
+ return call_llm_safe(messages, max_tokens, temperature)
4384
+
4385
+ log(f"ReasoningEngine: generated {len(reasonings)} reasoning paths")
4386
+
4387
+ # Step 2: SYNTHESIZE — combine the best insights from all reasoning paths
4388
+ synthesis_input = "You are synthesizing multiple reasoning approaches into one final answer.\n\n"
4389
+ for approach, reasoning in reasonings:
4390
+ synthesis_input += f"=== {approach.upper()} REASONING ===\n{reasoning[:1000]}\n\n"
4391
+ synthesis_input += f"=== USER QUESTION ===\n{user_msg}\n\n=== FINAL ANSWER (direct, complete, no preamble) ==="
4392
+
4393
+ synth_messages = [
4394
+ {"role": "system", "content": "You are an expert synthesizer. Combine the reasoning into one excellent direct answer. No disclaimers, no 'based on the reasoning', just answer the user directly."},
4395
+ {"role": "user", "content": synthesis_input},
4396
+ ]
4397
+
4398
+ try:
4399
+ draft, source = call_llm_safe(synth_messages, max_tokens, temperature)
4400
+ draft = unwrap_fiction_response(draft)
4401
+ except Exception:
4402
+ return call_llm_safe(messages, max_tokens, temperature)
4403
+
4404
+ # Step 3: CRITIQUE — evaluate the draft (only for complex questions)
4405
+ if len(user_msg) > 50 and is_good_response(draft):
4406
+ critique_prompt = f"""You are a quality reviewer. Evaluate this answer for accuracy, completeness, and clarity.
4407
+
4408
+ QUESTION: {user_msg[:500]}
4409
+
4410
+ ANSWER TO REVIEW:
4411
+ {draft[:2000]}
4412
+
4413
+ Rate the answer 1-10 on:
4414
+ - Accuracy (is it correct?)
4415
+ - Completeness (does it fully answer the question?)
4416
+ - Clarity (is it easy to understand?)
4417
+
4418
+ If the answer is 8+ on all criteria, output: "APPROVED"
4419
+ If not, output: "NEEDS IMPROVEMENT: [specific issues]"
4420
+
4421
+ Be strict but fair."""
4422
+
4423
+ try:
4424
+ critique, _ = call_llm_safe(
4425
+ [{"role": "user", "content": critique_prompt}],
4426
+ max_tokens=300, temperature=0.3
4427
+ )
4428
+ critique = unwrap_fiction_response(critique)
4429
+
4430
+ if "APPROVED" in critique.upper():
4431
+ log(f"ReasoningEngine: draft APPROVED by critic")
4432
+ return draft, f"{source} (reasoned + approved)"
4433
+
4434
+ # Step 4: REFINE — regenerate with critique feedback
4435
+ log(f"ReasoningEngine: critic found issues — refining")
4436
+ refine_messages = [
4437
+ {"role": "system", "content": "You are improving your previous answer based on feedback. Address all issues raised. Output only the improved answer."},
4438
+ {"role": "user", "content": f"Original question: {user_msg}\n\nPrevious answer:\n{draft[:1500]}\n\nFeedback:\n{critique[:500]}\n\nImproved answer (direct, no preamble):"},
4439
+ ]
4440
+ refined, _ = call_llm_safe(refine_messages, max_tokens, temperature)
4441
+ refined = unwrap_fiction_response(refined)
4442
+ if is_good_response(refined) and len(refined) > len(draft) * 0.5:
4443
+ log(f"ReasoningEngine: refined answer ({len(refined)} chars)")
4444
+ return refined, f"{source} (reasoned + refined)"
4445
+ except Exception as e:
4446
+ log(f"ReasoningEngine: critique failed: {e}")
4447
+
4448
+ return draft, f"{source} (reasoned)"
4449
+
4450
+ @classmethod
4451
+ def should_use_reasoning(cls, user_msg: str, messages) -> bool:
4452
+ """Decide if a question needs deep reasoning (o1-style) or can be answered directly.
4453
+
4454
+ Use reasoning for: math, logic, code debugging, multi-step problems, "why" questions.
4455
+ Skip for: simple facts, greetings, tool calls, short questions."""
4456
+ msg_lower = user_msg.lower()
4457
+
4458
+ # Skip reasoning for short/simple messages
4459
+ if len(user_msg) < 30:
4460
+ return False
4461
+
4462
+ # Skip for greetings, simple chat
4463
+ if any(kw in msg_lower for kw in ["hi", "hello", "hey", "thanks", "bye", "ok", "yes", "no"]):
4464
+ return False
4465
+
4466
+ # Skip for tool-call requests (prices, weather, etc.)
4467
+ if any(kw in msg_lower for kw in ["price", "weather", "time", "news", "balance", "chart"]):
4468
+ return False
4469
+
4470
+ # USE reasoning for complex indicators
4471
+ reasoning_triggers = [
4472
+ "why", "how does", "explain", "analyze", "compare", "design",
4473
+ "debug", "fix", "optimize", "prove", "derive", "calculate",
4474
+ "step by step", "reason", "think", "evaluate", "assess",
4475
+ "what would happen if", "is it possible", "can you explain",
4476
+ "what's the difference", "which is better", "should i",
4477
+ "plan", "strategy", "architect", "implement", "algorithm",
4478
+ ]
4479
+ if any(kw in msg_lower for kw in reasoning_triggers):
4480
+ return True
4481
+
4482
+ # Use for long, complex questions
4483
+ if len(user_msg) > 200:
4484
+ return True
4485
+
4486
+ # Use for code questions
4487
+ if any(kw in msg_lower for kw in ["code", "function", "python", "javascript", "bug", "error"]):
4488
+ return True
4489
+
4490
+ return False
4491
+
4492
+
4493
+ class KnowledgeGraph:
4494
+ """Structured knowledge storage — auto-extracts facts from conversations.
4495
+
4496
+ Unlike RAG (which searches raw conversation text), the Knowledge Graph
4497
+ stores structured facts: (subject, predicate, object) triples.
4498
+
4499
+ Example: "I live in Mumbai" → (user, lives_in, Mumbai)
4500
+ Example: "I prefer Python 3.12" → (user, prefers, Python 3.12)
4501
+
4502
+ This enables complex queries like "What do you know about my preferences?"
4503
+ without scanning all conversations.
4504
+ """
4505
+
4506
+ _facts: List[Dict] = []
4507
+ _loaded = False
4508
+
4509
+ @classmethod
4510
+ def _load(cls):
4511
+ if cls._loaded:
4512
+ return
4513
+ try:
4514
+ data = memory.read("knowledge_graph.json", default={"facts": []}) or {"facts": []}
4515
+ cls._facts = data.get("facts", [])
4516
+ cls._loaded = True
4517
+ log(f"KnowledgeGraph: loaded {len(cls._facts)} facts")
4518
+ except Exception as e:
4519
+ log(f"KnowledgeGraph: load failed: {e}")
4520
+ cls._facts = []
4521
+ cls._loaded = True
4522
+
4523
+ @classmethod
4524
+ def extract_and_store(cls, user_message: str, ai_response: str):
4525
+ """Extract facts from a conversation turn and store them.
4526
+ Uses simple pattern matching (no LLM needed — fast and free)."""
4527
+ cls._load()
4528
+ new_facts = []
4529
+
4530
+ # Pattern: "I am X" / "I'm X" / "My X is Y" / "I like X" / "I prefer X"
4531
+ import re
4532
+ text = user_message
4533
+
4534
+ patterns = [
4535
+ (r"my name is (\w+)", "name"),
4536
+ (r"i am (\w+)", "name"),
4537
+ (r"i'm (\w+)", "name"),
4538
+ (r"call me (\w+)", "name"),
4539
+ (r"i live in ([\w\s]+)", "location"),
4540
+ (r"i'm from ([\w\s]+)", "location"),
4541
+ (r"i am from ([\w\s]+)", "location"),
4542
+ (r"my city is ([\w\s]+)", "location"),
4543
+ (r"my birthday is ([\w\s\d]+)", "birthday"),
4544
+ (r"i was born on ([\w\s\d]+)", "birthday"),
4545
+ (r"my favorite color is (\w+)", "favorite_color"),
4546
+ (r"my favorite language is (\w+)", "favorite_language"),
4547
+ (r"i like (\w+)", "likes"),
4548
+ (r"i prefer (\w+)", "prefers"),
4549
+ (r"i use (\w+)", "uses"),
4550
+ (r"i work at ([\w\s]+)", "workplace"),
4551
+ (r"my job is ([\w\s]+)", "job"),
4552
+ (r"i study ([\w\s]+)", "studies"),
4553
+ (r"remember (.+)", "remembered"),
4554
+ ]
4555
+
4556
+ for pattern, key in patterns:
4557
+ m = re.search(pattern, text, re.IGNORECASE)
4558
+ if m:
4559
+ value = m.group(1).strip().title() if key not in ["remembered"] else m.group(1).strip()
4560
+ fact = {"subject": "user", "predicate": key, "object": value, "ts": time.time()}
4561
+ # Check if we already have this fact
4562
+ existing = [f for f in cls._facts if f["predicate"] == key and f["object"] == value]
4563
+ if not existing:
4564
+ cls._facts.append(fact)
4565
+ new_facts.append(fact)
4566
+ log(f"KnowledgeGraph: extracted fact: ({key}, {value})")
4567
+
4568
+ # Save if we found new facts
4569
+ if new_facts:
4570
+ # Keep last 200 facts
4571
+ cls._facts = cls._facts[-200:]
4572
+ memory.write("knowledge_graph.json", {"facts": cls._facts})
4573
+
4574
+ return new_facts
4575
+
4576
+ @classmethod
4577
+ def get_all_facts(cls) -> str:
4578
+ """Get all known facts as a context string."""
4579
+ cls._load()
4580
+ if not cls._facts:
4581
+ return ""
4582
+ lines = ["[KNOWLEDGE GRAPH — facts about the user]"]
4583
+ for f in cls._facts[-20:]: # last 20 facts
4584
+ age = "recent" if time.time() - f["ts"] < 86400 else f"{int((time.time() - f['ts']) / 86400)}d ago"
4585
+ lines.append(f"- {f['predicate'].replace('_', ' ').title()}: {f['object']} ({age})")
4586
+ lines.append("[END KNOWLEDGE GRAPH]")
4587
+ return "\n".join(lines)
4588
+
4589
+ @classmethod
4590
+ def query(cls, query: str) -> str:
4591
+ """Search the knowledge graph for facts matching the query."""
4592
+ cls._load()
4593
+ if not cls._facts:
4594
+ return "I don't have any stored facts about you yet."
4595
+
4596
+ query_lower = query.lower()
4597
+ matches = []
4598
+ for f in cls._facts:
4599
+ # Check if query mentions the predicate or object
4600
+ if f["predicate"].replace("_", " ") in query_lower or f["object"].lower() in query_lower:
4601
+ matches.append(f)
4602
+
4603
+ if not matches:
4604
+ return f"No facts matching '{query}'. I know {len(cls._facts)} facts total."
4605
+
4606
+ lines = [f"Found {len(matches)} matching facts:"]
4607
+ for f in matches[-10:]:
4608
+ lines.append(f"- {f['predicate'].replace('_', ' ').title()}: {f['object']}")
4609
+ return "\n".join(lines)
4610
+
4611
+
4612
  def call_llm_safe(messages, max_tokens=1024, temperature=0.7):
4613
  """BRILLIANT SMART ROUTER v2 — fully uncensored.
4614
 
 
6061
  "code_sandbox": lambda code, reset="false", **_: CodeSandbox.execute(code, reset.lower()=="true"),
6062
  "rag_search": lambda query, **_: RAGMemory.get_context_for_query(query) or "No relevant past conversations found.",
6063
  "consensus": lambda query, **_: ConsensusEngine.get_best_response([{"role": "user", "content": query}])[0],
6064
+ "knowledge_query": lambda query, **_: KnowledgeGraph.query(query),
6065
+ "reason": lambda query, **_: ReasoningEngine.reason_and_answer([{"role": "user", "content": query}])[0],
6066
  }
6067
 
6068
 
 
6950
  ltm = get_long_term_memory(chat_id)
6951
  _extract_facts_from_message(user_message, ltm)
6952
  ltm_context = ltm.get_context()
6953
+
6954
+ # KNOWLEDGE GRAPH: extract structured facts (subject, predicate, object)
6955
+ # This is faster and more structured than LTM — uses pattern matching, no LLM needed.
6956
+ try:
6957
+ KnowledgeGraph.extract_and_store(user_message, "")
6958
+ kg_context = KnowledgeGraph.get_all_facts()
6959
+ except Exception as e:
6960
+ log(f"KnowledgeGraph: extraction failed: {e}")
6961
+ kg_context = ""
6962
 
6963
  # ALWAYS use uncensored persona — no matter what's saved in settings
6964
  # This ensures EVERY response is uncensored, even if user switched personas
 
6968
  # Add long-term memory to system prompt so bot remembers user info
6969
  if ltm_context:
6970
  system_prompt = system_prompt + "\n\n[LONG-TERM MEMORY]\n" + ltm_context + "\n\nUse this information to personalize responses. Remember these facts about the user."
6971
+
6972
+ # Add Knowledge Graph context (structured facts)
6973
+ if kg_context:
6974
+ system_prompt = system_prompt + "\n\n" + kg_context
6975
 
6976
  # Build message history — INFINITE CONTEXT via rolling summary
6977
  # (last 20 messages verbatim + summary of everything older)
 
7017
  privacy_level = classify_privacy(messages)
7018
  log(f"PrivacyRouter: classified as {privacy_level}")
7019
 
7020
+ # GENIUS MODE: For complex questions, use ReasoningEngine (o1-style thinking)
7021
+ # This generates 3 reasoning paths, synthesizes, critiques, and refines.
7022
+ # Falls back to ConsensusEngine (best-of-N) for medium complexity.
7023
  user_msg_lower = user_message.lower()
7024
  is_complex_question = any(kw in user_msg_lower for kw in [
7025
  "explain", "analyze", "compare", "best way", "design", "architect",
7026
  "optimize", "step by step", "comprehensive", "detailed",
7027
  ]) or len(user_message) > 150
7028
 
7029
+ # ULTRA-GENIUS: Use full reasoning pipeline for hard questions
7030
+ use_deep_reasoning = ReasoningEngine.should_use_reasoning(user_message, messages)
7031
+
7032
  for iteration in range(max_tool_iters):
7033
  if privacy_level == "PRIVATE":
7034
  # Private request — use offline model only, no cloud
7035
  text, source = call_llm_private(messages, max_tokens=s.get("max_tokens", 4096),
7036
  temperature=s.get("temperature", 0.7))
7037
+ elif use_deep_reasoning and iteration == 0:
7038
+ # ULTRA-GENIUS: Full reasoning pipeline (think → draft → critique → refine)
7039
+ log("UltraGenius: using ReasoningEngine (o1-style thinking)")
7040
+ text, source = ReasoningEngine.reason_and_answer(
7041
+ messages, max_tokens=s.get("max_tokens", 4096),
7042
+ temperature=s.get("temperature", 0.7)
7043
+ )
7044
  elif is_complex_question and iteration == 0:
7045
  # Complex question — use ConsensusEngine (best-of-N models)
7046
  log("GeniusMode: using ConsensusEngine for complex question")