gabejavitt commited on
Commit
4482b2c
·
verified ·
1 Parent(s): 11d2e23

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +50 -11
app.py CHANGED
@@ -520,7 +520,21 @@ def should_continue(state: AgentState):
520
  print("--- Condition: Tools called, routing to tools node. ---")
521
  return "tools"
522
 
523
- # 4. Loop back to agent (reasoning/planning step)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
524
  print(f"--- Condition: No tool call (Turn {current_turn}). Continuing to agent. ---")
525
  return "agent"
526
 
@@ -614,7 +628,7 @@ Your goal: Provide the EXACT answer in the EXACT format requested.
614
  chat_llm = ChatGroq(
615
  temperature=0, # Maximum determinism
616
  groq_api_key=GROQ_API_KEY,
617
- model_name="openai/gpt-oss-120b", # Best reasoning model
618
  max_tokens=4096,
619
  timeout=60
620
  )
@@ -627,10 +641,33 @@ Your goal: Provide the EXACT answer in the EXACT format requested.
627
  print("✅ Tools bound to LLM")
628
 
629
  # --- Agent Node ---
630
- def agent_node(state: AgentState):
631
- current_turn = state.get('turn', 0) + 1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
632
  print(f"\n{'='*60}")
633
  print(f"AGENT TURN {current_turn}/{MAX_TURNS}")
 
 
634
  print('='*60)
635
 
636
  messages_to_send = state["messages"]
@@ -651,27 +688,29 @@ Your goal: Provide the EXACT answer in the EXACT format requested.
651
  )
652
  return {"messages": [error_msg], "turn": current_turn}
653
  time.sleep(2 ** attempt) # Exponential backoff
 
654
  # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
655
- # --- ADD THIS RULE ENFORCEMENT BLOCK ---
656
  #
657
- # Force compliance with the "Plan on Turn 1" rule.
658
- # If the agent tries to call a tool on turn 1, we
659
- # strip the tool call and send a correction message.
660
  if current_turn == 1 and ai_message.tool_calls:
661
  print("⚠️ AGENT VIOLATION: Tried to call tools on Turn 1. Forcing replan.")
662
 
663
  # Strip the illegal tool call
664
  ai_message.tool_calls = []
665
 
666
- # Create a correction message
667
  correction_message = SystemMessage(
668
  content="SYSTEM: Protocol Violation. Your FIRST turn MUST be a plan with NO tool calls. "
669
  "You are not allowed to call any tools on your first turn. "
670
  "Re-read the protocol and provide your 2-3 sentence plan now."
671
  )
672
 
673
- # Return the (now harmless) AI message + the correction
674
- return {"messages": [ai_message, correction_message], "turn": current_turn}
 
 
675
  # --- END OF RULE ENFORCEMENT BLOCK ---
676
  # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
677
  # --- FIX #2: REPLACE THE FALLBACK PARSING BLOCK ---
 
520
  print("--- Condition: Tools called, routing to tools node. ---")
521
  return "tools"
522
 
523
+ # 4. NEW LOOP PREVENTION:
524
+ # Check for consecutive AI messages without tool calls.
525
+ # This catches "thinking" loops or raw answer dribbling (like "58").
526
+ if isinstance(last_message, AIMessage) and not last_message.tool_calls:
527
+ # Check if the message *before* this one was ALSO an AIMessage.
528
+ # We need at least 3 messages total (System, Human, AI-Turn1-Plan)
529
+ # for this check to be valid, so we check len > 2.
530
+ if len(state['messages']) > 2 and isinstance(state['messages'][-2], AIMessage):
531
+ print(f"--- Condition: Detected 2+ consecutive AI messages (Turn {current_turn}). Ending to prevent loop. ---")
532
+ state['messages'].append(
533
+ SystemMessage(content=f"SYSTEM: Agent stuck in a loop (consecutive non-tool-call AI messages). Ending execution.")
534
+ )
535
+ return END
536
+
537
+ # 5. Default: Loop back to agent (e.g., after Turn 1 plan)
538
  print(f"--- Condition: No tool call (Turn {current_turn}). Continuing to agent. ---")
539
  return "agent"
540
 
 
628
  chat_llm = ChatGroq(
629
  temperature=0, # Maximum determinism
630
  groq_api_key=GROQ_API_KEY,
631
+ model_name="qwen/qwen3-32b", # Best reasoning model
632
  max_tokens=4096,
633
  timeout=60
634
  )
 
641
  print("✅ Tools bound to LLM")
642
 
643
  # --- Agent Node ---
644
+ def agent_node(state: AgentState):
645
+
646
+ # --- Turn Counter Logic ---
647
+ # We need to check if this is a retry of a failed turn (e.g., Turn 1 violation)
648
+ # We identify a retry if the *last* message was our "Protocol Violation" message
649
+ last_msg = state['messages'][-1]
650
+ is_a_retry = False
651
+ if isinstance(last_msg, SystemMessage) and "Protocol Violation" in last_msg.content:
652
+ is_a_retry = True
653
+
654
+ # Get the state's current turn number
655
+ current_turn = state.get('turn', 0)
656
+
657
+ # If this is NOT a retry, increment the turn.
658
+ # If it IS a retry, we *stay on the same turn number*
659
+ if not is_a_retry:
660
+ current_turn += 1
661
+
662
+ # Handle the very first run (where state['turn'] is 0)
663
+ if current_turn == 0:
664
+ current_turn = 1
665
+ # --- End Turn Counter Logic ---
666
+
667
  print(f"\n{'='*60}")
668
  print(f"AGENT TURN {current_turn}/{MAX_TURNS}")
669
+ if is_a_retry:
670
+ print("--- (Re-trying after protocol violation) ---")
671
  print('='*60)
672
 
673
  messages_to_send = state["messages"]
 
688
  )
689
  return {"messages": [error_msg], "turn": current_turn}
690
  time.sleep(2 ** attempt) # Exponential backoff
691
+
692
  # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
693
+ # --- (FIX #1) RULE ENFORCEMENT BLOCK ---
694
  #
695
+ # If it's Turn 1 AND the agent tried to call tools, we reject it
696
+ # and force it to re-do Turn 1.
 
697
  if current_turn == 1 and ai_message.tool_calls:
698
  print("⚠️ AGENT VIOLATION: Tried to call tools on Turn 1. Forcing replan.")
699
 
700
  # Strip the illegal tool call
701
  ai_message.tool_calls = []
702
 
703
+ # Create the correction message that forces the plan
704
  correction_message = SystemMessage(
705
  content="SYSTEM: Protocol Violation. Your FIRST turn MUST be a plan with NO tool calls. "
706
  "You are not allowed to call any tools on your first turn. "
707
  "Re-read the protocol and provide your 2-3 sentence plan now."
708
  )
709
 
710
+ # Return the messages.
711
+ # Critically, we set the state's turn counter back to 1.
712
+ # This ensures the *next* run of this node is *still* Turn 1.
713
+ return {"messages": [ai_message, correction_message], "turn": 1}
714
  # --- END OF RULE ENFORCEMENT BLOCK ---
715
  # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
716
  # --- FIX #2: REPLACE THE FALLBACK PARSING BLOCK ---