JatsTheAIGen commited on
Commit
d761f8e
Β·
1 Parent(s): b25c250

Process flow visualizer + key skills [for validation only) V2

Browse files
Files changed (2) hide show
  1. app.py +160 -4
  2. test_process_flow_integration.py +151 -0
app.py CHANGED
@@ -21,6 +21,20 @@ logger = logging.getLogger(__name__)
21
  orchestrator = None
22
  orchestrator_available = False
23
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  try:
25
  logger.info("Attempting to import orchestration components...")
26
  import sys
@@ -30,7 +44,12 @@ try:
30
  from src.agents.intent_agent import create_intent_agent
31
  from src.agents.synthesis_agent import create_synthesis_agent
32
  from src.agents.safety_agent import create_safety_agent
33
- from src.agents.skills_identification_agent import create_skills_identification_agent
 
 
 
 
 
34
  from llm_router import LLMRouter
35
  from orchestrator_engine import MVPOrchestrator
36
  from context_manager import EfficientContextManager
@@ -305,11 +324,18 @@ def create_mobile_optimized_interface():
305
  show_label=False
306
  )
307
  interface_components['context_display'] = context_display
 
 
 
 
 
308
 
309
  # Mobile Bottom Navigation
310
  with gr.Row(visible=False, elem_id="mobile_nav") as mobile_navigation:
311
  chat_nav_btn = gr.Button("πŸ’¬ Chat", variant="secondary", size="sm", min_width=0)
312
  details_nav_btn = gr.Button("πŸ” Details", variant="secondary", size="sm", min_width=0)
 
 
313
  settings_nav_btn = gr.Button("βš™οΈ Settings", variant="secondary", size="sm", min_width=0)
314
 
315
  # Settings Panel (Modal for Mobile)
@@ -373,6 +399,21 @@ def create_mobile_optimized_interface():
373
  outputs.append(interface_components['skills_tags'])
374
  outputs.append(skills_display_row) # Add visibility control for skills display row
375
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
376
  # Include session_info in inputs to pass session ID
377
  inputs = [interface_components['message_input'], interface_components['chatbot']]
378
  if 'session_info' in interface_components:
@@ -417,6 +458,36 @@ def create_mobile_optimized_interface():
417
  interface_components.get('cache_enabled', None)
418
  ]
419
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
420
 
421
  return demo, interface_components
422
 
@@ -518,6 +589,7 @@ async def process_message_async(message: str, history: Optional[List], session_i
518
  reasoning_data = {}
519
  performance_data = {}
520
  context_data = {}
 
521
 
522
  # GUARANTEE: Always get a response
523
  response = "Hello! I'm processing your request..."
@@ -649,6 +721,7 @@ async def process_message_async(message: str, history: Optional[List], session_i
649
  "evidence_sources": [],
650
  "confidence_calibration": {"overall_confidence": 0.5, "initialization_mode": True}
651
  }
 
652
 
653
  # Add assistant response
654
  new_history.append({"role": "assistant", "content": response})
@@ -758,14 +831,89 @@ if SPACES_GPU_AVAILABLE and GPU is not None:
758
  chat_handler_fn = gpu_chat_handler
759
  else:
760
  def chat_handler_wrapper(message, history, session_id=None):
761
- """Wrapper to handle session ID"""
762
  if not session_id:
763
  session_id = str(uuid.uuid4())[:8]
764
  result = process_message(message, history, session_id)
765
  # Extract skills_html from result and determine visibility
766
  skills_html = result[6]
767
  skills_content, skills_visible = _update_skills_display(skills_html)
768
- return result[0], result[1], result[2], result[3], result[4], result[5], skills_content, gr.update(visible=skills_visible)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
769
  chat_handler_fn = chat_handler_wrapper
770
 
771
  # Initialize orchestrator on module load
@@ -798,8 +946,16 @@ def initialize_orchestrator():
798
  'intent_recognition': create_intent_agent(llm_router),
799
  'response_synthesis': create_synthesis_agent(llm_router),
800
  'safety_check': create_safety_agent(llm_router),
801
- 'skills_identification': create_skills_identification_agent(llm_router)
802
  }
 
 
 
 
 
 
 
 
 
