Add web browser example to doc (#439)
This commit is contained in:
parent
cedf63cde7
commit
b453d63f33
|
@ -28,6 +28,8 @@
|
|||
title: Master you knowledge base with agentic RAG
|
||||
- local: examples/multiagents
|
||||
title: Orchestrate a multi-agent system
|
||||
- local: examples/web_browser
|
||||
title: Build a web browser agent using vision models
|
||||
- title: Reference
|
||||
sections:
|
||||
- local: reference/agents
|
||||
|
|
|
@ -0,0 +1,218 @@
|
|||
# Web Browser Automation with Agents 🤖🌐
|
||||
|
||||
[[open-in-colab]]
|
||||
|
||||
In this notebook, we'll create an **agent-powered web browser automation system**! This system can navigate websites, interact with elements, and extract information automatically.
|
||||
|
||||
The agent will be able to:
|
||||
✅ Navigate to web pages
|
||||
✅ Click on elements
|
||||
✅ Search within pages
|
||||
✅ Handle popups and modals
|
||||
✅ Take screenshots
|
||||
✅ Extract information
|
||||
|
||||
Let's set up this system step by step.
|
||||
|
||||
First, run these lines to install the required dependencies:
|
||||
|
||||
```bash
|
||||
pip install smolagents selenium helium pillow python-dotenv -q
|
||||
```
|
||||
|
||||
Let's import our required libraries and set up environment variables:
|
||||
|
||||
```python
|
||||
from io import BytesIO
|
||||
from time import sleep
|
||||
|
||||
import helium
|
||||
from dotenv import load_dotenv
|
||||
from PIL import Image
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.common.keys import Keys
|
||||
|
||||
from smolagents import CodeAgent, tool
|
||||
from smolagents.agents import ActionStep
|
||||
|
||||
# Load environment variables
|
||||
load_dotenv()
|
||||
```
|
||||
|
||||
Now let's create our core browser interaction tools that will allow our agent to navigate and interact with web pages:
|
||||
|
||||
```python
|
||||
@tool
|
||||
def search_item_ctrl_f(text: str, nth_result: int = 1) -> str:
|
||||
"""
|
||||
Searches for text on the current page via Ctrl + F and jumps to the nth occurrence.
|
||||
Args:
|
||||
text: The text to search for
|
||||
nth_result: Which occurrence to jump to (default: 1)
|
||||
"""
|
||||
elements = driver.find_elements(By.XPATH, f"//*[contains(text(), '{text}')]")
|
||||
if nth_result > len(elements):
|
||||
raise Exception(f"Match n°{nth_result} not found (only {len(elements)} matches found)")
|
||||
result = f"Found {len(elements)} matches for '{text}'."
|
||||
elem = elements[nth_result - 1]
|
||||
driver.execute_script("arguments[0].scrollIntoView(true);", elem)
|
||||
result += f"Focused on element {nth_result} of {len(elements)}"
|
||||
return result
|
||||
|
||||
@tool
|
||||
def go_back() -> None:
|
||||
"""Goes back to previous page."""
|
||||
driver.back()
|
||||
|
||||
@tool
|
||||
def close_popups() -> str:
|
||||
"""
|
||||
Closes any visible modal or pop-up on the page. Use this to dismiss pop-up windows!
|
||||
This does not work on cookie consent banners.
|
||||
"""
|
||||
webdriver.ActionChains(driver).send_keys(Keys.ESCAPE).perform()
|
||||
```
|
||||
|
||||
Let's set up our browser with Chrome and configure screenshot capabilities:
|
||||
|
||||
```python
|
||||
# Configure Chrome options
|
||||
chrome_options = webdriver.ChromeOptions()
|
||||
chrome_options.add_argument("--force-device-scale-factor=1")
|
||||
chrome_options.add_argument("--window-size=1000,1350")
|
||||
chrome_options.add_argument("--disable-pdf-viewer")
|
||||
chrome_options.add_argument("--window-position=0,0")
|
||||
|
||||
# Initialize the browser
|
||||
driver = helium.start_chrome(headless=False, options=chrome_options)
|
||||
|
||||
# Set up screenshot callback
|
||||
def save_screenshot(memory_step: ActionStep, agent: CodeAgent) -> None:
|
||||
sleep(1.0) # Let JavaScript animations happen before taking the screenshot
|
||||
driver = helium.get_driver()
|
||||
current_step = memory_step.step_number
|
||||
if driver is not None:
|
||||
for previous_memory_step in agent.memory.steps: # Remove previous screenshots for lean processing
|
||||
if isinstance(previous_memory_step, ActionStep) and previous_memory_step.step_number <= current_step - 2:
|
||||
previous_memory_step.observations_images = None
|
||||
png_bytes = driver.get_screenshot_as_png()
|
||||
image = Image.open(BytesIO(png_bytes))
|
||||
print(f"Captured a browser screenshot: {image.size} pixels")
|
||||
memory_step.observations_images = [image.copy()] # Create a copy to ensure it persists
|
||||
|
||||
# Update observations with current URL
|
||||
url_info = f"Current url: {driver.current_url}"
|
||||
memory_step.observations = (
|
||||
url_info if memory_step.observations is None else memory_step.observations + "\n" + url_info
|
||||
)
|
||||
```
|
||||
|
||||
Now let's create our web automation agent:
|
||||
|
||||
```python
|
||||
# Initialize the model
|
||||
model_id = "meta-llama/Llama-3.3-70B-Instruct" # You can change this to your preferred model
|
||||
model = HfApiModel(model_id)
|
||||
|
||||
# Create the agent
|
||||
agent = CodeAgent(
|
||||
tools=[go_back, close_popups, search_item_ctrl_f],
|
||||
model=model,
|
||||
additional_authorized_imports=["helium"],
|
||||
step_callbacks=[save_screenshot],
|
||||
max_steps=20,
|
||||
verbosity_level=2,
|
||||
)
|
||||
|
||||
# Import helium for the agent
|
||||
agent.python_executor("from helium import *", agent.state)
|
||||
```
|
||||
|
||||
The agent needs instructions on how to use Helium for web automation. Here are the instructions we'll provide:
|
||||
|
||||
```python
|
||||
helium_instructions = """
|
||||
You can use helium to access websites. Don't bother about the helium driver, it's already managed.
|
||||
We've already ran "from helium import *"
|
||||
Then you can go to pages!
|
||||
Code:
|
||||
```py
|
||||
go_to('github.com/trending')
|
||||
```<end_code>
|
||||
|
||||
You can directly click clickable elements by inputting the text that appears on them.
|
||||
Code:
|
||||
```py
|
||||
click("Top products")
|
||||
```<end_code>
|
||||
|
||||
If it's a link:
|
||||
Code:
|
||||
```py
|
||||
click(Link("Top products"))
|
||||
```<end_code>
|
||||
|
||||
If you try to interact with an element and it's not found, you'll get a LookupError.
|
||||
In general stop your action after each button click to see what happens on your screenshot.
|
||||
Never try to login in a page.
|
||||
|
||||
To scroll up or down, use scroll_down or scroll_up with as an argument the number of pixels to scroll from.
|
||||
Code:
|
||||
```py
|
||||
scroll_down(num_pixels=1200) # This will scroll one viewport down
|
||||
```<end_code>
|
||||
|
||||
When you have pop-ups with a cross icon to close, don't try to click the close icon by finding its element or targeting an 'X' element (this most often fails).
|
||||
Just use your built-in tool `close_popups` to close them:
|
||||
Code:
|
||||
```py
|
||||
close_popups()
|
||||
```<end_code>
|
||||
|
||||
You can use .exists() to check for the existence of an element. For example:
|
||||
Code:
|
||||
```py
|
||||
if Text('Accept cookies?').exists():
|
||||
click('I accept')
|
||||
```<end_code>
|
||||
"""
|
||||
```
|
||||
|
||||
Now we can run our agent with a task! Let's try finding information on Wikipedia:
|
||||
|
||||
```python
|
||||
search_request = """
|
||||
Please navigate to https://en.wikipedia.org/wiki/Chicago and give me a sentence containing the word "1992" that mentions a construction accident.
|
||||
"""
|
||||
|
||||
agent_output = agent.run(search_request + helium_instructions)
|
||||
print("Final output:")
|
||||
print(agent_output)
|
||||
```
|
||||
|
||||
You can run different tasks by modifying the request. For example, here's for me to know if I should work harder:
|
||||
|
||||
```python
|
||||
github_request = """
|
||||
I'm trying to find how hard I have to work to get a repo in github.com/trending.
|
||||
Can you navigate to the profile for the top author of the top trending repo, and give me their total number of commits over the last year?
|
||||
"""
|
||||
|
||||
agent_output = agent.run(github_request + helium_instructions)
|
||||
print("Final output:")
|
||||
print(agent_output)
|
||||
```
|
||||
|
||||
The system is particularly effective for tasks like:
|
||||
- Data extraction from websites
|
||||
- Web research automation
|
||||
- UI testing and verification
|
||||
- Content monitoring
|
||||
|
||||
Best Practices:
|
||||
1. Always provide clear, specific instructions
|
||||
2. Use the screenshot callback for debugging
|
||||
3. Handle errors gracefully
|
||||
4. Clean up old screenshots to manage memory
|
||||
5. Set reasonable step limits for your tasks
|
Loading…
Reference in New Issue