|
| 1 | +""" |
| 2 | +AutomationTask Example |
| 3 | +
|
| 4 | +Demonstrates using AutomationTask for flexible task definition with: |
| 5 | +- Task categories for better heuristics |
| 6 | +- Success criteria for verification |
| 7 | +- Recovery configuration for rollback |
| 8 | +- Extraction specification for data extraction tasks |
| 9 | +
|
| 10 | +Prerequisites: |
| 11 | + pip install predicate-sdk openai |
| 12 | + export OPENAI_API_KEY=sk-... |
| 13 | +""" |
| 14 | + |
| 15 | +import asyncio |
| 16 | + |
| 17 | +from predicate import AsyncPredicateBrowser |
| 18 | +from predicate.agent_runtime import AgentRuntime |
| 19 | +from predicate.agents import ( |
| 20 | + AutomationTask, |
| 21 | + ExtractionSpec, |
| 22 | + PlannerExecutorAgent, |
| 23 | + PlannerExecutorConfig, |
| 24 | + TaskCategory, |
| 25 | +) |
| 26 | +from predicate.llm_provider import OpenAIProvider |
| 27 | + |
| 28 | + |
| 29 | +async def basic_task_example(): |
| 30 | + """Basic AutomationTask usage.""" |
| 31 | + print("\n=== Basic AutomationTask Example ===\n") |
| 32 | + |
| 33 | + # Create LLM providers |
| 34 | + planner = OpenAIProvider(model="gpt-4o") |
| 35 | + executor = OpenAIProvider(model="gpt-4o-mini") |
| 36 | + |
| 37 | + # Create agent |
| 38 | + agent = PlannerExecutorAgent( |
| 39 | + planner=planner, |
| 40 | + executor=executor, |
| 41 | + ) |
| 42 | + |
| 43 | + # Create a basic task |
| 44 | + task = AutomationTask( |
| 45 | + task_id="search-example", |
| 46 | + starting_url="https://example.com", |
| 47 | + task="Find the main heading on the page", |
| 48 | + ) |
| 49 | + |
| 50 | + print(f"Task ID: {task.task_id}") |
| 51 | + print(f"Starting URL: {task.starting_url}") |
| 52 | + print(f"Task: {task.task}") |
| 53 | + |
| 54 | + async with AsyncPredicateBrowser() as browser: |
| 55 | + page = await browser.new_page() |
| 56 | + await page.goto(task.starting_url) |
| 57 | + |
| 58 | + runtime = AgentRuntime.from_page(page) |
| 59 | + result = await agent.run(runtime, task) |
| 60 | + |
| 61 | + print(f"\nResult: {'Success' if result.success else 'Failed'}") |
| 62 | + print(f"Steps completed: {result.steps_completed}/{result.steps_total}") |
| 63 | + |
| 64 | + |
| 65 | +async def transaction_task_example(): |
| 66 | + """E-commerce transaction task with recovery.""" |
| 67 | + print("\n=== Transaction Task Example ===\n") |
| 68 | + |
| 69 | + planner = OpenAIProvider(model="gpt-4o") |
| 70 | + executor = OpenAIProvider(model="gpt-4o-mini") |
| 71 | + |
| 72 | + agent = PlannerExecutorAgent( |
| 73 | + planner=planner, |
| 74 | + executor=executor, |
| 75 | + ) |
| 76 | + |
| 77 | + # Create a transaction task with category and recovery |
| 78 | + task = AutomationTask( |
| 79 | + task_id="purchase-laptop", |
| 80 | + starting_url="https://amazon.com", |
| 81 | + task="Search for 'laptop under $500' and add the first result to cart", |
| 82 | + category=TaskCategory.TRANSACTION, # Helps with element selection |
| 83 | + enable_recovery=True, # Enable rollback on failure |
| 84 | + max_recovery_attempts=2, |
| 85 | + max_steps=50, |
| 86 | + ) |
| 87 | + |
| 88 | + # Add success criteria |
| 89 | + task = task.with_success_criteria( |
| 90 | + {"predicate": "url_contains", "args": ["/cart"]}, |
| 91 | + {"predicate": "exists", "args": [".cart-item, .sc-list-item"]}, |
| 92 | + ) |
| 93 | + |
| 94 | + print(f"Task: {task.task}") |
| 95 | + print(f"Category: {task.category}") |
| 96 | + print(f"Recovery enabled: {task.enable_recovery}") |
| 97 | + print(f"Success criteria: {task.success_criteria}") |
| 98 | + |
| 99 | + async with AsyncPredicateBrowser() as browser: |
| 100 | + page = await browser.new_page() |
| 101 | + await page.goto(task.starting_url) |
| 102 | + |
| 103 | + runtime = AgentRuntime.from_page(page) |
| 104 | + result = await agent.run(runtime, task) |
| 105 | + |
| 106 | + print(f"\nResult: {'Success' if result.success else 'Failed'}") |
| 107 | + print(f"Steps completed: {result.steps_completed}/{result.steps_total}") |
| 108 | + print(f"Replans used: {result.replans_used}") |
| 109 | + |
| 110 | + if result.error: |
| 111 | + print(f"Error: {result.error}") |
| 112 | + |
| 113 | + |
| 114 | +async def extraction_task_example(): |
| 115 | + """Data extraction task with schema.""" |
| 116 | + print("\n=== Extraction Task Example ===\n") |
| 117 | + |
| 118 | + planner = OpenAIProvider(model="gpt-4o") |
| 119 | + executor = OpenAIProvider(model="gpt-4o-mini") |
| 120 | + |
| 121 | + agent = PlannerExecutorAgent( |
| 122 | + planner=planner, |
| 123 | + executor=executor, |
| 124 | + ) |
| 125 | + |
| 126 | + # Create an extraction task with output schema |
| 127 | + task = AutomationTask( |
| 128 | + task_id="extract-product-info", |
| 129 | + starting_url="https://amazon.com/dp/B0EXAMPLE", |
| 130 | + task="Extract the product name, price, and rating", |
| 131 | + category=TaskCategory.EXTRACTION, |
| 132 | + extraction_spec=ExtractionSpec( |
| 133 | + output_schema={ |
| 134 | + "name": "str", |
| 135 | + "price": "float", |
| 136 | + "rating": "float", |
| 137 | + "num_reviews": "int", |
| 138 | + }, |
| 139 | + format="json", |
| 140 | + require_evidence=True, |
| 141 | + ), |
| 142 | + ) |
| 143 | + |
| 144 | + print(f"Task: {task.task}") |
| 145 | + print(f"Category: {task.category}") |
| 146 | + print(f"Output schema: {task.extraction_spec.output_schema}") |
| 147 | + print(f"Format: {task.extraction_spec.format}") |
| 148 | + |
| 149 | + # Note: This example won't run successfully as the URL is fake |
| 150 | + # In real usage, provide a valid product URL |
| 151 | + |
| 152 | + |
| 153 | +async def form_fill_task_example(): |
| 154 | + """Form filling task example.""" |
| 155 | + print("\n=== Form Fill Task Example ===\n") |
| 156 | + |
| 157 | + planner = OpenAIProvider(model="gpt-4o") |
| 158 | + executor = OpenAIProvider(model="gpt-4o-mini") |
| 159 | + |
| 160 | + agent = PlannerExecutorAgent( |
| 161 | + planner=planner, |
| 162 | + executor=executor, |
| 163 | + ) |
| 164 | + |
| 165 | + # Create a form fill task |
| 166 | + task = AutomationTask( |
| 167 | + task_id="contact-form", |
| 168 | + starting_url="https://example.com/contact", |
| 169 | + task="Fill the contact form with name 'John Doe', email 'john@example.com', and message 'Hello, I have a question'", |
| 170 | + category=TaskCategory.FORM_FILL, |
| 171 | + ) |
| 172 | + |
| 173 | + # Add success criteria for form submission |
| 174 | + task = task.with_success_criteria( |
| 175 | + {"predicate": "any_of", "args": [ |
| 176 | + {"predicate": "exists", "args": [".success-message"]}, |
| 177 | + {"predicate": "url_contains", "args": ["/thank-you"]}, |
| 178 | + ]}, |
| 179 | + ) |
| 180 | + |
| 181 | + print(f"Task: {task.task}") |
| 182 | + print(f"Category: {task.category}") |
| 183 | + |
| 184 | + |
| 185 | +async def from_string_example(): |
| 186 | + """Create task from simple string.""" |
| 187 | + print("\n=== From String Example ===\n") |
| 188 | + |
| 189 | + # Quick task creation from string |
| 190 | + task = AutomationTask.from_string( |
| 191 | + "Search for 'headphones' and filter by price under $50", |
| 192 | + "https://amazon.com", |
| 193 | + category=TaskCategory.SEARCH, |
| 194 | + ) |
| 195 | + |
| 196 | + print(f"Task ID: {task.task_id}") # Auto-generated UUID |
| 197 | + print(f"Task: {task.task}") |
| 198 | + print(f"Starting URL: {task.starting_url}") |
| 199 | + print(f"Category: {task.category}") |
| 200 | + |
| 201 | + |
| 202 | +async def with_extraction_example(): |
| 203 | + """Add extraction to existing task.""" |
| 204 | + print("\n=== With Extraction Example ===\n") |
| 205 | + |
| 206 | + # Create basic task |
| 207 | + task = AutomationTask( |
| 208 | + task_id="product-search", |
| 209 | + starting_url="https://amazon.com", |
| 210 | + task="Search for the cheapest laptop", |
| 211 | + ) |
| 212 | + |
| 213 | + # Add extraction specification using fluent API |
| 214 | + task_with_extraction = task.with_extraction( |
| 215 | + output_schema={"product_name": "str", "price": "float"}, |
| 216 | + format="json", |
| 217 | + ) |
| 218 | + |
| 219 | + print(f"Original category: {task.category}") |
| 220 | + print(f"After with_extraction: {task_with_extraction.category}") |
| 221 | + print(f"Extraction spec: {task_with_extraction.extraction_spec}") |
| 222 | + |
| 223 | + |
| 224 | +async def main(): |
| 225 | + """Run all examples.""" |
| 226 | + print("=" * 60) |
| 227 | + print("AutomationTask Examples") |
| 228 | + print("=" * 60) |
| 229 | + |
| 230 | + # Show task creation patterns (no browser needed) |
| 231 | + await from_string_example() |
| 232 | + await with_extraction_example() |
| 233 | + |
| 234 | + # These require browser and API keys |
| 235 | + # Uncomment to run: |
| 236 | + # await basic_task_example() |
| 237 | + # await transaction_task_example() |
| 238 | + # await form_fill_task_example() |
| 239 | + |
| 240 | + |
| 241 | +if __name__ == "__main__": |
| 242 | + asyncio.run(main()) |
0 commit comments