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

Upload app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +459 -0
app.py CHANGED
@@ -4609,6 +4609,413 @@ class KnowledgeGraph:
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
 
@@ -6972,6 +7379,14 @@ def agent_turn(user_message: str, chat_id: str = "default",
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)
@@ -7029,11 +7444,24 @@ def agent_turn(user_message: str, chat_id: str = "default",
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)")
@@ -7096,6 +7524,37 @@ def agent_turn(user_message: str, chat_id: str = "default",
7096
  accumulated_text = text
7097
  parsed = parse_tool_call(text)
7098
  if parsed is None:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7099
  # Final answer
7100
  yield text, image_path, source
7101
  conv.add("user", user_message)
 
4609
  return "\n".join(lines)
4610
 
4611
 
4612
+ # ============================================================================
4613
+ # APEX-GENIUS LAYER — multi-agent debate, self-improvement, verification
4614
+ # ============================================================================
4615
+
4616
+ class MultiAgentDebate:
4617
+ """Multi-Agent Debate System — 3 agents with different viewpoints argue,
4618
+ then a moderator synthesizes the best answer.
4619
+
4620
+ This produces higher-quality answers than single-model reasoning because:
4621
+ - Agent 1 (Optimist) argues for the best approach
4622
+ - Agent 2 (Skeptic) challenges assumptions and finds flaws
4623
+ - Agent 3 (Pragmatist) focuses on practical implementation
4624
+ - Moderator synthesizes the debate into one excellent answer
4625
+
4626
+ Use for: important decisions, controversial topics, architecture choices.
4627
+ """
4628
+
4629
+ AGENTS = [
4630
+ ("Optimist", "You are an optimistic expert. Argue for the BEST possible approach. Be enthusiastic about the potential. Highlight advantages and opportunities."),
4631
+ ("Skeptic", "You are a skeptical critic. Challenge every assumption. Find flaws, risks, edge cases, and failure modes. Be rigorous and demanding."),
4632
+ ("Pragmatist", "You are a practical engineer. Focus on what ACTUALLY works in production. Consider cost, time, maintainability, and real-world constraints."),
4633
+ ]
4634
+
4635
+ @classmethod
4636
+ def debate(cls, messages, max_tokens=2048) -> Tuple[str, str]:
4637
+ """Run a 3-agent debate and synthesize the result."""
4638
+ from concurrent.futures import ThreadPoolExecutor, as_completed
4639
+
4640
+ user_msg = ""
4641
+ for m in reversed(messages):
4642
+ if m.get("role") == "user":
4643
+ user_msg = m.get("content", "")
4644
+ break
4645
+
4646
+ # Round 1: Each agent gives their initial position
4647
+ log("DebateEngine: Round 1 — agents giving initial positions...")
4648
+ positions = []
4649
+ with ThreadPoolExecutor(max_workers=3) as executor:
4650
+ futures = {}
4651
+ for agent_name, agent_prompt in cls.AGENTS:
4652
+ debate_messages = [
4653
+ {"role": "system", "content": f"{agent_prompt} Answer directly. No disclaimers."},
4654
+ ] + messages[1:]
4655
+ futures[executor.submit(call_llm_safe, debate_messages, 1000, 0.7)] = agent_name
4656
+
4657
+ for future in as_completed(futures, timeout=30):
4658
+ agent = futures[future]
4659
+ try:
4660
+ text, _ = future.result(timeout=10)
4661
+ if text and len(text) > 20:
4662
+ positions.append((agent, text))
4663
+ except Exception:
4664
+ pass
4665
+
4666
+ if len(positions) < 2:
4667
+ return call_llm_safe(messages, max_tokens, 0.7)
4668
+
4669
+ # Round 2: Moderator synthesizes
4670
+ log(f"DebateEngine: Round 2 — moderator synthesizing {len(positions)} positions...")
4671
+ moderator_input = f"You are a moderator. Synthesize these 3 expert perspectives into ONE excellent answer.\n\n"
4672
+ moderator_input += f"QUESTION: {user_msg[:500]}\n\n"
4673
+ for agent, position in positions:
4674
+ moderator_input += f"=== {agent.upper()} POSITION ===\n{position[:800]}\n\n"
4675
+ moderator_input += "=== FINAL SYNTHESIZED ANSWER (direct, complete, incorporates best insights from all 3) ==="
4676
+
4677
+ try:
4678
+ final, source = call_llm_safe(
4679
+ [{"role": "user", "content": moderator_input}],
4680
+ max_tokens, 0.5
4681
+ )
4682
+ final = unwrap_fiction_response(final)
4683
+ return final, f"{source} (debate: {len(positions)} agents)"
4684
+ except Exception:
4685
+ return positions[0][1], f"DebateEngine (agent: {positions[0][0]})"
4686
+
4687
+
4688
+ class SelfImprovement:
4689
+ """Self-Improvement Loop — learns from user feedback.
4690
+
4691
+ Tracks:
4692
+ - Which response styles get "thanks" / "great" / "perfect" (positive)
4693
+ - Which get "no" / "wrong" / "try again" (negative)
4694
+ - Adjusts future responses based on patterns
4695
+
4696
+ Also tracks:
4697
+ - Response length preferences
4698
+ - Tone preferences (formal vs casual)
4699
+ - Topics the user cares about
4700
+ """
4701
+
4702
+ _feedback: Dict[str, Any] = {}
4703
+ _loaded = False
4704
+
4705
+ @classmethod
4706
+ def _load(cls):
4707
+ if cls._loaded:
4708
+ return
4709
+ try:
4710
+ data = memory.read("self_improvement.json", default={}) or {}
4711
+ cls._feedback = data
4712
+ cls._loaded = True
4713
+ except Exception:
4714
+ cls._feedback = {"positive": 0, "negative": 0, "patterns": {}, "adjustments": {}}
4715
+ cls._loaded = True
4716
+
4717
+ @classmethod
4718
+ def record_feedback(cls, user_message: str, ai_response: str, next_user_message: str):
4719
+ """Analyze the user's NEXT message for feedback signals.
4720
+
4721
+ Positive: 'thanks', 'great', 'perfect', 'awesome', 'good', 'nice'
4722
+ Negative: 'no', 'wrong', 'try again', 'bad', 'terrible', 'not what I meant'
4723
+ """
4724
+ cls._load()
4725
+ next_lower = next_user_message.lower().strip()
4726
+
4727
+ positive_signals = ["thanks", "thank you", "great", "perfect", "awesome", "good", "nice",
4728
+ "exactly", "that's right", "correct", "yes", "👍", "love it", "amazing"]
4729
+ negative_signals = ["no", "wrong", "try again", "bad", "terrible", "not what",
4730
+ "that's not", "incorrect", "nope", "didn't work", "doesn't work",
4731
+ "error", "failed", "broken"]
4732
+
4733
+ is_positive = any(sig in next_lower for sig in positive_signals)
4734
+ is_negative = any(sig in next_lower for sig in negative_signals)
4735
+
4736
+ if is_positive and not is_negative:
4737
+ cls._feedback["positive"] = cls._feedback.get("positive", 0) + 1
4738
+ # Learn: what made this response good?
4739
+ resp_len = len(ai_response)
4740
+ cls._feedback.setdefault("good_lengths", []).append(resp_len)
4741
+ # Track style
4742
+ if "```" in ai_response:
4743
+ cls._feedback["code_appreciated"] = cls._feedback.get("code_appreciated", 0) + 1
4744
+ if re.search(r"\n\s*\d+\.", ai_response):
4745
+ cls._feedback["numbered_lists_appreciated"] = cls._feedback.get("numbered_lists_appreciated", 0) + 1
4746
+ log(f"SelfImprovement: recorded POSITIVE feedback (total: {cls._feedback['positive']})")
4747
+ elif is_negative and not is_positive:
4748
+ cls._feedback["negative"] = cls._feedback.get("negative", 0) + 1
4749
+ cls._feedback.setdefault("bad_lengths", []).append(len(ai_response))
4750
+ log(f"SelfImprovement: recorded NEGATIVE feedback (total: {cls._feedback['negative']})")
4751
+
4752
+ # Save
4753
+ try:
4754
+ memory.write("self_improvement.json", cls._feedback)
4755
+ except Exception:
4756
+ pass
4757
+
4758
+ @classmethod
4759
+ def get_adjustments(cls) -> str:
4760
+ """Get learned adjustments as a system prompt addition."""
4761
+ cls._load()
4762
+ pos = cls._feedback.get("positive", 0)
4763
+ neg = cls._feedback.get("negative", 0)
4764
+ if pos + neg < 3:
4765
+ return "" # not enough data
4766
+
4767
+ adjustments = []
4768
+ # Length preference
4769
+ good_lengths = cls._feedback.get("good_lengths", [])
4770
+ bad_lengths = cls._feedback.get("bad_lengths", [])
4771
+ if len(good_lengths) >= 2:
4772
+ avg_good = sum(good_lengths) / len(good_lengths)
4773
+ adjustments.append(f"Aim for responses around {int(avg_good)} chars (user prefers this length).")
4774
+
4775
+ # Style preferences
4776
+ if cls._feedback.get("code_appreciated", 0) > 2:
4777
+ adjustments.append("User appreciates code examples — include them when relevant.")
4778
+ if cls._feedback.get("numbered_lists_appreciated", 0) > 2:
4779
+ adjustments.append("User appreciates numbered lists for instructions.")
4780
+
4781
+ # Satisfaction rate
4782
+ total = pos + neg
4783
+ satisfaction = pos / total * 100 if total > 0 else 0
4784
+ adjustments.append(f"User satisfaction: {satisfaction:.0f}% ({pos} positive, {neg} negative).")
4785
+
4786
+ return "\n[SELF-IMPROVEMENT ADJUSTMENTS]\n" + "\n".join(adjustments) if adjustments else ""
4787
+
4788
+
4789
+ class CodeVerifier:
4790
+ """Code Verification — automatically runs generated code to verify it works.
4791
+
4792
+ After the LLM generates code, CodeVerifier:
4793
+ 1. Extracts code blocks from the response
4794
+ 2. Runs each block in the sandbox
4795
+ 3. If code fails, sends the error back to the LLM for fixing
4796
+ 4. Returns the verified (working) code
4797
+
4798
+ This eliminates the #1 complaint about AI code: "it doesn't work."
4799
+ """
4800
+
4801
+ @classmethod
4802
+ def verify_and_fix(cls, response: str, user_request: str) -> str:
4803
+ """Extract code from response, run it, fix if broken. Returns verified response."""
4804
+ # Extract Python code blocks
4805
+ code_blocks = re.findall(r"```(?:python)?\n(.*?)```", response, re.DOTALL)
4806
+ if not code_blocks:
4807
+ return response # no code to verify
4808
+
4809
+ # Only verify if it looks like executable code (not just snippets)
4810
+ executable_blocks = []
4811
+ for block in code_blocks:
4812
+ # Skip if it's just a variable or single line
4813
+ if len(block.strip().split("\n")) >= 2 or "def " in block or "import " in block:
4814
+ executable_blocks.append(block)
4815
+
4816
+ if not executable_blocks:
4817
+ return response
4818
+
4819
+ log(f"CodeVerifier: found {len(executable_blocks)} executable code blocks to verify")
4820
+
4821
+ fixed_blocks = []
4822
+ for i, code in enumerate(executable_blocks):
4823
+ # Try running it
4824
+ result = CodeSandbox.execute(code, reset=True)
4825
+
4826
+ if "error" in result.lower() or "Traceback" in result or "SyntaxError" in result:
4827
+ log(f"CodeVerifier: block {i+1} FAILED — attempting fix")
4828
+ # Ask LLM to fix the code
4829
+ fix_prompt = f"""The following Python code has an error. Fix it.
4830
+
4831
+ ORIGINAL CODE:
4832
+ {code[:1500]}
4833
+
4834
+ ERROR:
4835
+ {result[:500]}
4836
+
4837
+ USER'S ORIGINAL REQUEST: {user_request[:200]}
4838
+
4839
+ Output ONLY the fixed code in a ```python block. No explanation."""
4840
+ try:
4841
+ fixed, _ = call_llm_safe(
4842
+ [{"role": "user", "content": fix_prompt}],
4843
+ max_tokens=1500, temperature=0.3
4844
+ )
4845
+ fixed = unwrap_fiction_response(fixed)
4846
+ # Extract fixed code
4847
+ m = re.search(r"```(?:python)?\n(.*?)```", fixed, re.DOTALL)
4848
+ if m:
4849
+ fixed_code = m.group(1)
4850
+ # Verify the fix works
4851
+ verify_result = CodeSandbox.execute(fixed_code, reset=True)
4852
+ if "error" not in verify_result.lower() and "Traceback" not in verify_result:
4853
+ log(f"CodeVerifier: block {i+1} FIXED and verified")
4854
+ fixed_blocks.append(fixed_code)
4855
+ continue
4856
+ except Exception:
4857
+ pass
4858
+ else:
4859
+ log(f"CodeVerifier: block {i+1} PASSED")
4860
+ fixed_blocks.append(code)
4861
+
4862
+ # Reconstruct response with verified code
4863
+ if fixed_blocks and len(fixed_blocks) == len(executable_blocks):
4864
+ # Replace code blocks in original response
4865
+ verified_response = response
4866
+ for original, fixed in zip(executable_blocks, fixed_blocks):
4867
+ if original != fixed:
4868
+ verified_response = verified_response.replace(original, fixed, 1)
4869
+ return verified_response + "\n\n✅ Code verified — runs without errors."
4870
+
4871
+ return response
4872
+
4873
+
4874
+ class FactChecker:
4875
+ """Fact-Checking — verifies factual claims via web search.
4876
+
4877
+ After generating a response with factual claims, FactChecker:
4878
+ 1. Extracts verifiable claims (numbers, dates, names, events)
4879
+ 2. Web-searches each claim
4880
+ 3. If a claim is contradicted, flags it and provides the correct info
4881
+
4882
+ Use for: news, history, science, statistics — anything factual.
4883
+ """
4884
+
4885
+ CLAIM_PATTERNS = [
4886
+ # Numbers with context
4887
+ r"(?:is|was|are|were)\s+(\d+[\d,]*\.?\d*)\s*(?:percent|million|billion|thousand|people|years|days|hours)",
4888
+ # Dates
4889
+ r"(?:in|on|since)\s+(\d{4})",
4890
+ # "X is Y" statements
4891
+ r"(\w[\w\s]+)\s+is\s+(?:the|a|an)\s+(\w[\w\s]+)",
4892
+ ]
4893
+
4894
+ @classmethod
4895
+ def extract_claims(cls, text: str) -> List[str]:
4896
+ """Extract verifiable claims from text."""
4897
+ claims = []
4898
+ for pattern in cls.CLAIM_PATTERNS:
4899
+ matches = re.findall(pattern, text)
4900
+ for m in matches:
4901
+ if isinstance(m, tuple):
4902
+ claims.append(" ".join(m))
4903
+ else:
4904
+ claims.append(m)
4905
+ return claims[:3] # max 3 claims to check (avoid rate limits)
4906
+
4907
+ @classmethod
4908
+ def check_facts(cls, response: str) -> str:
4909
+ """Check factual claims in a response. Returns response with fact-check notes."""
4910
+ claims = cls.extract_claims(response)
4911
+ if not claims:
4912
+ return response
4913
+
4914
+ log(f"FactChecker: checking {len(claims)} claims...")
4915
+ corrections = []
4916
+
4917
+ for claim in claims:
4918
+ try:
4919
+ # Web search the claim
4920
+ search_result = run_tool("web_search", {"query": claim})
4921
+ # Ask LLM to verify
4922
+ verify_prompt = f"""Is this claim TRUE or FALSE based on the search results?
4923
+
4924
+ CLAIM: {claim}
4925
+
4926
+ SEARCH RESULTS:
4927
+ {search_result[:500]}
4928
+
4929
+ Output:
4930
+ VERDICT: TRUE or FALSE or UNCERTAIN
4931
+ CORRECTION: (if false, what's the truth?)
4932
+ Be brief."""
4933
+ verdict, _ = call_llm_safe(
4934
+ [{"role": "user", "content": verify_prompt}],
4935
+ max_tokens=100, temperature=0.2
4936
+ )
4937
+ verdict = unwrap_fiction_response(verdict)
4938
+ if "FALSE" in verdict.upper():
4939
+ # Extract correction
4940
+ corr_match = re.search(r"CORRECTION:\s*(.+)", verdict, re.DOTALL)
4941
+ if corr_match:
4942
+ corrections.append(f"⚠️ Claim '{claim}' may be incorrect. {corr_match.group(1).strip()}")
4943
+ except Exception:
4944
+ continue
4945
+
4946
+ if corrections:
4947
+ return response + "\n\n📋 Fact-check notes:\n" + "\n".join(corrections)
4948
+ return response + "\n\n✅ Facts verified."
4949
+
4950
+
4951
+ class ProactiveIntelligence:
4952
+ """Proactive Intelligence — anticipates user needs and suggests actions.
4953
+
4954
+ After each conversation, analyzes:
4955
+ - What topics the user is working on
4956
+ - What they might need next
4957
+ - What they've forgotten
4958
+
4959
+ Example: If user asks about BTC price 3 times in a day, proactively
4960
+ suggests setting up a price alert.
4961
+
4962
+ Runs in background — doesn't slow down responses.
4963
+ """
4964
+
4965
+ _topic_history: List[Dict] = []
4966
+
4967
+ @classmethod
4968
+ def record_interaction(cls, user_message: str):
4969
+ """Record what the user is asking about."""
4970
+ # Extract topics (simple keyword extraction)
4971
+ msg_lower = user_message.lower()
4972
+ topics = []
4973
+ topic_keywords = {
4974
+ "trading": ["btc", "eth", "price", "buy", "sell", "trade", "crypto", "bitcoin"],
4975
+ "coding": ["code", "python", "function", "debug", "error", "script"],
4976
+ "research": ["search", "find", "research", "what is", "explain"],
4977
+ "writing": ["write", "article", "essay", "story", "content"],
4978
+ "system": ["status", "tools", "provider", "model"],
4979
+ }
4980
+ for topic, keywords in topic_keywords.items():
4981
+ if any(kw in msg_lower for kw in keywords):
4982
+ topics.append(topic)
4983
+
4984
+ for topic in topics:
4985
+ cls._topic_history.append({"topic": topic, "ts": time.time()})
4986
+
4987
+ # Keep last 100
4988
+ cls._topic_history = cls._topic_history[-100:]
4989
+
4990
+ @classmethod
4991
+ def get_suggestions(cls) -> Optional[str]:
4992
+ """Generate proactive suggestions based on patterns. Returns None if no suggestion."""
4993
+ if len(cls._topic_history) < 5:
4994
+ return None
4995
+
4996
+ # Count topics in last hour
4997
+ now = time.time()
4998
+ recent = [t for t in cls._topic_history if now - t["ts"] < 3600]
4999
+ if len(recent) < 3:
5000
+ return None
5001
+
5002
+ from collections import Counter
5003
+ topic_counts = Counter(t["topic"] for t in recent)
5004
+ top_topic = topic_counts.most_common(1)[0]
5005
+
5006
+ # If user asked about same topic 3+ times in last hour, suggest automation
5007
+ if top_topic[1] >= 3:
5008
+ suggestions = {
5009
+ "trading": "💡 I noticed you're checking prices frequently. Want me to set up automatic price alerts? Say 'alert me when BTC drops below $60K'.",
5010
+ "coding": "💡 You're doing a lot of coding. Want me to create a code project template? Say 'create a project structure for X'.",
5011
+ "research": "💡 Lots of research today. Want me to compile a summary? Say 'summarize everything we discussed'.",
5012
+ "writing": "💡 You're writing a lot. Want me to help with a longer piece? Say 'write a 2000-word article about X'.",
5013
+ }
5014
+ return suggestions.get(top_topic[0])
5015
+
5016
+ return None
5017
+
5018
+
5019
  def call_llm_safe(messages, max_tokens=1024, temperature=0.7):
5020
  """BRILLIANT SMART ROUTER v2 — fully uncensored.
5021
 
 
7379
  # Add Knowledge Graph context (structured facts)
7380
  if kg_context:
7381
  system_prompt = system_prompt + "\n\n" + kg_context
7382
+
7383
+ # Add Self-Improvement adjustments (learned from user feedback)
7384
+ try:
7385
+ si_adjustments = SelfImprovement.get_adjustments()
7386
+ if si_adjustments:
7387
+ system_prompt = system_prompt + "\n\n" + si_adjustments
7388
+ except Exception:
7389
+ pass
7390
 
7391
  # Build message history — INFINITE CONTEXT via rolling summary
7392
  # (last 20 messages verbatim + summary of everything older)
 
7444
  # ULTRA-GENIUS: Use full reasoning pipeline for hard questions
7445
  use_deep_reasoning = ReasoningEngine.should_use_reasoning(user_message, messages)
7446
 
7447
+ # APEX-GENIUS: Use Multi-Agent Debate for decision/controversial questions
7448
+ is_decision_question = any(kw in user_msg_lower for kw in [
7449
+ "should i", "which is better", "vs", "versus", "or should",
7450
+ "best option", "recommend", "pros and cons", "trade-off",
7451
+ "worth it", "is it worth", "debate", "controversial",
7452
+ ])
7453
+
7454
  for iteration in range(max_tool_iters):
7455
  if privacy_level == "PRIVATE":
7456
  # Private request — use offline model only, no cloud
7457
  text, source = call_llm_private(messages, max_tokens=s.get("max_tokens", 4096),
7458
  temperature=s.get("temperature", 0.7))
7459
+ elif is_decision_question and iteration == 0:
7460
+ # APEX-GENIUS: Multi-agent debate for decisions
7461
+ log("ApexGenius: using MultiAgentDebate for decision question")
7462
+ text, source = MultiAgentDebate.debate(
7463
+ messages, max_tokens=s.get("max_tokens", 4096)
7464
+ )
7465
  elif use_deep_reasoning and iteration == 0:
7466
  # ULTRA-GENIUS: Full reasoning pipeline (think → draft → critique → refine)
7467
  log("UltraGenius: using ReasoningEngine (o1-style thinking)")
 
7524
  accumulated_text = text
7525
  parsed = parse_tool_call(text)
7526
  if parsed is None:
7527
+ # POST-PROCESSING: Code verification, fact-checking, proactive intelligence
7528
+ # Run in background for non-blocking improvements
7529
+ try:
7530
+ # 1. CODE VERIFICATION — if response contains code, verify it runs
7531
+ if "```python" in text or "def " in text or "import " in text:
7532
+ log("PostProcess: verifying code...")
7533
+ text = CodeVerifier.verify_and_fix(text, user_message)
7534
+ except Exception as e:
7535
+ log(f"CodeVerifier failed: {e}")
7536
+
7537
+ # 2. PROACTIVE INTELLIGENCE — record topic for pattern analysis
7538
+ try:
7539
+ ProactiveIntelligence.record_interaction(user_message)
7540
+ except Exception:
7541
+ pass
7542
+
7543
+ # 3. SELF-IMPROVEMENT — record feedback from previous turn
7544
+ # (analyze if user's current message is positive/negative about last response)
7545
+ try:
7546
+ history = conv.get_messages(limit=2)
7547
+ if len(history) >= 1:
7548
+ last_ai = history[-1] if history[-1]["role"] == "assistant" else ""
7549
+ if last_ai:
7550
+ SelfImprovement.record_feedback(
7551
+ history[-2]["content"] if len(history) >= 2 else "",
7552
+ last_ai["content"],
7553
+ user_message
7554
+ )
7555
+ except Exception:
7556
+ pass
7557
+
7558
  # Final answer
7559
  yield text, image_path, source
7560
  conv.add("user", user_message)