JatinAutonomousLabs commited on
Commit
c33c1d5
·
verified ·
1 Parent(s): 0e1cdba

Update graph.py

Browse files
Files changed (1) hide show
  1. graph.py +42 -25
graph.py CHANGED
@@ -411,61 +411,78 @@ def run_intent_agent(state: AgentState):
411
 
412
  def run_pm_agent(state: AgentState):
413
  log.info("--- PM ---")
414
- current_cycles = ensure_int(state, 'rework_cycles', 0) + 1
415
- max_loops_val = ensure_int(state, 'max_loops', 0)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
416
  path = ensure_list(state, 'execution_path') + ["PM"]
417
-
 
 
418
  context_parts = [
419
  f"=== USER REQUEST ===\n{state.get('userInput', '')}",
420
  f"\n=== OBJECTIVE ===\n{state.get('coreObjectivePrompt', '')}",
421
  f"\n=== MEMORY ===\n{state.get('retrievedMemory', 'None')}",
422
  ]
423
-
424
  if state.get('qaFeedback'):
425
  context_parts.append(f"\n=== QA FEEDBACK (MUST FIX) ===\n{state.get('qaFeedback')}")
426
  context_parts.append(f"\n=== PREVIOUS PLAN ===\n{json.dumps(state.get('pmPlan', {}).get('plan_steps', []), indent=2)}")
427
-
428
  full_context = "\n".join(context_parts)
429
-
430
  prompt = f"""Create DETAILED, EXECUTABLE plan.
431
 
432
  {full_context}
433
 
434
- Each step must be SPECIFIC and ACTIONABLE:
435
- - State EXACTLY what will be created/analyzed
436
- - Specify WHAT data/information will be used
437
- - Define WHAT methods will be applied
438
-
439
- JSON format:
440
  {{
441
- "plan_steps": ["Specific step 1...", "Specific step 2..."],
442
  "experiment_needed": true/false,
443
  "experiment_type": "notebook|script|excel|word|pdf|repo",
444
- "experiment_goal": "Detailed artifact description",
445
- "key_requirements": ["Critical requirements"]
446
  }}
 
 
 
 
 
 
 
 
447
 
448
- Be specific about using uploaded files, implementing algorithms, creating schemas."""
449
-
450
- response = llm.invoke(prompt)
451
- plan = parse_json_from_llm(getattr(response, "content", "") or "")
452
-
453
  if not plan:
454
  detection = detect_requested_output_types(state.get('userInput', ''))
455
  plan = {
456
  "plan_steps": ["Analyze request", "Process information", "Create deliverable", "Review"],
457
  "experiment_needed": detection.get('requires_artifact', False),
458
  "experiment_type": detection.get('artifact_type', 'word'),
459
- "experiment_goal": state.get('coreObjectivePrompt', state.get('userInput', ''))
 
460
  }
461
-
 
462
  exp_type = normalize_experiment_type(plan.get('experiment_type'), plan.get('experiment_goal',''))
463
  plan['experiment_type'] = exp_type
464
-
465
  if plan.get('experiment_needed') and not plan.get('experiment_goal'):
466
  plan['experiment_goal'] = state.get('userInput','')
467
-
468
- return {"pmPlan": plan, "execution_path": path, "rework_cycles": current_cycles, "status_update": f"Plan created ({len(plan.get('plan_steps', []))} steps)"}
 
 
 
469
 
470
  def _extract_code_blocks(text: str, lang_hint: Optional[str]=None) -> List[str]:
471
  if lang_hint and "python" in (lang_hint or "").lower():
 
411
 
412
  def run_pm_agent(state: AgentState):
413
  log.info("--- PM ---")
