Commit
·
d771375
1
Parent(s):
fa57725
Details enhancement V1
Browse files- app.py +115 -13
- orchestrator_engine.py +286 -7
app.py
CHANGED
|
@@ -429,12 +429,31 @@ async def process_message_async(message: str, history: Optional[List], session_i
|
|
| 429 |
str(result.get('result', ''))
|
| 430 |
)
|
| 431 |
|
| 432 |
-
# Extract metadata for Details tab
|
| 433 |
-
reasoning_data = {
|
| 434 |
-
"
|
| 435 |
-
"
|
| 436 |
-
"
|
| 437 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 438 |
|
| 439 |
performance_data = {
|
| 440 |
"agent_trace": result.get('agent_trace', []),
|
|
@@ -464,14 +483,52 @@ async def process_message_async(message: str, history: Optional[List], session_i
|
|
| 464 |
|
| 465 |
except Exception as orch_error:
|
| 466 |
logger.error(f"Orchestrator error: {orch_error}", exc_info=True)
|
| 467 |
-
# Fallback response with error info
|
| 468 |
response = f"I'm experiencing some technical difficulties. Your message was: '{message[:100]}...' Please try again or rephrase your question."
|
| 469 |
-
reasoning_data = {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 470 |
else:
|
| 471 |
-
# System initialization message
|
| 472 |
logger.info("Orchestrator not yet available")
|
| 473 |
response = f"Hello! I received your message about: '{message}'.\n\nThe orchestration system is initializing. Your question is important and I'll provide a comprehensive answer shortly."
|
| 474 |
-
reasoning_data = {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 475 |
|
| 476 |
# Add assistant response
|
| 477 |
new_history.append({"role": "assistant", "content": response})
|
|
@@ -480,7 +537,7 @@ async def process_message_async(message: str, history: Optional[List], session_i
|
|
| 480 |
return new_history, "", reasoning_data, performance_data, context_data, session_id
|
| 481 |
|
| 482 |
except Exception as e:
|
| 483 |
-
# FINAL FALLBACK: Always return something to user
|
| 484 |
logger.error(f"Error in process_message_async: {e}", exc_info=True)
|
| 485 |
|
| 486 |
# Create error history with helpful message
|
|
@@ -494,7 +551,29 @@ async def process_message_async(message: str, history: Optional[List], session_i
|
|
| 494 |
)
|
| 495 |
error_history.append({"role": "assistant", "content": error_message})
|
| 496 |
|
| 497 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 498 |
|
| 499 |
def process_message(message: str, history: Optional[List], session_id: Optional[str] = None) -> Tuple[List, str, dict, dict, dict, str]:
|
| 500 |
"""
|
|
@@ -518,7 +597,30 @@ def process_message(message: str, history: Optional[List], session_id: Optional[
|
|
| 518 |
error_history = list(history) if history else []
|
| 519 |
error_history.append({"role": "user", "content": message})
|
| 520 |
error_history.append({"role": "assistant", "content": f"Error: {str(e)}"})
|
| 521 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 522 |
|
| 523 |
# Decorate the chat handler with GPU if available
|
| 524 |
if SPACES_GPU_AVAILABLE and GPU is not None:
|
|
|
|
| 429 |
str(result.get('result', ''))
|
| 430 |
)
|
| 431 |
|
| 432 |
+
# Extract metadata for Details tab with enhanced reasoning chain
|
| 433 |
+
reasoning_data = result.get('metadata', {}).get('reasoning_chain', {
|
| 434 |
+
"chain_of_thought": {},
|
| 435 |
+
"alternative_paths": [],
|
| 436 |
+
"uncertainty_areas": [],
|
| 437 |
+
"evidence_sources": [],
|
| 438 |
+
"confidence_calibration": {}
|
| 439 |
+
})
|
| 440 |
+
|
| 441 |
+
# Ensure we have the enhanced structure even if orchestrator didn't provide it
|
| 442 |
+
if not reasoning_data.get('chain_of_thought'):
|
| 443 |
+
reasoning_data = {
|
| 444 |
+
"chain_of_thought": {
|
| 445 |
+
"step_1": {
|
| 446 |
+
"hypothesis": "Processing user request",
|
| 447 |
+
"evidence": [f"User input: {message[:50]}..."],
|
| 448 |
+
"confidence": 0.7,
|
| 449 |
+
"reasoning": "Basic request processing"
|
| 450 |
+
}
|
| 451 |
+
},
|
| 452 |
+
"alternative_paths": [],
|
| 453 |
+
"uncertainty_areas": [],
|
| 454 |
+
"evidence_sources": [],
|
| 455 |
+
"confidence_calibration": {"overall_confidence": 0.7}
|
| 456 |
+
}
|
| 457 |
|
| 458 |
performance_data = {
|
| 459 |
"agent_trace": result.get('agent_trace', []),
|
|
|
|
| 483 |
|
| 484 |
except Exception as orch_error:
|
| 485 |
logger.error(f"Orchestrator error: {orch_error}", exc_info=True)
|
| 486 |
+
# Fallback response with error info and enhanced reasoning
|
| 487 |
response = f"I'm experiencing some technical difficulties. Your message was: '{message[:100]}...' Please try again or rephrase your question."
|
| 488 |
+
reasoning_data = {
|
| 489 |
+
"chain_of_thought": {
|
| 490 |
+
"step_1": {
|
| 491 |
+
"hypothesis": "System encountered an error during processing",
|
| 492 |
+
"evidence": [f"Error: {str(orch_error)[:100]}..."],
|
| 493 |
+
"confidence": 0.3,
|
| 494 |
+
"reasoning": "Orchestrator failure - fallback mode activated"
|
| 495 |
+
}
|
| 496 |
+
},
|
| 497 |
+
"alternative_paths": [],
|
| 498 |
+
"uncertainty_areas": [
|
| 499 |
+
{
|
| 500 |
+
"aspect": "System reliability",
|
| 501 |
+
"confidence": 0.3,
|
| 502 |
+
"mitigation": "Error handling and graceful degradation"
|
| 503 |
+
}
|
| 504 |
+
],
|
| 505 |
+
"evidence_sources": [],
|
| 506 |
+
"confidence_calibration": {"overall_confidence": 0.3, "error_mode": True}
|
| 507 |
+
}
|
| 508 |
else:
|
| 509 |
+
# System initialization message with enhanced reasoning
|
| 510 |
logger.info("Orchestrator not yet available")
|
| 511 |
response = f"Hello! I received your message about: '{message}'.\n\nThe orchestration system is initializing. Your question is important and I'll provide a comprehensive answer shortly."
|
| 512 |
+
reasoning_data = {
|
| 513 |
+
"chain_of_thought": {
|
| 514 |
+
"step_1": {
|
| 515 |
+
"hypothesis": "System is initializing and not yet ready",
|
| 516 |
+
"evidence": ["Orchestrator not available", f"User input: {message[:50]}..."],
|
| 517 |
+
"confidence": 0.5,
|
| 518 |
+
"reasoning": "System startup phase - components loading"
|
| 519 |
+
}
|
| 520 |
+
},
|
| 521 |
+
"alternative_paths": [],
|
| 522 |
+
"uncertainty_areas": [
|
| 523 |
+
{
|
| 524 |
+
"aspect": "System readiness",
|
| 525 |
+
"confidence": 0.5,
|
| 526 |
+
"mitigation": "Graceful initialization message"
|
| 527 |
+
}
|
| 528 |
+
],
|
| 529 |
+
"evidence_sources": [],
|
| 530 |
+
"confidence_calibration": {"overall_confidence": 0.5, "initialization_mode": True}
|
| 531 |
+
}
|
| 532 |
|
| 533 |
# Add assistant response
|
| 534 |
new_history.append({"role": "assistant", "content": response})
|
|
|
|
| 537 |
return new_history, "", reasoning_data, performance_data, context_data, session_id
|
| 538 |
|
| 539 |
except Exception as e:
|
| 540 |
+
# FINAL FALLBACK: Always return something to user with enhanced reasoning
|
| 541 |
logger.error(f"Error in process_message_async: {e}", exc_info=True)
|
| 542 |
|
| 543 |
# Create error history with helpful message
|
|
|
|
| 551 |
)
|
| 552 |
error_history.append({"role": "assistant", "content": error_message})
|
| 553 |
|
| 554 |
+
# Enhanced reasoning for error case
|
| 555 |
+
reasoning_data = {
|
| 556 |
+
"chain_of_thought": {
|
| 557 |
+
"step_1": {
|
| 558 |
+
"hypothesis": "Critical system error occurred",
|
| 559 |
+
"evidence": [f"Exception: {str(e)[:100]}...", f"User input: {message[:50]}..."],
|
| 560 |
+
"confidence": 0.2,
|
| 561 |
+
"reasoning": "System error handling - final fallback activated"
|
| 562 |
+
}
|
| 563 |
+
},
|
| 564 |
+
"alternative_paths": [],
|
| 565 |
+
"uncertainty_areas": [
|
| 566 |
+
{
|
| 567 |
+
"aspect": "System stability",
|
| 568 |
+
"confidence": 0.2,
|
| 569 |
+
"mitigation": "Error logging and user notification"
|
| 570 |
+
}
|
| 571 |
+
],
|
| 572 |
+
"evidence_sources": [],
|
| 573 |
+
"confidence_calibration": {"overall_confidence": 0.2, "critical_error": True}
|
| 574 |
+
}
|
| 575 |
+
|
| 576 |
+
return error_history, "", reasoning_data, {}, {}, session_id
|
| 577 |
|
| 578 |
def process_message(message: str, history: Optional[List], session_id: Optional[str] = None) -> Tuple[List, str, dict, dict, dict, str]:
|
| 579 |
"""
|
|
|
|
| 597 |
error_history = list(history) if history else []
|
| 598 |
error_history.append({"role": "user", "content": message})
|
| 599 |
error_history.append({"role": "assistant", "content": f"Error: {str(e)}"})
|
| 600 |
+
|
| 601 |
+
# Enhanced reasoning for sync error case
|
| 602 |
+
reasoning_data = {
|
| 603 |
+
"chain_of_thought": {
|
| 604 |
+
"step_1": {
|
| 605 |
+
"hypothesis": "Synchronous processing error",
|
| 606 |
+
"evidence": [f"Sync error: {str(e)[:100]}...", f"User input: {message[:50]}..."],
|
| 607 |
+
"confidence": 0.2,
|
| 608 |
+
"reasoning": "Synchronous wrapper error handling"
|
| 609 |
+
}
|
| 610 |
+
},
|
| 611 |
+
"alternative_paths": [],
|
| 612 |
+
"uncertainty_areas": [
|
| 613 |
+
{
|
| 614 |
+
"aspect": "Processing reliability",
|
| 615 |
+
"confidence": 0.2,
|
| 616 |
+
"mitigation": "Error logging and fallback response"
|
| 617 |
+
}
|
| 618 |
+
],
|
| 619 |
+
"evidence_sources": [],
|
| 620 |
+
"confidence_calibration": {"overall_confidence": 0.2, "sync_error": True}
|
| 621 |
+
}
|
| 622 |
+
|
| 623 |
+
return error_history, "", reasoning_data, {}, {}, session_id
|
| 624 |
|
| 625 |
# Decorate the chat handler with GPU if available
|
| 626 |
if SPACES_GPU_AVAILABLE and GPU is not None:
|
orchestrator_engine.py
CHANGED
|
@@ -16,7 +16,7 @@ class MVPOrchestrator:
|
|
| 16 |
|
| 17 |
async def process_request(self, session_id: str, user_input: str) -> dict:
|
| 18 |
"""
|
| 19 |
-
Main orchestration flow with academic differentiation
|
| 20 |
"""
|
| 21 |
logger.info(f"Processing request for session {session_id}")
|
| 22 |
logger.info(f"User input: {user_input[:100]}")
|
|
@@ -25,17 +25,38 @@ class MVPOrchestrator:
|
|
| 25 |
self.execution_trace = []
|
| 26 |
start_time = time.time()
|
| 27 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
try:
|
| 29 |
# Step 1: Generate unique interaction ID
|
| 30 |
interaction_id = self._generate_interaction_id(session_id)
|
| 31 |
logger.info(f"Generated interaction ID: {interaction_id}")
|
| 32 |
|
| 33 |
-
# Step 2: Context management
|
| 34 |
logger.info("Step 2: Managing context...")
|
| 35 |
context = await self.context_manager.manage_context(session_id, user_input)
|
| 36 |
logger.info(f"Context retrieved: {len(context.get('interactions', []))} interactions")
|
| 37 |
|
| 38 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
logger.info("Step 3: Recognizing intent...")
|
| 40 |
self.execution_trace.append({
|
| 41 |
"step": "intent_recognition",
|
|
@@ -52,16 +73,40 @@ class MVPOrchestrator:
|
|
| 52 |
})
|
| 53 |
logger.info(f"Intent detected: {intent_result.get('primary_intent', 'unknown')}")
|
| 54 |
|
| 55 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 56 |
logger.info("Step 4: Creating execution plan...")
|
| 57 |
execution_plan = await self._create_execution_plan(intent_result, context)
|
| 58 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
# Step 5: Parallel agent execution
|
| 60 |
logger.info("Step 5: Executing agents...")
|
| 61 |
agent_results = await self._execute_agents(execution_plan, user_input, context)
|
| 62 |
logger.info(f"Agent execution complete: {len(agent_results)} results")
|
| 63 |
|
| 64 |
-
# Step 6: Response synthesis
|
| 65 |
logger.info("Step 6: Synthesizing response...")
|
| 66 |
self.execution_trace.append({
|
| 67 |
"step": "response_synthesis",
|
|
@@ -78,7 +123,19 @@ class MVPOrchestrator:
|
|
| 78 |
"result": {"synthesis_method": final_response.get('synthesis_method', 'unknown')}
|
| 79 |
})
|
| 80 |
|
| 81 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
logger.info("Step 7: Safety check...")
|
| 83 |
self.execution_trace.append({
|
| 84 |
"step": "safety_check",
|
|
@@ -94,6 +151,24 @@ class MVPOrchestrator:
|
|
| 94 |
"result": {"warnings": safety_checked.get('warnings', [])}
|
| 95 |
})
|
| 96 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
processing_time = time.time() - start_time
|
| 98 |
|
| 99 |
result = self._format_final_output(safety_checked, interaction_id, {
|
|
@@ -110,7 +185,8 @@ class MVPOrchestrator:
|
|
| 110 |
'processing_time': processing_time,
|
| 111 |
'agents_used': list(self.agents.keys()),
|
| 112 |
'intent_result': intent_result,
|
| 113 |
-
'synthesis_result': final_response
|
|
|
|
| 114 |
})
|
| 115 |
|
| 116 |
# Update context with the final response for future context retrieval
|
|
@@ -220,4 +296,207 @@ class MVPOrchestrator:
|
|
| 220 |
Clear the execution trace
|
| 221 |
"""
|
| 222 |
self.execution_trace = []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 223 |
|
|
|
|
| 16 |
|
| 17 |
async def process_request(self, session_id: str, user_input: str) -> dict:
|
| 18 |
"""
|
| 19 |
+
Main orchestration flow with academic differentiation and enhanced reasoning chain
|
| 20 |
"""
|
| 21 |
logger.info(f"Processing request for session {session_id}")
|
| 22 |
logger.info(f"User input: {user_input[:100]}")
|
|
|
|
| 25 |
self.execution_trace = []
|
| 26 |
start_time = time.time()
|
| 27 |
|
| 28 |
+
# Initialize enhanced reasoning chain
|
| 29 |
+
reasoning_chain = {
|
| 30 |
+
"chain_of_thought": {},
|
| 31 |
+
"alternative_paths": [],
|
| 32 |
+
"uncertainty_areas": [],
|
| 33 |
+
"evidence_sources": [],
|
| 34 |
+
"confidence_calibration": {}
|
| 35 |
+
}
|
| 36 |
+
|
| 37 |
try:
|
| 38 |
# Step 1: Generate unique interaction ID
|
| 39 |
interaction_id = self._generate_interaction_id(session_id)
|
| 40 |
logger.info(f"Generated interaction ID: {interaction_id}")
|
| 41 |
|
| 42 |
+
# Step 2: Context management with reasoning
|
| 43 |
logger.info("Step 2: Managing context...")
|
| 44 |
context = await self.context_manager.manage_context(session_id, user_input)
|
| 45 |
logger.info(f"Context retrieved: {len(context.get('interactions', []))} interactions")
|
| 46 |
|
| 47 |
+
# Add context analysis to reasoning chain
|
| 48 |
+
reasoning_chain["chain_of_thought"]["step_1"] = {
|
| 49 |
+
"hypothesis": "Analyzing conversation context and user history",
|
| 50 |
+
"evidence": [
|
| 51 |
+
f"Previous interactions: {len(context.get('interactions', []))}",
|
| 52 |
+
f"Session duration: {self._calculate_session_duration(context)}",
|
| 53 |
+
f"Topic continuity: {self._analyze_topic_continuity(context, user_input)}"
|
| 54 |
+
],
|
| 55 |
+
"confidence": 0.85,
|
| 56 |
+
"reasoning": "Context analysis provides foundation for intent recognition and response personalization"
|
| 57 |
+
}
|
| 58 |
+
|
| 59 |
+
# Step 3: Intent recognition with enhanced CoT
|
| 60 |
logger.info("Step 3: Recognizing intent...")
|
| 61 |
self.execution_trace.append({
|
| 62 |
"step": "intent_recognition",
|
|
|
|
| 73 |
})
|
| 74 |
logger.info(f"Intent detected: {intent_result.get('primary_intent', 'unknown')}")
|
| 75 |
|
| 76 |
+
# Add intent reasoning to chain
|
| 77 |
+
reasoning_chain["chain_of_thought"]["step_2"] = {
|
| 78 |
+
"hypothesis": f"User intent is '{intent_result.get('primary_intent', 'unknown')}'",
|
| 79 |
+
"evidence": [
|
| 80 |
+
f"Pattern analysis: {self._extract_pattern_evidence(user_input)}",
|
| 81 |
+
f"Confidence scores: {intent_result.get('confidence_scores', {})}",
|
| 82 |
+
f"Secondary intents: {intent_result.get('secondary_intents', [])}"
|
| 83 |
+
],
|
| 84 |
+
"confidence": intent_result.get('confidence_scores', {}).get(intent_result.get('primary_intent', 'unknown'), 0.7),
|
| 85 |
+
"reasoning": f"Intent recognition based on linguistic patterns and context analysis"
|
| 86 |
+
}
|
| 87 |
+
|
| 88 |
+
# Step 4: Agent execution planning with reasoning
|
| 89 |
logger.info("Step 4: Creating execution plan...")
|
| 90 |
execution_plan = await self._create_execution_plan(intent_result, context)
|
| 91 |
|
| 92 |
+
# Add execution planning reasoning
|
| 93 |
+
reasoning_chain["chain_of_thought"]["step_3"] = {
|
| 94 |
+
"hypothesis": f"Optimal agent sequence for '{intent_result.get('primary_intent', 'unknown')}' intent",
|
| 95 |
+
"evidence": [
|
| 96 |
+
f"Intent complexity: {self._assess_intent_complexity(intent_result)}",
|
| 97 |
+
f"Required agents: {execution_plan.get('agents_to_execute', [])}",
|
| 98 |
+
f"Execution strategy: {execution_plan.get('execution_order', 'sequential')}"
|
| 99 |
+
],
|
| 100 |
+
"confidence": 0.80,
|
| 101 |
+
"reasoning": "Agent selection based on intent requirements and system capabilities"
|
| 102 |
+
}
|
| 103 |
+
|
| 104 |
# Step 5: Parallel agent execution
|
| 105 |
logger.info("Step 5: Executing agents...")
|
| 106 |
agent_results = await self._execute_agents(execution_plan, user_input, context)
|
| 107 |
logger.info(f"Agent execution complete: {len(agent_results)} results")
|
| 108 |
|
| 109 |
+
# Step 6: Response synthesis with reasoning
|
| 110 |
logger.info("Step 6: Synthesizing response...")
|
| 111 |
self.execution_trace.append({
|
| 112 |
"step": "response_synthesis",
|
|
|
|
| 123 |
"result": {"synthesis_method": final_response.get('synthesis_method', 'unknown')}
|
| 124 |
})
|
| 125 |
|
| 126 |
+
# Add synthesis reasoning
|
| 127 |
+
reasoning_chain["chain_of_thought"]["step_4"] = {
|
| 128 |
+
"hypothesis": f"Response synthesis using '{final_response.get('synthesis_method', 'unknown')}' method",
|
| 129 |
+
"evidence": [
|
| 130 |
+
f"Synthesis quality: {final_response.get('coherence_score', 0.7)}",
|
| 131 |
+
f"Source integration: {len(final_response.get('source_references', []))} sources",
|
| 132 |
+
f"Response length: {len(str(final_response.get('final_response', '')))} characters"
|
| 133 |
+
],
|
| 134 |
+
"confidence": final_response.get('coherence_score', 0.7),
|
| 135 |
+
"reasoning": "Multi-source information integration with quality optimization"
|
| 136 |
+
}
|
| 137 |
+
|
| 138 |
+
# Step 7: Safety and bias check with reasoning
|
| 139 |
logger.info("Step 7: Safety check...")
|
| 140 |
self.execution_trace.append({
|
| 141 |
"step": "safety_check",
|
|
|
|
| 151 |
"result": {"warnings": safety_checked.get('warnings', [])}
|
| 152 |
})
|
| 153 |
|
| 154 |
+
# Add safety reasoning
|
| 155 |
+
reasoning_chain["chain_of_thought"]["step_5"] = {
|
| 156 |
+
"hypothesis": "Response passes safety and bias checks",
|
| 157 |
+
"evidence": [
|
| 158 |
+
f"Safety score: {safety_checked.get('safety_analysis', {}).get('overall_safety_score', 0.8)}",
|
| 159 |
+
f"Warnings generated: {len(safety_checked.get('warnings', []))}",
|
| 160 |
+
f"Analysis method: {safety_checked.get('safety_analysis', {}).get('analysis_method', 'unknown')}"
|
| 161 |
+
],
|
| 162 |
+
"confidence": safety_checked.get('safety_analysis', {}).get('overall_safety_score', 0.8),
|
| 163 |
+
"reasoning": "Comprehensive safety analysis with non-blocking warning system"
|
| 164 |
+
}
|
| 165 |
+
|
| 166 |
+
# Generate alternative paths and uncertainty analysis
|
| 167 |
+
reasoning_chain["alternative_paths"] = self._generate_alternative_paths(intent_result, user_input)
|
| 168 |
+
reasoning_chain["uncertainty_areas"] = self._identify_uncertainty_areas(intent_result, final_response, safety_checked)
|
| 169 |
+
reasoning_chain["evidence_sources"] = self._extract_evidence_sources(intent_result, final_response, context)
|
| 170 |
+
reasoning_chain["confidence_calibration"] = self._calibrate_confidence_scores(reasoning_chain)
|
| 171 |
+
|
| 172 |
processing_time = time.time() - start_time
|
| 173 |
|
| 174 |
result = self._format_final_output(safety_checked, interaction_id, {
|
|
|
|
| 185 |
'processing_time': processing_time,
|
| 186 |
'agents_used': list(self.agents.keys()),
|
| 187 |
'intent_result': intent_result,
|
| 188 |
+
'synthesis_result': final_response,
|
| 189 |
+
'reasoning_chain': reasoning_chain
|
| 190 |
})
|
| 191 |
|
| 192 |
# Update context with the final response for future context retrieval
|
|
|
|
| 296 |
Clear the execution trace
|
| 297 |
"""
|
| 298 |
self.execution_trace = []
|
| 299 |
+
|
| 300 |
+
def _calculate_session_duration(self, context: dict) -> str:
|
| 301 |
+
"""Calculate session duration for reasoning context"""
|
| 302 |
+
interactions = context.get('interactions', [])
|
| 303 |
+
if not interactions:
|
| 304 |
+
return "New session"
|
| 305 |
+
|
| 306 |
+
# Get first and last interaction timestamps
|
| 307 |
+
first_interaction = interactions[-1] if interactions else {}
|
| 308 |
+
last_interaction = interactions[0] if interactions else {}
|
| 309 |
+
|
| 310 |
+
# Simple duration calculation (in practice, would use actual timestamps)
|
| 311 |
+
interaction_count = len(interactions)
|
| 312 |
+
if interaction_count < 5:
|
| 313 |
+
return "Short session (< 5 interactions)"
|
| 314 |
+
elif interaction_count < 20:
|
| 315 |
+
return "Medium session (5-20 interactions)"
|
| 316 |
+
else:
|
| 317 |
+
return "Long session (> 20 interactions)"
|
| 318 |
+
|
| 319 |
+
def _analyze_topic_continuity(self, context: dict, user_input: str) -> str:
|
| 320 |
+
"""Analyze topic continuity for reasoning context"""
|
| 321 |
+
interactions = context.get('interactions', [])
|
| 322 |
+
if not interactions:
|
| 323 |
+
return "No previous context"
|
| 324 |
+
|
| 325 |
+
# Simple topic analysis based on keywords
|
| 326 |
+
recent_topics = []
|
| 327 |
+
for interaction in interactions[:3]: # Last 3 interactions
|
| 328 |
+
user_msg = interaction.get('user_input', '').lower()
|
| 329 |
+
if 'machine learning' in user_msg or 'ml' in user_msg:
|
| 330 |
+
recent_topics.append('machine learning')
|
| 331 |
+
elif 'ai' in user_msg or 'artificial intelligence' in user_msg:
|
| 332 |
+
recent_topics.append('artificial intelligence')
|
| 333 |
+
elif 'data' in user_msg:
|
| 334 |
+
recent_topics.append('data science')
|
| 335 |
+
|
| 336 |
+
current_input_lower = user_input.lower()
|
| 337 |
+
if 'machine learning' in current_input_lower or 'ml' in current_input_lower:
|
| 338 |
+
current_topic = 'machine learning'
|
| 339 |
+
elif 'ai' in current_input_lower or 'artificial intelligence' in current_input_lower:
|
| 340 |
+
current_topic = 'artificial intelligence'
|
| 341 |
+
elif 'data' in current_input_lower:
|
| 342 |
+
current_topic = 'data science'
|
| 343 |
+
else:
|
| 344 |
+
current_topic = 'general'
|
| 345 |
+
|
| 346 |
+
if current_topic in recent_topics:
|
| 347 |
+
return f"Continuing {current_topic} discussion"
|
| 348 |
+
else:
|
| 349 |
+
return f"New topic: {current_topic}"
|
| 350 |
+
|
| 351 |
+
def _extract_pattern_evidence(self, user_input: str) -> str:
|
| 352 |
+
"""Extract pattern evidence for intent reasoning"""
|
| 353 |
+
input_lower = user_input.lower()
|
| 354 |
+
|
| 355 |
+
# Question patterns
|
| 356 |
+
if any(word in input_lower for word in ['what', 'how', 'why', 'when', 'where', 'which']):
|
| 357 |
+
return "Question pattern detected"
|
| 358 |
+
|
| 359 |
+
# Request patterns
|
| 360 |
+
if any(word in input_lower for word in ['please', 'can you', 'could you', 'help me']):
|
| 361 |
+
return "Request pattern detected"
|
| 362 |
+
|
| 363 |
+
# Explanation patterns
|
| 364 |
+
if any(word in input_lower for word in ['explain', 'describe', 'tell me about']):
|
| 365 |
+
return "Explanation pattern detected"
|
| 366 |
+
|
| 367 |
+
# Analysis patterns
|
| 368 |
+
if any(word in input_lower for word in ['analyze', 'compare', 'evaluate', 'assess']):
|
| 369 |
+
return "Analysis pattern detected"
|
| 370 |
+
|
| 371 |
+
return "General conversational pattern"
|
| 372 |
+
|
| 373 |
+
def _assess_intent_complexity(self, intent_result: dict) -> str:
|
| 374 |
+
"""Assess intent complexity for reasoning"""
|
| 375 |
+
primary_intent = intent_result.get('primary_intent', 'unknown')
|
| 376 |
+
confidence = intent_result.get('confidence_scores', {}).get(primary_intent, 0.5)
|
| 377 |
+
secondary_intents = intent_result.get('secondary_intents', [])
|
| 378 |
+
|
| 379 |
+
if confidence > 0.8 and len(secondary_intents) == 0:
|
| 380 |
+
return "Simple, clear intent"
|
| 381 |
+
elif confidence > 0.7 and len(secondary_intents) <= 1:
|
| 382 |
+
return "Moderate complexity"
|
| 383 |
+
else:
|
| 384 |
+
return "Complex, multi-faceted intent"
|
| 385 |
+
|
| 386 |
+
def _generate_alternative_paths(self, intent_result: dict, user_input: str) -> list:
|
| 387 |
+
"""Generate alternative reasoning paths"""
|
| 388 |
+
primary_intent = intent_result.get('primary_intent', 'unknown')
|
| 389 |
+
secondary_intents = intent_result.get('secondary_intents', [])
|
| 390 |
+
|
| 391 |
+
alternative_paths = []
|
| 392 |
+
|
| 393 |
+
# Add secondary intents as alternative paths
|
| 394 |
+
for secondary_intent in secondary_intents:
|
| 395 |
+
alternative_paths.append({
|
| 396 |
+
"path": f"Alternative intent: {secondary_intent}",
|
| 397 |
+
"reasoning": f"Could interpret as {secondary_intent} based on linguistic patterns",
|
| 398 |
+
"confidence": intent_result.get('confidence_scores', {}).get(secondary_intent, 0.3),
|
| 399 |
+
"rejected_reason": f"Primary intent '{primary_intent}' has higher confidence"
|
| 400 |
+
})
|
| 401 |
+
|
| 402 |
+
# Add method-based alternatives
|
| 403 |
+
if primary_intent == "information_request":
|
| 404 |
+
alternative_paths.append({
|
| 405 |
+
"path": "Technical deep-dive approach",
|
| 406 |
+
"reasoning": "Could provide mathematical foundations and technical details",
|
| 407 |
+
"confidence": 0.6,
|
| 408 |
+
"rejected_reason": "User level suggests conceptual approach"
|
| 409 |
+
})
|
| 410 |
+
|
| 411 |
+
return alternative_paths
|
| 412 |
+
|
| 413 |
+
def _identify_uncertainty_areas(self, intent_result: dict, final_response: dict, safety_checked: dict) -> list:
|
| 414 |
+
"""Identify areas of uncertainty in the reasoning"""
|
| 415 |
+
uncertainty_areas = []
|
| 416 |
+
|
| 417 |
+
# Intent uncertainty
|
| 418 |
+
primary_intent = intent_result.get('primary_intent', 'unknown')
|
| 419 |
+
confidence = intent_result.get('confidence_scores', {}).get(primary_intent, 0.5)
|
| 420 |
+
if confidence < 0.8:
|
| 421 |
+
uncertainty_areas.append({
|
| 422 |
+
"aspect": f"Intent classification ({primary_intent})",
|
| 423 |
+
"confidence": confidence,
|
| 424 |
+
"mitigation": "Provided multiple interpretation options"
|
| 425 |
+
})
|
| 426 |
+
|
| 427 |
+
# Response quality uncertainty
|
| 428 |
+
coherence_score = final_response.get('coherence_score', 0.7)
|
| 429 |
+
if coherence_score < 0.8:
|
| 430 |
+
uncertainty_areas.append({
|
| 431 |
+
"aspect": "Response coherence and structure",
|
| 432 |
+
"confidence": coherence_score,
|
| 433 |
+
"mitigation": "Applied quality enhancement techniques"
|
| 434 |
+
})
|
| 435 |
+
|
| 436 |
+
# Safety uncertainty
|
| 437 |
+
safety_score = safety_checked.get('safety_analysis', {}).get('overall_safety_score', 0.8)
|
| 438 |
+
if safety_score < 0.9:
|
| 439 |
+
uncertainty_areas.append({
|
| 440 |
+
"aspect": "Content safety and bias assessment",
|
| 441 |
+
"confidence": safety_score,
|
| 442 |
+
"mitigation": "Generated advisory warnings for user awareness"
|
| 443 |
+
})
|
| 444 |
+
|
| 445 |
+
return uncertainty_areas
|
| 446 |
+
|
| 447 |
+
def _extract_evidence_sources(self, intent_result: dict, final_response: dict, context: dict) -> list:
|
| 448 |
+
"""Extract evidence sources for reasoning"""
|
| 449 |
+
evidence_sources = []
|
| 450 |
+
|
| 451 |
+
# Intent evidence
|
| 452 |
+
evidence_sources.append({
|
| 453 |
+
"type": "linguistic_analysis",
|
| 454 |
+
"source": "Pattern matching and NLP analysis",
|
| 455 |
+
"relevance": 0.9,
|
| 456 |
+
"description": "Intent classification based on linguistic patterns"
|
| 457 |
+
})
|
| 458 |
+
|
| 459 |
+
# Context evidence
|
| 460 |
+
interactions = context.get('interactions', [])
|
| 461 |
+
if interactions:
|
| 462 |
+
evidence_sources.append({
|
| 463 |
+
"type": "conversation_history",
|
| 464 |
+
"source": f"Previous {len(interactions)} interactions",
|
| 465 |
+
"relevance": 0.7,
|
| 466 |
+
"description": "Conversation context and topic continuity"
|
| 467 |
+
})
|
| 468 |
+
|
| 469 |
+
# Synthesis evidence
|
| 470 |
+
synthesis_method = final_response.get('synthesis_method', 'unknown')
|
| 471 |
+
evidence_sources.append({
|
| 472 |
+
"type": "synthesis_method",
|
| 473 |
+
"source": f"{synthesis_method} approach",
|
| 474 |
+
"relevance": 0.8,
|
| 475 |
+
"description": f"Response generated using {synthesis_method} methodology"
|
| 476 |
+
})
|
| 477 |
+
|
| 478 |
+
return evidence_sources
|
| 479 |
+
|
| 480 |
+
def _calibrate_confidence_scores(self, reasoning_chain: dict) -> dict:
|
| 481 |
+
"""Calibrate confidence scores across the reasoning chain"""
|
| 482 |
+
chain_of_thought = reasoning_chain.get('chain_of_thought', {})
|
| 483 |
+
|
| 484 |
+
# Calculate overall confidence
|
| 485 |
+
step_confidences = []
|
| 486 |
+
for step_data in chain_of_thought.values():
|
| 487 |
+
if isinstance(step_data, dict) and 'confidence' in step_data:
|
| 488 |
+
step_confidences.append(step_data['confidence'])
|
| 489 |
+
|
| 490 |
+
overall_confidence = sum(step_confidences) / len(step_confidences) if step_confidences else 0.7
|
| 491 |
+
|
| 492 |
+
return {
|
| 493 |
+
"overall_confidence": overall_confidence,
|
| 494 |
+
"step_count": len(chain_of_thought),
|
| 495 |
+
"confidence_distribution": {
|
| 496 |
+
"high_confidence": len([c for c in step_confidences if c > 0.8]),
|
| 497 |
+
"medium_confidence": len([c for c in step_confidences if 0.6 <= c <= 0.8]),
|
| 498 |
+
"low_confidence": len([c for c in step_confidences if c < 0.6])
|
| 499 |
+
},
|
| 500 |
+
"calibration_method": "Weighted average of step confidences"
|
| 501 |
+
}
|
| 502 |
|