803
  logger.info(f"βœ“ Initialized {len(agents)} agents")
804
 
805
  # Initialize Context Manager
 
21
  orchestrator = None
22
  orchestrator_available = False
23
 
24
+ # Import Process Flow Visualization
25
+ try:
26
+ from process_flow_visualizer import (
27
+ create_process_flow_tab,
28
+ update_process_flow_visualization,
29
+ clear_flow_history,
30
+ export_flow_data
31
+ )
32
+ process_flow_available = True
33
+ logger.info("βœ“ Process Flow Visualization available")
34
+ except ImportError as e:
35
+ logger.warning(f"Process Flow Visualization not available: {e}")
36
+ process_flow_available = False
37
+
38
  try:
39
  logger.info("Attempting to import orchestration components...")
40
  import sys
 
44
  from src.agents.intent_agent import create_intent_agent
45
  from src.agents.synthesis_agent import create_synthesis_agent
46
  from src.agents.safety_agent import create_safety_agent
47
+ try:
48
+ from src.agents.skills_identification_agent import create_skills_identification_agent
49
+ except ImportError:
50
+ logger.warning("Skills identification agent not available, using placeholder")
51
+ def create_skills_identification_agent(llm_router=None):
52
+ return None
53
  from llm_router import LLMRouter
54
  from orchestrator_engine import MVPOrchestrator
55
  from context_manager import EfficientContextManager
 
324
  show_label=False
325
  )
326
  interface_components['context_display'] = context_display
327
+
328
+ # Process Flow Tab (if available)
329
+ if process_flow_available:
330
+ process_flow_tab = create_process_flow_tab(interface_components)
331
+ interface_components['process_flow_tab'] = process_flow_tab
332
 
333
  # Mobile Bottom Navigation
334
  with gr.Row(visible=False, elem_id="mobile_nav") as mobile_navigation:
335
  chat_nav_btn = gr.Button("πŸ’¬ Chat", variant="secondary", size="sm", min_width=0)
336
  details_nav_btn = gr.Button("πŸ” Details", variant="secondary", size="sm", min_width=0)
337
+ if process_flow_available:
338
+ flow_nav_btn = gr.Button("πŸ”„ Flow", variant="secondary", size="sm", min_width=0)
339
  settings_nav_btn = gr.Button("βš™οΈ Settings", variant="secondary", size="sm", min_width=0)
340
 
341
  # Settings Panel (Modal for Mobile)
 
399
  outputs.append(interface_components['skills_tags'])
400
  outputs.append(skills_display_row) # Add visibility control for skills display row
401
 
402
+ # Add Process Flow outputs if available
403
+ if process_flow_available:
404
+ if 'flow_display' in interface_components:
405
+ outputs.append(interface_components['flow_display'])
406
+ if 'flow_stats' in interface_components:
407
+ outputs.append(interface_components['flow_stats'])
408
+ if 'performance_metrics' in interface_components:
409
+ outputs.append(interface_components['performance_metrics'])
410
+ if 'intent_details' in interface_components:
411
+ outputs.append(interface_components['intent_details'])
412
+ if 'synthesis_details' in interface_components:
413
+ outputs.append(interface_components['synthesis_details'])
414
+ if 'safety_details' in interface_components:
415
+ outputs.append(interface_components['safety_details'])
416
+
417
  # Include session_info in inputs to pass session ID
418
  inputs = [interface_components['message_input'], interface_components['chatbot']]
419
  if 'session_info' in interface_components:
 
458
  interface_components.get('cache_enabled', None)
459
  ]
460
  )
