Skip to content
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

[FEAT][Add Tool logic to Agent class #79

Closed
ZackBradshaw opened this issue Nov 2, 2023 · 6 comments
Closed

[FEAT][Add Tool logic to Agent class #79

ZackBradshaw opened this issue Nov 2, 2023 · 6 comments
Assignees
Labels
good first issue Good for newcomers help wanted Extra attention is needed no-issue-activity

Comments

@ZackBradshaw
Copy link
Contributor

ZackBradshaw commented Nov 2, 2023

Integrating tools with Flow

  • Parse the wrapped tool function for the docstrings
  • Inject the tool usage prompt with the function into the llm's prompt
  • We need to parse the llm output to use the tool
            @tool("search", return_direct=True)
            def search_api(query: str) -> str:
                # Searches the API for the query.
                return

Example

from swarms.models import OpenAIChat
from swarms.structs import Flow
from swarms.tools import tool


api_key = ""

# Initialize the language model, this model can be swapped out with Anthropic, ETC, Huggingface Models like Mistral, ETC
llm = OpenAIChat(
    openai_api_key=api_key,
    temperature=0.5,
    max_tokens=3000,
)



# Tool usage example
@tool
def search_api(query: str):
   """Search the web with this tool"""
     pass



# Initialize the flow
flow = Flow(llm=llm, max_loops=5, dashboard=True, tools=[search_api])

out = flow.run("Generate a 10,000 word blog on health and wellness.")

print(out)

Reference

Learn how the worker uses tool: https://github.com/kyegomez/swarms/blob/master/swarms/agents/agent.py

tool Documentation

How It Works

  1. Decorator Functionality:
    The tool decorator can be used in several ways, based on the arguments passed to it. It supports transforming simple functions, asynchronous functions, or objects implementing a Runnable interface into a tool.

  2. Arguments Handling:

    • *args: This is a variable argument list allowing different types of inputs (string, Callable, or Runnable).
    • return_direct: If set to True, the tool returns directly without continuing the loop in which it's running.
    • args_schema: An optional Pydantic model (BaseModel) for validating input arguments to the tool.
    • infer_schema: If True, the tool attempts to infer the argument schema from the function signature.
  3. Tool Creation:

    • The decorator checks the type of arguments it receives and accordingly creates a tool.
    • For a Runnable object, it wraps its invocation methods (ainvoke for async, invoke for sync) into a tool.
    • For a function, it either uses StructuredTool.from_function if infer_schema is True or creates a basic Tool otherwise.
  4. Schema Inference:

    • If infer_schema is True, the decorator infers the input schema for the tool based on the function's signature.
    • This allows the resultant tool to accept a dictionary as input to its run() method.
  5. Error Handling:

    • The decorator ensures that if infer_schema is False, the function must have a docstring to provide a description.

Example Usages

  1. Simple Function as a Tool:

    @tool
    def search_api(query: str) -> str:
        # Function body
  2. Named Tool with Direct Return:

    @tool("search", return_direct=True)
    def search_api(query: str) -> str:
        # Function body
  3. Using Runnable:

    @tool("runnable_tool")
    class MyRunnable(Runnable):
        # Implementation of Runnable

Expected Outputs

  • The decorator converts functions or runnables into tools that can be utilized within a larger framework, possibly an agent-based system.
  • These tools can be executed either synchronously or asynchronously, depending on their nature.
  • They may accept structured inputs (if schema inference is enabled) and can be designed to either return their output directly or continue in a loop.

Use Cases

This kind of tool creation is particularly useful in systems where you need modular, reusable components that can be plugged into different parts of an application, especially in scenarios involving asynchronous operations, agent-based simulations, or complex workflows requiring structured input/output handling.

Upvote & Fund

  • We're using Polar.sh so you can upvote and help fund this issue.
  • We receive the funding once the issue is completed & confirmed by you.
  • Thank you in advance for helping prioritize & fund our backlog.
Fund with Polar
@kyegomez kyegomez added help wanted Extra attention is needed good first issue Good for newcomers labels Nov 2, 2023
@ZackBradshaw ZackBradshaw linked a pull request Nov 10, 2023 that will close this issue
@kyegomez
Copy link
Owner

tool

Integrating the tool function with basic Language Learning Models (LLMs) like OpenAI's GPT models can be a creative and powerful way to combine structured programming with generative AI capabilities. The integration would depend on how the LLM is being used and the nature of the tool created. Let's explore the possibilities:

Integration with LLMs:

  1. Parsing Docstrings for LLM Prompts:

    • The docstrings of the functions decorated with tool can provide context or instructions that can be passed to the LLM. For example, if a tool is designed to perform a specific task, its docstring can be used to formulate a prompt that guides the LLM in generating relevant responses.
    • The prompt can include the function's objective, inputs, expected outputs, or any guidelines mentioned in the docstring.
  2. Executing the Tool:

    • The execution of the tool will depend on whether it's synchronous or asynchronous and the nature of its task.
    • For synchronous tools, you can directly call the tool's function and pass the necessary arguments.
    • For asynchronous tools or runnables, you would typically use an await statement or handle them within an asynchronous event loop.
  3. Combining Tool Output with LLM:

    • The output from these tools can be used as input for LLMs. For example, if a tool generates a list of topics, these can be fed into an LLM to generate detailed content on each topic.
    • Conversely, you might use an LLM to generate initial data or ideas, which are then processed or refined by the tool.
  4. LLM as a Backend for Tools:

    • In some cases, you might want the tool itself to utilize an LLM. Here, the tool's functionality could involve sending a prompt to the LLM and processing its response. For example, a tool might format a query, send it to the LLM, and then parse the LLM's output for specific information.

Example Scenario:

Suppose you have a tool for generating blog topics and another tool for reviewing text quality. Here's how you might integrate these with an LLM:

@tool
def generate_blog_topics(subject: str) -> str:
    """Generate blog topics based on a given subject."""
    # This function could internally use an LLM to generate topics.
    prompt = f"Generate blog topics about {subject}"
    topics = llm(prompt)
    return topics

@tool
def review_text(text: str) -> str:
    """Review the given text and suggest improvements."""
    # This function could use LLM to review and suggest improvements.
    prompt = f"Review this text: {text}"
    review = llm(prompt)
    return review

# Using the tools
topics = generate_blog_topics("Artificial Intelligence")
review = review_text("Sample text to be reviewed")

Key Points:

  • The integration of tools with LLMs can make your workflow more dynamic and powerful, leveraging the strengths of both structured programming and AI-generated content.
  • The tool decorator enhances the modularity and reusability of functions, making them more adaptable for various use cases, including those involving LLMs.
  • Proper error handling and input validation become crucial, especially when dealing with outputs from AI models, to ensure the reliability and usefulness of the tools.

@kyegomez
Copy link
Owner

Tools

To pass the outputs of tools as input to a Language Model (LM), you need to structure your workflow in a way that allows the tools to process data or perform specific operations, and then feed their outputs into the LM. Here's a conceptual walkthrough and an example in Python code to illustrate this process:

Conceptual Workflow:

  1. Define Tools: Create tools using the tool decorator for specific tasks (e.g., data processing, query generation, summarization).

  2. Execute Tools: Run these tools to get outputs. This step might involve processing data, generating prompts, or any other operation relevant to your application.

  3. Feed to LM: Use the outputs from these tools as inputs or prompts for the LM.

  4. Process LM Output: Optionally, process the output from the LM for further steps or to feed back into another tool.

Python Code Example:

Let's consider a scenario where you have two tools: one to generate a query and another to process text. You'll then use these tools to interact with an LM.

First, define the tools:

# Assuming you have the `tool` decorator defined as per your context

@tool
def generate_query(topic: str) -> str:
    """Generate a query based on a topic."""
    return f"Tell me about {topic}"

@tool
def process_text(text: str) -> str:
    """Process the given text."""
    # Some processing logic
    processed_text = text.upper()  # Example processing
    return processed_text

Next, define a function to interact with the LM:

def query_lm(llm, prompt: str) -> str:
    """Query the language model with a given prompt."""
    response = llm(prompt)  # Interacting with the LM
    return response

Finally, create a workflow that uses these tools and the LM:

def main_workflow(llm, topic: str):
    # Generate query using the tool
    query = generate_query(topic)

    # Get response from LM
    lm_response = query_lm(llm, query)

    # Process the LM's response using another tool
    processed_response = process_text(lm_response)

    return processed_response

# Example usage
llm = YourLanguageModel()  # Replace with your actual LM instance
topic = "Artificial Intelligence"
result = main_workflow(llm, topic)
print(result)

Explanation:

  • The generate_query tool creates a query based on a given topic.
  • The process_text tool processes text in some manner (here, it's just converting it to uppercase as an example).
  • The query_lm function sends the generated query to the LM and gets a response.
  • The main_workflow function orchestrates these steps, ensuring that the output from one step feeds into the next.

Key Points:

  • Ensure that the outputs from your tools are in a format compatible with your LM's input requirements.
  • This example assumes synchronous execution. If your tools or LM interaction are asynchronous, you'll need to adjust the code to handle asynchronous calls (async/await).
  • The example is simplified for illustration. Depending on your actual use case, you might need additional error handling, input validation, and more complex data processing logic.

@ZackBradshaw
Copy link
Contributor Author

image

@kyegomez kyegomez changed the title [FEAT][Add Tool logic to Flow class [FEAT][Add Tool logic to Agent class Nov 28, 2023
@kyegomez
Copy link
Owner

Tool usage script

"""
    
    
tool decorated func [search_api] -> agent which parses the docs of the tool func 
-> injected into prompt -> agent will output json containing tool usage -> agent output will be parsed -> tool executed
-> terminal response can be returned to agent for self-healing
    
    
"""

import os

from dotenv import load_dotenv

# Import the OpenAIChat model and the Agent struct
from swarms.models import OpenAIChat
from swarms.structs import Agent
from swarms.tools.tool import tool

# Load the environment variables
load_dotenv()

# Define a tool
@tool
def search_api(query: str):
    """Search the web for the query

    Args:
        query (str): _description_

    Returns:
        _type_: _description_
    """
    return f"Search results for {query}"


# Get the API key from the environment
api_key = os.environ.get("OPENAI_API_KEY")

# Initialize the language model
llm = OpenAIChat(
    temperature=0.5,
    openai_api_key=api_key,
)


## Initialize the workflow
agent = Agent(
    llm=llm, max_loops=1, dashboard=True, tools=[search_api]
)

# Run the workflow on a task
out = agent.run("Generate a 10,000 word blog on health and wellness.")
print(out)

@evelynmitchell
Copy link
Contributor

Is this implemented? Can it be closed?

Copy link

Stale issue message

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Mar 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers help wanted Extra attention is needed no-issue-activity
Projects
Status: ✅ Done
Development

Successfully merging a pull request may close this issue.

3 participants