[Add] browser-use and main.py
This commit is contained in:
parent
08e64bdf45
commit
96914d44ac
221 changed files with 30952 additions and 1 deletions
|
|
@ -0,0 +1,236 @@
|
|||
"""
|
||||
Description: These Python modules are designed to capture detailed
|
||||
browser usage datafor analysis, with both server and client
|
||||
components working together to record and store the information.
|
||||
|
||||
Author: Carlos A. Planchón
|
||||
https://github.com/carlosplanchon/
|
||||
|
||||
Adapt this code to your needs.
|
||||
|
||||
Feedback is appreciated!
|
||||
"""
|
||||
|
||||
#####################
|
||||
# #
|
||||
# --- UTILS --- #
|
||||
# #
|
||||
#####################
|
||||
|
||||
import base64
|
||||
|
||||
|
||||
def b64_to_png(b64_string: str, output_file):
|
||||
"""
|
||||
Convert a Base64-encoded string to a PNG file.
|
||||
|
||||
:param b64_string: A string containing Base64-encoded data
|
||||
:param output_file: The path to the output PNG file
|
||||
"""
|
||||
with open(output_file, 'wb') as f:
|
||||
f.write(base64.b64decode(b64_string))
|
||||
|
||||
|
||||
###################################################################
|
||||
# #
|
||||
# --- FASTAPI API TO RECORD AND SAVE Browser-Use ACTIVITY --- #
|
||||
# #
|
||||
###################################################################
|
||||
|
||||
# Save to api.py and run with `python api.py`
|
||||
|
||||
# ! pip install uvicorn
|
||||
# ! pip install fastapi
|
||||
# ! pip install prettyprinter
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
import prettyprinter
|
||||
from fastapi import FastAPI, Request
|
||||
|
||||
prettyprinter.install_extras()
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
@app.post('/post_agent_history_step')
|
||||
async def post_agent_history_step(request: Request):
|
||||
data = await request.json()
|
||||
prettyprinter.cpprint(data)
|
||||
|
||||
# Ensure the "recordings" folder exists using pathlib
|
||||
recordings_folder = Path('recordings')
|
||||
recordings_folder.mkdir(exist_ok=True)
|
||||
|
||||
# Determine the next file number by examining existing .json files
|
||||
existing_numbers = []
|
||||
for item in recordings_folder.iterdir():
|
||||
if item.is_file() and item.suffix == '.json':
|
||||
try:
|
||||
file_num = int(item.stem)
|
||||
existing_numbers.append(file_num)
|
||||
except ValueError:
|
||||
# In case the file name isn't just a number
|
||||
...
|
||||
|
||||
if existing_numbers:
|
||||
next_number = max(existing_numbers) + 1
|
||||
else:
|
||||
next_number = 1
|
||||
|
||||
# Construct the file path
|
||||
file_path = recordings_folder / f'{next_number}.json'
|
||||
|
||||
# Save the JSON data to the file
|
||||
with file_path.open('w') as f:
|
||||
json.dump(data, f, indent=2)
|
||||
|
||||
return {'status': 'ok', 'message': f'Saved to {file_path}'}
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import uvicorn
|
||||
|
||||
uvicorn.run(app, host='0.0.0.0', port=9000)
|
||||
|
||||
|
||||
##############################################################
|
||||
# #
|
||||
# --- CLIENT TO RECORD AND SAVE Browser-Use ACTIVITY --- #
|
||||
# #
|
||||
##############################################################
|
||||
|
||||
"""
|
||||
pyobjtojson:
|
||||
|
||||
A Python library to safely and recursively serialize any Python object
|
||||
(including Pydantic models and dataclasses) into JSON-ready structures,
|
||||
gracefully handling circular references.
|
||||
"""
|
||||
|
||||
# ! pip install -U pyobjtojson
|
||||
# ! pip install -U prettyprinter
|
||||
|
||||
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()
|
||||
|
||||
import requests
|
||||
from langchain_openai import ChatOpenAI
|
||||
from pyobjtojson import obj_to_json
|
||||
|
||||
from browser_use import Agent
|
||||
|
||||
# import prettyprinter
|
||||
# prettyprinter.install_extras()
|
||||
|
||||
|
||||
def send_agent_history_step(data):
|
||||
url = 'http://127.0.0.1:9000/post_agent_history_step'
|
||||
response = requests.post(url, json=data)
|
||||
return response.json()
|
||||
|
||||
|
||||
async def record_activity(agent_obj):
|
||||
website_html = None
|
||||
website_screenshot = None
|
||||
urls_json_last_elem = None
|
||||
model_thoughts_last_elem = None
|
||||
model_outputs_json_last_elem = None
|
||||
model_actions_json_last_elem = None
|
||||
extracted_content_json_last_elem = None
|
||||
|
||||
print('--- ON_STEP_START HOOK ---')
|
||||
website_html: str = await agent_obj.browser_context.get_page_html()
|
||||
website_screenshot: str = await agent_obj.browser_context.take_screenshot()
|
||||
|
||||
print('--> History:')
|
||||
if hasattr(agent_obj, 'state'):
|
||||
history = agent_obj.state.history
|
||||
else:
|
||||
history = None
|
||||
|
||||
model_thoughts = obj_to_json(obj=history.model_thoughts(), check_circular=False)
|
||||
|
||||
# print("--- MODEL THOUGHTS ---")
|
||||
if len(model_thoughts) > 0:
|
||||
model_thoughts_last_elem = model_thoughts[-1]
|
||||
# prettyprinter.cpprint(model_thoughts_last_elem)
|
||||
|
||||
# print("--- MODEL OUTPUT ACTION ---")
|
||||
model_outputs = agent_obj.state.history.model_outputs()
|
||||
model_outputs_json = obj_to_json(obj=model_outputs, check_circular=False)
|
||||
|
||||
if len(model_outputs_json) > 0:
|
||||
model_outputs_json_last_elem = model_outputs_json[-1]
|
||||
# prettyprinter.cpprint(model_outputs_json_last_elem)
|
||||
|
||||
# print("--- MODEL INTERACTED ELEM ---")
|
||||
model_actions = agent_obj.state.history.model_actions()
|
||||
model_actions_json = obj_to_json(obj=model_actions, check_circular=False)
|
||||
|
||||
if len(model_actions_json) > 0:
|
||||
model_actions_json_last_elem = model_actions_json[-1]
|
||||
# prettyprinter.cpprint(model_actions_json_last_elem)
|
||||
|
||||
# print("--- EXTRACTED CONTENT ---")
|
||||
extracted_content = agent_obj.state.history.extracted_content()
|
||||
extracted_content_json = obj_to_json(obj=extracted_content, check_circular=False)
|
||||
if len(extracted_content_json) > 0:
|
||||
extracted_content_json_last_elem = extracted_content_json[-1]
|
||||
# prettyprinter.cpprint(extracted_content_json_last_elem)
|
||||
|
||||
# print("--- URLS ---")
|
||||
urls = agent_obj.state.history.urls()
|
||||
# prettyprinter.cpprint(urls)
|
||||
urls_json = obj_to_json(obj=urls, check_circular=False)
|
||||
|
||||
if len(urls_json) > 0:
|
||||
urls_json_last_elem = urls_json[-1]
|
||||
# prettyprinter.cpprint(urls_json_last_elem)
|
||||
|
||||
model_step_summary = {
|
||||
'website_html': website_html,
|
||||
'website_screenshot': website_screenshot,
|
||||
'url': urls_json_last_elem,
|
||||
'model_thoughts': model_thoughts_last_elem,
|
||||
'model_outputs': model_outputs_json_last_elem,
|
||||
'model_actions': model_actions_json_last_elem,
|
||||
'extracted_content': extracted_content_json_last_elem,
|
||||
}
|
||||
|
||||
print('--- MODEL STEP SUMMARY ---')
|
||||
# prettyprinter.cpprint(model_step_summary)
|
||||
|
||||
send_agent_history_step(data=model_step_summary)
|
||||
|
||||
# response = send_agent_history_step(data=history)
|
||||
# print(response)
|
||||
|
||||
# print("--> Website HTML:")
|
||||
# print(website_html[:200])
|
||||
# print("--> Website Screenshot:")
|
||||
# print(website_screenshot[:200])
|
||||
|
||||
|
||||
agent = Agent(
|
||||
task='Compare the price of gpt-4o and DeepSeek-V3',
|
||||
llm=ChatOpenAI(model='gpt-4o'),
|
||||
)
|
||||
|
||||
|
||||
async def run_agent():
|
||||
try:
|
||||
await agent.run(on_step_start=record_activity, max_steps=30)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
|
||||
asyncio.run(run_agent())
|
||||
Loading…
Add table
Add a link
Reference in a new issue