461
+
462
+ # Wire up Process Flow event handlers if available
463
+ if process_flow_available:
464
+ # Clear flow history button
465
+ if 'clear_flow_btn' in interface_components:
466
+ interface_components['clear_flow_btn'].click(
467
+ fn=clear_flow_history,
468
+ outputs=[
469
+ interface_components.get('flow_display'),
470
+ interface_components.get('flow_stats'),
471
+ interface_components.get('performance_metrics'),
472
+ interface_components.get('intent_details'),
473
+ interface_components.get('synthesis_details'),
474
+ interface_components.get('safety_details')
475
+ ]
476
+ )
477
+
478
+ # Export flow data button
479
+ if 'export_flow_btn' in interface_components:
480
+ interface_components['export_flow_btn'].click(
481
+ fn=export_flow_data,
482
+ outputs=[gr.File(label="Download Flow Data")]
483
+ )
484
+
485
+ # Share flow button (placeholder)
486
+ if 'share_flow_btn' in interface_components:
487
+ interface_components['share_flow_btn'].click(
488
+ fn=lambda: gr.Info("Flow sharing feature coming soon!"),
489
+ outputs=[]
490
+ )
491
 
492
  return demo, interface_components
493
 
 
589
  reasoning_data = {}
590
  performance_data = {}
591
  context_data = {}
592
+ skills_html = "" # Initialize skills_html
593
 
594
  # GUARANTEE: Always get a response
595
  response = "Hello! I'm processing your request..."
 
721
  "evidence_sources": [],
722
  "confidence_calibration": {"overall_confidence": 0.5, "initialization_mode": True}
723
  }
724
+ skills_html = "" # Initialize skills_html for orchestrator not available case
725
 
726
  # Add assistant response
727
  new_history.append({"role": "assistant", "content": response})
 
831
  chat_handler_fn = gpu_chat_handler
832
  else:
833
  def chat_handler_wrapper(message, history, session_id=None):
834
+ """Wrapper to handle session ID with Process Flow Visualization"""
835
  if not session_id:
836
  session_id = str(uuid.uuid4())[:8]
837
  result = process_message(message, history, session_id)
838
  # Extract skills_html from result and determine visibility
839
  skills_html = result[6]
840
  skills_content, skills_visible = _update_skills_display(skills_html)
