Skip to content

browser tools #907

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
from langchain.agents import create_openai_functions_agent, AgentExecutor
from langchain import hub
from langchain_openai import ChatOpenAI
from composio_langchain import ComposioToolSet
llm = ChatOpenAI()
import asyncio
import logging

prompt = hub.pull("hwchase17/openai-functions-agent")

composio_toolset = ComposioToolSet(api_key="fcau1ynif45lumo8txt5o", connected_account_ids={})
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Issue: API key should not be hardcoded in the source code. Consider using environment variables or a secure configuration management system.

# Instead of:
composio_toolset = ComposioToolSet(api_key="fcau1ynif45lumo8txt5o")

# Use:
import os
from dotenv import load_dotenv

load_dotenv()
composio_toolset = ComposioToolSet(api_key=os.getenv('COMPOSIO_API_KEY'))

tools = composio_toolset.get_tools(actions=['BROWSER_TOOL_GET_PAGE_DETAILS','BROWSER_TOOL_GOTO_PAGE', 'BROWSER_TOOL_SCROLL_PAGE', 'BROWSER_TOOL_REFRESH_PAGE', 'GMAIL_SEND_EMAIL'])

agent = create_openai_functions_agent(llm, tools, prompt)
agent_executor = AgentExecutor(
agent=agent,
tools=tools,
verbose=True,
handle_parsing_errors=True
)
def get_reviews(url):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Input Validation: The URL input is not validated before processing. Add URL validation to prevent processing invalid URLs:

from urllib.parse import urlparse

def validate_url(url: str) -> bool:
    """Validate if the given URL is properly formatted."""
    try:
        result = urlparse(url)
        return all([result.scheme, result.netloc])
    except Exception:
        return False

def get_reviews(url: str) -> None:
    if not validate_url(url):
        raise ValueError(f"Invalid URL format: {url}")
    # Continue with processing...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing Documentation: The code lacks proper documentation. Add docstrings to explain the purpose and usage of functions:

def get_reviews(url: str) -> None:
    """
    Scrape and analyze reviews from a given URL.
    
    Args:
        url (str): The target URL to scrape reviews from
        
    Raises:
        ValueError: If URL is invalid
        ConnectionError: If network connection fails
        TimeoutError: If request times out
        
    Example:
        >>> get_reviews("https://example.com/product")
    """

tasks = [
f"Go to {url}",
"Wait for the page to fully load and verify the content is accessible",
"scroll down the page",
"Locate the customer reviews",
"Keep repeating the process till you find all the reviews",
"Analyze all customer reviews on the page and provide a concise summary that includes: \
\n- Overall rating and total number of reviews \
\n- Key positive points mentioned frequently \
\n- Common complaints or issues \
\n- Notable specific feedback about product features \
\nKeep the summary focused on helping potential buyers make an informed decision."
"Format the summary and send the summary using gmail send mail <add email here>"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace the placeholder <add email here> with an actual email address or a variable that holds the email address.

Suggested change
"Format the summary and send the summary using gmail send mail <add email here>"
"Format the summary and send the summary using gmail send mail [email protected]"

]

for task in tasks:
try:
result = agent_executor.invoke({"input": task})
print(f"Task: {task}")
print(f"Result: {result}\n")
except Exception as e:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error Handling: The current error handling is too broad and only prints errors. Consider implementing proper logging and specific error handling:

import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

try:
    result = agent_executor.invoke({"input": task})
except ConnectionError as e:
    logger.error(f"Network error during task '{task}': {str(e)}")
except TimeoutError as e:
    logger.error(f"Timeout during task '{task}': {str(e)}")
except Exception as e:
    logger.error(f"Unexpected error during task '{task}': {str(e)}")
    raise

print(f"Error executing task '{task}': {str(e)}\n")


url = input("Enter the URL: ")
get_reviews(url)



Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
from langchain.agents import create_openai_functions_agent, AgentExecutor
from langchain import hub
from langchain_openai import ChatOpenAI
from composio_langchain import ComposioToolSet
from composio import Action
from openai import OpenAI

llm = ChatOpenAI()
from composio.client.collections import TriggerEventData
import asyncio
import logging

prompt = hub.pull("hwchase17/openai-functions-agent")

composio_toolset = ComposioToolSet(api_key="fcau1ynif45lumo8txt5o", connected_account_ids={})
tools = composio_toolset.get_tools(actions=['BROWSER_TOOL_GET_PAGE_DETAILS','BROWSER_TOOL_GOTO_PAGE', 'BROWSER_TOOL_SCROLL_PAGE', 'BROWSER_TOOL_REFRESH_PAGE', 'SLACK_SENDS_A_MESSAGE_TO_A_SLACK_CHANNEL'])
openai_client = OpenAI()

agent = create_openai_functions_agent(llm, tools, prompt)
agent_executor = AgentExecutor(
agent=agent,
tools=tools,
verbose=True,
handle_parsing_errors=True
)

listener = composio_toolset.create_trigger_listener()
@listener.callback(filters={"trigger_name": "slack_receive_message"})
def handle_slack_message(event: TriggerEventData):
payload = event.payload
message = payload.get("text", "")
channel_id = payload.get("channel", "")
if channel_id != "<add channel id here>":
return
print(message)
print(channel_id)
composio_toolset.execute_action(
action=Action.SLACK_SENDS_A_MESSAGE_TO_A_SLACK_CHANNEL,
params={
"channel": "<add channel id here>",
"text": f"Collating responses using the composio browser tool......."
},
)
print("Message sent to Slack channel. Waiting for user response...")
get_reviews(message)


def get_reviews(url):
tasks = [
f"Go to {url}",
"Wait for the page to fully load and verify the content is accessible",
"scroll down the page",
"Locate the customer reviews",
"Keep repeating the process till you find all the reviews",
"Analyze all customer reviews on the page and provide a concise summary that includes: \
\n- Overall rating and total number of reviews \
\n- Key positive points mentioned frequently \
\n- Common complaints or issues \
\n- Notable specific feedback about product features \
\nKeep the summary focused on helping potential buyers make an informed decision."
"Format the summary and send the summary to the slack channel with id <add channel id here>"
]

for task in tasks:
try:
result = agent_executor.invoke({"input": task})
print(f"Task: {task}")
print(f"Result: {result}\n")
except Exception as e:
print(f"Error executing task '{task}': {str(e)}\n")


async def main():
logging.info("AI Agent started. Listening for Slack messages and Gmail emails...")
# Run the agent and listener concurrently
await asyncio.gather(asyncio.to_thread(listener.listen))
if __name__ == "__main__":
try:
asyncio.run(main())
except KeyboardInterrupt:
logging.info("Program terminated by user.")
Loading