fix:rebase from int
This commit is contained in:
commit
b6724a797f
2 changed files with 106 additions and 59 deletions
|
|
@ -54,8 +54,9 @@ async def process(self, parameters: Dict[str, Any]) -> ActionResult:
|
||||||
logger.error(f"Invalid documentList type: {type(documentListParam)}")
|
logger.error(f"Invalid documentList type: {type(documentListParam)}")
|
||||||
documentList = DocumentReferenceList(references=[])
|
documentList = DocumentReferenceList(references=[])
|
||||||
|
|
||||||
# Optional: if omitted, formats determined from prompt. Default "txt" is validation fallback only.
|
resultType = parameters.get("resultType", "txt")
|
||||||
resultType = parameters.get("resultType")
|
simpleMode = parameters.get("simpleMode", False)
|
||||||
|
|
||||||
|
|
||||||
if not aiPrompt:
|
if not aiPrompt:
|
||||||
logger.error(f"aiPrompt is missing or empty. Parameters: {parameters}")
|
logger.error(f"aiPrompt is missing or empty. Parameters: {parameters}")
|
||||||
|
|
@ -63,18 +64,11 @@ async def process(self, parameters: Dict[str, Any]) -> ActionResult:
|
||||||
error="AI prompt is required"
|
error="AI prompt is required"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Handle optional resultType: if None, formats determined from prompt by AI
|
# Determine output extension and default MIME type without duplicating service logic
|
||||||
if resultType:
|
normalized_result_type = (str(resultType).strip().lstrip('.').lower() or "txt")
|
||||||
normalized_result_type = (str(resultType).strip().lstrip('.').lower() or "txt")
|
output_extension = f".{normalized_result_type}"
|
||||||
output_extension = f".{normalized_result_type}"
|
output_mime_type = "application/octet-stream" # Prefer service-provided mimeType when available
|
||||||
output_format = output_extension.replace('.', '') or 'txt'
|
logger.info(f"Using result type: {resultType} -> {output_extension}, simpleMode: {simpleMode}")
|
||||||
logger.info(f"Using result type: {resultType} -> {output_extension}")
|
|
||||||
else:
|
|
||||||
# No format specified - AI will determine formats from prompt
|
|
||||||
normalized_result_type = None
|
|
||||||
output_extension = None
|
|
||||||
output_format = None
|
|
||||||
logger.debug("resultType not provided - formats will be determined from prompt by AI")
|
|
||||||
|
|
||||||
output_mime_type = "application/octet-stream" # Prefer service-provided mimeType when available
|
output_mime_type = "application/octet-stream" # Prefer service-provided mimeType when available
|
||||||
|
|
||||||
|
|
@ -96,38 +90,99 @@ async def process(self, parameters: Dict[str, Any]) -> ActionResult:
|
||||||
# Update progress - preparing AI call
|
# Update progress - preparing AI call
|
||||||
self.services.chat.progressLogUpdate(operationId, 0.4, "Preparing AI call")
|
self.services.chat.progressLogUpdate(operationId, 0.4, "Preparing AI call")
|
||||||
|
|
||||||
# Detect image generation from resultType (if provided)
|
# Build options
|
||||||
imageFormats = ["png", "jpg", "jpeg", "gif", "webp"]
|
output_format = output_extension.replace('.', '') or 'txt'
|
||||||
isImageGeneration = normalized_result_type in imageFormats if normalized_result_type else False
|
|
||||||
|
|
||||||
# Build options with correct operationType
|
# Simple mode: fast path without document generation pipeline
|
||||||
from modules.datamodels.datamodelAi import OperationTypeEnum
|
if simpleMode:
|
||||||
# resultFormat in options can be None - formats will be determined by AI if not provided
|
# Update progress - calling AI (simple mode)
|
||||||
options = AiCallOptions(
|
self.services.chat.progressLogUpdate(operationId, 0.6, "Calling AI (simple mode)")
|
||||||
resultFormat=output_format, # Can be None - formats determined by AI
|
|
||||||
operationType=OperationTypeEnum.IMAGE_GENERATE if isImageGeneration else OperationTypeEnum.DATA_GENERATE
|
# Extract context from documents if provided
|
||||||
)
|
context_text = ""
|
||||||
|
if documentList and len(documentList.references) > 0:
|
||||||
# Get generationIntent from parameters (required for DATA_GENERATE)
|
try:
|
||||||
# Default to "document" if not provided (most common use case)
|
# Get documents from workflow
|
||||||
# For code generation, use ai.generateCode action or explicitly pass generationIntent="code"
|
documents = self.services.chat.getChatDocumentsFromDocumentList(documentList)
|
||||||
generationIntent = parameters.get("generationIntent", "document")
|
context_parts = []
|
||||||
|
for doc in documents:
|
||||||
|
if hasattr(doc, 'fileId') and doc.fileId:
|
||||||
|
# Get file data
|
||||||
|
fileData = self.services.interfaceDbComponent.getFileData(doc.fileId)
|
||||||
|
if fileData:
|
||||||
|
if isinstance(fileData, bytes):
|
||||||
|
doc_text = fileData.decode('utf-8', errors='ignore')
|
||||||
|
else:
|
||||||
|
doc_text = str(fileData)
|
||||||
|
context_parts.append(doc_text)
|
||||||
|
if context_parts:
|
||||||
|
context_text = "\n\n".join(context_parts)
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"Error extracting context from documents in simple mode: {e}")
|
||||||
|
|
||||||
|
# Use direct AI call without document generation pipeline
|
||||||
|
from modules.datamodels.datamodelAi import AiCallRequest, OperationTypeEnum, ProcessingModeEnum
|
||||||
|
request = AiCallRequest(
|
||||||
|
prompt=aiPrompt,
|
||||||
|
context=context_text if context_text else None,
|
||||||
|
options=AiCallOptions(
|
||||||
|
resultFormat=output_format,
|
||||||
|
operationType=OperationTypeEnum.DATA_ANALYSE,
|
||||||
|
processingMode=ProcessingModeEnum.BASIC
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
aiResponse_obj = await self.services.ai.callAi(request)
|
||||||
|
|
||||||
|
# Convert AiCallResponse to AiResponse format
|
||||||
|
from modules.datamodels.datamodelWorkflow import AiResponse, AiResponseMetadata
|
||||||
|
aiResponse = AiResponse(
|
||||||
|
content=aiResponse_obj.content,
|
||||||
|
metadata=AiResponseMetadata(
|
||||||
|
additionalData={
|
||||||
|
"modelName": aiResponse_obj.modelName,
|
||||||
|
"priceUsd": aiResponse_obj.priceUsd,
|
||||||
|
"processingTime": aiResponse_obj.processingTime,
|
||||||
|
"bytesSent": aiResponse_obj.bytesSent,
|
||||||
|
"bytesReceived": aiResponse_obj.bytesReceived,
|
||||||
|
"errorCount": aiResponse_obj.errorCount
|
||||||
|
}
|
||||||
|
),
|
||||||
|
documents=[] # Simple mode doesn't generate documents
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# Full mode: use unified callAiContent method
|
||||||
|
options = AiCallOptions(
|
||||||
|
resultFormat=output_format
|
||||||
|
)
|
||||||
|
|
||||||
# Update progress - calling AI
|
# Update progress - calling AI
|
||||||
self.services.chat.progressLogUpdate(operationId, 0.6, "Calling AI")
|
self.services.chat.progressLogUpdate(operationId, 0.6, "Calling AI")
|
||||||
|
|
||||||
# Use unified callAiContent method with BOTH documentList and contentParts
|
# Use unified callAiContent method
|
||||||
# Extraction is handled by AI service - no extraction here
|
# If contentParts provided (pre-extracted), use them directly
|
||||||
# outputFormat: Optional - if None, formats determined from prompt by AI
|
# Otherwise, pass documentList and let callAiContent handle Phases 5A-5E internally
|
||||||
aiResponse = await self.services.ai.callAiContent(
|
# Note: ContentExtracted documents (from context.extractContent) are now handled
|
||||||
prompt=aiPrompt,
|
# automatically in _extractAndPrepareContent() (Phase 5B)
|
||||||
options=options,
|
if contentParts:
|
||||||
documentList=documentList, # Pass documentList - AI service handles extraction
|
# Pre-extracted ContentParts - use them directly
|
||||||
contentParts=contentParts, # Pass contentParts if provided (or None)
|
aiResponse = await self.services.ai.callAiContent(
|
||||||
outputFormat=output_format, # Can be None - AI determines from prompt
|
prompt=aiPrompt,
|
||||||
parentOperationId=operationId,
|
options=options,
|
||||||
generationIntent=generationIntent # REQUIRED for DATA_GENERATE
|
contentParts=contentParts, # Pre-extracted ContentParts
|
||||||
)
|
outputFormat=output_format,
|
||||||
|
parentOperationId=operationId
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# Pass documentList - callAiContent handles Phases 5A-5E internally
|
||||||
|
# This includes automatic detection of ContentExtracted documents
|
||||||
|
aiResponse = await self.services.ai.callAiContent(
|
||||||
|
prompt=aiPrompt,
|
||||||
|
options=options,
|
||||||
|
documentList=documentList, # callAiContent macht Phasen 5A-5E
|
||||||
|
outputFormat=output_format,
|
||||||
|
parentOperationId=operationId
|
||||||
|
)
|
||||||
|
|
||||||
# Update progress - processing result
|
# Update progress - processing result
|
||||||
self.services.chat.progressLogUpdate(operationId, 0.8, "Processing result")
|
self.services.chat.progressLogUpdate(operationId, 0.8, "Processing result")
|
||||||
|
|
|
||||||
|
|
@ -60,24 +60,16 @@ class MethodAi(MethodBase):
|
||||||
frontendOptions=["txt", "json", "md", "csv", "xml", "html", "pdf", "docx", "xlsx", "pptx", "png", "jpg"],
|
frontendOptions=["txt", "json", "md", "csv", "xml", "html", "pdf", "docx", "xlsx", "pptx", "png", "jpg"],
|
||||||
required=False,
|
required=False,
|
||||||
default="txt",
|
default="txt",
|
||||||
description="Output file extension. Optional: if omitted, formats are determined from prompt by AI. Default \"txt\" is validation fallback only. With per-document format determination, AI can determine different formats for different documents based on prompt."
|
description="Output file extension. All output documents will use this format"
|
||||||
),
|
),
|
||||||
"generationIntent": WorkflowActionParameter(
|
"simpleMode": WorkflowActionParameter(
|
||||||
name="generationIntent",
|
name="simpleMode",
|
||||||
type="str",
|
type="bool",
|
||||||
frontendType=FrontendType.SELECT,
|
frontendType=FrontendType.CHECKBOX,
|
||||||
frontendOptions=["document", "code", "image"],
|
|
||||||
required=False,
|
required=False,
|
||||||
default="document",
|
default=False,
|
||||||
description="Explicit generation intent (\"document\" | \"code\" | \"image\"). Required for DATA_GENERATE operations. Defaults to \"document\" if not provided. For code generation, use ai.generateCode action or explicitly pass generationIntent=\"code\". For IMAGE_GENERATE operations, this parameter is ignored."
|
description="If true, uses fast simple AI call without document generation pipeline. Use for chatbot responses and simple text generation."
|
||||||
),
|
)
|
||||||
"contentParts": WorkflowActionParameter(
|
|
||||||
name="contentParts",
|
|
||||||
type="List[ContentPart]",
|
|
||||||
frontendType=FrontendType.HIDDEN,
|
|
||||||
required=False,
|
|
||||||
description="Pre-extracted content parts (internal parameter, typically passed between actions). If provided, these will be used instead of extracting from documentList. Can be a list of ContentPart objects or an object with a 'parts' attribute."
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
execute=process.__get__(self, self.__class__)
|
execute=process.__get__(self, self.__class__)
|
||||||
),
|
),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue