ai-agent-book 精选快照(<2MB 代码与文档,来自 github.com/bojieli/ai-agent-book)
Build latest book artifacts / build (push) Canceled after 0s
dependency resolution / resolve (3.11) (push) Canceled after 0s
dependency resolution / resolve (3.13) (push) Canceled after 0s
deploy-pages / build (push) Canceled after 0s
deploy-pages / deploy (push) Canceled after 0s
i18n consistency check / check (push) Canceled after 0s
provider adoption tests / test (chapter2/context-compression) (push) Canceled after 0s
provider adoption tests / test (chapter2/prompt-injection) (push) Canceled after 0s
provider adoption tests / test (chapter2/system-hint) (push) Canceled after 0s
provider adoption tests / test (chapter3/log-sanitization) (push) Canceled after 0s
web-search-agent tests / test (push) Canceled after 0s
web-search-agent tests / agentbook (push) Canceled after 0s
Build latest book artifacts / build (push) Canceled after 0s
dependency resolution / resolve (3.11) (push) Canceled after 0s
dependency resolution / resolve (3.13) (push) Canceled after 0s
deploy-pages / build (push) Canceled after 0s
deploy-pages / deploy (push) Canceled after 0s
i18n consistency check / check (push) Canceled after 0s
provider adoption tests / test (chapter2/context-compression) (push) Canceled after 0s
provider adoption tests / test (chapter2/prompt-injection) (push) Canceled after 0s
provider adoption tests / test (chapter2/system-hint) (push) Canceled after 0s
provider adoption tests / test (chapter3/log-sanitization) (push) Canceled after 0s
web-search-agent tests / test (push) Canceled after 0s
web-search-agent tests / agentbook (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
"""
|
||||
Goal: Automates CAPTCHA solving on a demo website.
|
||||
|
||||
|
||||
Simple try of the agent.
|
||||
@dev You need to add OPENAI_API_KEY to your environment variables.
|
||||
NOTE: captchas are hard. For this example it works. But e.g. for iframes it does not.
|
||||
for this example it helps to zoom in.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
from browser_use import Agent, ChatOpenAI
|
||||
|
||||
|
||||
async def main():
|
||||
llm = ChatOpenAI(model='gpt-4.1-mini')
|
||||
agent = Agent(
|
||||
task='go to https://captcha.com/demos/features/captcha-demo.aspx and solve the captcha',
|
||||
llm=llm,
|
||||
)
|
||||
await agent.run()
|
||||
input('Press Enter to exit')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,52 @@
|
||||
# Goal: Checks for available visa appointment slots on the Greece MFA website.
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from browser_use import ChatOpenAI
|
||||
from browser_use.agent.service import Agent
|
||||
from browser_use.tools.service import Tools
|
||||
|
||||
if not os.getenv('OPENAI_API_KEY'):
|
||||
raise ValueError('OPENAI_API_KEY is not set. Please add it to your environment variables.')
|
||||
|
||||
tools = Tools()
|
||||
|
||||
|
||||
class WebpageInfo(BaseModel):
|
||||
"""Model for webpage link."""
|
||||
|
||||
link: str = 'https://appointment.mfa.gr/en/reservations/aero/ireland-grcon-dub/'
|
||||
|
||||
|
||||
@tools.action('Go to the webpage', param_model=WebpageInfo)
|
||||
def go_to_webpage(webpage_info: WebpageInfo):
|
||||
"""Returns the webpage link."""
|
||||
return webpage_info.link
|
||||
|
||||
|
||||
async def main():
|
||||
"""Main function to execute the agent task."""
|
||||
task = (
|
||||
'Go to the Greece MFA webpage via the link I provided you.'
|
||||
'Check the visa appointment dates. If there is no available date in this month, check the next month.'
|
||||
'If there is no available date in both months, tell me there is no available date.'
|
||||
)
|
||||
|
||||
model = ChatOpenAI(model='gpt-4.1-mini')
|
||||
agent = Agent(task, model, tools=tools, use_vision=True)
|
||||
|
||||
await agent.run()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env -S uv run --script
|
||||
# /// script
|
||||
# requires-python = ">=3.11"
|
||||
# dependencies = ["browser-use", "mistralai"]
|
||||
# ///
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
|
||||
from browser_use import Agent, ChatOpenAI
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def main():
|
||||
agent = Agent(
|
||||
task="""
|
||||
Objective: Navigate to the following UR, what is on page 3?
|
||||
|
||||
URL: https://docs.house.gov/meetings/GO/GO00/20220929/115171/HHRG-117-GO00-20220929-SD010.pdf
|
||||
""",
|
||||
llm=ChatOpenAI(model='gpt-4.1-mini'),
|
||||
)
|
||||
result = await agent.run()
|
||||
logger.info(result)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,157 @@
|
||||
"""
|
||||
Goal: Searches for job listings, evaluates relevance based on a CV, and applies
|
||||
|
||||
@dev You need to add OPENAI_API_KEY to your environment variables.
|
||||
Also you have to install PyPDF2 to read pdf files: pip install PyPDF2
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import csv
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
from pydantic import BaseModel
|
||||
from PyPDF2 import PdfReader # type: ignore
|
||||
|
||||
from browser_use import ActionResult, Agent, ChatOpenAI, Tools
|
||||
from browser_use.browser import BrowserProfile, BrowserSession
|
||||
|
||||
required_env_vars = ['AZURE_OPENAI_KEY', 'AZURE_OPENAI_ENDPOINT']
|
||||
for var in required_env_vars:
|
||||
if not os.getenv(var):
|
||||
raise ValueError(f'{var} is not set. Please add it to your environment variables.')
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
# full screen mode
|
||||
tools = Tools()
|
||||
|
||||
# NOTE: This is the path to your cv file
|
||||
# create a dummy cv
|
||||
CV = Path.cwd() / 'dummy_cv.pdf'
|
||||
with open(CV, 'w') as f:
|
||||
f.write('Hi I am a machine learning engineer with 3 years of experience in the field')
|
||||
|
||||
logger.info(f'Using dummy cv at {CV}')
|
||||
|
||||
|
||||
class Job(BaseModel):
|
||||
title: str
|
||||
link: str
|
||||
company: str
|
||||
fit_score: float
|
||||
location: str | None = None
|
||||
salary: str | None = None
|
||||
|
||||
|
||||
@tools.action('Save jobs to file - with a score how well it fits to my profile', param_model=Job)
|
||||
def save_jobs(job: Job):
|
||||
with open('jobs.csv', 'a', newline='') as f:
|
||||
writer = csv.writer(f)
|
||||
writer.writerow([job.title, job.company, job.link, job.salary, job.location])
|
||||
|
||||
return 'Saved job to file'
|
||||
|
||||
|
||||
@tools.action('Read jobs from file')
|
||||
def read_jobs():
|
||||
with open('jobs.csv') as f:
|
||||
return f.read()
|
||||
|
||||
|
||||
@tools.action('Read my cv for context to fill forms')
|
||||
def read_cv():
|
||||
pdf = PdfReader(CV)
|
||||
text = ''
|
||||
for page in pdf.pages:
|
||||
text += page.extract_text() or ''
|
||||
logger.info(f'Read cv with {len(text)} characters')
|
||||
return ActionResult(extracted_content=text, include_in_memory=True)
|
||||
|
||||
|
||||
@tools.action(
|
||||
'Upload cv to element - call this function to upload if element is not found, try with different index of the same upload element',
|
||||
)
|
||||
async def upload_cv(index: int, browser_session: BrowserSession):
|
||||
path = str(CV.absolute())
|
||||
|
||||
# Get the element by index
|
||||
dom_element = await browser_session.get_element_by_index(index)
|
||||
|
||||
if dom_element is None:
|
||||
logger.info(f'No element found at index {index}')
|
||||
return ActionResult(error=f'No element found at index {index}')
|
||||
|
||||
# Check if it's a file input element
|
||||
if not browser_session.is_file_input(dom_element):
|
||||
logger.info(f'Element at index {index} is not a file upload element')
|
||||
return ActionResult(error=f'Element at index {index} is not a file upload element')
|
||||
|
||||
try:
|
||||
# Dispatch upload file event with the file input element
|
||||
from browser_use.browser.events import UploadFileEvent
|
||||
|
||||
event = browser_session.event_bus.dispatch(UploadFileEvent(node=dom_element, file_path=path))
|
||||
await event
|
||||
await event.event_result(raise_if_any=True, raise_if_none=False)
|
||||
msg = f'Successfully uploaded file "{path}" to index {index}'
|
||||
logger.info(msg)
|
||||
return ActionResult(extracted_content=msg)
|
||||
except Exception as e:
|
||||
logger.debug(f'Error in upload: {str(e)}')
|
||||
return ActionResult(error=f'Failed to upload file to index {index}')
|
||||
|
||||
|
||||
browser_session = BrowserSession(
|
||||
browser_profile=BrowserProfile(
|
||||
executable_path='/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
|
||||
disable_security=True,
|
||||
user_data_dir='~/.config/browseruse/profiles/default',
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
async def main():
|
||||
# ground_task = (
|
||||
# 'You are a professional job finder. '
|
||||
# '1. Read my cv with read_cv'
|
||||
# '2. Read the saved jobs file '
|
||||
# '3. start applying to the first link of Amazon '
|
||||
# 'You can navigate through pages e.g. by scrolling '
|
||||
# 'Make sure to be on the english version of the page'
|
||||
# )
|
||||
ground_task = (
|
||||
'You are a professional job finder. '
|
||||
'1. Read my cv with read_cv'
|
||||
'find ml internships in and save them to a file'
|
||||
'search at company:'
|
||||
)
|
||||
tasks = [
|
||||
ground_task + '\n' + 'Google',
|
||||
# ground_task + '\n' + 'Amazon',
|
||||
# ground_task + '\n' + 'Apple',
|
||||
# ground_task + '\n' + 'Microsoft',
|
||||
# ground_task
|
||||
# + '\n'
|
||||
# + 'go to https://nvidia.wd5.myworkdayjobs.com/en-US/NVIDIAExternalCareerSite/job/Taiwan%2C-Remote/Fulfillment-Analyst---New-College-Graduate-2025_JR1988949/apply/autofillWithResume?workerSubType=0c40f6bd1d8f10adf6dae42e46d44a17&workerSubType=ab40a98049581037a3ada55b087049b7 NVIDIA',
|
||||
# ground_task + '\n' + 'Meta',
|
||||
]
|
||||
model = ChatOpenAI(model='gpt-4.1-mini')
|
||||
|
||||
agents = []
|
||||
for task in tasks:
|
||||
agent = Agent(task=task, llm=model, tools=tools, browser_session=browser_session)
|
||||
agents.append(agent)
|
||||
|
||||
await asyncio.gather(*[agent.run() for agent in agents])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,89 @@
|
||||
"""
|
||||
Show how to use custom outputs.
|
||||
|
||||
@dev You need to add OPENAI_API_KEY to your environment variables.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
import httpx
|
||||
from pydantic import BaseModel
|
||||
|
||||
from browser_use import Agent, ChatOpenAI, Tools
|
||||
from browser_use.agent.views import ActionResult
|
||||
|
||||
|
||||
class Profile(BaseModel):
|
||||
platform: str
|
||||
profile_url: str
|
||||
|
||||
|
||||
class Profiles(BaseModel):
|
||||
profiles: list[Profile]
|
||||
|
||||
|
||||
tools = Tools(exclude_actions=['search_google'], output_model=Profiles)
|
||||
BEARER_TOKEN = os.getenv('BEARER_TOKEN')
|
||||
|
||||
if not BEARER_TOKEN:
|
||||
# use the api key for ask tessa
|
||||
# you can also use other apis like exa, xAI, perplexity, etc.
|
||||
raise ValueError('BEARER_TOKEN is not set - go to https://www.heytessa.ai/ and create an api key')
|
||||
|
||||
|
||||
@tools.registry.action('Search the web for a specific query')
|
||||
async def search_web(query: str):
|
||||
keys_to_use = ['url', 'title', 'content', 'author', 'score']
|
||||
headers = {'Authorization': f'Bearer {BEARER_TOKEN}'}
|
||||
async with httpx.AsyncClient() as client:
|
||||
response = await client.post(
|
||||
'https://asktessa.ai/api/search',
|
||||
headers=headers,
|
||||
json={'query': query},
|
||||
)
|
||||
|
||||
final_results = [
|
||||
{key: source[key] for key in keys_to_use if key in source}
|
||||
for source in await response.json()['sources']
|
||||
if source['score'] >= 0.2
|
||||
]
|
||||
# print(json.dumps(final_results, indent=4))
|
||||
result_text = json.dumps(final_results, indent=4)
|
||||
print(result_text)
|
||||
return ActionResult(extracted_content=result_text, include_in_memory=True)
|
||||
|
||||
|
||||
async def main():
|
||||
task = (
|
||||
'Go to this tiktok video url, open it and extract the @username from the resulting url. Then do a websearch for this username to find all his social media profiles. Return me the links to the social media profiles with the platform name.'
|
||||
' https://www.tiktokv.com/share/video/7470981717659110678/ '
|
||||
)
|
||||
model = ChatOpenAI(model='gpt-4.1-mini')
|
||||
agent = Agent(task=task, llm=model, tools=tools)
|
||||
|
||||
history = await agent.run()
|
||||
|
||||
result = history.final_result()
|
||||
if result:
|
||||
parsed: Profiles = Profiles.model_validate_json(result)
|
||||
|
||||
for profile in parsed.profiles:
|
||||
print('\n--------------------------------')
|
||||
print(f'Platform: {profile.platform}')
|
||||
print(f'Profile URL: {profile.profile_url}')
|
||||
|
||||
else:
|
||||
print('No result')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,120 @@
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
from browser_use import Agent, ChatOpenAI
|
||||
|
||||
task = """
|
||||
### Prompt for Shopping Agent – Migros Online Grocery Order
|
||||
|
||||
**Objective:**
|
||||
Visit [Migros Online](https://www.migros.ch/en), search for the required grocery items, add them to the cart, select an appropriate delivery window, and complete the checkout process using TWINT.
|
||||
|
||||
**Important:**
|
||||
- Make sure that you don't buy more than it's needed for each article.
|
||||
- After your search, if you click the "+" button, it adds the item to the basket.
|
||||
- if you open the basket sidewindow menu, you can close it by clicking the X button on the top right. This will help you navigate easier.
|
||||
---
|
||||
|
||||
### Step 1: Navigate to the Website
|
||||
- Open [Migros Online](https://www.migros.ch/en).
|
||||
- You should be logged in as Nikolaos Kaliorakis
|
||||
|
||||
---
|
||||
|
||||
### Step 2: Add Items to the Basket
|
||||
|
||||
#### Shopping List:
|
||||
|
||||
**Meat & Dairy:**
|
||||
- Beef Minced meat (1 kg)
|
||||
- Gruyère cheese (grated preferably)
|
||||
- 2 liters full-fat milk
|
||||
- Butter (cheapest available)
|
||||
|
||||
**Vegetables:**
|
||||
- Carrots (1kg pack)
|
||||
- Celery
|
||||
- Leeks (1 piece)
|
||||
- 1 kg potatoes
|
||||
|
||||
At this stage, check the basket on the top right (indicates the price) and check if you bought the right items.
|
||||
|
||||
**Fruits:**
|
||||
- 2 lemons
|
||||
- Oranges (for snacking)
|
||||
|
||||
**Pantry Items:**
|
||||
- Lasagna sheets
|
||||
- Tahini
|
||||
- Tomato paste (below CHF2)
|
||||
- Black pepper refill (not with the mill)
|
||||
- 2x 1L Oatly Barista(oat milk)
|
||||
- 1 pack of eggs (10 egg package)
|
||||
|
||||
#### Ingredients I already have (DO NOT purchase):
|
||||
- Olive oil, garlic, canned tomatoes, dried oregano, bay leaves, salt, chili flakes, flour, nutmeg, cumin.
|
||||
|
||||
---
|
||||
|
||||
### Step 3: Handling Unavailable Items
|
||||
- If an item is **out of stock**, find the best alternative.
|
||||
- Use the following recipe contexts to choose substitutions:
|
||||
- **Pasta Bolognese & Lasagna:** Minced meat, tomato paste, lasagna sheets, milk (for béchamel), Gruyère cheese.
|
||||
- **Hummus:** Tahini, chickpeas, lemon juice, olive oil.
|
||||
- **Chickpea Curry Soup:** Chickpeas, leeks, curry, lemons.
|
||||
- **Crispy Slow-Cooked Pork Belly with Vegetables:** Potatoes, butter.
|
||||
- Example substitutions:
|
||||
- If Gruyère cheese is unavailable, select another semi-hard cheese.
|
||||
- If Tahini is unavailable, a sesame-based alternative may work.
|
||||
|
||||
---
|
||||
|
||||
### Step 4: Adjusting for Minimum Order Requirement
|
||||
- If the total order **is below CHF 99**, add **a liquid soap refill** to reach the minimum. If it;s still you can buy some bread, dark chockolate.
|
||||
- At this step, check if you have bought MORE items than needed. If the price is more then CHF200, you MUST remove items.
|
||||
- If an item is not available, choose an alternative.
|
||||
- if an age verification is needed, remove alcoholic products, we haven't verified yet.
|
||||
|
||||
---
|
||||
|
||||
### Step 5: Select Delivery Window
|
||||
- Choose a **delivery window within the current week**. It's ok to pay up to CHF2 for the window selection.
|
||||
- Preferably select a slot within the workweek.
|
||||
|
||||
---
|
||||
|
||||
### Step 6: Checkout
|
||||
- Proceed to checkout.
|
||||
- Select **TWINT** as the payment method.
|
||||
- Check out.
|
||||
-
|
||||
- if it's needed the username is: nikoskalio.dev@gmail.com
|
||||
- and the password is : TheCircuit.Migros.dev!
|
||||
---
|
||||
|
||||
### Step 7: Confirm Order & Output Summary
|
||||
- Once the order is placed, output a summary including:
|
||||
- **Final list of items purchased** (including any substitutions).
|
||||
- **Total cost**.
|
||||
- **Chosen delivery time**.
|
||||
|
||||
**Important:** Ensure efficiency and accuracy throughout the process."""
|
||||
|
||||
|
||||
agent = Agent(task=task, llm=ChatOpenAI(model='gpt-4.1-mini'))
|
||||
|
||||
|
||||
async def main():
|
||||
await agent.run()
|
||||
input('Press Enter to close the browser...')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user