fixed ui harmonization

This commit is contained in:
ValueOn AG 2025-11-02 15:36:02 +01:00
parent 5c006da27d
commit fa91016e16
2 changed files with 62 additions and 17 deletions

View file

@ -197,6 +197,7 @@ Respond with ONLY a JSON object in this exact format:
iteration = 0 iteration = 0
allSections = [] # Accumulate all sections across iterations allSections = [] # Accumulate all sections across iterations
lastRawResponse = None # Store last raw JSON response for continuation lastRawResponse = None # Store last raw JSON response for continuation
documentMetadata = None # Store document metadata (title, filename) from first iteration
while iteration < maxIterations: while iteration < maxIterations:
iteration += 1 iteration += 1
@ -276,7 +277,11 @@ Respond with ONLY a JSON object in this exact format:
pass # Flag detected, will stop in _shouldContinueGeneration pass # Flag detected, will stop in _shouldContinueGeneration
# Extract sections from response (handles both valid and broken JSON) # Extract sections from response (handles both valid and broken JSON)
extractedSections, wasJsonComplete = self._extractSectionsFromResponse(result, iteration, debugPrefix) extractedSections, wasJsonComplete, parsedResult = self._extractSectionsFromResponse(result, iteration, debugPrefix)
# Extract document metadata from first iteration if available
if iteration == 1 and parsedResult and not documentMetadata:
documentMetadata = self._extractDocumentMetadata(parsedResult)
# Update progress after parsing # Update progress after parsing
if operationId: if operationId:
@ -313,7 +318,7 @@ Respond with ONLY a JSON object in this exact format:
logger.warning(f"AI call stopped after maximum iterations ({maxIterations})") logger.warning(f"AI call stopped after maximum iterations ({maxIterations})")
# Build final result from accumulated sections # Build final result from accumulated sections
final_result = self._buildFinalResultFromSections(allSections) final_result = self._buildFinalResultFromSections(allSections, documentMetadata)
# Write final result to debug file # Write final result to debug file
self.services.utils.writeDebugFile(final_result, f"{debugPrefix}_final_result") self.services.utils.writeDebugFile(final_result, f"{debugPrefix}_final_result")
@ -325,12 +330,12 @@ Respond with ONLY a JSON object in this exact format:
result: str, result: str,
iteration: int, iteration: int,
debugPrefix: str debugPrefix: str
) -> Tuple[List[Dict[str, Any]], bool]: ) -> Tuple[List[Dict[str, Any]], bool, Optional[Dict[str, Any]]]:
""" """
Extract sections from AI response, handling both valid and broken JSON. Extract sections from AI response, handling both valid and broken JSON.
Uses repair mechanism for broken JSON. Uses repair mechanism for broken JSON.
Checks for "complete_response": true flag to determine completion. Checks for "complete_response": true flag to determine completion.
Returns (sections, wasJsonComplete) Returns (sections, wasJsonComplete, parsedResult)
""" """
# First, try to parse as valid JSON # First, try to parse as valid JSON
try: try:
@ -345,18 +350,18 @@ Respond with ONLY a JSON object in this exact format:
# If AI marked as complete, always return as complete # If AI marked as complete, always return as complete
if isComplete: if isComplete:
return sections, True return sections, True, parsed_result
# If in continuation mode (iteration > 1), continuation responses are expected to be fragments # If in continuation mode (iteration > 1), continuation responses are expected to be fragments
# A fragment with 0 extractable sections means JSON is incomplete - need another iteration # A fragment with 0 extractable sections means JSON is incomplete - need another iteration
if len(sections) == 0 and iteration > 1: if len(sections) == 0 and iteration > 1:
return sections, False # Mark as incomplete so loop continues return sections, False, parsed_result # Mark as incomplete so loop continues
# First iteration with 0 sections means empty response - stop # First iteration with 0 sections means empty response - stop
if len(sections) == 0: if len(sections) == 0:
return sections, True # Complete but empty return sections, True, parsed_result # Complete but empty
return sections, True # JSON was complete with sections return sections, True, parsed_result # JSON was complete with sections
except json.JSONDecodeError as e: except json.JSONDecodeError as e:
# Broken JSON - try repair mechanism (normal in iterative generation) # Broken JSON - try repair mechanism (normal in iterative generation)
@ -368,15 +373,15 @@ Respond with ONLY a JSON object in this exact format:
if repaired_json: if repaired_json:
# Extract sections from repaired JSON # Extract sections from repaired JSON
sections = extractSectionsFromDocument(repaired_json) sections = extractSectionsFromDocument(repaired_json)
return sections, False # JSON was broken but repaired return sections, False, repaired_json # JSON was broken but repaired
else: else:
# Repair failed - log error # Repair failed - log error
logger.error(f"Iteration {iteration}: All repair strategies failed") logger.error(f"Iteration {iteration}: All repair strategies failed")
return [], False return [], False, None
except Exception as e: except Exception as e:
logger.error(f"Iteration {iteration}: Unexpected error during parsing: {str(e)}") logger.error(f"Iteration {iteration}: Unexpected error during parsing: {str(e)}")
return [], False return [], False, None
def _shouldContinueGeneration( def _shouldContinueGeneration(
self, self,
@ -414,22 +419,58 @@ Respond with ONLY a JSON object in this exact format:
# JSON was incomplete/broken - continue # JSON was incomplete/broken - continue
return True return True
def _extractDocumentMetadata(
self,
parsedResult: Dict[str, Any]
) -> Optional[Dict[str, Any]]:
"""
Extract document metadata (title, filename) from parsed AI response.
Returns dict with 'title' and 'filename' keys if found, None otherwise.
"""
if not isinstance(parsedResult, dict):
return None
# Try to get from documents array (preferred structure)
if "documents" in parsedResult and isinstance(parsedResult["documents"], list) and len(parsedResult["documents"]) > 0:
firstDoc = parsedResult["documents"][0]
if isinstance(firstDoc, dict):
title = firstDoc.get("title")
filename = firstDoc.get("filename")
if title or filename:
return {
"title": title,
"filename": filename
}
return None
def _buildFinalResultFromSections( def _buildFinalResultFromSections(
self, self,
allSections: List[Dict[str, Any]] allSections: List[Dict[str, Any]],
documentMetadata: Optional[Dict[str, Any]] = None
) -> str: ) -> str:
""" """
Build final JSON result from accumulated sections. Build final JSON result from accumulated sections.
Uses AI-provided metadata (title, filename) if available.
""" """
if not allSections: if not allSections:
return "" return ""
# Extract metadata from AI response if available
title = "Generated Document"
filename = "document.json"
if documentMetadata:
if documentMetadata.get("title"):
title = documentMetadata["title"]
if documentMetadata.get("filename"):
filename = documentMetadata["filename"]
# Build documents structure # Build documents structure
# Assuming single document for now # Assuming single document for now
documents = [{ documents = [{
"id": "doc_1", "id": "doc_1",
"title": "Generated Document", # This should come from prompt "title": title,
"filename": "document.json", "filename": filename,
"sections": allSections "sections": allSections
}] }]

View file

@ -74,6 +74,8 @@ async def buildGenerationPrompt(
continuationText = "\n".join(continuationGuidance) if continuationGuidance else "Continue from where it stopped." continuationText = "\n".join(continuationGuidance) if continuationGuidance else "Continue from where it stopped."
# PROMPT FOR CONTINUATION
generationPrompt = f"""User request: "{userPrompt}" generationPrompt = f"""User request: "{userPrompt}"
The user already received part of the response. Continue generating the remaining content. The user already received part of the response. Continue generating the remaining content.
@ -93,7 +95,7 @@ Instructions:
- Arrays must contain ONLY JSON values; do not include comments or ellipses. - Arrays must contain ONLY JSON values; do not include comments or ellipses.
- Use ONLY the element structures shown in the template. - Use ONLY the element structures shown in the template.
- Continue from where it stopped add NEW items only; do not repeat existing items. - Continue from where it stopped add NEW items only; do not repeat existing items.
- Generate remaining content to complete the user request. - Generate remaining content to complete the user request. Do NOT just give an instruction or comments. Deliver the complete response.
- Fill with actual content (no placeholders or instructional text such as "Add more..."). - Fill with actual content (no placeholders or instructional text such as "Add more...").
- IMPORTANT: Ensure "filename" in each document has meaningful name with appropriate extension matching the content. - IMPORTANT: Ensure "filename" in each document has meaningful name with appropriate extension matching the content.
- When the request is fully satisfied, add "complete_response": true at root level. - When the request is fully satisfied, add "complete_response": true at root level.
@ -104,7 +106,9 @@ IMPORTANT: Before responding, analyse the remaining data to fully satisfy user r
Continue generating: Continue generating:
""" """
else: else:
# FIRST CALL - initial generation
# PROMPT FOR FIRST CALL
generationPrompt = f"""User request: "{userPrompt}" generationPrompt = f"""User request: "{userPrompt}"
Generate a VALID JSON response for the user request. The template below shows ONLY the structure pattern - it is NOT existing content. Generate a VALID JSON response for the user request. The template below shows ONLY the structure pattern - it is NOT existing content.
@ -116,7 +120,7 @@ Instructions:
- Start with {{"metadata": ...}} return COMPLETE, STRICT JSON. - Start with {{"metadata": ...}} return COMPLETE, STRICT JSON.
- Return ONLY valid JSON (strict). No comments. No trailing commas. Use double quotes. - Return ONLY valid JSON (strict). No comments. No trailing commas. Use double quotes.
- Do NOT reuse example section IDs; create your own. - Do NOT reuse example section IDs; create your own.
- Generate complete content based on the user request. - Generate complete content based on the user request. Do NOT just give an instruction or comments. Deliver the complete response.
- IMPORTANT: Set a meaningful "filename" in each document with appropriate file extension (e.g., "prime_numbers.txt", "report.docx", "data.json"). The filename should reflect the content and task objective. - IMPORTANT: Set a meaningful "filename" in each document with appropriate file extension (e.g., "prime_numbers.txt", "report.docx", "data.json"). The filename should reflect the content and task objective.
- When the request is fully satisfied, add "complete_response": true at root level. - When the request is fully satisfied, add "complete_response": true at root level.
- Output JSON only; no markdown fences or extra text. - Output JSON only; no markdown fences or extra text.