feat: Add comprehensive debug information for workflow nodes
Backend changes: - workflow_models.py: Add debug_prompt, debug_raw_response, debug_node_type, debug_prompt_slug, metadata fields to NodeExecutionState - workflow_executor.py: Capture and store debug info for analysis, logic, and join nodes when enable_debug=True - Analysis nodes: store full prompt + raw AI response - Logic nodes: store expression + evaluation result - Join nodes: store strategy + path statistics Frontend changes: - Analysis.jsx: Enable debug mode by default (debug=true) for all workflow executions This allows developers to see exactly what prompt was sent to the AI, what response was received, and how each node was processed - essential for debugging workflow issues.
This commit is contained in:
parent
3664f53c51
commit
12d4d7c63b
|
|
@ -314,11 +314,11 @@ async def execute_node(
|
|||
|
||||
# Logic Nodes (Phase 3)
|
||||
if node.type == "logic":
|
||||
return execute_logic_node(node, context, graph)
|
||||
return execute_logic_node(node, context, graph, enable_debug)
|
||||
|
||||
# Join Nodes (Phase 4)
|
||||
if node.type == "join":
|
||||
return execute_join_node(node, context, graph)
|
||||
return execute_join_node(node, context, graph, enable_debug)
|
||||
|
||||
# Analysis Nodes
|
||||
if node.type == "analysis":
|
||||
|
|
@ -398,6 +398,11 @@ async def execute_node(
|
|||
decision_signals=parsed["decision_signals"],
|
||||
normalized_signals=normalized_signals,
|
||||
reasoning_anchors=parsed.get("reasoning_anchors"),
|
||||
# Debug information (nur wenn enable_debug=True)
|
||||
debug_prompt=augmented_prompt if enable_debug else None,
|
||||
debug_raw_response=llm_response if enable_debug else None,
|
||||
debug_node_type="analysis",
|
||||
debug_prompt_slug=node.prompt_slug if enable_debug else None,
|
||||
started_at=started_at,
|
||||
completed_at=datetime.utcnow().isoformat()
|
||||
)
|
||||
|
|
@ -419,7 +424,8 @@ async def execute_node(
|
|||
def execute_logic_node(
|
||||
node,
|
||||
context: Dict[str, Any],
|
||||
graph: WorkflowGraph
|
||||
graph: WorkflowGraph,
|
||||
enable_debug: bool = False
|
||||
) -> NodeExecutionState:
|
||||
"""
|
||||
Führt Logic Node aus (Phase 3).
|
||||
|
|
@ -519,7 +525,15 @@ def execute_logic_node(
|
|||
"evaluation_result": result if not error else None,
|
||||
"error": error,
|
||||
"activated_edges": activated_edges
|
||||
})
|
||||
}),
|
||||
# Debug information
|
||||
debug_prompt=json.dumps(expression.model_dump() if hasattr(expression, 'model_dump') else str(expression), ensure_ascii=False) if enable_debug and expression else None,
|
||||
debug_raw_response=json.dumps({
|
||||
"result": result,
|
||||
"error": error,
|
||||
"activated_edges": activated_edges
|
||||
}, ensure_ascii=False) if enable_debug else None,
|
||||
debug_node_type="logic"
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
|
|
@ -536,7 +550,8 @@ def execute_logic_node(
|
|||
def execute_join_node(
|
||||
node,
|
||||
context: Dict[str, Any],
|
||||
graph: WorkflowGraph
|
||||
graph: WorkflowGraph,
|
||||
enable_debug: bool = False
|
||||
) -> NodeExecutionState:
|
||||
"""
|
||||
Führt Join Node aus (Phase 4).
|
||||
|
|
@ -608,7 +623,16 @@ def execute_join_node(
|
|||
normalized_signals=consolidated_signals_list,
|
||||
metadata=join_result.metadata,
|
||||
started_at=started_at,
|
||||
completed_at=datetime.utcnow().isoformat()
|
||||
completed_at=datetime.utcnow().isoformat(),
|
||||
# Debug information
|
||||
debug_prompt=f"Join Strategy: {node.join_strategy.value if node.join_strategy else 'wait_all'}\nPaths: {total_count}\nMinimum Required: {node.min_paths if node.min_paths else 'all'}" if enable_debug else None,
|
||||
debug_raw_response=json.dumps({
|
||||
"executed_paths": executed_count,
|
||||
"total_paths": total_count,
|
||||
"strategy": node.join_strategy.value if node.join_strategy else 'wait_all',
|
||||
"consolidated_nodes": list(join_result.consolidated_analysis_core.keys())
|
||||
}, ensure_ascii=False) if enable_debug else None,
|
||||
debug_node_type="join"
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
|
|
|
|||
|
|
@ -349,6 +349,15 @@ class NodeExecutionState(BaseModel):
|
|||
normalized_signals: List[NormalizedSignal] = Field(default_factory=list, description="Normalisierte Signale (Phase 2)")
|
||||
reasoning_anchors: Optional[str] = Field(None, description="Begründungsanker aus ## Begründung")
|
||||
|
||||
# Debug Information (nur wenn enable_debug=True)
|
||||
debug_prompt: Optional[str] = Field(None, description="Vollständiger Prompt der an die KI gesendet wurde")
|
||||
debug_raw_response: Optional[str] = Field(None, description="Rohe KI-Antwort (ungeparst)")
|
||||
debug_node_type: Optional[str] = Field(None, description="Node-Typ (analysis, logic, join, etc.)")
|
||||
debug_prompt_slug: Optional[str] = Field(None, description="Verwendeter Prompt-Slug (bei ANALYSIS nodes)")
|
||||
|
||||
# Metadata (für Join Nodes und andere Zusatzinfos)
|
||||
metadata: Optional[Dict[str, Any]] = Field(None, description="Zusätzliche Metadaten (z.B. Join-Statistiken)")
|
||||
|
||||
# Error & Timing
|
||||
error: Optional[str] = Field(None, description="Fehlermeldung bei failed")
|
||||
started_at: Optional[str] = Field(None, description="Start-Timestamp (ISO)")
|
||||
|
|
|
|||
|
|
@ -382,7 +382,7 @@ export default function Analysis() {
|
|||
setLoading(slug); setError(null); setNewResult(null); setProgress(null)
|
||||
try {
|
||||
// Use SSE-based executor for long-running workflows
|
||||
const result = await api.executeUnifiedPromptStream(slug, null, null, false, true, (event) => {
|
||||
const result = await api.executeUnifiedPromptStream(slug, null, null, true, true, (event) => {
|
||||
// Progress callback: update UI in real-time
|
||||
if (event.type === 'execution_started') {
|
||||
setProgress({ total_nodes: 0, completed_nodes: 0, current_node_label: 'Starte...' })
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user