crewAI icon indicating copy to clipboard operation
crewAI copied to clipboard

Weird behavior on how the parameters are passed or processed by an Agent that uses a custom Tool

Open ing-norante opened this issue 1 year ago • 3 comments

I have defined a custom tool that fetches a local API as this search_api_tool.py:

import json
from langchain.tools import tool
from dotenv import load_dotenv
import requests
import os

load_dotenv()  # This loads the environment variables from .env

@tool
def search_api_tool(input_string: str) -> dict:
    """
    Tool to fetch conversation counts from the Search API.
    Expects 'input_string' as a JSON string containing 'start_date', 'end_date', and 'symbol'.
    """
    try:
        params = json.loads(input_string)
    except json.JSONDecodeError:
        return {"error": "Invalid input format. Expected JSON string."}


    # Check for either 'keyword' or 'symbol' and use whichever is available
    symbol = params.get("symbol") or params.get("keyword")
    start_date = params.get("start_date")
    end_date = params.get("end_date")

    if not all([symbol, start_date, end_date]):
        return {"error": "Missing required parameters."}

    url = f"http://localhost:3000/api/messages?start_date={start_date}&end_date={end_date}&symbol={symbol}"
    headers = {
        'Authorization': f'Bearer {os.getenv("API_KEY")}'
    }

    try:
        response = requests.get(url, headers=headers)
        response.raise_for_status()
        return response.json()
    except requests.RequestException as e:
        return {"error": str(e)}

In my main.py I've defined my custom tool for the agent as:

# Create a custom tool for the agent
custom_tool = Tool(
    name="SearchAPI",
    func=search_api_tool,  # Directly use the search_api_tool
    description="Tool to fetch conversation counts from the Search API."
)

# Create an agent
market_analyst = Agent(
  role='Market Analyst',
  goal='Analyze market trends based on conversation data.',
  backstory='A skilled analyst with expertise in identifying market trends from conversation data.',
  tools=[custom_tool],
  verbose=True
)


# Function to prompt user for input
def prompt_user_for_input():
    symbol = input("What is the symbol you want to analyze? ")
    start_date = input("What is the start date? (YYYY-MM-DD) ")
    end_date = input("What is the end date? (YYYY-MM-DD) ")
    return symbol, start_date, end_date

# Get user input
symbol, start_date, end_date = prompt_user_for_input()

# Custom method for executing the task with the correct parameters
def execute_market_analysis_task(agent, tool, symbol, start_date, end_date):
    params_str = json.dumps({"symbol": symbol, "start_date": start_date, "end_date": end_date})
    return tool.run(params_str)

# Define a task for the agent with user-provided parameters
market_analysis_task = Task(
    description=f'Analyze market conversations for {symbol} between {start_date} and {end_date}.',
    agent=market_analyst,
    tools=[custom_tool],
    execute=execute_market_analysis_task(market_analyst, custom_tool, symbol, start_date, end_date)
)

I've prepared a test.py file to debug and when passing the correct JSON as input the search_api_tool function outputs the correct stuff:

import json
from search_api_tool import search_api_tool
# Test the search_api_tool directly
test_input = json.dumps({"start_date": "02/02/2021", "end_date": "15/02/2021", "symbol": "AAPL"})
test_output = search_api_tool(test_input)
print("Test output:", test_output)

outputs:

python test.py
Test output: {'2021-02-02': 15, '2021-02-03': 43, '2021-02-04': 80, '2021-02-05': 49, '2021-02-06': 35, '2021-02-07': 36, '2021-02-08': 34, '2021-02-09': 49, '2021-02-10': 43, '2021-02-11': 46, '2021-02-12': 49, '2021-02-13': 43, '2021-02-14': 28}

But when I try to execute my main.py file, on the first call, it always mismatches the parameters and does weird stuff as replacing symbol with keyword. The issue here seems to be with how the input parameters are being formatted and passed to the search_api_tool. Initially, the agent is passing the parameters as a comma-separated list (AAPL, 2020-05-19, 2020-10-18), which leads to an error since the tool expects a JSON string. The agent then self-corrects by formatting the input as a JSON string, but the keys used ("keyword", "start_date", "end_date") might not match what the search_api_tool is expecting.

What am I missing here? I just want the Agent to call the API with the simple JSON as in the test file... Thank you very much for any suggestions!

ing-norante avatar Jan 02 '24 18:01 ing-norante

In your docstring for search_api_tool be specific and give a concrete example of what you expect.

:param str input_string: a JSON serialized object containing the properties: start_date, end_date, symbol
Example:
{
    "start_date":"2023-04-20",
    "end_date":"2023-04-21",
    "symbol":"AAPL"
}

svickers avatar Jan 20 '24 18:01 svickers

@svickers is a good suggestions, there is an option of creating multiple input tools as well, maybe we are missing documentation around that.

@ing-norante let us know how that doinf

joaomdmoura avatar Jan 21 '24 03:01 joaomdmoura

Hello, and thanks for your suggestions! I've tried modifying the docstring for search_api_tool as this:

@tool
def search_api_tool(input_string: str) -> dict:
    """
    Tool to fetch conversation counts from the Search API.
    :param str input_string: a JSON serialized object containing the properties: start_date, end_date, symbol
    Example:
    {
        "start_date":"2023-04-20",
        "end_date":"2023-04-21",
        "symbol":"AAVE"
    }
    """

But when I try to execute the main script I'm always getting that strange format, see below:

> Entering new CrewAgentExecutor chain...
Thought: Do I need to use a tool? Yes
Action: SearchAPI
Action Input: AAPL, 2020-07-14, 2020-08-26{'error': 'Invalid input format. Expected JSON string.'}I need to correct the format of my input to match what the SearchAPI expects, which is a JSON string.
Action: SearchAPI
Action Input: {"term": "AAPL", "start_date": "2020-07-14", "end_date": "2020-08-26"}{'error': 'Missing required parameters.'}I seem to be missing some required parameters in my input. I need to check which parameters are required and make sure I include them in my query.

I'm not getting why it's using "term" instead of "symbol"... any help would be very appreciated!

ing-norante avatar Jan 22 '24 18:01 ing-norante