mirror of
https://github.com/browser-use/browser-use
synced 2026-05-06 17:52:15 +02:00
174 lines
6.8 KiB
Python
174 lines
6.8 KiB
Python
"""
|
|
Script that demonstrates how to use the new customizable MemoryConfig with Browser Use, showcasing two different vector store providers:
|
|
the default FAISS (local) and a more scalable option like Qdrant
|
|
You'll need a Qdrant server running locally to run the Qdrant example.
|
|
You can visualize your Qdrant memories at http://localhost:6333/dashboard#/collections
|
|
"""
|
|
|
|
import asyncio
|
|
import os
|
|
|
|
from dotenv import load_dotenv
|
|
from langchain_openai import ChatOpenAI
|
|
|
|
from browser_use import Agent
|
|
from browser_use.agent.memory import MemoryConfig
|
|
|
|
# Load environment variables (e.g., OPENAI_API_KEY)
|
|
load_dotenv()
|
|
|
|
# Ensure OpenAI API key is set
|
|
if not os.getenv('OPENAI_API_KEY'):
|
|
print('Error: OPENAI_API_KEY environment variable not set.')
|
|
exit()
|
|
|
|
|
|
async def run_agent_with_memory_config(
|
|
task: str,
|
|
llm: ChatOpenAI,
|
|
memory_config: MemoryConfig | None,
|
|
agent_name: str,
|
|
max_steps: int = 5, # Keep low for demo purposes
|
|
):
|
|
print(f'\n--- Running Agent: {agent_name} ---')
|
|
if memory_config:
|
|
print(f'Memory Provider: {memory_config.vector_store_provider}')
|
|
if memory_config.vector_store_provider != 'memory': # 'memory' provider doesn't use path or collection
|
|
print(f'Vector Store Collection: {memory_config.vector_store_config_dict["config"].get("collection_name", "N/A")}')
|
|
if memory_config.vector_store_provider in ['faiss', 'chroma']:
|
|
print(f'Vector Store Path: {memory_config.vector_store_config_dict["config"].get("path", "N/A")}')
|
|
|
|
agent = Agent(
|
|
task=task,
|
|
llm=llm,
|
|
enable_memory=True if memory_config else False, # Enable memory if config is provided
|
|
memory_config=memory_config, # Pass the specific memory config
|
|
# Set a lower planner_interval for more frequent planning in short demos
|
|
# and potentially see memory summarization happen sooner if memory_interval is also low.
|
|
planner_interval=2,
|
|
)
|
|
|
|
print(f'Starting task: {task}')
|
|
history = await agent.run(max_steps=max_steps)
|
|
|
|
print(f'\n--- {agent_name} Finished ---')
|
|
print(f'Task completed: {history.is_done()}')
|
|
print(f'Final result/summary: {history.final_result()}')
|
|
print(f'Number of steps taken: {len(history.history)}')
|
|
|
|
# Let's refine how to access summaries. The summary is added as a 'memory' type message.
|
|
|
|
summaries_created = []
|
|
for step_messages in agent.message_manager.state.history.get_messages():
|
|
if isinstance(step_messages, list):
|
|
for msg in step_messages:
|
|
if (
|
|
hasattr(msg, 'additional_kwargs')
|
|
and msg.additional_kwargs.get('metadata', {}).get('message_type') == 'memory'
|
|
):
|
|
summaries_created.append(msg.content)
|
|
elif (
|
|
hasattr(step_messages, 'additional_kwargs')
|
|
and step_messages.additional_kwargs.get('metadata', {}).get('message_type') == 'memory'
|
|
): # if it's a list of messages
|
|
summaries_created.append(step_messages.content)
|
|
|
|
if summaries_created:
|
|
print('\nProcedural Summaries Created during run:')
|
|
for i, summary in enumerate(summaries_created):
|
|
print(f' Summary {i + 1}: {summary[:150]}...') # Print first 150 chars
|
|
else:
|
|
# Check if messages were consolidated by looking at the agent's final message history
|
|
final_messages = agent.message_manager.get_messages()
|
|
summaries_in_final_context = [
|
|
m.content
|
|
for m in final_messages
|
|
if hasattr(m, 'additional_kwargs') and m.additional_kwargs.get('message_type') == 'memory'
|
|
]
|
|
if summaries_in_final_context:
|
|
print('\nProcedural Summaries in final context:')
|
|
for i, summary in enumerate(summaries_in_final_context):
|
|
print(f' Summary {i + 1}: {summary[:150]}...')
|
|
else:
|
|
print(
|
|
'No explicit procedural summaries found in final context (task might have been too short or memory interval not reached).'
|
|
)
|
|
|
|
print('---------------------------\n')
|
|
return history
|
|
|
|
|
|
async def main():
|
|
"""Main function to run the agent with different memory configurations."""
|
|
common_task = 'Find the current CEO of OpenAI and then search for news about their latest projects. Summarize your findings.'
|
|
shared_agent_id = 'persistent_browser_agent_001' # Use the same ID to test persistence with Qdrant
|
|
|
|
# Initialize the LLM (e.g., OpenAI's GPT-4o)
|
|
# Ensure your OPENAI_API_KEY is set in your environment or .env file
|
|
llm = ChatOpenAI(model='gpt-4o', temperature=0)
|
|
|
|
# --- Scenario 1: Default FAISS Memory ---
|
|
# MemoryConfig will use its defaults: FAISS, HuggingFace embedder if llm_instance not directly used by Mem0 for defaults
|
|
# Since we pass llm_instance, it will likely pick OpenAI embedder
|
|
faiss_memory_config = MemoryConfig(
|
|
llm_instance=llm, # Crucial for Mem0 to use this LLM for summarization
|
|
agent_id=shared_agent_id,
|
|
memory_interval=3, # Summarize more frequently for demo
|
|
# vector_store_provider is 'faiss' by default
|
|
# embedder_provider will default based on llm_instance
|
|
)
|
|
await run_agent_with_memory_config(common_task, llm, faiss_memory_config, 'Agent with FAISS Memory')
|
|
|
|
print('\n === PAUSE: Check FAISS data in /tmp/mem0... (if created) ===\n')
|
|
# You might need to adjust the path based on your embedder_dims, e.g., /tmp/mem0_1536_faiss
|
|
input('Press Enter to continue to Qdrant example...')
|
|
|
|
# --- Scenario 2: Qdrant Memory ---
|
|
# Ensure Qdrant server is running (e.g., `docker run -p 6333:6333 qdrant/qdrant`)
|
|
print('Attempting to use Qdrant. Make sure Qdrant server is running on localhost:6333.')
|
|
try:
|
|
qdrant_memory_config = MemoryConfig(
|
|
llm_instance=llm, # Pass the LLM for Mem0's internal use
|
|
agent_id=shared_agent_id, # Same agent_id for potential persistence
|
|
memory_interval=3, # Summarize more frequently
|
|
embedder_provider='openai', # Explicitly set for consistency
|
|
embedder_model='text-embedding-3-small',
|
|
embedder_dims=1536,
|
|
vector_store_provider='qdrant',
|
|
vector_store_collection_name='browser_use_qdrant_demo', # Custom collection name
|
|
vector_store_config_override={
|
|
'host': 'localhost',
|
|
'port': 6333,
|
|
# For Qdrant Cloud, you'd add "api_key": "YOUR_QDRANT_CLOUD_KEY", "url": "YOUR_QDRANT_CLOUD_URL"
|
|
# "path": ":memory:" # For in-memory Qdrant, useful for quick tests without persistence
|
|
},
|
|
)
|
|
await run_agent_with_memory_config(
|
|
common_task, # Could be a follow-up task to test memory persistence
|
|
llm,
|
|
qdrant_memory_config,
|
|
'Agent with Qdrant Memory',
|
|
)
|
|
except ImportError as e:
|
|
print(f'Could not run Qdrant example due to missing dependency: {e}')
|
|
print('Please install qdrant-client: pip install qdrant-client')
|
|
except Exception as e:
|
|
print(f'Error running Qdrant agent: {e}')
|
|
print('Ensure Qdrant server is running and accessible.')
|
|
|
|
# --- Scenario 3: No Memory (for comparison) ---
|
|
# await run_agent_with_memory_config(
|
|
# common_task,
|
|
# llm,
|
|
# None, # Pass None for memory_config to disable memory
|
|
# "Agent with NO Memory"
|
|
# )
|
|
|
|
|
|
if __name__ == '__main__':
|
|
import sys
|
|
|
|
if sys.platform.startswith('win'):
|
|
asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
|
|
asyncio.run(main())
|