[Add] browser-use and main.py
This commit is contained in:
parent
08e64bdf45
commit
96914d44ac
221 changed files with 30952 additions and 1 deletions
160
browser-use/examples/use-cases/find_and_apply_to_jobs.py
Normal file
160
browser-use/examples/use-cases/find_and_apply_to_jobs.py
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
"""
|
||||
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 langchain_openai import AzureChatOpenAI
|
||||
from pydantic import BaseModel, SecretStr
|
||||
from PyPDF2 import PdfReader
|
||||
|
||||
from browser_use import ActionResult, Agent, Controller
|
||||
from browser_use.browser.browser import Browser, BrowserConfig
|
||||
from browser_use.browser.context import BrowserContext
|
||||
|
||||
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
|
||||
controller = Controller()
|
||||
|
||||
# NOTE: This is the path to your cv file
|
||||
CV = Path.cwd() / 'cv_04_24.pdf'
|
||||
|
||||
if not CV.exists():
|
||||
raise FileNotFoundError(f'You need to set the path to your cv file in the CV variable. CV file not found at {CV}')
|
||||
|
||||
|
||||
class Job(BaseModel):
|
||||
title: str
|
||||
link: str
|
||||
company: str
|
||||
fit_score: float
|
||||
location: str | None = None
|
||||
salary: str | None = None
|
||||
|
||||
|
||||
@controller.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'
|
||||
|
||||
|
||||
@controller.action('Read jobs from file')
|
||||
def read_jobs():
|
||||
with open('jobs.csv') as f:
|
||||
return f.read()
|
||||
|
||||
|
||||
@controller.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)
|
||||
|
||||
|
||||
@controller.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: BrowserContext):
|
||||
path = str(CV.absolute())
|
||||
dom_el = await browser.get_dom_element_by_index(index)
|
||||
|
||||
if dom_el is None:
|
||||
return ActionResult(error=f'No element found at index {index}')
|
||||
|
||||
file_upload_dom_el = dom_el.get_file_upload_element()
|
||||
|
||||
if file_upload_dom_el is None:
|
||||
logger.info(f'No file upload element found at index {index}')
|
||||
return ActionResult(error=f'No file upload element found at index {index}')
|
||||
|
||||
file_upload_el = await browser.get_locate_element(file_upload_dom_el)
|
||||
|
||||
if file_upload_el is None:
|
||||
logger.info(f'No file upload element found at index {index}')
|
||||
return ActionResult(error=f'No file upload element found at index {index}')
|
||||
|
||||
try:
|
||||
await file_upload_el.set_input_files(path)
|
||||
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 set_input_files: {str(e)}')
|
||||
return ActionResult(error=f'Failed to upload file to index {index}')
|
||||
|
||||
|
||||
browser = Browser(
|
||||
config=BrowserConfig(
|
||||
browser_binary_path='/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
|
||||
disable_security=True,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
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 = AzureChatOpenAI(
|
||||
model='gpt-4o',
|
||||
api_version='2024-10-21',
|
||||
azure_endpoint=os.getenv('AZURE_OPENAI_ENDPOINT', ''),
|
||||
api_key=SecretStr(os.getenv('AZURE_OPENAI_KEY', '')),
|
||||
)
|
||||
|
||||
agents = []
|
||||
for task in tasks:
|
||||
agent = Agent(task=task, llm=model, controller=controller, browser=browser)
|
||||
agents.append(agent)
|
||||
|
||||
await asyncio.gather(*[agent.run() for agent in agents])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
||||
Loading…
Add table
Add a link
Reference in a new issue