From a8ef757046529e3f164e13e89e50974af26b3fe7 Mon Sep 17 00:00:00 2001
From: ValueOn AG
Date: Sun, 30 Nov 2025 23:09:25 +0100
Subject: [PATCH] fixed kpi identification
---
modules/services/serviceAi/mainServiceAi.py | 41 +++++++++------------
1 file changed, 18 insertions(+), 23 deletions(-)
diff --git a/modules/services/serviceAi/mainServiceAi.py b/modules/services/serviceAi/mainServiceAi.py
index 99e509dc..2a4f304c 100644
--- a/modules/services/serviceAi/mainServiceAi.py
+++ b/modules/services/serviceAi/mainServiceAi.py
@@ -316,9 +316,10 @@ Respond with ONLY a JSON object in this exact format:
if accumulationState and accumulationState.isAccumulationMode and iteration == 1 and not accumulationState.kpis:
logger.info(f"Iteration {iteration}: Defining KPIs for accumulation tracking")
continuationContext = buildContinuationContext(allSections, result)
+ # Pass raw response string from first iteration for KPI definition
kpiDefinitions = await self._defineKpisFromPrompt(
userPrompt or prompt,
- parsedResult,
+ result, # Pass raw JSON string from first iteration
continuationContext,
debugPrefix
)
@@ -509,46 +510,40 @@ Respond with ONLY a JSON object in this exact format:
async def _defineKpisFromPrompt(
self,
userPrompt: str,
- parsedJson: Optional[Dict[str, Any]],
+ rawJsonString: Optional[str],
continuationContext: Dict[str, Any],
debugPrefix: str = "kpi"
) -> List[Dict[str, Any]]:
"""
- Make separate AI call to define KPIs based on user prompt and delivered data.
+ Make separate AI call to define KPIs based on user prompt and incomplete JSON.
Args:
userPrompt: Original user prompt
- parsedJson: Parsed JSON from first iteration (if available)
- continuationContext: Continuation context with delivered summary
+ rawJsonString: Raw JSON string from first iteration response
+ continuationContext: Continuation context (not used for JSON, kept for compatibility)
Returns:
List of KPI definitions: [{"id": str, "description": str, "jsonPath": str, "targetValue": int}, ...]
"""
- deliveredSummary = continuationContext.get("delivered_summary", "")
- cutOffElement = continuationContext.get("cut_off_element")
- elementBeforeCutoff = continuationContext.get("element_before_cutoff")
+ # Use raw JSON string from first iteration response
+ if rawJsonString:
+ # Remove markdown code fences if present
+ from modules.shared.jsonUtils import stripCodeFences
+ incompleteJson = stripCodeFences(rawJsonString.strip())
+ else:
+ incompleteJson = "Not available"
- # Build prompt for KPI definition
- kpiDefinitionPrompt = f"""Analyze the user request and delivered data to define KPIs (Key Performance Indicators) for tracking progress.
+ kpiDefinitionPrompt = f"""Analyze the user request and incomplete JSON to define KPIs (Key Performance Indicators) for tracking progress.
User Request:
{userPrompt}
-Delivered Data Summary:
-{deliveredSummary}
-
-Current JSON Structure (if available):
-{json.dumps(parsedJson, indent=2) if parsedJson else "Not available"}
-
-Cut-off Element:
-{cutOffElement if cutOffElement else "Not available"}
-
-Last Complete Element:
-{elementBeforeCutoff if elementBeforeCutoff else "Not available"}
+Delivered JSON part:
+{incompleteJson}
Task: Define which JSON items should be tracked to measure completion progress.
-IMPORTANT: Analyze the JSON structure to understand what is being tracked:
+IMPORTANT: Analyze the Delivered JSON part structure to understand what is being tracked:
1. Identify the structure type (table with rows, list with items, etc.)
2. Determine what the jsonPath actually counts (number of rows, number of items, etc.)
3. Calculate targetValue based on what is being tracked, NOT the total quantity requested
@@ -556,7 +551,7 @@ IMPORTANT: Analyze the JSON structure to understand what is being tracked:
For each trackable item, provide:
- id: Unique identifier (use descriptive name)
- description: What this KPI measures (be specific about what is counted)
-- jsonPath: Path to extract value from JSON (use dot notation with array indices, e.g., "documents[0].sections[0].elements")
+- jsonPath: Path to extract value from JSON (use dot notation with array indices, e.g., "documents[0].sections[1].elements[0].rows")
- targetValue: Target value to reach (integer) - MUST match what jsonPath actually tracks (rows count, items count, etc.)
Return ONLY valid JSON in this format: