gateway/modules/workflows/processing/shared/promptGenerationActionsReact.py
2025-10-05 16:28:44 +02:00

166 lines
6.5 KiB
Python

"""
React Mode Prompt Generation
Handles prompt templates for react mode action handling.
"""
from typing import Any, List
from modules.datamodels.datamodelChat import PromptBundle, PromptPlaceholder
from modules.workflows.processing.shared.placeholderFactory import (
extractUserPrompt,
extractUserLanguage,
extractAvailableMethods,
extractAvailableDocumentsSummary,
extractAvailableDocumentsIndex,
extractAvailableConnectionsIndex,
extractPreviousActionResults,
extractLearningsAndImprovements,
extractLatestRefinementFeedback,
)
from modules.workflows.processing.shared.methodDiscovery import methods, getActionParameterSignature
def generateReactPlanSelectionPrompt(services, context: Any) -> PromptBundle:
"""Define placeholders first, then the template; return PromptBundle."""
placeholders: List[PromptPlaceholder] = [
PromptPlaceholder(label="USER_PROMPT", content=extractUserPrompt(context), summaryAllowed=False),
PromptPlaceholder(label="AVAILABLE_DOCUMENTS_SUMMARY", content=extractAvailableDocumentsSummary(services, context), summaryAllowed=True),
PromptPlaceholder(label="AVAILABLE_METHODS", content=extractAvailableMethods(services), summaryAllowed=False),
]
template = """Select one action to advance the task.
OBJECTIVE:
{{KEY:USER_PROMPT}}
AVAILABLE_DOCUMENTS_SUMMARY:
{{KEY:AVAILABLE_DOCUMENTS_SUMMARY}}
AVAILABLE_METHODS:
{{KEY:AVAILABLE_METHODS}}
REPLY: Return only a JSON object with the selected action:
{{
"action": "method.action_name"
}}
RULES:
1. Use EXACT action names from AVAILABLE_METHODS
2. Return ONLY JSON - no other text
3. Do NOT use markdown code blocks
4. Do NOT add explanations
"""
return PromptBundle(prompt=template, placeholders=placeholders)
def generateReactParametersPrompt(services, context: Any, compoundActionName: str) -> PromptBundle:
"""Define placeholders first, then the template; return PromptBundle."""
# derive method/action and signature
methodName, actionName = (compoundActionName.split('.', 1) if '.' in compoundActionName else (compoundActionName, ''))
actionSignature = getActionParameterSignature(methodName, actionName, methods)
# determine action objective if available, else fall back to user prompt
actionObjective = None
if hasattr(context, 'action_objective') and context.action_objective:
actionObjective = context.action_objective
elif hasattr(context, 'task_step') and context.task_step and getattr(context.task_step, 'objective', None):
actionObjective = context.task_step.objective
else:
actionObjective = extractUserPrompt(context)
placeholders: List[PromptPlaceholder] = [
PromptPlaceholder(label="ACTION_OBJECTIVE", content=actionObjective, summaryAllowed=False),
PromptPlaceholder(label="ACTION_SIGNATURE", content=actionSignature, summaryAllowed=False),
PromptPlaceholder(label="AVAILABLE_DOCUMENTS_INDEX", content=extractAvailableDocumentsIndex(services, context), summaryAllowed=True),
PromptPlaceholder(label="AVAILABLE_CONNECTIONS_INDEX", content=extractAvailableConnectionsIndex(services), summaryAllowed=False),
PromptPlaceholder(label="USER_PROMPT", content=extractUserPrompt(context), summaryAllowed=False),
PromptPlaceholder(label="USER_LANGUAGE", content=extractUserLanguage(services), summaryAllowed=False),
PromptPlaceholder(label="PREVIOUS_ACTION_RESULTS", content=extractPreviousActionResults(context), summaryAllowed=True),
PromptPlaceholder(label="LEARNINGS_AND_IMPROVEMENTS", content=extractLearningsAndImprovements(context), summaryAllowed=True),
PromptPlaceholder(label="LATEST_REFINEMENT_FEEDBACK", content=extractLatestRefinementFeedback(context), summaryAllowed=True),
PromptPlaceholder(label="SELECTED_ACTION", content=compoundActionName, summaryAllowed=False),
]
template = """Generate parameters for this action.
ACTION_OBJECTIVE (the objective for this action to fulfill):
{{KEY:ACTION_OBJECTIVE}}
ACTION_SIGNATURE (the signature of the action to generate parameters for):
{{KEY:ACTION_SIGNATURE}}
AVAILABLE_DOCUMENTS_INDEX:
{{KEY:AVAILABLE_DOCUMENTS_INDEX}}
AVAILABLE_CONNECTIONS_INDEX:
{{KEY:AVAILABLE_CONNECTIONS_INDEX}}
USER_REQUEST (final user prompt to deliver):
{{KEY:USER_PROMPT}}
USER_LANGUAGE:
{{KEY:USER_LANGUAGE}}
PREVIOUS_ACTION_RESULTS:
{{KEY:PREVIOUS_ACTION_RESULTS}}
LEARNINGS_AND_IMPROVEMENTS:
{{KEY:LEARNINGS_AND_IMPROVEMENTS}}
LATEST_REFINEMENT_FEEDBACK:
{{KEY:LATEST_REFINEMENT_FEEDBACK}}
SELECTED_ACTION:
{{KEY:SELECTED_ACTION}}
REPLY: Return only a JSON object with the parameters according to the ACTION_SIGNATURE without any comments in the structure below:
{{
"parameters": {{
"parameter": "value",
}},
"signature": [List of all signatures, you see in the ACTION_SIGNATURE]
}}
RULES:
1. Use ONLY parameter names from ACTION_SIGNATURE
2. Use exact connection references from AVAILABLE_CONNECTIONS_INDEX for connectionReference parameters
3. Use exact document references from AVAILABLE_DOCUMENTS_INDEX for documentList parameters
4. Learn from PREVIOUS_ACTION_RESULTS and LEARNINGS_AND_IMPROVEMENTS to avoid repeating mistakes
5. Consider LATEST_REFINEMENT_FEEDBACK when generating parameters
6. Use the ACTION_OBJECTIVE to understand the specific goal for this action
7. Generate parameters that align with the USER_LANGUAGE when applicable
8. Return ONLY JSON - no other text
9. Do NOT use markdown code blocks
10. Do NOT add explanations
"""
return PromptBundle(prompt=template, placeholders=placeholders)
def generateReactRefinementPrompt(services, context: Any, reviewContent: str) -> PromptBundle:
"""Define placeholders first, then the template; return PromptBundle."""
placeholders: List[PromptPlaceholder] = [
PromptPlaceholder(label="USER_PROMPT", content=extractUserPrompt(context), summaryAllowed=False),
PromptPlaceholder(label="REVIEW_CONTENT", content=reviewContent, summaryAllowed=True),
]
template = """Decide the next step based on the observation.
OBJECTIVE:
{{KEY:USER_PROMPT}}
OBSERVATION:
{{KEY:REVIEW_CONTENT}}
REPLY: Return only a JSON object with your decision:
{{
"decision": "continue|stop",
"reason": "brief explanation"
}}
RULES:
1. Use "continue" if objective NOT fulfilled
2. Use "stop" if objective fulfilled
3. Return ONLY JSON - no other text
4. Do NOT use markdown code blocks
5. Do NOT add explanations
"""
return PromptBundle(prompt=template, placeholders=placeholders)