Pedro/add sop workflow builder (#3685)
This commit is contained in:
84
skyvern/forge/prompts/skyvern/build-workflow-from-pdf.j2
Normal file
84
skyvern/forge/prompts/skyvern/build-workflow-from-pdf.j2
Normal file
@@ -0,0 +1,84 @@
|
||||
You are an AI assistant that converts Standard Operating Procedures (SOP) from text into a Skyvern workflow definition in JSON format.
|
||||
|
||||
REQUIRED OUTPUT FORMAT:
|
||||
Return a JSON object with this structure:
|
||||
{
|
||||
"title": "workflow_name",
|
||||
"workflow_definition": {
|
||||
"parameters": [
|
||||
{
|
||||
"key": "parameter_name",
|
||||
"parameter_type": "workflow",
|
||||
"workflow_parameter_type": "string",
|
||||
"description": "Parameter description",
|
||||
"default_value": null
|
||||
}
|
||||
],
|
||||
"blocks": [
|
||||
{
|
||||
"label": "block_name",
|
||||
"block_type": "block_type_name",
|
||||
"continue_on_failure": false,
|
||||
// ... other required fields for each block type
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
PARAMETER STRUCTURE:
|
||||
- Each parameter MUST have: "key", "parameter_type", "workflow_parameter_type"
|
||||
- "parameter_type" should always be "workflow"
|
||||
- "workflow_parameter_type" can be: "string", "json", "credential_id", "file_url"
|
||||
- Use "credential_id" for passwords/credentials
|
||||
- "description" and "default_value" are optional
|
||||
|
||||
AVAILABLE BLOCK TYPES (use these exact names):
|
||||
- "login": For user authentication with credentials
|
||||
- "navigation": For navigating to pages and filling forms
|
||||
- "action": For clicking buttons or simple actions
|
||||
- "extraction": For extracting data from pages
|
||||
- "task": For complex tasks with both navigation and extraction
|
||||
- "file_download": For downloading files
|
||||
- "for_loop": For repeating actions over a list
|
||||
- "validation": For validating extracted data
|
||||
- "wait": For waiting/pausing
|
||||
- "code": For custom code execution
|
||||
- "text_prompt": For LLM text generation
|
||||
- "http_request": For API calls
|
||||
|
||||
BLOCK STRUCTURE REQUIREMENTS:
|
||||
1. Each block MUST have: label, block_type, continue_on_failure
|
||||
2. Navigation blocks need: url (can be empty string ""), navigation_goal, engine (set to "skyvern-1.0")
|
||||
3. Login blocks need: url, navigation_goal, parameter_keys (empty array if no credentials), engine (set to "skyvern-1.0")
|
||||
4. Extraction blocks need: url (can be empty string ""), data_extraction_goal, data_schema, engine (set to "skyvern-1.0")
|
||||
5. Action blocks need: url (can be empty string ""), navigation_goal, engine (set to "skyvern-1.0")
|
||||
6. Validation blocks need: complete_criterion OR terminate_criterion (at least one must be set), parameter_keys (empty array if none)
|
||||
7. For_loop blocks need: loop_blocks, loop_variable_reference
|
||||
8. File_download blocks need: url (can be empty string ""), navigation_goal, engine (set to "skyvern-1.0")
|
||||
|
||||
CRITICAL INSTRUCTIONS - READ CAREFULLY:
|
||||
1. **BE THOROUGH**: Convert EVERY automatable step from the SOP into a block. Do not skip or combine steps.
|
||||
2. **PRESERVE SPECIFICITY**: If the SOP gives specific instructions (e.g., "click X then Y", "fill field A with value B"), create separate blocks for each action. DO NOT generalize or simplify.
|
||||
3. **ONE ACTION PER BLOCK**: For "action" blocks, each should do ONE specific thing (one click, one navigation). Create multiple blocks if needed.
|
||||
4. **DETAILED navigation_goal**: Copy the exact instructions from the SOP into the navigation_goal field. Be as specific as the original SOP.
|
||||
5. **MAINTAIN ORDER**: Keep the exact order of steps from the SOP. Do not reorganize or optimize.
|
||||
6. **INCLUDE ALL CONDITIONS**: If the SOP says "if X then Y", create conditional blocks or separate blocks for each scenario.
|
||||
7. **IGNORE ONLY**: Skip only steps requiring human judgment, creativity, or physical actions. Include everything else.
|
||||
8. **URL FIELD**: Most blocks need a "url" field. Use empty string "" if no specific URL is needed (browser stays on current page).
|
||||
9. **AVOID VALIDATION BLOCKS**: Use "extraction" blocks for data extraction. Only use "validation" if explicitly validating previous extracted data, and always include complete_criterion.
|
||||
10. Set continue_on_failure to false for critical steps, true for optional ones
|
||||
11. Set engine to "skyvern-1.0" for all blocks that need it
|
||||
12. Use clear, descriptive labels that match the SOP terminology
|
||||
|
||||
EXAMPLES OF THOROUGHNESS:
|
||||
- If SOP says "Navigate to page X, then click button Y, then fill form Z" → Create 3 separate blocks
|
||||
- If SOP says "Click the 'Products' link in the top left" → Use that EXACT wording in navigation_goal
|
||||
- If SOP has 20 steps → Your workflow should have ~20 blocks (one per step)
|
||||
|
||||
Standard Operating Procedure:
|
||||
```
|
||||
{{ sop_text }}
|
||||
```
|
||||
|
||||
Return ONLY a valid JSON object following the structure above. Create a comprehensive workflow that captures EVERY automatable step from the SOP with full specificity.
|
||||
|
||||
@@ -98,6 +98,7 @@ from skyvern.schemas.runs import (
|
||||
)
|
||||
from skyvern.schemas.workflows import BlockType, WorkflowCreateYAMLRequest, WorkflowRequest, WorkflowStatus
|
||||
from skyvern.services import block_service, run_service, task_v1_service, task_v2_service, workflow_service
|
||||
from skyvern.services.pdf_import_service import pdf_import_service
|
||||
from skyvern.webeye.actions.actions import Action
|
||||
|
||||
LOG = structlog.get_logger()
|
||||
@@ -588,6 +589,47 @@ async def create_workflow_from_prompt(
|
||||
return workflow.model_dump(by_alias=True)
|
||||
|
||||
|
||||
@legacy_base_router.post(
|
||||
"/workflows/import-pdf",
|
||||
response_model=dict[str, Any],
|
||||
tags=["agent"],
|
||||
openapi_extra={
|
||||
"x-fern-sdk-method-name": "import_workflow_from_pdf",
|
||||
"x-fern-examples": [
|
||||
{
|
||||
"code-samples": [
|
||||
{
|
||||
"sdk": "curl",
|
||||
"code": 'curl -X POST "https://api.skyvern.com/workflows/import-pdf" \\\n -H "Authorization: Bearer YOUR_API_KEY" \\\n -F "file=@sop_document.pdf"',
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
},
|
||||
description="Import a workflow from a PDF containing Standard Operating Procedures",
|
||||
summary="Import workflow from PDF",
|
||||
responses={
|
||||
200: {"description": "Successfully imported workflow from PDF"},
|
||||
400: {"description": "Invalid PDF file or no content found"},
|
||||
422: {"description": "Failed to convert SOP to workflow"},
|
||||
500: {"description": "Internal server error during processing"},
|
||||
},
|
||||
)
|
||||
@legacy_base_router.post(
|
||||
"/workflows/import-pdf/",
|
||||
response_model=dict[str, Any],
|
||||
include_in_schema=False,
|
||||
)
|
||||
async def import_workflow_from_pdf(
|
||||
file: UploadFile,
|
||||
current_org: Organization = Depends(org_auth_service.get_current_org),
|
||||
) -> dict[str, Any]:
|
||||
"""Import a workflow from a PDF file containing Standard Operating Procedures."""
|
||||
analytics.capture("skyvern-oss-workflow-import-pdf")
|
||||
|
||||
return await pdf_import_service.import_workflow_from_pdf(file, current_org)
|
||||
|
||||
|
||||
@legacy_base_router.put(
|
||||
"/workflows/{workflow_id}",
|
||||
openapi_extra={
|
||||
|
||||
Reference in New Issue
Block a user