841
+
842
+ # Prepare process flow updates if available
843
+ flow_updates = {}
844
+ if process_flow_available:
845
+ try:
846
+ # Extract data for process flow visualization
847
+ reasoning_data = result[2]
848
+ performance_data = result[3]
849
+ context_data = result[4]
850
+
851
+ # Create mock agent results for visualization
852
+ intent_result = {
853
+ "primary_intent": reasoning_data.get("chain_of_thought", {}).get("step_1", {}).get("hypothesis", "unknown"),
854
+ "confidence_scores": {"overall": reasoning_data.get("confidence_calibration", {}).get("overall_confidence", 0.7)},
855
+ "secondary_intents": [],
856
+ "reasoning_chain": list(reasoning_data.get("chain_of_thought", {}).keys()),
857
+ "context_tags": ["general"],
858
+ "processing_time": performance_data.get("processing_time", 0.5),
859
+ "agent_id": "INTENT_REC_001"
860
+ }
861
+
862
+ synthesis_result = {
863
+ "final_response": result[0][-1]["content"] if result[0] else "",
864
+ "draft_response": "",
865
+ "source_references": ["INTENT_REC_001"],
866
+ "coherence_score": 0.85,
867
+ "synthesis_method": "llm_enhanced",
868
+ "intent_alignment": {"intent_detected": intent_result["primary_intent"], "alignment_score": 0.8},
869
+ "processing_time": performance_data.get("processing_time", 0.5) - 0.15,
870
+ "agent_id": "RESP_SYNTH_001"
871
+ }
872
+
873
+ safety_result = {
874
+ "original_response": result[0][-1]["content"] if result[0] else "",
875
+ "safety_checked_response": result[0][-1]["content"] if result[0] else "",
876
+ "warnings": [],
877
+ "safety_analysis": {
878
+ "toxicity_score": 0.1,
879
+ "bias_indicators": [],
880
+ "privacy_concerns": [],
881
+ "overall_safety_score": 0.9,
882
+ "confidence_scores": {"safety": 0.9}
883
+ },
884
+ "blocked": False,
885
+ "processing_time": 0.1,
886
+ "agent_id": "SAFETY_BIAS_001"
887
+ }
888
+
889
+ # Update process flow visualization
890
+ flow_updates = update_process_flow_visualization(
891
+ user_input=message,
892
+ intent_result=intent_result,
893
+ synthesis_result=synthesis_result,
894
+ safety_result=safety_result,
895
+ final_response=result[0][-1]["content"] if result[0] else "",
896
+ session_id=session_id,
897
+ processing_time=performance_data.get("processing_time", 1.0)
898
+ )
899
+ except Exception as e:
900
+ logger.error(f"Error updating process flow: {e}")
901
+ flow_updates = {}
902
+
903
+ # Return all updates including process flow
904
+ if process_flow_available and flow_updates:
905
+ return (
906
+ result[0], result[1], result[2], result[3], result[4], result[5],
907
+ skills_content, gr.update(visible=skills_visible),
908
+ flow_updates.get("flow_display", ""),
909
+ flow_updates.get("flow_stats", {}),
910
+ flow_updates.get("performance_metrics", {}),
911
+ flow_updates.get("intent_details", {}),
912
+ flow_updates.get("synthesis_details", {}),
913
+ flow_updates.get("safety_details", {})
914
+ )
915
+ else:
916
+ return result[0], result[1], result[2], result[3], result[4], result[5], skills_content, gr.update(visible=skills_visible)
917
  chat_handler_fn = chat_handler_wrapper
918
 
919
  # Initialize orchestrator on module load
 
946
  'intent_recognition': create_intent_agent(llm_router),
947
  'response_synthesis': create_synthesis_agent(llm_router),
948
  'safety_check': create_safety_agent(llm_router),
 
949
  }
950
+
951
+ # Add skills identification agent if available
952
+ skills_agent = create_skills_identification_agent(llm_router)
953
+ if skills_agent is not None:
954
+ agents['skills_identification'] = skills_agent
955
+ logger.info("βœ“ Skills identification agent initialized")
956
+ else:
957
+ logger.info("⚠ Skills identification agent not available")
958
+
959
  logger.info(f"βœ“ Initialized {len(agents)} agents")
960
 
961
  # Initialize Context Manager
