Skip to content

Commit 4396977

Browse files
authored
Merge pull request #28 from richard-devbot/main
Update LLM configuration Tab to display list of models
2 parents 0fdb9e8 + 2953661 commit 4396977

File tree

3 files changed

+103
-66
lines changed

3 files changed

+103
-66
lines changed

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ browser-use>=0.1.18
22
langchain-google-genai>=2.0.8
33
pyperclip
44
gradio
5-
langchain-ollama
5+
langchain-ollama
6+

src/utils/utils.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from langchain_google_genai import ChatGoogleGenerativeAI
1313
from langchain_ollama import ChatOllama
1414
from langchain_openai import AzureChatOpenAI, ChatOpenAI
15-
15+
import gradio as gr
1616

1717
def get_llm_model(provider: str, **kwargs):
1818
"""
@@ -106,8 +106,34 @@ def get_llm_model(provider: str, **kwargs):
106106
)
107107
else:
108108
raise ValueError(f"Unsupported provider: {provider}")
109+
110+
# Predefined model names for common providers
111+
model_names = {
112+
"anthropic": ["claude-3-5-sonnet-20240620", "claude-3-opus-20240229"],
113+
"openai": ["gpt-4o", "gpt-4", "gpt-3.5-turbo"],
114+
"deepseek": ["deepseek-chat"],
115+
"gemini": ["gemini-2.0-flash-exp", "gemini-2.0-flash-thinking-exp", "gemini-1.5-flash-latest", "gemini-1.5-flash-8b-latest", "gemini-2.0-flash-thinking-exp-1219" ],
116+
"ollama": ["qwen2.5:7b", "llama2:7b"],
117+
"azure_openai": ["gpt-4o", "gpt-4", "gpt-3.5-turbo"]
118+
}
109119

120+
# Callback to update the model name dropdown based on the selected provider
121+
def update_model_dropdown(llm_provider, api_key=None, base_url=None):
122+
"""
123+
Update the model name dropdown with predefined models for the selected provider.
124+
"""
125+
# Use API keys from .env if not provided
126+
if not api_key:
127+
api_key = os.getenv(f"{llm_provider.upper()}_API_KEY", "")
128+
if not base_url:
129+
base_url = os.getenv(f"{llm_provider.upper()}_BASE_URL", "")
110130

131+
# Use predefined models for the selected provider
132+
if llm_provider in model_names:
133+
return gr.Dropdown(choices=model_names[llm_provider], value=model_names[llm_provider][0], interactive=True)
134+
else:
135+
return gr.Dropdown(choices=[], value="", interactive=True, allow_custom_value=True)
136+
111137
def encode_image(img_path):
112138
if not img_path:
113139
return None

webui.py

Lines changed: 74 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,21 @@
55
# @Project : browser-use-webui
66
# @FileName: webui.py
77

8+
import pdb
9+
810
from dotenv import load_dotenv
911

1012
load_dotenv()
1113
import argparse
1214
import os
1315

1416
import gradio as gr
17+
import argparse
18+
19+
20+
from gradio.themes import Base, Default, Soft, Monochrome, Glass, Origin, Citrus, Ocean
21+
import asyncio
22+
import os, glob
1523
from browser_use.agent.service import Agent
1624
from browser_use.browser.browser import Browser, BrowserConfig
1725
from browser_use.browser.context import (
@@ -26,7 +34,7 @@
2634
from src.browser.custom_context import BrowserContextConfig
2735
from src.controller.custom_controller import CustomController
2836
from src.utils import utils
29-
37+
from src.utils.utils import update_model_dropdown
3038

3139
async def run_browser_agent(
3240
agent_type,
@@ -268,11 +276,6 @@ async def run_custom_agent(
268276
await browser.close()
269277
return final_result, errors, model_actions, model_thoughts
270278

271-
272-
import glob
273-
274-
from gradio.themes import Citrus, Default, Glass, Monochrome, Ocean, Origin, Soft
275-
276279
# Define the theme map globally
277280
theme_map = {
278281
"Default": Default(),
@@ -282,6 +285,7 @@ async def run_custom_agent(
282285
"Origin": Origin(),
283286
"Citrus": Citrus(),
284287
"Ocean": Ocean(),
288+
"Base": Base()
285289
}
286290

287291

@@ -364,39 +368,39 @@ def create_ui(theme_name="Ocean"):
364368
with gr.TabItem("🔧 LLM Configuration", id=2):
365369
with gr.Group():
366370
llm_provider = gr.Dropdown(
367-
[
368-
"anthropic",
369-
"openai",
370-
"gemini",
371-
"azure_openai",
372-
"deepseek",
373-
"ollama",
374-
],
371+
["anthropic", "openai", "deepseek", "gemini", "ollama", "azure_openai"],
375372
label="LLM Provider",
376-
value="openai",
377-
info="Select your preferred language model provider",
373+
value="",
374+
info="Select your preferred language model provider"
378375
)
379-
llm_model_name = gr.Textbox(
376+
llm_model_name = gr.Dropdown(
380377
label="Model Name",
381-
value="gpt-4o",
382-
info="Specify the model to use",
378+
value="",
379+
interactive=True,
380+
allow_custom_value=True, # Allow users to input custom model names
381+
info="Select a model from the dropdown or type a custom model name"
383382
)
384383
llm_temperature = gr.Slider(
385384
minimum=0.0,
386385
maximum=2.0,
387386
value=1.0,
388387
step=0.1,
389388
label="Temperature",
390-
info="Controls randomness in model outputs",
389+
info="Controls randomness in model outputs"
391390
)
392391
with gr.Row():
393392
llm_base_url = gr.Textbox(
394-
label="Base URL", info="API endpoint URL (if required)"
393+
label="Base URL",
394+
value=os.getenv(f"{llm_provider.value.upper()}_BASE_URL ", ""), # Default to .env value
395+
info="API endpoint URL (if required)"
395396
)
396397
llm_api_key = gr.Textbox(
397-
label="API Key", type="password", info="Your API key"
398+
label="API Key",
399+
type="password",
400+
value=os.getenv(f"{llm_provider.value.upper()}_API_KEY", ""), # Default to .env value
401+
info="Your API key (leave blank to use .env)"
398402
)
399-
403+
400404
with gr.TabItem("🌐 Browser Settings", id=3):
401405
with gr.Group():
402406
with gr.Row():
@@ -454,7 +458,7 @@ def create_ui(theme_name="Ocean"):
454458
run_button = gr.Button("▶️ Run Agent", variant="primary", scale=2)
455459
stop_button = gr.Button("⏹️ Stop", variant="stop", scale=1)
456460

457-
with gr.TabItem("🎬 Recordings", id=5):
461+
with gr.TabItem("📊 Results", id=5):
458462
recording_display = gr.Video(label="Latest Recording")
459463

460464
with gr.Group():
@@ -477,61 +481,67 @@ def create_ui(theme_name="Ocean"):
477481
model_thoughts_output = gr.Textbox(
478482
label="Model Thoughts", lines=3, show_label=True
479483
)
484+
485+
with gr.TabItem("🎥 Recordings", id=6):
486+
def list_recordings(save_recording_path):
487+
if not os.path.exists(save_recording_path):
488+
return []
489+
490+
# Get all video files
491+
recordings = glob.glob(os.path.join(save_recording_path, "*.[mM][pP]4")) + glob.glob(os.path.join(save_recording_path, "*.[wW][eE][bB][mM]"))
492+
493+
# Sort recordings by creation time (oldest first)
494+
recordings.sort(key=os.path.getctime)
495+
496+
# Add numbering to the recordings
497+
numbered_recordings = []
498+
for idx, recording in enumerate(recordings, start=1):
499+
filename = os.path.basename(recording)
500+
numbered_recordings.append((recording, f"{idx}. {filename}"))
501+
502+
return numbered_recordings
503+
504+
recordings_gallery = gr.Gallery(
505+
label="Recordings",
506+
value=list_recordings("./tmp/record_videos"),
507+
columns=3,
508+
height="auto",
509+
object_fit="contain"
510+
)
511+
512+
refresh_button = gr.Button("🔄 Refresh Recordings", variant="secondary")
513+
refresh_button.click(
514+
fn=list_recordings,
515+
inputs=save_recording_path,
516+
outputs=recordings_gallery
517+
)
518+
519+
# Attach the callback to the LLM provider dropdown
520+
llm_provider.change(
521+
lambda provider, api_key, base_url: update_model_dropdown(provider, api_key, base_url),
522+
inputs=[llm_provider, llm_api_key, llm_base_url],
523+
outputs=llm_model_name
524+
)
480525

481526
# Run button click handler
482527
run_button.click(
483528
fn=run_browser_agent,
484-
inputs=[
485-
agent_type,
486-
llm_provider,
487-
llm_model_name,
488-
llm_temperature,
489-
llm_base_url,
490-
llm_api_key,
491-
use_own_browser,
492-
headless,
493-
disable_security,
494-
window_w,
495-
window_h,
496-
save_recording_path,
497-
task,
498-
add_infos,
499-
max_steps,
500-
use_vision,
501-
max_actions_per_step,
502-
tool_call_in_content
503-
],
504-
outputs=[
505-
final_result_output,
506-
errors_output,
507-
model_actions_output,
508-
model_thoughts_output,
509-
recording_display,
510-
],
529+
inputs=[agent_type, llm_provider, llm_model_name, llm_temperature, llm_base_url, llm_api_key, use_own_browser, headless, disable_security, window_w, window_h, save_recording_path, task, add_infos, max_steps, use_vision, max_actions_per_step, tool_call_in_content],
530+
outputs=[final_result_output, errors_output, model_actions_output, model_thoughts_output, recording_display,],
511531
)
512532

513533
return demo
514534

515-
516535
def main():
517536
parser = argparse.ArgumentParser(description="Gradio UI for Browser Agent")
518-
parser.add_argument(
519-
"--ip", type=str, default="127.0.0.1", help="IP address to bind to"
520-
)
537+
parser.add_argument("--ip", type=str, default="127.0.0.1", help="IP address to bind to")
521538
parser.add_argument("--port", type=int, default=7788, help="Port to listen on")
522-
parser.add_argument(
523-
"--theme",
524-
type=str,
525-
default="Ocean",
526-
choices=theme_map.keys(),
527-
help="Theme to use for the UI",
528-
)
539+
parser.add_argument("--theme", type=str, default="Ocean", choices=theme_map.keys(), help="Theme to use for the UI")
529540
parser.add_argument("--dark-mode", action="store_true", help="Enable dark mode")
530541
args = parser.parse_args()
531542

532543
demo = create_ui(theme_name=args.theme)
533544
demo.launch(server_name=args.ip, server_port=args.port)
534545

535-
536-
if __name__ == "__main__":
546+
if __name__ == '__main__':
537547
main()

0 commit comments

Comments
 (0)