mirror of
https://github.com/browser-use/web-ui.git
synced 2026-03-22 11:17:17 +08:00
adapt webui
This commit is contained in:
282
webui.py
282
webui.py
@@ -72,19 +72,18 @@ def resolve_sensitive_env_variables(text):
|
||||
|
||||
async def stop_agent():
|
||||
"""Request the agent to stop and update UI with enhanced feedback"""
|
||||
global _global_agent_state, _global_browser_context, _global_browser, _global_agent
|
||||
global _global_agent
|
||||
|
||||
try:
|
||||
# Request stop
|
||||
_global_agent.stop()
|
||||
|
||||
if _global_agent is not None:
|
||||
# Request stop
|
||||
_global_agent.stop()
|
||||
# Update UI immediately
|
||||
message = "Stop requested - the agent will halt at the next safe point"
|
||||
logger.info(f"🛑 {message}")
|
||||
|
||||
# Return UI updates
|
||||
return (
|
||||
message, # errors_output
|
||||
gr.update(value="Stopping...", interactive=False), # stop_button
|
||||
gr.update(interactive=False), # run_button
|
||||
)
|
||||
@@ -92,7 +91,6 @@ async def stop_agent():
|
||||
error_msg = f"Error during stop: {str(e)}"
|
||||
logger.error(error_msg)
|
||||
return (
|
||||
error_msg,
|
||||
gr.update(value="Stop", interactive=True),
|
||||
gr.update(interactive=True)
|
||||
)
|
||||
@@ -100,7 +98,7 @@ async def stop_agent():
|
||||
|
||||
async def stop_research_agent():
|
||||
"""Request the agent to stop and update UI with enhanced feedback"""
|
||||
global _global_agent_state, _global_browser_context, _global_browser
|
||||
global _global_agent_state
|
||||
|
||||
try:
|
||||
# Request stop
|
||||
@@ -148,11 +146,9 @@ async def run_browser_agent(
|
||||
use_vision,
|
||||
max_actions_per_step,
|
||||
tool_calling_method,
|
||||
chrome_cdp
|
||||
chrome_cdp,
|
||||
max_input_tokens
|
||||
):
|
||||
global _global_agent_state
|
||||
_global_agent_state.clear_stop() # Clear any previous stop requests
|
||||
|
||||
try:
|
||||
# Disable recording if the checkbox is unchecked
|
||||
if not enable_recording:
|
||||
@@ -198,7 +194,8 @@ async def run_browser_agent(
|
||||
use_vision=use_vision,
|
||||
max_actions_per_step=max_actions_per_step,
|
||||
tool_calling_method=tool_calling_method,
|
||||
chrome_cdp=chrome_cdp
|
||||
chrome_cdp=chrome_cdp,
|
||||
max_input_tokens=max_input_tokens
|
||||
)
|
||||
elif agent_type == "custom":
|
||||
final_result, errors, model_actions, model_thoughts, trace_file, history_file = await run_custom_agent(
|
||||
@@ -218,27 +215,30 @@ async def run_browser_agent(
|
||||
use_vision=use_vision,
|
||||
max_actions_per_step=max_actions_per_step,
|
||||
tool_calling_method=tool_calling_method,
|
||||
chrome_cdp=chrome_cdp
|
||||
chrome_cdp=chrome_cdp,
|
||||
max_input_tokens=max_input_tokens
|
||||
)
|
||||
else:
|
||||
raise ValueError(f"Invalid agent type: {agent_type}")
|
||||
|
||||
# Get the list of videos after the agent runs (if recording is enabled)
|
||||
latest_video = None
|
||||
if save_recording_path:
|
||||
new_videos = set(
|
||||
glob.glob(os.path.join(save_recording_path, "*.[mM][pP]4"))
|
||||
+ glob.glob(os.path.join(save_recording_path, "*.[wW][eE][bB][mM]"))
|
||||
)
|
||||
if new_videos - existing_videos:
|
||||
latest_video = list(new_videos - existing_videos)[0] # Get the first new video
|
||||
# latest_video = None
|
||||
# if save_recording_path:
|
||||
# new_videos = set(
|
||||
# glob.glob(os.path.join(save_recording_path, "*.[mM][pP]4"))
|
||||
# + glob.glob(os.path.join(save_recording_path, "*.[wW][eE][bB][mM]"))
|
||||
# )
|
||||
# if new_videos - existing_videos:
|
||||
# latest_video = list(new_videos - existing_videos)[0] # Get the first new video
|
||||
|
||||
gif_path = os.path.join(os.path.dirname(__file__), "agent_history.gif")
|
||||
|
||||
return (
|
||||
final_result,
|
||||
errors,
|
||||
model_actions,
|
||||
model_thoughts,
|
||||
latest_video,
|
||||
gif_path,
|
||||
trace_file,
|
||||
history_file,
|
||||
gr.update(value="Stop", interactive=True), # Re-enable stop button
|
||||
@@ -281,13 +281,11 @@ async def run_org_agent(
|
||||
use_vision,
|
||||
max_actions_per_step,
|
||||
tool_calling_method,
|
||||
chrome_cdp
|
||||
chrome_cdp,
|
||||
max_input_tokens
|
||||
):
|
||||
try:
|
||||
global _global_browser, _global_browser_context, _global_agent_state, _global_agent
|
||||
|
||||
# Clear any previous stop request
|
||||
_global_agent_state.clear_stop()
|
||||
global _global_browser, _global_browser_context, _global_agent
|
||||
|
||||
extra_chromium_args = [f"--window-size={window_w},{window_h}"]
|
||||
cdp_url = chrome_cdp
|
||||
@@ -334,7 +332,9 @@ async def run_org_agent(
|
||||
browser=_global_browser,
|
||||
browser_context=_global_browser_context,
|
||||
max_actions_per_step=max_actions_per_step,
|
||||
tool_calling_method=tool_calling_method
|
||||
tool_calling_method=tool_calling_method,
|
||||
max_input_tokens=max_input_tokens,
|
||||
generate_gif=True
|
||||
)
|
||||
history = await _global_agent.run(max_steps=max_steps)
|
||||
|
||||
@@ -384,13 +384,11 @@ async def run_custom_agent(
|
||||
use_vision,
|
||||
max_actions_per_step,
|
||||
tool_calling_method,
|
||||
chrome_cdp
|
||||
chrome_cdp,
|
||||
max_input_tokens
|
||||
):
|
||||
try:
|
||||
global _global_browser, _global_browser_context, _global_agent_state, _global_agent
|
||||
|
||||
# Clear any previous stop request
|
||||
_global_agent_state.clear_stop()
|
||||
global _global_browser, _global_browser_context, _global_agent
|
||||
|
||||
extra_chromium_args = [f"--window-size={window_w},{window_h}"]
|
||||
cdp_url = chrome_cdp
|
||||
@@ -446,7 +444,9 @@ async def run_custom_agent(
|
||||
system_prompt_class=CustomSystemPrompt,
|
||||
agent_prompt_class=CustomAgentMessagePrompt,
|
||||
max_actions_per_step=max_actions_per_step,
|
||||
tool_calling_method=tool_calling_method
|
||||
tool_calling_method=tool_calling_method,
|
||||
max_input_tokens=max_input_tokens,
|
||||
generate_gif=True
|
||||
)
|
||||
history = await _global_agent.run(max_steps=max_steps)
|
||||
|
||||
@@ -503,9 +503,11 @@ async def run_with_stream(
|
||||
use_vision,
|
||||
max_actions_per_step,
|
||||
tool_calling_method,
|
||||
chrome_cdp
|
||||
chrome_cdp,
|
||||
max_input_tokens
|
||||
):
|
||||
global _global_agent_state
|
||||
global _global_agent
|
||||
|
||||
stream_vw = 80
|
||||
stream_vh = int(80 * window_h // window_w)
|
||||
if not headless:
|
||||
@@ -533,14 +535,14 @@ async def run_with_stream(
|
||||
use_vision=use_vision,
|
||||
max_actions_per_step=max_actions_per_step,
|
||||
tool_calling_method=tool_calling_method,
|
||||
chrome_cdp=chrome_cdp
|
||||
chrome_cdp=chrome_cdp,
|
||||
max_input_tokens=max_input_tokens
|
||||
)
|
||||
# Add HTML content at the start of the result array
|
||||
html_content = f"<h1 style='width:{stream_vw}vw; height:{stream_vh}vh'>Using browser...</h1>"
|
||||
yield [html_content] + list(result)
|
||||
else:
|
||||
try:
|
||||
_global_agent_state.clear_stop()
|
||||
# Run the browser agent in the background
|
||||
agent_task = asyncio.create_task(
|
||||
run_browser_agent(
|
||||
@@ -567,14 +569,15 @@ async def run_with_stream(
|
||||
use_vision=use_vision,
|
||||
max_actions_per_step=max_actions_per_step,
|
||||
tool_calling_method=tool_calling_method,
|
||||
chrome_cdp=chrome_cdp
|
||||
chrome_cdp=chrome_cdp,
|
||||
max_input_tokens=max_input_tokens
|
||||
)
|
||||
)
|
||||
|
||||
# Initialize values for streaming
|
||||
html_content = f"<h1 style='width:{stream_vw}vw; height:{stream_vh}vh'>Using browser...</h1>"
|
||||
final_result = errors = model_actions = model_thoughts = ""
|
||||
latest_videos = trace = history_file = None
|
||||
recording_gif = trace = history_file = None
|
||||
|
||||
# Periodically update the stream while the agent task is running
|
||||
while not agent_task.done():
|
||||
@@ -587,14 +590,14 @@ async def run_with_stream(
|
||||
except Exception as e:
|
||||
html_content = f"<h1 style='width:{stream_vw}vw; height:{stream_vh}vh'>Waiting for browser session...</h1>"
|
||||
|
||||
if _global_agent_state and _global_agent_state.is_stop_requested():
|
||||
if _global_agent and _global_agent.state.stopped:
|
||||
yield [
|
||||
html_content,
|
||||
final_result,
|
||||
errors,
|
||||
model_actions,
|
||||
model_thoughts,
|
||||
latest_videos,
|
||||
recording_gif,
|
||||
trace,
|
||||
history_file,
|
||||
gr.update(value="Stopping...", interactive=False), # stop_button
|
||||
@@ -608,23 +611,23 @@ async def run_with_stream(
|
||||
errors,
|
||||
model_actions,
|
||||
model_thoughts,
|
||||
latest_videos,
|
||||
recording_gif,
|
||||
trace,
|
||||
history_file,
|
||||
gr.update(value="Stop", interactive=True), # Re-enable stop button
|
||||
gr.update(interactive=True) # Re-enable run button
|
||||
gr.update(), # Re-enable stop button
|
||||
gr.update() # Re-enable run button
|
||||
]
|
||||
await asyncio.sleep(0.05)
|
||||
await asyncio.sleep(0.1)
|
||||
|
||||
# Once the agent task completes, get the results
|
||||
try:
|
||||
result = await agent_task
|
||||
final_result, errors, model_actions, model_thoughts, latest_videos, trace, history_file, stop_button, run_button = result
|
||||
final_result, errors, model_actions, model_thoughts, recording_gif, trace, history_file, stop_button, run_button = result
|
||||
except gr.Error:
|
||||
final_result = ""
|
||||
model_actions = ""
|
||||
model_thoughts = ""
|
||||
latest_videos = trace = history_file = None
|
||||
recording_gif = trace = history_file = None
|
||||
|
||||
except Exception as e:
|
||||
errors = f"Agent error: {str(e)}"
|
||||
@@ -635,7 +638,7 @@ async def run_with_stream(
|
||||
errors,
|
||||
model_actions,
|
||||
model_thoughts,
|
||||
latest_videos,
|
||||
recording_gif,
|
||||
trace,
|
||||
history_file,
|
||||
stop_button,
|
||||
@@ -774,6 +777,12 @@ def create_ui(config, theme_name="Ocean"):
|
||||
value=config['use_vision'],
|
||||
info="Enable visual processing capabilities",
|
||||
)
|
||||
max_input_tokens = gr.Number(
|
||||
label="Max Input Tokens",
|
||||
value=128000,
|
||||
precision=0
|
||||
|
||||
)
|
||||
tool_calling_method = gr.Dropdown(
|
||||
label="Tool Calling Method",
|
||||
value=config['tool_calling_method'],
|
||||
@@ -784,7 +793,7 @@ def create_ui(config, theme_name="Ocean"):
|
||||
visible=False
|
||||
)
|
||||
|
||||
with gr.TabItem("🔧 LLM Configuration", id=2):
|
||||
with gr.TabItem("🔧 LLM Settings", id=2):
|
||||
with gr.Group():
|
||||
llm_provider = gr.Dropdown(
|
||||
choices=[provider for provider, model in utils.model_names.items()],
|
||||
@@ -882,14 +891,6 @@ def create_ui(config, theme_name="Ocean"):
|
||||
info="Browser window height",
|
||||
)
|
||||
|
||||
save_recording_path = gr.Textbox(
|
||||
label="Recording Path",
|
||||
placeholder="e.g. ./tmp/record_videos",
|
||||
value=config['save_recording_path'],
|
||||
info="Path to save browser recordings",
|
||||
interactive=True, # Allow editing only if recording is enabled
|
||||
)
|
||||
|
||||
chrome_cdp = gr.Textbox(
|
||||
label="CDP URL",
|
||||
placeholder="http://localhost:9222",
|
||||
@@ -947,6 +948,29 @@ def create_ui(config, theme_name="Ocean"):
|
||||
label="Live Browser View",
|
||||
)
|
||||
|
||||
gr.Markdown("### Results")
|
||||
with gr.Row():
|
||||
with gr.Column():
|
||||
final_result_output = gr.Textbox(
|
||||
label="Final Result", lines=3, show_label=True
|
||||
)
|
||||
with gr.Column():
|
||||
errors_output = gr.Textbox(
|
||||
label="Errors", lines=3, show_label=True
|
||||
)
|
||||
with gr.Row():
|
||||
with gr.Column():
|
||||
model_actions_output = gr.Textbox(
|
||||
label="Model Actions", lines=3, show_label=True, visible=False
|
||||
)
|
||||
with gr.Column():
|
||||
model_thoughts_output = gr.Textbox(
|
||||
label="Model Thoughts", lines=3, show_label=True, visible=False
|
||||
)
|
||||
recording_gif = gr.Image(label="Result GIF", format="gif")
|
||||
trace_file = gr.File(label="Trace File")
|
||||
agent_history_file = gr.File(label="Agent History")
|
||||
|
||||
with gr.TabItem("🧐 Deep Research", id=5):
|
||||
research_task_input = gr.Textbox(label="Research Task", lines=5,
|
||||
value="Compose a report on the use of Reinforcement Learning for training Large Language Models, encompassing its origins, current advancements, and future prospects, substantiated with examples of relevant models and techniques. The report should reflect original insights and analysis, moving beyond mere summarization of existing literature.")
|
||||
@@ -961,82 +985,55 @@ def create_ui(config, theme_name="Ocean"):
|
||||
markdown_output_display = gr.Markdown(label="Research Report")
|
||||
markdown_download = gr.File(label="Download Research Report")
|
||||
|
||||
with gr.TabItem("📊 Results", id=6):
|
||||
with gr.Group():
|
||||
recording_display = gr.Video(label="Latest Recording")
|
||||
|
||||
gr.Markdown("### Results")
|
||||
with gr.Row():
|
||||
with gr.Column():
|
||||
final_result_output = gr.Textbox(
|
||||
label="Final Result", lines=3, show_label=True
|
||||
)
|
||||
with gr.Column():
|
||||
errors_output = gr.Textbox(
|
||||
label="Errors", lines=3, show_label=True
|
||||
)
|
||||
with gr.Row():
|
||||
with gr.Column():
|
||||
model_actions_output = gr.Textbox(
|
||||
label="Model Actions", lines=3, show_label=True
|
||||
)
|
||||
with gr.Column():
|
||||
model_thoughts_output = gr.Textbox(
|
||||
label="Model Thoughts", lines=3, show_label=True
|
||||
)
|
||||
# Bind the stop button click event after errors_output is defined
|
||||
stop_button.click(
|
||||
fn=stop_agent,
|
||||
inputs=[],
|
||||
outputs=[errors_output, stop_button, run_button],
|
||||
)
|
||||
|
||||
trace_file = gr.File(label="Trace File")
|
||||
# Run button click handler
|
||||
run_button.click(
|
||||
fn=run_with_stream,
|
||||
inputs=[
|
||||
agent_type, llm_provider, llm_model_name, llm_num_ctx, llm_temperature, llm_base_url,
|
||||
llm_api_key,
|
||||
use_own_browser, keep_browser_open, headless, disable_security, window_w, window_h,
|
||||
save_recording_path, save_agent_history_path, save_trace_path, # Include the new path
|
||||
enable_recording, task, add_infos, max_steps, use_vision, max_actions_per_step,
|
||||
tool_calling_method, chrome_cdp, max_input_tokens
|
||||
],
|
||||
outputs=[
|
||||
browser_view, # Browser view
|
||||
final_result_output, # Final result
|
||||
errors_output, # Errors
|
||||
model_actions_output, # Model actions
|
||||
model_thoughts_output, # Model thoughts
|
||||
recording_gif, # Latest recording
|
||||
trace_file, # Trace file
|
||||
agent_history_file, # Agent history file
|
||||
stop_button, # Stop button
|
||||
run_button # Run button
|
||||
],
|
||||
)
|
||||
|
||||
agent_history_file = gr.File(label="Agent History")
|
||||
# Run Deep Research
|
||||
research_button.click(
|
||||
fn=run_deep_search,
|
||||
inputs=[research_task_input, max_search_iteration_input, max_query_per_iter_input, llm_provider,
|
||||
llm_model_name, llm_num_ctx, llm_temperature, llm_base_url, llm_api_key, use_vision,
|
||||
use_own_browser, headless, chrome_cdp],
|
||||
outputs=[markdown_output_display, markdown_download, stop_research_button, research_button]
|
||||
)
|
||||
# Bind the stop button click event after errors_output is defined
|
||||
stop_research_button.click(
|
||||
fn=stop_research_agent,
|
||||
inputs=[],
|
||||
outputs=[stop_research_button, research_button],
|
||||
)
|
||||
|
||||
# Bind the stop button click event after errors_output is defined
|
||||
stop_button.click(
|
||||
fn=stop_agent,
|
||||
inputs=[],
|
||||
outputs=[errors_output, stop_button, run_button],
|
||||
)
|
||||
|
||||
# Run button click handler
|
||||
run_button.click(
|
||||
fn=run_with_stream,
|
||||
inputs=[
|
||||
agent_type, llm_provider, llm_model_name, llm_num_ctx, llm_temperature, llm_base_url,
|
||||
llm_api_key,
|
||||
use_own_browser, keep_browser_open, headless, disable_security, window_w, window_h,
|
||||
save_recording_path, save_agent_history_path, save_trace_path, # Include the new path
|
||||
enable_recording, task, add_infos, max_steps, use_vision, max_actions_per_step,
|
||||
tool_calling_method, chrome_cdp
|
||||
],
|
||||
outputs=[
|
||||
browser_view, # Browser view
|
||||
final_result_output, # Final result
|
||||
errors_output, # Errors
|
||||
model_actions_output, # Model actions
|
||||
model_thoughts_output, # Model thoughts
|
||||
recording_display, # Latest recording
|
||||
trace_file, # Trace file
|
||||
agent_history_file, # Agent history file
|
||||
stop_button, # Stop button
|
||||
run_button # Run button
|
||||
],
|
||||
)
|
||||
|
||||
# Run Deep Research
|
||||
research_button.click(
|
||||
fn=run_deep_search,
|
||||
inputs=[research_task_input, max_search_iteration_input, max_query_per_iter_input, llm_provider,
|
||||
llm_model_name, llm_num_ctx, llm_temperature, llm_base_url, llm_api_key, use_vision,
|
||||
use_own_browser, headless, chrome_cdp],
|
||||
outputs=[markdown_output_display, markdown_download, stop_research_button, research_button]
|
||||
)
|
||||
# Bind the stop button click event after errors_output is defined
|
||||
stop_research_button.click(
|
||||
fn=stop_research_agent,
|
||||
inputs=[],
|
||||
outputs=[stop_research_button, research_button],
|
||||
)
|
||||
|
||||
with gr.TabItem("🎥 Recordings", id=7):
|
||||
with gr.TabItem("🎥 Recordings", id=7, visible=True):
|
||||
def list_recordings(save_recording_path):
|
||||
if not os.path.exists(save_recording_path):
|
||||
return []
|
||||
@@ -1071,22 +1068,21 @@ def create_ui(config, theme_name="Ocean"):
|
||||
outputs=recordings_gallery
|
||||
)
|
||||
|
||||
with gr.TabItem("📁 Configuration", id=8):
|
||||
with gr.Group():
|
||||
config_file_input = gr.File(
|
||||
label="Load Config File",
|
||||
file_types=[".pkl"],
|
||||
interactive=True
|
||||
)
|
||||
|
||||
with gr.TabItem("📁 UI Configuration", id=8):
|
||||
config_file_input = gr.File(
|
||||
label="Load Config File",
|
||||
file_types=[".pkl"],
|
||||
interactive=True
|
||||
)
|
||||
with gr.Row():
|
||||
load_config_button = gr.Button("Load Existing Config From File", variant="primary")
|
||||
save_config_button = gr.Button("Save Current Config", variant="primary")
|
||||
|
||||
config_status = gr.Textbox(
|
||||
label="Status",
|
||||
lines=2,
|
||||
interactive=False
|
||||
)
|
||||
config_status = gr.Textbox(
|
||||
label="Status",
|
||||
lines=2,
|
||||
interactive=False
|
||||
)
|
||||
|
||||
load_config_button.click(
|
||||
fn=update_ui_from_config,
|
||||
|
||||
Reference in New Issue
Block a user