From 300d96a9d82114317af95503c1805f9f03e29c4d Mon Sep 17 00:00:00 2001 From: Lars Date: Sat, 11 Apr 2026 11:42:54 +0200 Subject: [PATCH] feat: Enhance prompt execution for workflows and analysis offers - Added support for handling aggregated results in workflow prompts, allowing for various data formats (string, object). - Introduced a utility function to filter active prompts for both pipeline and workflow types in the analysis page. - Updated content handling in the analysis component to accommodate new workflow data structures. This improves the flexibility and usability of the prompt execution process in both backend and frontend components. --- backend/routers/prompts.py | 12 ++++++++++++ frontend/src/pages/Analysis.jsx | 25 ++++++++++++++++++++----- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/backend/routers/prompts.py b/backend/routers/prompts.py index 732bfea..cc90c5c 100644 --- a/backend/routers/prompts.py +++ b/backend/routers/prompts.py @@ -1253,6 +1253,18 @@ async def execute_unified_prompt( content = list(final_output.values())[0] else: content = json.dumps(final_output, ensure_ascii=False) + elif result['type'] == 'workflow': + # Graph-Workflows: kein "output", sondern aggregated_result + agg = result.get('aggregated_result') + if isinstance(agg, dict) and len(agg) == 1: + v = list(agg.values())[0] + content = v if isinstance(v, str) else json.dumps(v, ensure_ascii=False) + elif agg is None: + content = '' + elif isinstance(agg, str): + content = agg + else: + content = json.dumps(agg, ensure_ascii=False) else: # For base prompts, use output directly content = result.get('output', '') diff --git a/frontend/src/pages/Analysis.jsx b/frontend/src/pages/Analysis.jsx index 25cea80..cea6271 100644 --- a/frontend/src/pages/Analysis.jsx +++ b/frontend/src/pages/Analysis.jsx @@ -45,6 +45,11 @@ function analysisCategoryLabel(key) { return ANALYSIS_CATEGORY_LABELS[k] || String(key) } +/** Analyse-Angebote: klassische Pipelines + graphbasierte KI-Workflows (`type === 'workflow'`) */ +function isAnalysisOfferPrompt(p) { + return p.active && (p.type === 'pipeline' || p.type === 'workflow') +} + /** Pipeline-Prompts nach `category` gruppieren (Backend-Feld), innerhalb Gruppe nach sort_order */ function buildPipelineGroups(pipelinePrompts) { const m = new Map() @@ -360,7 +365,7 @@ export default function Analysis() { },[]) useEffect(() => { - const list = prompts.filter(p => p.active && p.type === 'pipeline') + const list = prompts.filter(isAnalysisOfferPrompt) setActiveCategoryKey(prev => { if (!list.length) return null const groups = buildPipelineGroups(list) @@ -372,7 +377,7 @@ export default function Analysis() { useEffect(() => { if (!newResult?.scope) return - const list = prompts.filter(p => p.active && p.type === 'pipeline') + const list = prompts.filter(isAnalysisOfferPrompt) const groups = buildPipelineGroups(list) const g = groups.find(gg => gg.prompts.some(p => p.slug === newResult.scope)) if (g) setActiveCategoryKey(g.categoryKey) @@ -394,6 +399,16 @@ export default function Analysis() { } else { content = JSON.stringify(finalOutput, null, 2) } + } else if (result.type === 'workflow') { + const agg = result.aggregated_result + if (agg != null && typeof agg === 'object' && !Array.isArray(agg) && Object.keys(agg).length === 1) { + const v = Object.values(agg)[0] + content = typeof v === 'string' ? v : JSON.stringify(v, null, 2) + } else if (typeof agg === 'string') { + content = agg + } else { + content = JSON.stringify(agg ?? {}, null, 2) + } } else { // For base prompts, use output directly content = typeof result.output === 'string' ? result.output : JSON.stringify(result.output, null, 2) @@ -405,7 +420,7 @@ export default function Analysis() { const placeholders = {} const resolved = result.debug.resolved_placeholders - // For pipeline, collect from all stages + // For pipeline, collect from all stages (Workflow: kein gleiches debug-Schema) if (result.type === 'pipeline' && result.debug.stages) { for (const stage of result.debug.stages) { for (const promptDebug of (stage.prompts || [])) { @@ -456,9 +471,9 @@ export default function Analysis() { grouped[key].push(ins) }) - // Show only active pipeline-type prompts (und nach DB-Kategorie gruppiert) + // Aktive Pipeline- + Workflow-Prompts (nach DB-Kategorie gruppiert) const { pipelinePrompts, pipelineGroups } = useMemo(() => { - const list = prompts.filter(p => p.active && p.type === 'pipeline') + const list = prompts.filter(isAnalysisOfferPrompt) return { pipelinePrompts: list, pipelineGroups: buildPipelineGroups(list) } }, [prompts])