test_process_flow_integration.py ADDED
@@ -0,0 +1,151 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Test script to verify Process Flow Visualization integration
4
+ """
5
+
6
+ import sys
7
+ import os
8
+
9
+ def test_imports():
10
+ """Test if all required imports work"""
11
+ print("Testing imports...")
12
+
13
+ try:
14
+ # Test process flow visualizer import
15
+ from process_flow_visualizer import (
16
+ create_process_flow_tab,
17
+ update_process_flow_visualization,
18
+ clear_flow_history,
19
+ export_flow_data
20
+ )
21
+ print("βœ“ Process Flow Visualizer imports successful")
22
+ return True
23
+ except ImportError as e:
24
+ print(f"βœ— Process Flow Visualizer import failed: {e}")
25
+ return False
26
+
27
+ def test_app_integration():
28
+ """Test if app.py can be imported without errors"""
29
+ print("Testing app.py integration...")
30
+
31
+ try:
32
+ # Add current directory to path
33
+ sys.path.insert(0, '.')
34
+
35
+ # Test importing app components
36
+ import app
37
+ print("βœ“ App.py imports successful")
38
+
39
+ # Test if process flow is available
40
+ if hasattr(app, 'process_flow_available'):
41
+ print(f"βœ“ Process Flow available: {app.process_flow_available}")
42
+ else:
43
+ print("⚠ Process Flow availability not detected")
44
+
45
+ return True
46
+ except Exception as e:
47
+ print(f"βœ— App.py integration failed: {e}")
48
+ return False
49
+
50
+ def test_process_flow_functions():
51
+ """Test process flow functions"""
52
+ print("Testing Process Flow functions...")
53
+
54
+ try:
55
+ from process_flow_visualizer import update_process_flow_visualization
56
+
57
+ # Test with mock data
58
+ mock_intent_result = {
59
+ "primary_intent": "information_request",
60
+ "confidence_scores": {"information_request": 0.8},
61
+ "secondary_intents": [],
62
+ "reasoning_chain": ["Step 1: Analyze user input"],
63
+ "context_tags": ["general"],
64
+ "processing_time": 0.15,
65
+ "agent_id": "INTENT_REC_001"
66
+ }
67
+
68
+ mock_synthesis_result = {
69
+ "final_response": "Test response",
70
+ "draft_response": "",
71
+ "source_references": ["INTENT_REC_001"],
72
+ "coherence_score": 0.85,
73
+ "synthesis_method": "llm_enhanced",
74
+ "intent_alignment": {"intent_detected": "information_request", "alignment_score": 0.8},
75
+ "processing_time": 0.5,
76
+ "agent_id": "RESP_SYNTH_001"
77
+ }
78
+
79
+ mock_safety_result = {
80
+ "original_response": "Test response",
81
+ "safety_checked_response": "Test response",
82
+ "warnings": [],
83
+ "safety_analysis": {
84
+ "toxicity_score": 0.1,
85
+ "bias_indicators": [],
86
+ "privacy_concerns": [],
87
+ "overall_safety_score": 0.9,
88
+ "confidence_scores": {"safety": 0.9}
89
+ },
90
+ "blocked": False,
91
+ "processing_time": 0.1,
92
+ "agent_id": "SAFETY_BIAS_001"
93
+ }
94
+
95
+ # Test the function
96
+ result = update_process_flow_visualization(
97
+ user_input="Test message",
98
+ intent_result=mock_intent_result,
99
+ synthesis_result=mock_synthesis_result,
100
+ safety_result=mock_safety_result,
101
+ final_response="Test response",
102
+ session_id="test_session",
103
+ processing_time=1.0
104
+ )
105
+
106
+ print("βœ“ Process Flow functions work correctly")
107
+ print(f"βœ“ Generated flow HTML length: {len(result.get('flow_display', ''))}")
108
+ return True
109
+
110
+ except Exception as e:
111
+ print(f"βœ— Process Flow functions failed: {e}")
112
+ return False
113
+
114
+ def main():
115
+ """Run all tests"""
116
+ print("=" * 60)
117
+ print("PROCESS FLOW VISUALIZATION INTEGRATION TEST")
118
+ print("=" * 60)
119
+
120
+ tests = [
121
+ test_imports,
122
+ test_app_integration,
123
+ test_process_flow_functions
124
+ ]
125
+
126
+ passed = 0
127
+ total = len(tests)
128
+
129
+ for test in tests:
130
+ try:
131
+ if test():
132
+ passed += 1
133
+ print()
134
+ except Exception as e:
135
+ print(f"βœ— Test {test.__name__} failed with exception: {e}")
136
+ print()
137
+
138
+ print("=" * 60)
139
+ print(f"TEST RESULTS: {passed}/{total} tests passed")
140
+ print("=" * 60)
141
+
142
+ if passed == total:
143
+ print("πŸŽ‰ All tests passed! Process Flow Visualization is ready!")
144
+ return True
145
+ else:
146
+ print("❌ Some tests failed. Please check the errors above.")
147
+ return False
148
+
149
+ if __name__ == "__main__":
150
+ success = main()
151
+ sys.exit(0 if success else 1)