414
+ # Ensure keys
415
+ current_rework = ensure_int(state, 'rework_cycles', 0)
416
+ max_loops_val = ensure_int(state, 'max_loops', INITIAL_MAX_REWORK_CYCLES)
417
+
418
+ # If we've exhausted loops, short-circuit and produce fallback plan with a note
419
+ if current_rework > max_loops_val:
420
+ path = ensure_list(state, 'execution_path') + ["PM"]
421
+ fallback_plan = {
422
+ "plan_steps": ["Rework limit exceeded. Manual review required."],
423
+ "experiment_needed": False,
424
+ "experiment_type": "word",
425
+ "experiment_goal": state.get('coreObjectivePrompt', state.get('userInput',''))
426
+ }
427
+ return {"pmPlan": fallback_plan, "execution_path": path, "rework_cycles": current_rework, "status_update": "Rework limit hit - manual review"}
428
+
429
+ # Normal behavior: increment rework count for this pass
430
+ current_cycles = current_rework + 1
431
  path = ensure_list(state, 'execution_path') + ["PM"]
432
+
433
+ # (rest of your original PM prompt & parse flow, but ensure the output sets rework_cycles and max_loops)
434
+ # --- build full_context like before ---
435
  context_parts = [
436
  f"=== USER REQUEST ===\n{state.get('userInput', '')}",
437
  f"\n=== OBJECTIVE ===\n{state.get('coreObjectivePrompt', '')}",
438
  f"\n=== MEMORY ===\n{state.get('retrievedMemory', 'None')}",
439
  ]
 
440
  if state.get('qaFeedback'):
441
  context_parts.append(f"\n=== QA FEEDBACK (MUST FIX) ===\n{state.get('qaFeedback')}")
442
  context_parts.append(f"\n=== PREVIOUS PLAN ===\n{json.dumps(state.get('pmPlan', {}).get('plan_steps', []), indent=2)}")
 
443
  full_context = "\n".join(context_parts)
444
+
445
  prompt = f"""Create DETAILED, EXECUTABLE plan.
446
 
447
  {full_context}
448
 
449
+ Return JSON with:
 
 
 
 
 
450
  {{
451
+ "plan_steps": [...],
452
  "experiment_needed": true/false,
453
  "experiment_type": "notebook|script|excel|word|pdf|repo",
454
+ "experiment_goal": "...",
455
+ "key_requirements": [...]
456
  }}
457
+ Be concrete.
458
+ """
459
+ try:
460
+ response = llm.invoke(prompt)
461
+ plan = parse_json_from_llm(getattr(response, "content", "") or "")
462
+ except Exception as e:
463
+ log.warning("PM LLM failed: %s", e)
464
+ plan = None
465
 
 
 
 
 
 
466
  if not plan:
467
  detection = detect_requested_output_types(state.get('userInput', ''))
468
  plan = {
469
  "plan_steps": ["Analyze request", "Process information", "Create deliverable", "Review"],
470
  "experiment_needed": detection.get('requires_artifact', False),
471
  "experiment_type": detection.get('artifact_type', 'word'),
472
+ "experiment_goal": state.get('coreObjectivePrompt', state.get('userInput', '')),
473
+ "key_requirements": []
474
  }
475
+
476
+ # Normalize experiment_type
477
  exp_type = normalize_experiment_type(plan.get('experiment_type'), plan.get('experiment_goal',''))
478
  plan['experiment_type'] = exp_type
 
479
  if plan.get('experiment_needed') and not plan.get('experiment_goal'):
480
  plan['experiment_goal'] = state.get('userInput','')
481
+
482
+ # Attach loop control info
483
+ plan['max_loops_initial'] = max_loops_val
484
+ plan['estimated_cost_usd'] = plan.get('estimated_cost_usd', plan.get('estimated_cost_usd', 0.0))
485
+ return {"pmPlan": plan, "execution_path": path, "rework_cycles": current_cycles, "max_loops": max_loops_val, "status_update": f"Plan created ({len(plan.get('plan_steps', []))} steps)"}
486
 
487
  def _extract_code_blocks(text: str, lang_hint: Optional[str]=None) -> List[str]:
488
  if lang_hint and "python" in (lang_hint or "").lower():