file verbose trace with config var APP_DEBUG_CHAT_WORKFLOW_ENABLED installed
This commit is contained in:
parent
d9ee4d9605
commit
aa86caa229
5 changed files with 110 additions and 91 deletions
|
|
@ -571,8 +571,10 @@ class ChatObjects:
|
||||||
actionName=createdMessage.get("actionName")
|
actionName=createdMessage.get("actionName")
|
||||||
)
|
)
|
||||||
|
|
||||||
# Debug: Store message and documents for debugging TODO REMOVE
|
# Debug: Store message and documents for debugging - only if debug enabled
|
||||||
self._storeDebugMessageAndDocuments(chat_message)
|
debug_enabled = APP_CONFIG.get("APP_DEBUG_CHAT_WORKFLOW_ENABLED", False)
|
||||||
|
if debug_enabled:
|
||||||
|
self._storeDebugMessageAndDocuments(chat_message)
|
||||||
|
|
||||||
return chat_message
|
return chat_message
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -786,19 +786,21 @@ class AiService:
|
||||||
# Log extraction response
|
# Log extraction response
|
||||||
self.services.utils.debugLogToFile(f"EXTRACTION RESPONSE LENGTH: {len(ai_result) if ai_result else 0} characters", "AI_SERVICE")
|
self.services.utils.debugLogToFile(f"EXTRACTION RESPONSE LENGTH: {len(ai_result) if ai_result else 0} characters", "AI_SERVICE")
|
||||||
|
|
||||||
# Save full extraction prompt and response to debug file
|
# Save full extraction prompt and response to debug file - only if debug enabled
|
||||||
try:
|
debug_enabled = self.services.utils.configGet("APP_DEBUG_CHAT_WORKFLOW_ENABLED", False)
|
||||||
import os
|
if debug_enabled:
|
||||||
from datetime import datetime, UTC
|
try:
|
||||||
ts = datetime.now(UTC).strftime("%Y%m%d-%H%M%S")
|
import os
|
||||||
debug_root = "./test-chat/ai"
|
from datetime import datetime, UTC
|
||||||
os.makedirs(debug_root, exist_ok=True)
|
ts = datetime.now(UTC).strftime("%Y%m%d-%H%M%S")
|
||||||
with open(os.path.join(debug_root, f"{ts}_extraction_container_chunk_{chunk_index}.txt"), "w", encoding="utf-8") as f:
|
debug_root = "./test-chat/ai"
|
||||||
f.write(f"EXTRACTION PROMPT:\n{prompt}\n\n")
|
os.makedirs(debug_root, exist_ok=True)
|
||||||
f.write(f"EXTRACTION CONTEXT:\n{part.data if part.data else 'No context'}\n\n")
|
with open(os.path.join(debug_root, f"{ts}_extraction_container_chunk_{chunk_index}.txt"), "w", encoding="utf-8") as f:
|
||||||
f.write(f"EXTRACTION RESPONSE:\n{ai_result if ai_result else 'No response'}\n")
|
f.write(f"EXTRACTION PROMPT:\n{prompt}\n\n")
|
||||||
except Exception:
|
f.write(f"EXTRACTION CONTEXT:\n{part.data if part.data else 'No context'}\n\n")
|
||||||
pass
|
f.write(f"EXTRACTION RESPONSE:\n{ai_result if ai_result else 'No response'}\n")
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
# If generating JSON, validate the response
|
# If generating JSON, validate the response
|
||||||
if generate_json:
|
if generate_json:
|
||||||
|
|
@ -878,17 +880,19 @@ class AiService:
|
||||||
# Log extraction response length
|
# Log extraction response length
|
||||||
self.services.utils.debugLogToFile(f"EXTRACTION RESPONSE LENGTH: {len(ai_result) if ai_result else 0} characters", "AI_SERVICE")
|
self.services.utils.debugLogToFile(f"EXTRACTION RESPONSE LENGTH: {len(ai_result) if ai_result else 0} characters", "AI_SERVICE")
|
||||||
|
|
||||||
# Save extraction response to debug file (without verbose prompt)
|
# Save extraction response to debug file (without verbose prompt) - only if debug enabled
|
||||||
try:
|
debug_enabled = self.services.utils.configGet("APP_DEBUG_CHAT_WORKFLOW_ENABLED", False)
|
||||||
import os
|
if debug_enabled:
|
||||||
from datetime import datetime, UTC
|
try:
|
||||||
ts = datetime.now(UTC).strftime("%Y%m%d-%H%M%S")
|
import os
|
||||||
debug_root = "./test-chat/ai"
|
from datetime import datetime, UTC
|
||||||
os.makedirs(debug_root, exist_ok=True)
|
ts = datetime.now(UTC).strftime("%Y%m%d-%H%M%S")
|
||||||
with open(os.path.join(debug_root, f"{ts}_extraction_chunk_{chunk_index}.txt"), "w", encoding="utf-8") as f:
|
debug_root = "./test-chat/ai"
|
||||||
f.write(f"EXTRACTION RESPONSE:\n{ai_result if ai_result else 'No response'}\n")
|
os.makedirs(debug_root, exist_ok=True)
|
||||||
except Exception:
|
with open(os.path.join(debug_root, f"{ts}_extraction_chunk_{chunk_index}.txt"), "w", encoding="utf-8") as f:
|
||||||
pass
|
f.write(f"EXTRACTION RESPONSE:\n{ai_result if ai_result else 'No response'}\n")
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
# If generating JSON, validate the response
|
# If generating JSON, validate the response
|
||||||
if generate_json:
|
if generate_json:
|
||||||
|
|
@ -1325,7 +1329,6 @@ class AiService:
|
||||||
call_type = self._determineCallType(documents, options.operationType)
|
call_type = self._determineCallType(documents, options.operationType)
|
||||||
options.callType = call_type
|
options.callType = call_type
|
||||||
|
|
||||||
# Log the prompt being sent to AI for debugging (before routing) TODO TO REMOVE
|
|
||||||
try:
|
try:
|
||||||
# Build the full prompt that will be sent to AI
|
# Build the full prompt that will be sent to AI
|
||||||
if placeholders:
|
if placeholders:
|
||||||
|
|
@ -1349,7 +1352,7 @@ class AiService:
|
||||||
# Handle document generation with specific output format
|
# Handle document generation with specific output format
|
||||||
if outputFormat:
|
if outputFormat:
|
||||||
result = await self._callAiWithDocumentGeneration(prompt, documents, options, outputFormat, title)
|
result = await self._callAiWithDocumentGeneration(prompt, documents, options, outputFormat, title)
|
||||||
# Log AI response for debugging TODO TO REMOVE
|
# Log AI response for debugging
|
||||||
try:
|
try:
|
||||||
if isinstance(result, dict) and 'content' in result:
|
if isinstance(result, dict) and 'content' in result:
|
||||||
self._writeAiResponseDebug(
|
self._writeAiResponseDebug(
|
||||||
|
|
@ -1365,7 +1368,7 @@ class AiService:
|
||||||
|
|
||||||
if call_type == "planning":
|
if call_type == "planning":
|
||||||
result = await self._callAiPlanning(prompt, placeholders_dict, placeholders_meta, options)
|
result = await self._callAiPlanning(prompt, placeholders_dict, placeholders_meta, options)
|
||||||
# Log AI response for debugging TODO TO REMOVE
|
# Log AI response for debugging
|
||||||
try:
|
try:
|
||||||
self._writeAiResponseDebug(
|
self._writeAiResponseDebug(
|
||||||
label='ai_planning',
|
label='ai_planning',
|
||||||
|
|
@ -1390,7 +1393,7 @@ class AiService:
|
||||||
full_prompt = prompt
|
full_prompt = prompt
|
||||||
|
|
||||||
result = await self._callAiText(full_prompt, documents, options)
|
result = await self._callAiText(full_prompt, documents, options)
|
||||||
# Log AI response for debugging (additional logging for text calls) TODO TO REMOVE
|
# Log AI response for debugging (additional logging for text calls)
|
||||||
try:
|
try:
|
||||||
self._writeAiResponseDebug(
|
self._writeAiResponseDebug(
|
||||||
label='ai_text_main',
|
label='ai_text_main',
|
||||||
|
|
@ -1697,8 +1700,13 @@ class AiService:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _writeAiResponseDebug(self, label: str, content: str, partIndex: int = 1, modelName: str = None, continuation: bool = None) -> None:
|
def _writeAiResponseDebug(self, label: str, content: str, partIndex: int = 1, modelName: str = None, continuation: bool = None) -> None:
|
||||||
"""Persist raw AI response parts for debugging under test-chat/ai."""
|
"""Persist raw AI response parts for debugging under test-chat/ai - only if debug enabled."""
|
||||||
try:
|
try:
|
||||||
|
# Check if debug logging is enabled
|
||||||
|
debug_enabled = self.services.utils.configGet("APP_DEBUG_CHAT_WORKFLOW_ENABLED", False)
|
||||||
|
if not debug_enabled:
|
||||||
|
return
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from datetime import datetime, UTC
|
from datetime import datetime, UTC
|
||||||
# Base dir: gateway/test-chat/ai (go up 4 levels from this file)
|
# Base dir: gateway/test-chat/ai (go up 4 levels from this file)
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
from modules.datamodels.datamodelExtraction import ContentExtracted, ContentPart
|
from modules.datamodels.datamodelExtraction import ContentExtracted, ContentPart
|
||||||
|
from modules.shared.configuration import APP_CONFIG
|
||||||
from .subUtils import makeId
|
from .subUtils import makeId
|
||||||
from .subRegistry import ExtractorRegistry, ChunkerRegistry
|
from .subRegistry import ExtractorRegistry, ChunkerRegistry
|
||||||
from .merging.mergerText import TextMerger
|
from .merging.mergerText import TextMerger
|
||||||
|
|
@ -100,38 +101,40 @@ def runExtraction(extractorRegistry: ExtractorRegistry, chunkerRegistry: Chunker
|
||||||
|
|
||||||
logger.debug(f"runExtraction: Final parts after merging: {len(parts)} (chunks: {len(chunk_parts)})")
|
logger.debug(f"runExtraction: Final parts after merging: {len(parts)} (chunks: {len(chunk_parts)})")
|
||||||
logger.debug(f"runExtraction - Final parts: {len(parts)} (chunks: {len(chunk_parts)})")
|
logger.debug(f"runExtraction - Final parts: {len(parts)} (chunks: {len(chunk_parts)})")
|
||||||
# DEBUG: dump parts and chunks to files TODO TO REMOVE
|
# DEBUG: dump parts and chunks to files - only if debug enabled
|
||||||
try:
|
try:
|
||||||
base_dir = "./test-chat/ai"
|
debug_enabled = APP_CONFIG.get("APP_DEBUG_CHAT_WORKFLOW_ENABLED", False)
|
||||||
os.makedirs(base_dir, exist_ok=True)
|
if debug_enabled:
|
||||||
|
base_dir = "./test-chat/ai"
|
||||||
|
os.makedirs(base_dir, exist_ok=True)
|
||||||
|
|
||||||
# Generate timestamp for consistent naming
|
# Generate timestamp for consistent naming
|
||||||
from datetime import datetime, UTC
|
from datetime import datetime, UTC
|
||||||
ts = datetime.now(UTC).strftime('%Y%m%d-%H%M%S-%f')[:-3]
|
ts = datetime.now(UTC).strftime('%Y%m%d-%H%M%S-%f')[:-3]
|
||||||
|
|
||||||
# Write a summary file
|
# Write a summary file
|
||||||
summary_lines: List[str] = [f"fileName: {fileName}", f"mimeType: {mimeType}", f"totalParts: {len(parts)}"]
|
summary_lines: List[str] = [f"fileName: {fileName}", f"mimeType: {mimeType}", f"totalParts: {len(parts)}"]
|
||||||
text_index = 0
|
text_index = 0
|
||||||
for idx, part in enumerate(parts):
|
for idx, part in enumerate(parts):
|
||||||
is_texty = part.typeGroup in ("text", "table", "structure")
|
is_texty = part.typeGroup in ("text", "table", "structure")
|
||||||
size = int(part.metadata.get("size", 0) or 0)
|
size = int(part.metadata.get("size", 0) or 0)
|
||||||
is_chunk = bool(part.metadata.get("chunk", False))
|
is_chunk = bool(part.metadata.get("chunk", False))
|
||||||
summary_lines.append(
|
summary_lines.append(
|
||||||
f"part[{idx}]: typeGroup={part.typeGroup}, label={part.label}, size={size}, chunk={is_chunk}"
|
f"part[{idx}]: typeGroup={part.typeGroup}, label={part.label}, size={size}, chunk={is_chunk}"
|
||||||
)
|
)
|
||||||
if is_texty and getattr(part, "data", None):
|
if is_texty and getattr(part, "data", None):
|
||||||
text_index += 1
|
text_index += 1
|
||||||
fname = f"{ts}_extract_{fileName}_part_{idx:03d}_{'chunk' if is_chunk else 'full'}_{text_index:03d}.txt"
|
fname = f"{ts}_extract_{fileName}_part_{idx:03d}_{'chunk' if is_chunk else 'full'}_{text_index:03d}.txt"
|
||||||
fpath = os.path.join(base_dir, fname)
|
fpath = os.path.join(base_dir, fname)
|
||||||
with open(fpath, "w", encoding="utf-8") as f:
|
with open(fpath, "w", encoding="utf-8") as f:
|
||||||
f.write(f"# typeGroup: {part.typeGroup}\n# label: {part.label}\n# chunk: {is_chunk}\n# size: {size}\n\n")
|
f.write(f"# typeGroup: {part.typeGroup}\n# label: {part.label}\n# chunk: {is_chunk}\n# size: {size}\n\n")
|
||||||
f.write(str(part.data))
|
f.write(str(part.data))
|
||||||
|
|
||||||
# Write summary file
|
# Write summary file
|
||||||
summary_fname = f"{ts}_extract_{fileName}_summary.txt"
|
summary_fname = f"{ts}_extract_{fileName}_summary.txt"
|
||||||
summary_fpath = os.path.join(base_dir, summary_fname)
|
summary_fpath = os.path.join(base_dir, summary_fname)
|
||||||
with open(summary_fpath, "w", encoding="utf-8") as f:
|
with open(summary_fpath, "w", encoding="utf-8") as f:
|
||||||
f.write("\n".join(summary_lines))
|
f.write("\n".join(summary_lines))
|
||||||
except Exception as _e:
|
except Exception as _e:
|
||||||
logger.debug(f"Debug dump skipped: {_e}")
|
logger.debug(f"Debug dump skipped: {_e}")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -318,17 +318,19 @@ class GenerationService:
|
||||||
if "sections" not in extractedContent:
|
if "sections" not in extractedContent:
|
||||||
raise ValueError("extractedContent must contain 'sections' field")
|
raise ValueError("extractedContent must contain 'sections' field")
|
||||||
|
|
||||||
# DEBUG: Log renderer input metadata only (no verbose JSON) TODO REMOVE
|
# DEBUG: Log renderer input metadata only (no verbose JSON) - only if debug enabled
|
||||||
try:
|
try:
|
||||||
import os
|
debug_enabled = self.services.utils.configGet("APP_DEBUG_CHAT_WORKFLOW_ENABLED", False)
|
||||||
ts = datetime.now(UTC).strftime("%Y%m%d-%H%M%S")
|
if debug_enabled:
|
||||||
debug_root = "./test-chat/ai"
|
import os
|
||||||
debug_dir = os.path.join(debug_root, f"render_input_{ts}")
|
ts = datetime.now(UTC).strftime("%Y%m%d-%H%M%S")
|
||||||
os.makedirs(debug_dir, exist_ok=True)
|
debug_root = "./test-chat/ai"
|
||||||
with open(os.path.join(debug_dir, "meta.txt"), "w", encoding="utf-8") as f:
|
debug_dir = os.path.join(debug_root, f"render_input_{ts}")
|
||||||
f.write(f"title: {title}\nformat: {outputFormat}\ncontent_type: {type(extractedContent).__name__}\n")
|
os.makedirs(debug_dir, exist_ok=True)
|
||||||
f.write(f"content_size: {len(str(extractedContent))} characters\n")
|
with open(os.path.join(debug_dir, "meta.txt"), "w", encoding="utf-8") as f:
|
||||||
f.write(f"sections_count: {len(extractedContent.get('sections', []))}\n")
|
f.write(f"title: {title}\nformat: {outputFormat}\ncontent_type: {type(extractedContent).__name__}\n")
|
||||||
|
f.write(f"content_size: {len(str(extractedContent))} characters\n")
|
||||||
|
f.write(f"sections_count: {len(extractedContent.get('sections', []))}\n")
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -114,16 +114,18 @@ Return only the JSON structure with actual data from the documents. Do not inclu
|
||||||
# Debug output
|
# Debug output
|
||||||
services.utils.debugLogToFile(f"EXTRACTION INTENT: Processed", "PROMPT_BUILDER")
|
services.utils.debugLogToFile(f"EXTRACTION INTENT: Processed", "PROMPT_BUILDER")
|
||||||
|
|
||||||
# Save full extraction prompt to debug file
|
# Save full extraction prompt to debug file - only if debug enabled
|
||||||
try:
|
try:
|
||||||
import os
|
debug_enabled = services.utils.configGet("APP_DEBUG_CHAT_WORKFLOW_ENABLED", False)
|
||||||
from datetime import datetime, UTC
|
if debug_enabled:
|
||||||
ts = datetime.now(UTC).strftime("%Y%m%d-%H%M%S")
|
import os
|
||||||
debug_root = "./test-chat/ai"
|
from datetime import datetime, UTC
|
||||||
os.makedirs(debug_root, exist_ok=True)
|
ts = datetime.now(UTC).strftime("%Y%m%d-%H%M%S")
|
||||||
with open(os.path.join(debug_root, f"{ts}_extraction_prompt.txt"), "w", encoding="utf-8") as f:
|
debug_root = "./test-chat/ai"
|
||||||
f.write(f"EXTRACTION PROMPT:\n{finalPrompt}\n\n")
|
os.makedirs(debug_root, exist_ok=True)
|
||||||
f.write(f"EXTRACTION INTENT:\n{extractionIntent}\n")
|
with open(os.path.join(debug_root, f"{ts}_extraction_prompt.txt"), "w", encoding="utf-8") as f:
|
||||||
|
f.write(f"EXTRACTION PROMPT:\n{finalPrompt}\n\n")
|
||||||
|
f.write(f"EXTRACTION INTENT:\n{extractionIntent}\n")
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
@ -194,17 +196,19 @@ Return only the generation prompt, starting with "Generate a {outputFormat} docu
|
||||||
# Debug output
|
# Debug output
|
||||||
services.utils.debugLogToFile(f"GENERATION PROMPT: Generated successfully", "PROMPT_BUILDER")
|
services.utils.debugLogToFile(f"GENERATION PROMPT: Generated successfully", "PROMPT_BUILDER")
|
||||||
|
|
||||||
# Save full generation prompt and AI response to debug file
|
# Save full generation prompt and AI response to debug file - only if debug enabled
|
||||||
try:
|
try:
|
||||||
import os
|
debug_enabled = services.utils.configGet("APP_DEBUG_CHAT_WORKFLOW_ENABLED", False)
|
||||||
from datetime import datetime, UTC
|
if debug_enabled:
|
||||||
ts = datetime.now(UTC).strftime("%Y%m%d-%H%M%S")
|
import os
|
||||||
debug_root = "./test-chat/ai"
|
from datetime import datetime, UTC
|
||||||
os.makedirs(debug_root, exist_ok=True)
|
ts = datetime.now(UTC).strftime("%Y%m%d-%H%M%S")
|
||||||
with open(os.path.join(debug_root, f"{ts}_generation_prompt.txt"), "w", encoding="utf-8") as f:
|
debug_root = "./test-chat/ai"
|
||||||
f.write(f"GENERATION PROMPT REQUEST:\n{generationPromptRequest}\n\n")
|
os.makedirs(debug_root, exist_ok=True)
|
||||||
f.write(f"GENERATION PROMPT AI RESPONSE:\n{response.content if response else 'No response'}\n\n")
|
with open(os.path.join(debug_root, f"{ts}_generation_prompt.txt"), "w", encoding="utf-8") as f:
|
||||||
f.write(f"GENERATION PROMPT FINAL:\n{result if result else 'None'}\n")
|
f.write(f"GENERATION PROMPT REQUEST:\n{generationPromptRequest}\n\n")
|
||||||
|
f.write(f"GENERATION PROMPT AI RESPONSE:\n{response.content if response else 'No response'}\n\n")
|
||||||
|
f.write(f"GENERATION PROMPT FINAL:\n{result if result else 'None'}\n")
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue