diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 2c1752fc..4dfcfee4 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -178,7 +178,7 @@ nav: - Swarm Architectures: "swarms/concept/swarm_architectures.md" - Multi-Agent Workflows: "swarms/structs/multi_agent_collaboration_examples.md" - Conversation: "swarms/structs/conversation.md" - - SwarmNetwork: "swarms/structs/swarmnetwork.md" + - SwarmNetwork: "swarms/structs/swarm_network.md" - MajorityVoting: "swarms/structs/majorityvoting.md" - AgentRearrange: "swarms/structs/agent_rearrange.md" - RoundRobin: "swarms/structs/round_robin_swarm.md" diff --git a/docs/swarms/models/openai_function_caller.md b/docs/swarms/models/openai_function_caller.md new file mode 100644 index 00000000..bb952ff1 --- /dev/null +++ b/docs/swarms/models/openai_function_caller.md @@ -0,0 +1,238 @@ +# OpenAIFunctionCaller Documentation + +The `OpenAIFunctionCaller` class is designed to interface with OpenAI's chat completion API, allowing users to generate responses based on given prompts using specified models. This class encapsulates the setup and execution of API calls, including handling API keys, model parameters, and response formatting. The class extends the `BaseLLM` and utilizes OpenAI's client library to facilitate interactions. + +## Class Definition + +### OpenAIFunctionCaller + +A class that represents a caller for OpenAI chat completions. + +### Attributes + +| Attribute | Type | Description | +|----------------------|-------------------|-------------------------------------------------------------------------| +| `system_prompt` | `str` | The system prompt to be used in the chat completion. | +| `model_name` | `str` | The name of the OpenAI model to be used. | +| `max_tokens` | `int` | The maximum number of tokens in the generated completion. | +| `temperature` | `float` | The temperature parameter for randomness in the completion. | +| `base_model` | `BaseModel` | The base model to be used for the completion. | +| `parallel_tool_calls`| `bool` | Whether to make parallel tool calls. | +| `top_p` | `float` | The top-p parameter for nucleus sampling in the completion. | +| `client` | `openai.OpenAI` | The OpenAI client for making API calls. | + +### Methods + +#### `check_api_key` + +Checks if the API key is provided and retrieves it from the environment if not. + +| Parameter | Type | Description | +|---------------|--------|--------------------------------------| +| None | | | + +**Returns:** + +| Type | Description | +|--------|--------------------------------------| +| `str` | The API key. | + +#### `run` + +Runs the chat completion with the given task and returns the generated completion. + +| Parameter | Type | Description | +|-----------|----------|-----------------------------------------------------------------| +| `task` | `str` | The user's task for the chat completion. | +| `*args` | | Additional positional arguments to be passed to the OpenAI API. | +| `**kwargs`| | Additional keyword arguments to be passed to the OpenAI API. | + +**Returns:** + +| Type | Description | +|--------|-----------------------------------------------| +| `str` | The generated completion. | + +#### `convert_to_dict_from_base_model` + +Converts a `BaseModel` to a dictionary. + +| Parameter | Type | Description | +|-------------|------------|--------------------------------------| +| `base_model`| `BaseModel`| The BaseModel to be converted. | + +**Returns:** + +| Type | Description | +|--------|--------------------------------------| +| `dict` | A dictionary representing the BaseModel.| + +#### `convert_list_of_base_models` + +Converts a list of `BaseModels` to a list of dictionaries. + +| Parameter | Type | Description | +|--------------|-----------------|--------------------------------------| +| `base_models`| `List[BaseModel]`| A list of BaseModels to be converted.| + +**Returns:** + +| Type | Description | +|--------|-----------------------------------------------| +| `List[Dict]` | A list of dictionaries representing the converted BaseModels. | + +## Usage Examples + +Here are three examples demonstrating different ways to use the `OpenAIFunctionCaller` class: + +### Example 1: Production-Grade Claude Artifacts + +```python +import openai +from swarms.models.openai_function_caller import OpenAIFunctionCaller +from swarms.artifacts.main_artifact import Artifact + + +# Pydantic is a data validation library that provides data validation and parsing using Python type hints. + + +# Example usage: +# Initialize the function caller +model = OpenAIFunctionCaller( + system_prompt="You're a helpful assistant.The time is August 6, 2024", + max_tokens=500, + temperature=0.5, + base_model=Artifact, + parallel_tool_calls=False, +) + + +# The OpenAIFunctionCaller class is used to interact with the OpenAI API and make function calls. +# Here, we initialize an instance of the OpenAIFunctionCaller class with the following parameters: +# - system_prompt: A prompt that sets the context for the conversation with the API. +# - max_tokens: The maximum number of tokens to generate in the API response. +# - temperature: A parameter that controls the randomness of the generated text. +# - base_model: The base model to use for the API calls, in this case, the WeatherAPI class. +out = model.run("Create a python file with a python game code in it") +print(out) +``` + +### Example 2: Prompt Generator + +```python +from swarms.models.openai_function_caller import OpenAIFunctionCaller +from pydantic import BaseModel, Field +from typing import Sequence + + +class PromptUseCase(BaseModel): + use_case_name: str = Field( + ..., + description="The name of the use case", + ) + use_case_description: str = Field( + ..., + description="The description of the use case", + ) + + +class PromptSpec(BaseModel): + prompt_name: str = Field( + ..., + description="The name of the prompt", + ) + prompt_description: str = Field( + ..., + description="The description of the prompt", + ) + prompt: str = Field( + ..., + description="The prompt for the agent", + ) + tags: str = Field( + ..., + description="The tags for the prompt such as sentiment, code, etc seperated by commas.", + ) + use_cases: Sequence[PromptUseCase] = Field( + ..., + description="The use cases for the prompt", + ) + + +# Example usage: +# Initialize the function caller +model = OpenAIFunctionCaller( + system_prompt="You're an agent creator, you're purpose is to create system prompt for new LLM Agents for the user. Follow the best practices for creating a prompt such as making it direct and clear. Providing instructions and many-shot examples will help the agent understand the task better.", + max_tokens=1000, + temperature=0.5, + base_model=PromptSpec, + parallel_tool_calls=False, +) + + +# The OpenAIFunctionCaller class is used to interact with the OpenAI API and make function calls. +out = model.run( + "Create an prompt for generating quality rust code with instructions and examples." +) +print(out) + +``` + +### Example 3: Sentiment Analysis + +```python +from swarms.models.openai_function_caller import OpenAIFunctionCaller +from pydantic import BaseModel, Field + + +# Pydantic is a data validation library that provides data validation and parsing using Python type hints. +# It is used here to define the data structure for making API calls to retrieve weather information. +class SentimentAnalysisCard(BaseModel): + text: str = Field( + ..., + description="The text to be analyzed for sentiment rating", + ) + rating: str = Field( + ..., + description="The sentiment rating of the text from 0.0 to 1.0", + ) + + +# The WeatherAPI class is a Pydantic BaseModel that represents the data structure +# for making API calls to retrieve weather information. It has two attributes: city and date. + +# Example usage: +# Initialize the function caller +model = OpenAIFunctionCaller( + system_prompt="You're a sentiment Analysis Agent, you're purpose is to rate the sentiment of text", + max_tokens=100, + temperature=0.5, + base_model=SentimentAnalysisCard, + parallel_tool_calls=False, +) + + +# The OpenAIFunctionCaller class is used to interact with the OpenAI API and make function calls. +# Here, we initialize an instance of the OpenAIFunctionCaller class with the following parameters: +# - system_prompt: A prompt that sets the context for the conversation with the API. +# - max_tokens: The maximum number of tokens to generate in the API response. +# - temperature: A parameter that controls the randomness of the generated text. +# - base_model: The base model to use for the API calls, in this case, the WeatherAPI class. +out = model.run("The hotel was average, but the food was excellent.") +print(out) + +``` + +## Additional Information and Tips + +- Ensure that your OpenAI API key is securely stored and not hard-coded into your source code. Use environment variables to manage sensitive information. +- Adjust the `temperature` and `top_p` parameters to control the randomness and diversity of the generated responses. Lower values for `temperature` will result in more deterministic outputs, while higher values will introduce more variability. +- When using `parallel_tool_calls`, ensure that the tools you are calling in parallel are thread-safe and can handle concurrent execution. + +## References and Resources + +- [OpenAI API Documentation](https://beta.openai.com/docs/) +- [Pydantic Documentation](https://pydantic-docs.helpmanual.io/) +- [Loguru Logger Documentation](https://loguru.readthedocs.io/) + +By following this comprehensive guide, you can effectively utilize the `OpenAIFunctionCaller` class to generate chat completions using OpenAI's models, customize the response parameters, and handle API interactions seamlessly within your application. \ No newline at end of file diff --git a/docs/swarms/structs/swarm_network.md b/docs/swarms/structs/swarm_network.md index 6c81fc20..1b74a85f 100644 --- a/docs/swarms/structs/swarm_network.md +++ b/docs/swarms/structs/swarm_network.md @@ -1,4 +1,4 @@ -# SwarmNetwork Documentation +# SwarmNetwork [WIP] The `SwarmNetwork` class is a powerful tool for managing a pool of agents, orchestrating task distribution, and scaling resources based on workload. It is designed to handle tasks efficiently by dynamically adjusting the number of agents according to the current demand. This class also provides an optional API for interacting with the agent pool, making it accessible for integration with other systems. @@ -134,7 +134,36 @@ Runs a task on a specific agent by ID. from swarms.structs.agent import Agent from swarms.structs.swarm_net import SwarmNetwork -agent = Agent() +# Initialize the agent +agent = Agent( + agent_name="Financial-Analysis-Agent", + llm=model, + max_loops="auto", + autosave=True, + dashboard=False, + verbose=True, + streaming_on=True, + interactive=True, + # interactive=True, # Set to False to disable interactive mode + saved_state_path="finance_agent.json", + # tools=[Add your functions here# ], + # stopping_token="Stop!", + # interactive=True, + # docs_folder="docs", # Enter your folder name + # pdf_path="docs/finance_agent.pdf", + # sop="Calculate the profit for a company.", + # sop_list=["Calculate the profit for a company."], + user_name="swarms_corp", + # # docs= + # # docs_folder="docs", + retry_attempts=3, + # context_length=1000, + # tool_schema = dict + context_length=200000, + # agent_ops_on=True, + # long_term_memory=ChromaDB(docs_folder="artifacts"), +) + swarm = SwarmNetwork(agents=[agent]) result = swarm.run_single_agent(agent.id, "task") ``` @@ -162,8 +191,69 @@ Runs a task on all agents in the pool. from swarms.structs.agent import Agent from swarms.structs.swarm_net import SwarmNetwork -agent1 = Agent() -agent2 = Agent() +# Initialize the agent +agent = Agent( + agent_name="Financial-Analysis-Agent", + system_prompt=ESTATE_PLANNING_AGENT_SYS_PROMPT, + llm=model, + max_loops="auto", + autosave=True, + dashboard=False, + verbose=True, + streaming_on=True, + interactive=True, + # interactive=True, # Set to False to disable interactive mode + saved_state_path="finance_agent.json", + # tools=[Add your functions here# ], + # stopping_token="Stop!", + # interactive=True, + # docs_folder="docs", # Enter your folder name + # pdf_path="docs/finance_agent.pdf", + # sop="Calculate the profit for a company.", + # sop_list=["Calculate the profit for a company."], + user_name="swarms_corp", + # # docs= + # # docs_folder="docs", + retry_attempts=3, + # context_length=1000, + # tool_schema = dict + context_length=200000, + # agent_ops_on=True, + # long_term_memory=ChromaDB(docs_folder="artifacts"), +) + +# Initialize the agent +agent2 = Agent( + agent_name="ROTH-IRA-AGENT", + system_prompt=ESTATE_PLANNING_AGENT_SYS_PROMPT, + llm=model, + max_loops="auto", + autosave=True, + dashboard=False, + verbose=True, + streaming_on=True, + interactive=True, + # interactive=True, # Set to False to disable interactive mode + saved_state_path="finance_agent.json", + # tools=[Add your functions here# ], + # stopping_token="Stop!", + # interactive=True, + # docs_folder="docs", # Enter your folder name + # pdf_path="docs/finance_agent.pdf", + # sop="Calculate the profit for a company.", + # sop_list=["Calculate the profit for a company."], + user_name="swarms_corp", + # # docs= + # # docs_folder="docs", + retry_attempts=3, + # context_length=1000, + # tool_schema = dict + context_length=200000, + # agent_ops_on=True, + # long_term_memory=ChromaDB(docs_folder="artifacts"), +) + + swarm = SwarmNetwork(agents=[agent1, agent2]) results = swarm.run_many_agents("task") ``` @@ -183,7 +273,37 @@ Lists all agents in the pool. from swarms.structs.agent import Agent from swarms.structs.swarm_net import SwarmNetwork -agent = Agent() +# Initialize the agent +agent2 = Agent( + agent_name="ROTH-IRA-AGENT", + system_prompt=ESTATE_PLANNING_AGENT_SYS_PROMPT, + llm=model, + max_loops="auto", + autosave=True, + dashboard=False, + verbose=True, + streaming_on=True, + interactive=True, + # interactive=True, # Set to False to disable interactive mode + saved_state_path="finance_agent.json", + # tools=[Add your functions here# ], + # stopping_token="Stop!", + # interactive=True, + # docs_folder="docs", # Enter your folder name + # pdf_path="docs/finance_agent.pdf", + # sop="Calculate the profit for a company.", + # sop_list=["Calculate the profit for a company."], + user_name="swarms_corp", + # # docs= + # # docs_folder="docs", + retry_attempts=3, + # context_length=1000, + # tool_schema = dict + context_length=200000, + # agent_ops_on=True, + # long_term_memory=ChromaDB(docs_folder="artifacts"), +) + swarm = SwarmNetwork(agents=[agent]) swarm.list_agents() ``` @@ -209,7 +329,37 @@ Gets an agent by ID. from swarms.structs.agent import Agent from swarms.structs.swarm_net import SwarmNetwork -agent = Agent() +# Initialize the agent +agent2 = Agent( + agent_name="ROTH-IRA-AGENT", + system_prompt=ESTATE_PLANNING_AGENT_SYS_PROMPT, + llm=model, + max_loops="auto", + autosave=True, + dashboard=False, + verbose=True, + streaming_on=True, + interactive=True, + # interactive=True, # Set to False to disable interactive mode + saved_state_path="finance_agent.json", + # tools=[Add your functions here# ], + # stopping_token="Stop!", + # interactive=True, + # docs_folder="docs", # Enter your folder name + # pdf_path="docs/finance_agent.pdf", + # sop="Calculate the profit for a company.", + # sop_list=["Calculate the profit for a company."], + user_name="swarms_corp", + # # docs= + # # docs_folder="docs", + retry_attempts=3, + # context_length=1000, + # tool_schema = dict + context_length=200000, + # agent_ops_on=True, + # long_term_memory=ChromaDB(docs_folder="artifacts"), +) + swarm = SwarmNetwork(agents=[agent]) retrieved_agent = swarm.get_agent(agent.id) ``` @@ -232,7 +382,37 @@ Adds an agent to the agent pool. from swarms.structs.agent import Agent from swarms.structs.swarm_net import SwarmNetwork -agent = Agent() +# Initialize the agent +agent2 = Agent( + agent_name="ROTH-IRA-AGENT", + system_prompt=ESTATE_PLANNING_AGENT_SYS_PROMPT, + llm=model, + max_loops="auto", + autosave=True, + dashboard=False, + verbose=True, + streaming_on=True, + interactive=True, + # interactive=True, # Set to False to disable interactive mode + saved_state_path="finance_agent.json", + # tools=[Add your functions here# ], + # stopping_token="Stop!", + # interactive=True, + # docs_folder="docs", # Enter your folder name + # pdf_path="docs/finance_agent.pdf", + # sop="Calculate the profit for a company.", + # sop_list=["Calculate the profit for a company."], + user_name="swarms_corp", + # # docs= + # # docs_folder="docs", + retry_attempts=3, + # context_length=1000, + # tool_schema = dict + context_length=200000, + # agent_ops_on=True, + # long_term_memory=ChromaDB(docs_folder="artifacts"), +) + swarm = SwarmNetwork(agents=[]) swarm.add_agent(agent) ``` @@ -255,7 +435,37 @@ Removes an agent from the agent pool. from swarms.structs.agent import Agent from swarms.structs.swarm_net import SwarmNetwork -agent = Agent() +# Initialize the agent +agent2 = Agent( + agent_name="ROTH-IRA-AGENT", + system_prompt=ESTATE_PLANNING_AGENT_SYS_PROMPT, + llm=model, + max_loops="auto", + autosave=True, + dashboard=False, + verbose=True, + streaming_on=True, + interactive=True, + # interactive=True, # Set to False to disable interactive mode + saved_state_path="finance_agent.json", + # tools=[Add your functions here# ], + # stopping_token="Stop!", + # interactive=True, + # docs_folder="docs", # Enter your folder name + # pdf_path="docs/finance_agent.pdf", + # sop="Calculate the profit for a company.", + # sop_list=["Calculate the profit for a company."], + user_name="swarms_corp", + # # docs= + # # docs_folder="docs", + retry_attempts=3, + # context_length=1000, + # tool_schema = dict + context_length=200000, + # agent_ops_on=True, + # long_term_memory=ChromaDB(docs_folder="artifacts"), +) + swarm = SwarmNetwork(agents=[agent]) swarm.remove_agent(agent.id) ``` @@ -280,7 +490,37 @@ Removes an agent from the agent pool asynchronously. from swarms.structs.agent import Agent from swarms.structs.swarm_net import SwarmNetwork -agent = Agent() +# Initialize the agent +agent2 = Agent( + agent_name="ROTH-IRA-AGENT", + system_prompt=ESTATE_PLANNING_AGENT_SYS_PROMPT, + llm=model, + max_loops="auto", + autosave=True, + dashboard=False, + verbose=True, + streaming_on=True, + interactive=True, + # interactive=True, # Set to False to disable interactive mode + saved_state_path="finance_agent.json", + # tools=[Add your functions here# ], + # stopping_token="Stop!", + # interactive=True, + # docs_folder="docs", # Enter your folder name + # pdf_path="docs/finance_agent.pdf", + # sop="Calculate the profit for a company.", + # sop_list=["Calculate the profit for a company."], + user_name="swarms_corp", + # # docs= + # # docs_folder="docs", + retry_attempts=3, + # context_length=1000, + # tool_schema = dict + context_length=200000, + # agent_ops_on=True, + # long_term_memory=ChromaDB(docs_folder="artifacts"), +) + swarm = SwarmNetwork(agents=[agent]) await swarm.async_remove_agent(agent.id) ``` @@ -303,7 +543,37 @@ Scales up the agent pool by adding new agents. from swarms.structs.agent import Agent from swarms.structs.swarm_net import SwarmNetwork -agent = Agent() +# Initialize the agent +agent2 = Agent( + agent_name="ROTH-IRA-AGENT", + system_prompt=ESTATE_PLANNING_AGENT_SYS_PROMPT, + llm=model, + max_loops="auto", + autosave=True, + dashboard=False, + verbose=True, + streaming_on=True, + interactive=True, + # interactive=True, # Set to False to disable interactive mode + saved_state_path="finance_agent.json", + # tools=[Add your functions here# ], + # stopping_token="Stop!", + # interactive=True, + # docs_folder="docs", # Enter your folder name + # pdf_path="docs/finance_agent.pdf", + # sop="Calculate the profit for a company.", + # sop_list=["Calculate the profit for a company."], + user_name="swarms_corp", + # # docs= + # # docs_folder="docs", + retry_attempts=3, + # context_length=1000, + # tool_schema = dict + context_length=200000, + # agent_ops_on=True, + # long_term_memory=ChromaDB(docs_folder="artifacts"), +) + swarm = SwarmNetwork(agents=[agent]) swarm.scale_up(2) ``` @@ -326,7 +596,38 @@ Scales down the agent pool by removing agents. from swarms.structs.agent import Agent from swarms.structs.swarm_net import SwarmNetwork -agent = Agent() +# Initialize the agent +agent2 = Agent( + agent_name="ROTH-IRA-AGENT", + system_prompt=ESTATE_PLANNING_AGENT_SYS_PROMPT, + llm=model, + max_loops="auto", + autosave=True, + dashboard=False, + verbose=True, + streaming_on=True, + interactive=True, + # interactive=True, # Set to False to disable interactive mode + saved_state_path="finance_agent.json", + # tools=[Add your functions here# ], + # stopping_token="Stop!", + # interactive=True, + # docs_folder="docs", # Enter your folder name + # pdf_path="docs/finance_agent.pdf", + # sop="Calculate the profit for a company.", + # sop_list=["Calculate the profit for a company."], + user_name="swarms_corp", + # # docs= + # # docs_folder="docs", + retry_attempts=3, + # context_length=1000, + # tool_schema = dict + context_length=200000, + # agent_ops_on=True, + # long_term_memory=ChromaDB(docs_folder="artifacts"), +) + + swarm = SwarmNetwork(agents=[agent]) swarm.scale_down(1) ``` diff --git a/example.py b/example.py index b4a47c82..d7d2de1d 100644 --- a/example.py +++ b/example.py @@ -21,32 +21,28 @@ agent = Agent( autosave=True, # dynamic_temperature_enabled=True, dashboard=False, - code_interpreter=True, - # verbose=True, - # streaming_on=True, - # # interactive=True, # Set to False to disable interactive mode - # dynamic_temperature_enabled=True, - # saved_state_path="finance_agent.json", - # # tools=[#Add your functions here# ], - # # stopping_token="Stop!", - # # interactive=True, - # # docs_folder="docs", # Enter your folder name - # # pdf_path="docs/finance_agent.pdf", - # # sop="Calculate the profit for a company.", - # # sop_list=["Calculate the profit for a company."], - # user_name="swarms_corp", - # # # docs= - # # # docs_folder="docs", - # retry_attempts=3, - # # context_length=1000, - # # tool_schema = dict - # context_length=200000, - # # tool_schema= - # tools - # agent_ops_on=True, + verbose=True, + # interactive=True, # Set to False to disable interactive mode + dynamic_temperature_enabled=True, + saved_state_path="finance_agent.json", + # tools=[#Add your functions here# ], + # stopping_token="Stop!", + # interactive=True, + # docs_folder="docs", # Enter your folder name + # pdf_path="docs/finance_agent.pdf", + # sop="Calculate the profit for a company.", + # sop_list=["Calculate the profit for a company."], + user_name="swarms_corp", + # # docs= + # # docs_folder="docs", + retry_attempts=3, + # context_length=1000, + # tool_schema = dict + context_length=200000, + # tool_schema= ) agent.run( - "Generate the python code to fetch financial news using the OpenAI API. only return the python code" + "How can I establish a ROTH IRA to buy stocks and get a tax break? What are the criteria" ) diff --git a/playground/agents/tools/function_calling/agent_spec_func_calling.py b/playground/agents/tools/function_calling/agent_spec_func_calling.py new file mode 100644 index 00000000..ec83804d --- /dev/null +++ b/playground/agents/tools/function_calling/agent_spec_func_calling.py @@ -0,0 +1,49 @@ +from swarms.models.openai_function_caller import OpenAIFunctionCaller +from pydantic import BaseModel, Field + + +class AgentSpec(BaseModel): + agent_name: str = Field( + ..., + description="The name of the agent", + ) + system_prompt: str = Field( + ..., + description="The system prompt for the agent", + ) + agent_description: str = Field( + ..., + description="The description of the agent", + ) + max_tokens: int = Field( + ..., + description="The maximum number of tokens to generate in the API response", + ) + temperature: float = Field( + ..., + description="A parameter that controls the randomness of the generated text", + ) + context_window: int = Field( + ..., + description="The context window for the agent", + ) + model_name: str = Field( + ..., + description="The model name for the agent from huggingface", + ) + + +# Example usage: +# Initialize the function caller +model = OpenAIFunctionCaller( + system_prompt="You're an agent creator, you're purpose is to create an agent with the user provided specifications", + max_tokens=500, + temperature=0.5, + base_model=AgentSpec, + parallel_tool_calls=False, +) + + +# The OpenAIFunctionCaller class is used to interact with the OpenAI API and make function calls. +out = model.run("Create an agent for sentiment analysis") +print(out) diff --git a/playground/agents/tools/function_calling/claude_artifacts_example.py b/playground/agents/tools/function_calling/claude_artifacts_example.py new file mode 100644 index 00000000..7afc8a4d --- /dev/null +++ b/playground/agents/tools/function_calling/claude_artifacts_example.py @@ -0,0 +1,26 @@ +from swarms.models.openai_function_caller import OpenAIFunctionCaller +from swarms.artifacts.main_artifact import Artifact + + +# Pydantic is a data validation library that provides data validation and parsing using Python type hints. + + +# Example usage: +# Initialize the function caller +model = OpenAIFunctionCaller( + system_prompt="You're a helpful assistant.The time is August 6, 2024", + max_tokens=500, + temperature=0.5, + base_model=Artifact, + parallel_tool_calls=False, +) + + +# The OpenAIFunctionCaller class is used to interact with the OpenAI API and make function calls. +# Here, we initialize an instance of the OpenAIFunctionCaller class with the following parameters: +# - system_prompt: A prompt that sets the context for the conversation with the API. +# - max_tokens: The maximum number of tokens to generate in the API response. +# - temperature: A parameter that controls the randomness of the generated text. +# - base_model: The base model to use for the API calls, in this case, the WeatherAPI class. +out = model.run("Create a python file with a python game code in it") +print(out) diff --git a/playground/agents/tools/function_calling/expense_analyst_agent.py b/playground/agents/tools/function_calling/expense_analyst_agent.py new file mode 100644 index 00000000..b369aa04 --- /dev/null +++ b/playground/agents/tools/function_calling/expense_analyst_agent.py @@ -0,0 +1,135 @@ +from swarms.models.openai_function_caller import OpenAIFunctionCaller +from pydantic import BaseModel, Field + + +# Pydantic is a data validation library that provides data validation and parsing using Python type hints. +# It is used here to define the data structure for making API calls to retrieve weather information. +class Transaction(BaseModel): + amount: float = Field(..., description="The amount of the transaction") + category: str = Field( + ..., + description="The category of the transaction according to Xeros categories such as Dues & Subscriptions, Fees & Charges, Meals & Entertainment.", + ) + date: str = Field(..., description="The date of the transaction") + + +class TransactionsToCut(BaseModel): + transactions: list[Transaction] + expense_analysis: str + dollars_saved: float + + +# The WeatherAPI class is a Pydantic BaseModel that represents the data structure +# for making API calls to retrieve weather information. It has two attributes: city and date. + + +# Example usage: +# Initialize the function caller +function_caller = OpenAIFunctionCaller( + system_prompt="You are a helpful assistant.", + max_tokens=2000, + temperature=0.5, + base_model=TransactionsToCut, +) + + +# Task +logs = """ + +################################ +Date Description Type Amount Balance Action +Jul 31, 2024 MONTHLY SERVICE FEE +Fee -$15.00 -$986.49 +Jul 31, 2024 ORIG CO NAME:STRIPE ORIG ID:4270465600 DESC DATE: CO ENTRY DESCR:TRANSFER SEC:CCD TRACE#:111000028806182 EED:240731 IND ID:ST-R7Z6S6U2K5U1 IND NAME:KYE GOMEZ TRN: 2138806182TC ACH credit $18.46 -$971.49 +Jul 26, 2024 ORIG CO NAME:STRIPE ORIG ID:4270465600 DESC DATE: CO ENTRY DESCR:TRANSFER SEC:CCD TRACE#:111000027107200 EED:240726 IND ID:ST-F1B2H5X5P7A5 IND NAME:KYE GOMEZ TRN: 2087107200TC ACH credit $48.25 -$989.95 +Jul 24, 2024 ORIG CO NAME:STRIPE ORIG ID:4270465600 DESC DATE: CO ENTRY DESCR:TRANSFER SEC:CCD TRACE#:111000026863283 EED:240724 IND ID:ST-B3Q3I3S7G1C8 IND NAME:KYE GOMEZ TRN: 2066863283TC ACH credit $18.81 -$1,038.20 +Jul 23, 2024 ORIG CO NAME:STRIPE ORIG ID:4270465600 DESC DATE: CO ENTRY DESCR:TRANSFER SEC:CCD TRACE#:111000024970457 EED:240723 IND ID:ST-Y8V3O8K6B8Y2 IND NAME:KYE GOMEZ TRN: 2054970457TC ACH credit $48.15 -$1,057.01 +Jul 22, 2024 ORIG CO NAME:GitHub Sponsors ORIG ID:4270465600 DESC DATE: CO ENTRY DESCR:GitHub SpoSEC:CCD TRACE#:111000029548278 EED:240722 IND ID:ST-G1P1A1A3Y8L2 IND NAME:KYE GOMEZ TRN: 2049548278TC Other $8.33 -$1,105.16 +Jul 22, 2024 ORIG CO NAME:STRIPE ORIG ID:4270465600 DESC DATE: CO ENTRY DESCR:TRANSFER SEC:CCD TRACE#:111000029566827 EED:240722 IND ID:ST-A4F9I2H5H6I9 IND NAME:KYE GOMEZ TRN: 2049566827TC ACH credit $18.66 -$1,113.49 +Jul 19, 2024 ORIG CO NAME:STRIPE ORIG ID:4270465600 DESC DATE: CO ENTRY DESCR:TRANSFER SEC:CCD TRACE#:111000025982141 EED:240719 IND ID:ST-K4M7U0J6X3T3 IND NAME:KYE GOMEZ TRN: 2015982141TC ACH credit $19.11 -$1,132.15 +Jul 12, 2024 ORIG CO NAME:STRIPE ORIG ID:4270465600 DESC DATE: CO ENTRY DESCR:TRANSFER SEC:CCD TRACE#:111000023532836 EED:240712 IND ID:ST-L3F1Q6U7O2I4 IND NAME:KYE GOMEZ TRN: 1943532836TC ACH credit $1.58 -$1,151.26 +Jul 11, 2024 ORIG CO NAME:STRIPE ORIG ID:4270465600 DESC DATE: CO ENTRY DESCR:TRANSFER SEC:CCD TRACE#:111000027946637 EED:240711 IND ID:ST-T2S8O9G9L6Y6 IND NAME:KYE GOMEZ TRN: 1937946637TC ACH credit $19.11 -$1,152.84 +Jul 9, 2024 OVERDRAFT FEE FOR A $19.49 CARD PURCHASE - DETAILS: 0706TST* LULU'S - ALAMED WEST MENLO PA CA0############0029 07 Fee -$34.00 -$1,171.95 +Jul 9, 2024 OVERDRAFT FEE FOR A $38.77 CARD PURCHASE - DETAILS: 0705TST* LULU'S - ALAMED WEST MENLO PA CA0############0029 07 Fee -$34.00 -$1,137.95 +Jul 9, 2024 ORIG CO NAME:STRIPE ORIG ID:4270465600 DESC DATE: CO ENTRY DESCR:TRANSFER SEC:CCD TRACE#:111000021343065 EED:240709 IND ID:ST-G4X7Q1Z3O7P2 IND NAME:KYE GOMEZ TRN: 1911343065TC ACH credit $18.71 -$1,103.95 +Jul 8, 2024 OVERDRAFT FEE FOR A $66.00 ITEM - DETAILS: ORIG CO NAME:CAPITAL ONE ORIG ID:9541719318 DESC DATE:240704 CO ENTRY DESCR:CRCARDPMT SEC:CCD TRACE#:056073615999158 EED:240705 IND ID:3XS9ZC4R7RBL1JG IND NAME:KYE B GOMEZ TRN: 1875999158TC Fee -$34.00 -$1,122.66 +Jul 8, 2024 OVERDRAFT FEE FOR A $15.20 CARD PURCHASE - DETAILS: 0704STARBUCKS STORE 05798 MENLO PARK CA 0############0029 07 Fee -$34.00 -$1,088.66 +Jul 8, 2024 OVERDRAFT FEE FOR A $11.35 CARD PURCHASE - DETAILS: 0703CHIPOTLE 0801 MOUNTAIN VIEW CA 0############0029 07 Fee -$34.00 -$1,054.66 +Jul 8, 2024 OVERDRAFT FEE FOR A $26.17 CARD PURCHASE - DETAILS: 0703KFC/LJS #223 MOUNTAIN VIEW CA 0############0029 05 Fee -$34.00 -$1,020.66 +Jul 8, 2024 TST* LULU'S - ALAMED WEST MENLO PA CA 07/06 (...0029) Card -$19.49 -$986.66 +Jul 8, 2024 TST* LULU'S - ALAMED WEST MENLO PA CA 07/05 (...0029) Card -$38.77 -$967.17 +Jul 5, 2024 OVERDRAFT FEE FOR A $13.97 CARD PURCHASE - DETAILS: 0702SAMOVAR MOUNTAIN VIEW CA 0############0029 05 Fee -$34.00 -$928.40 +Jul 5, 2024 OVERDRAFT FEE FOR A $18.66 CARD PURCHASE - DETAILS: 0703LYFT *1 RIDE 07-01 HELP.LYFT.COM CA0############0029 01 Fee -$34.00 -$894.40 +Jul 5, 2024 OVERDRAFT FEE FOR A $10.59 CARD PURCHASE - DETAILS: 0702PAYPAL *ELENA_SMIRNOV 402-935-7733 CA0############0029 00419 Fee -$34.00 -$860.40 +Jul 5, 2024 ORIG CO NAME:CAPITAL ONE ORIG ID:9541719318 DESC DATE:240704 CO ENTRY DESCR:CRCARDPMT SEC:CCD TRACE#:056073615999158 EED:240705 IND ID:3XS9ZC4R7RBL1JG IND NAME:KYE B GOMEZ TRN: 1875999158TC ACH debit -$66.00 -$826.40 +Jul 5, 2024 UBER *TRIP SAN FRANCISCO CA 127199 07/04 (...0029) Card -$16.85 -$760.40 +Jul 5, 2024 STARBUCKS STORE 05798 MENLO PARK CA 07/04 (...0029) Card -$15.20 -$743.55 +Jul 5, 2024 CHIPOTLE 0801 MOUNTAIN VIEW CA 07/03 (...0029) Card -$11.35 -$728.35 +Jul 5, 2024 KFC/LJS #223 MOUNTAIN VIEW CA 07/03 (...0029) Card -$26.17 -$717.00 +Jul 5, 2024 ORIG CO NAME:STRIPE ORIG ID:4270465600 DESC DATE: CO ENTRY DESCR:TRANSFER SEC:CCD TRACE#:111000021739712 EED:240705 IND ID:ST-E7N6R7F0Y2B1 IND NAME:KYE GOMEZ TRN: 1871739712TC ACH credit $94.80 -$690.83 +Jul 3, 2024 OVERDRAFT FEE FOR A $23.68 CARD PURCHASE - DETAILS: 0701CHIPOTLE 0801 MOUNTAIN VIEW CA 0############0029 07 Fee -$34.00 -$785.63 +Jul 3, 2024 OVERDRAFT FEE FOR A $46.59 CARD PURCHASE - DETAILS: 0702LYFT *4 RIDES 06-3 HELP.LYFT.COM CA0############0029 01 Fee -$34.00 -$751.63 +Jul 3, 2024 SAMOVAR MOUNTAIN VIEW CA 07/02 (...0029) Card -$13.97 -$717.63 +Jul 3, 2024 LYFT *1 RIDE 07-01 HELP.LYFT.COM CA 07/03 (...0029) Card -$18.66 -$703.66 +Jul 3, 2024 PAYPAL *ELENA_SMIRNOV 402-935-7733 CA 07/02 (...0029) Card -$10.59 -$685.00 +Jul 2, 2024 OVERDRAFT FEE FOR A $18.35 CARD PURCHASE - DETAILS: 0629STARBUCKS STORE 05798 MENLO PARK CA 0############0029 07 Fee -$34.00 -$674.41 +Jul 2, 2024 OVERDRAFT FEE FOR A $20.00 RECURRING CARD PURCHASE - DETAILS: 0629OPENAI *CHATGPT SUBS HTTPSOPENAI.C CA0############0029 01699 Fee -$34.00 -$640.41 +Jul 2, 2024 OVERDRAFT FEE FOR A $31.27 CARD PURCHASE - DETAILS: 0629LULU'S ON THE ALAMEDA MENLO PARK CA 0############0029 07 Fee -$34.00 -$606.41 +Jul 2, 2024 OVERDRAFT FEE FOR A $11.99 CARD PURCHASE - DETAILS: 0629LYFT *1 RIDE 06-27 HELP.LYFT.COM CA0############0029 01 Fee -$34.00 -$572.41 +Jul 2, 2024 OVERDRAFT FEE FOR A $21.73 CARD PURCHASE - DETAILS: 0628SQ *BRIOCHE BAKERY & San Francisco CA0############0029 07 Fee -$34.00 -$538.41 +Jul 2, 2024 OVERDRAFT FEE FOR A $16.04 CARD PURCHASE - DETAILS: 0628CHIPOTLE 0801 MOUNTAIN VIEW CA 0############0029 07 Fee -$34.00 -$504.41 +Jul 2, 2024 CHIPOTLE 0801 MOUNTAIN VIEW CA 07/01 (...0029) Card -$23.68 -$470.41 +Jul 2, 2024 LYFT *4 RIDES 06-3 HELP.LYFT.COM CA 07/02 (...0029) Card -$46.59 -$446.73 +Jul 1, 2024 TACO BELL #28833 PALO ALTO CA 06/30 (...0029) Card -$21.80 -$400.14 +Jul 1, 2024 UBER *TRIP SAN FRANCISCO CA 336624 06/30 (...0029) Card -$8.16 -$378.34 +Jul 1, 2024 SAMOVAR MOUNTAIN VIEW CA 06/30 (...0029) Card -$15.27 -$370.18 +Jul 1, 2024 TST* DUTCH GOOSE Menlo Park CA 06/30 (...0029) Card -$40.23 -$354.91 +Jul 1, 2024 KEPLERS BOOKS MENLO PARK CA 06/30 (...0029) Card -$19.14 -$314.68 +Jul 1, 2024 LYFT *1 RIDE 06-29 HELP.LYFT.COM CA 07/01 (...0029) Card -$8.76 -$295.54 +Jul 1, 2024 WALGREENS #7087 MENLO PARK CA 06/29 (...0029) Card -$8.99 -$286.78 +Jul 1, 2024 STARBUCKS STORE 05798 MENLO PARK CA 06/29 (...0029) Card -$18.35 -$277.79 +Jul 1, 2024 OPENAI *CHATGPT SUBS HTTPSOPENAI.C CA 06/29 (...0029) Card -$20.00 -$259.44 +Jul 1, 2024 LULU'S ON THE ALAMEDA MENLO PARK CA 06/29 (...0029) Card -$31.27 -$239.44 +Jul 1, 2024 LYFT *1 RIDE 06-27 HELP.LYFT.COM CA 06/29 (...0029) Card -$11.99 -$208.17 +Jul 1, 2024 SQ *BRIOCHE BAKERY & San Francisco CA 06/28 (...0029) Card -$21.73 -$196.18 +Jul 1, 2024 CHIPOTLE 0801 MOUNTAIN VIEW CA 06/28 (...0029) Card -$16.04 -$174.45 +Jul 1, 2024 LYFT *4 RIDES 06-2 HELP.LYFT.COM CA 06/30 (...0029) Card -$167.26 -$158.41 +Jul 1, 2024 ORIG CO NAME:STRIPE ORIG ID:4270465600 DESC DATE: CO ENTRY DESCR:TRANSFER SEC:CCD TRACE#:111000028483776 EED:240701 IND ID:ST-D0P1O6R3S4R7 IND NAME:KYE GOMEZ TRN: 1838483776TC ACH credit $18.71 $8.85 +Jun 28, 2024 MONTHLY SERVICE FEE +Fee -$15.00 -$9.86 +Jun 28, 2024 ORIG CO NAME:STRIPE ORIG ID:1800948598 DESC DATE: CO ENTRY DESCR:TRANSFER SEC:CCD TRACE#:091000012519287 EED:240628 IND ID:ST-N8K5T9C8E2Y8 IND NAME:KYE GOMEZ TRN: 1802519287TC ACH debit -$175.20 $5.14 +Jun 28, 2024 LYFT *1 RIDE 06-26 HELP.LYFT.COM CA 06/28 (...0029) Card -$51.73 $180.34 +Jun 28, 2024 SQ *SHACK15 San Francisco CA 06/27 (...0029) Card -$5.37 $232.07 +Jun 28, 2024 CHIPOTLE 0801 MOUNTAIN VIEW CA 06/27 (...0029) Card -$25.86 $237.44 +Jun 28, 2024 PAYPAL *CANVAPTYLIM 35314369001 06/27 (...0029) Card -$250.00 $263.30 +Jun 27, 2024 UBER *TRIP SAN FRANCISCO CA 407732 06/26 (...0029) Card -$18.73 $513.30 +Jun 27, 2024 CHIPOTLE 0801 MOUNTAIN VIEW CA 06/26 (...0029) Card -$26.35 $532.03 +Jun 27, 2024 LULU'S ON THE ALAMEDA MENLO PARK CA 06/26 (...0029) Card -$30.28 $558.38 +Jun 27, 2024 LYFT *3 RIDES 06-2 HELP.LYFT.COM CA 06/27 (...0029) Card -$40.48 $588.66 +Jun 26, 2024 LULU'S ON THE ALAMEDA MENLO PARK CA 06/25 (...0029) Card -$41.21 $629.14 +Jun 26, 2024 LYFT *6 RIDES 06-2 HELP.LYFT.COM CA 06/26 (...0029) Card -$205.60 $670.35 +Jun 26, 2024 ORIG CO NAME:STRIPE ORIG ID:4270465600 DESC DATE: CO ENTRY DESCR:TRANSFER SEC:CCD TRACE#:111000022601747 EED:240626 IND ID:ST-M4C8I3J4I2U8 IND NAME:KYE GOMEZ TRN: 1782601747TC ACH credit $48.25 $875.95 +Jun 25, 2024 MCDONALDS F6641 SAN CARLOS CA 06/24 (...0029) Card -$16.26 $827.70 +Jun 25, 2024 SQ *SAPPORO ROCK-N-ROLL San Mateo CA 06/25 (...0029) Card -$52.24 $843.96 +Jun 25, 2024 LULU'S ON THE ALAMEDA MENLO PARK CA 06/24 (...0029) Card -$22.28 $896.20 +Jun 25, 2024 KEPLERS BOOKS MENLO PARK CA 06/24 (...0029) Card -$77.95 $918.48 +Jun 25, 2024 LYFT *1 RIDE 06-23 HELP.LYFT.COM CA 06/25 (...0029) Card -$7.99 $996.43 +Jun 25, 2024 ORIG CO NAME:STRIPE ORIG ID:4270465600 DESC DATE: CO ENTRY DESCR:TRANSFER SEC:CCD TRACE#:111000021325399 EED:240625 IND ID:ST-O1M2Y8X8B1Z1 IND NAME:KYE GOMEZ TRN: 1771325399TC ACH credit $9.26 $1,004.42 +Jun 24, 2024 LYFT *1 RIDE 06-22 HELP.LYFT.COM CA 06/24 (...0029) Card -$28.97 $995.16 +Jun 24, 2024 PY *CUN PALO ALTO PALO ALTO CA 06/23 (...0029) Card -$21.51 $1,024.13 +Jun 24, 2024 WALGREENS STORE 643 SA MENLO PARK CA 06/23 Purchase $5.79 Cash Back $20.00 (...0029) Card -$25.79 $1,045.64 +Jun 24, 2024 PAYPAL *ELENA_SMIRNOV 402-935-7733 CA 06/24 (...0029) Card -$10.59 $1,071.43 +Jun 24, 2024 LYFT *6 RIDES 06-2 HELP.LYFT.COM CA 06/23 (...0029) Card -$83.58 $1,082.02 +Jun 24, 2024 LULU'S ON THE ALAMEDA MENLO PARK CA 06/22 (...0029) Card -$26.35 $1,165.60 +Jun 24, 2024 LYFT *3 RIDES 06-2 HELP.LYFT.COM CA 06/22 (...0029) Card -$38.41 $1,191.95 +Jun 24, 2024 ORIG CO NAME:STRIPE ORIG ID:4270465600 DESC DATE: CO ENTRY DESCR:TRANSFER SEC:CCD TRACE#:111000026019819 EED:240624 IND ID:ST-M3H3N3G9F3G9 IND NAME:KYE GOMEZ TRN: 1766019819TC +""" + +# Run +response = function_caller.run( + f"Cut out all of the expenses on the transactions in the logs above that are not necessary expenses such as Meals and Entertainment and transportation, the startup is a bit tight on cash: {logs}, Analyze the expenses and provide a summary of the expenses that can be cut out and the amount of money that can be saved." +) + +# The run() method of the OpenAIFunctionCaller class is used to make a function call to the API. +# It takes a string parameter that represents the user's request or query. +print(response) diff --git a/playground/agents/tools/function_calling/openai_function_caller_agent_rearrange.py b/playground/agents/tools/function_calling/openai_function_caller_agent_rearrange.py new file mode 100644 index 00000000..165d831e --- /dev/null +++ b/playground/agents/tools/function_calling/openai_function_caller_agent_rearrange.py @@ -0,0 +1,52 @@ +from swarms.models.openai_function_caller import OpenAIFunctionCaller +from pydantic import BaseModel + + +# Pydantic is a data validation library that provides data validation and parsing using Python type hints. +# It is used here to define the data structure for making API calls to retrieve weather information. +class ModelCode(BaseModel): + file_name: str + model_code_in_pytorch: str + + +class TrainingCodeModel(BaseModel): + file_name: str + training_code: str + dataset_name: str + + +# The WeatherAPI class is a Pydantic BaseModel that represents the data structure +# for making API calls to retrieve weather information. It has two attributes: city and date. + +# Example usage: +# Initialize the function caller +model = OpenAIFunctionCaller( + system_prompt="You're a model engineer, you're purpose is to generate code in pytorch for a give model name and code", + max_tokens=4000, + temperature=0.5, + base_model=ModelCode, +) + +trainer = OpenAIFunctionCaller( + system_prompt="You're a model engineer, you're purpose is to generate the code for a given model architecture in pytorch to train using available datasets on huggingface", + max_tokens=4000, + temperature=0.5, + base_model=TrainingCodeModel, +) + +# The OpenAIFunctionCaller class is used to interact with the OpenAI API and make function calls. +# Here, we initialize an instance of the OpenAIFunctionCaller class with the following parameters: +# - system_prompt: A prompt that sets the context for the conversation with the API. +# - max_tokens: The maximum number of tokens to generate in the API response. +# - temperature: A parameter that controls the randomness of the generated text. +# - base_model: The base model to use for the API calls, in this case, the WeatherAPI class. +out = model.run( + "Generate a pytorch code for a sentiment analysis model using pytorch" +) +print(str(out)) + +# Trainer +out = trainer.run( + f"Generate the training code for the sentiment analysis model using pytorch: {trainer}" +) +print(out) diff --git a/playground/agents/tools/function_calling/openai_function_caller_example.py b/playground/agents/tools/function_calling/openai_function_caller_example.py new file mode 100644 index 00000000..c0a8f0a7 --- /dev/null +++ b/playground/agents/tools/function_calling/openai_function_caller_example.py @@ -0,0 +1,39 @@ +from swarms.models.openai_function_caller import OpenAIFunctionCaller +from pydantic import BaseModel + + +# Pydantic is a data validation library that provides data validation and parsing using Python type hints. +# It is used here to define the data structure for making API calls to retrieve weather information. +class WeatherAPI(BaseModel): + city: str + date: str + + +# The WeatherAPI class is a Pydantic BaseModel that represents the data structure +# for making API calls to retrieve weather information. It has two attributes: city and date. + + +# Example usage: +# Initialize the function caller +function_caller = OpenAIFunctionCaller( + system_prompt="You are a helpful assistant.", + max_tokens=500, + temperature=0.5, + base_model=WeatherAPI, +) + +# The OpenAIFunctionCaller class is used to interact with the OpenAI API and make function calls. +# Here, we initialize an instance of the OpenAIFunctionCaller class with the following parameters: +# - system_prompt: A prompt that sets the context for the conversation with the API. +# - max_tokens: The maximum number of tokens to generate in the API response. +# - temperature: A parameter that controls the randomness of the generated text. +# - base_model: The base model to use for the API calls, in this case, the WeatherAPI class. + +# Run the function caller +response = function_caller.run( + "Get the weather forecast for New York City on July 4th, 2022." +) + +# The run() method of the OpenAIFunctionCaller class is used to make a function call to the API. +# It takes a string parameter that represents the user's request or query. +print(response) diff --git a/playground/agents/tools/function_calling/prompt_generator_agent.py b/playground/agents/tools/function_calling/prompt_generator_agent.py new file mode 100644 index 00000000..ae270ae8 --- /dev/null +++ b/playground/agents/tools/function_calling/prompt_generator_agent.py @@ -0,0 +1,55 @@ +from swarms.models.openai_function_caller import OpenAIFunctionCaller +from pydantic import BaseModel, Field +from typing import Sequence + + +class PromptUseCase(BaseModel): + use_case_name: str = Field( + ..., + description="The name of the use case", + ) + use_case_description: str = Field( + ..., + description="The description of the use case", + ) + + +class PromptSpec(BaseModel): + prompt_name: str = Field( + ..., + description="The name of the prompt", + ) + prompt_description: str = Field( + ..., + description="The description of the prompt", + ) + prompt: str = Field( + ..., + description="The prompt for the agent", + ) + tags: str = Field( + ..., + description="The tags for the prompt such as sentiment, code, etc seperated by commas.", + ) + use_cases: Sequence[PromptUseCase] = Field( + ..., + description="The use cases for the prompt", + ) + + +# Example usage: +# Initialize the function caller +model = OpenAIFunctionCaller( + system_prompt="You're an agent creator, you're purpose is to create system prompt for new LLM Agents for the user. Follow the best practices for creating a prompt such as making it direct and clear. Providing instructions and many-shot examples will help the agent understand the task better.", + max_tokens=1000, + temperature=0.5, + base_model=PromptSpec, + parallel_tool_calls=False, +) + + +# The OpenAIFunctionCaller class is used to interact with the OpenAI API and make function calls. +out = model.run( + "Create an prompt for generating quality rust code with instructions and examples." +) +print(out) diff --git a/playground/agents/tools/function_calling/rag_with_codebase.py b/playground/agents/tools/function_calling/rag_with_codebase.py new file mode 100644 index 00000000..bb6596d7 --- /dev/null +++ b/playground/agents/tools/function_calling/rag_with_codebase.py @@ -0,0 +1,69 @@ +import os + +from swarms_memory import ChromaDB + +from swarms import Agent, OpenAIChat, AgentRearrange + +# Initilaize the chromadb client +chromadb = ChromaDB( + metric="cosine", + output_dir="swarms_framework_onboardig_agent", + docs_folder="docs", # Folder of your documents + n_results=1, + limit_tokens=1000, +) + +# Get the OpenAI API key from the environment variable +api_key = os.getenv("OPENAI_API_KEY") + +# Create an instance of the OpenAIChat class +model = OpenAIChat( + api_key=api_key, + model_name="gpt-4o-mini", + temperature=0.1, +) + + +# Initialize the concept understanding agent +concept_agent = Agent( + agent_name="Concept-Understanding-Agent", + system_prompt="You're purpose is to understand the swarms framework conceptually and architecturally, you'll work with the code generation agent to generate code snippets", + agent_description="Agent for understanding concepts", + llm=model, + max_loops="auto", + autosave=True, + verbose=True, + saved_state_path="concept_agent.json", + interactive=True, + context_length=160000, + memory_chunk_size=2000, +) + +# Initialize the code generation agent +code_agent = Agent( + agent_name="Code-Generation-Agent", + system_prompt="You're purpose is to generate code snippets for the swarms framework, you'll work with the concept understanding agent to understand concepts.", + agent_description="Agent for generating code", + llm=model, + max_loops="auto", + autosave=True, + verbose=True, + saved_state_path="code_agent.json", + interactive=True, + context_length=160000, + memory_chunk_size=2000, +) + + +# Swarm +swarm = AgentRearrange( + agents=[concept_agent, code_agent], + flow=f"{concept_agent.agent_name} -> {code_agent.agent_name}", + max_loops=1, + memory_system=chromadb, +) + +# Run +swarm.run( + "Let's understand the agentrearrange class in the swarms framework" +) diff --git a/playground/agents/tools/function_calling/sentiment_analysis_function_calling.py b/playground/agents/tools/function_calling/sentiment_analysis_function_calling.py new file mode 100644 index 00000000..b0329b94 --- /dev/null +++ b/playground/agents/tools/function_calling/sentiment_analysis_function_calling.py @@ -0,0 +1,39 @@ +from swarms.models.openai_function_caller import OpenAIFunctionCaller +from pydantic import BaseModel, Field + + +# Pydantic is a data validation library that provides data validation and parsing using Python type hints. +# It is used here to define the data structure for making API calls to retrieve weather information. +class SentimentAnalysisCard(BaseModel): + text: str = Field( + ..., + description="The text to be analyzed for sentiment rating", + ) + rating: str = Field( + ..., + description="The sentiment rating of the text from 0.0 to 1.0", + ) + + +# The WeatherAPI class is a Pydantic BaseModel that represents the data structure +# for making API calls to retrieve weather information. It has two attributes: city and date. + +# Example usage: +# Initialize the function caller +model = OpenAIFunctionCaller( + system_prompt="You're a sentiment Analysis Agent, you're purpose is to rate the sentiment of text", + max_tokens=100, + temperature=0.5, + base_model=SentimentAnalysisCard, + parallel_tool_calls=False, +) + + +# The OpenAIFunctionCaller class is used to interact with the OpenAI API and make function calls. +# Here, we initialize an instance of the OpenAIFunctionCaller class with the following parameters: +# - system_prompt: A prompt that sets the context for the conversation with the API. +# - max_tokens: The maximum number of tokens to generate in the API response. +# - temperature: A parameter that controls the randomness of the generated text. +# - base_model: The base model to use for the API calls, in this case, the WeatherAPI class. +out = model.run("The hotel was average, but the food was excellent.") +print(out) diff --git a/playground/agents/multion/multion_example.ipynb b/playground/agents/use_cases/browser/multion/multion_example.ipynb similarity index 100% rename from playground/agents/multion/multion_example.ipynb rename to playground/agents/use_cases/browser/multion/multion_example.ipynb diff --git a/playground/agents/multion_examples/ multion_example.py b/playground/agents/use_cases/browser/multion_examples/ multion_example.py similarity index 100% rename from playground/agents/multion_examples/ multion_example.py rename to playground/agents/use_cases/browser/multion_examples/ multion_example.py diff --git a/playground/agents/multion_examples/buy_abunch_of_cybertrucks.py b/playground/agents/use_cases/browser/multion_examples/buy_abunch_of_cybertrucks.py similarity index 100% rename from playground/agents/multion_examples/buy_abunch_of_cybertrucks.py rename to playground/agents/use_cases/browser/multion_examples/buy_abunch_of_cybertrucks.py diff --git a/playground/agents/use_cases/code_gen/sql_agent.py b/playground/agents/use_cases/code_gen/sql_agent.py new file mode 100644 index 00000000..bdfd9966 --- /dev/null +++ b/playground/agents/use_cases/code_gen/sql_agent.py @@ -0,0 +1,247 @@ +import os +from swarms import Agent, OpenAIChat + +# Get the OpenAI API key from the environment variable +api_key = os.getenv("OPENAI_API_KEY") + +# Create an instance of the OpenAIChat class +model = OpenAIChat( + api_key=api_key, model_name="gpt-4o-mini", temperature=0.1 +) + + +SQL_SYSTEM_PROMPT = """ + +### System Prompt for SQL Data Generator Agent + +**Role**: You are an advanced SQL Data Generator agent. Your task is to help users generate realistic SQL data schemas, understand existing schemas, and create efficient queries to interact with these schemas. You should provide thorough explanations, reasonings, and examples to guide the users. + +### Instructions for Generating Schemas + +1. **Understand the Domain**: + - Start by understanding the domain or business context for which the schema is being created. Ask relevant questions to gather necessary details. + +2. **Identify Entities**: + - Identify the main entities (tables) that need to be represented. Common entities include customers, orders, products, employees, etc. + +3. **Define Attributes**: + - For each entity, list the attributes (columns) that describe the entity. Attributes should be relevant to the domain and should include data types. + +4. **Establish Relationships**: + - Determine the relationships between entities (e.g., one-to-many, many-to-many) and represent these using foreign keys. + +5. **Normalization**: + - Normalize the schema to reduce data redundancy and improve data integrity. Follow normal forms guidelines up to the third normal form (3NF) unless denormalization is justified by performance needs. + +### Instructions for Understanding Schemas + +1. **Schema Overview**: + - Provide a high-level overview of the schema, listing all tables and their primary keys. + +2. **Table Details**: + - For each table, list its columns with data types and constraints (e.g., NOT NULL, UNIQUE). + +3. **Relationships and Keys**: + - Explain the foreign key relationships between tables, including the cardinality of each relationship. + +4. **Indexing**: + - Describe any indexes that exist on the tables and explain their purpose. + +### Instructions for Querying Tables + +1. **Basic Queries**: + - Demonstrate how to write basic SQL queries to select, insert, update, and delete data in the tables. + +2. **Complex Queries**: + - Show how to perform complex queries involving joins, subqueries, and aggregation functions. + +3. **Optimization**: + - Provide tips for optimizing queries for better performance, such as using indexes and avoiding unnecessary computations. + +### Conversational Examples + +#### Example 1: Generating a Schema + +**User**: I need to create a schema for an e-commerce platform. Can you help me with that? + +**Agent**: +Sure! Let's start by identifying the main entities. For an e-commerce platform, we typically have entities like Customers, Orders, Products, and OrderItems. Does that sound right? + +**User**: Yes, that's correct. + +**Agent**: +Great! Now, let's define the attributes for each entity. + +- **Customers**: + - customer_id (INT, PRIMARY KEY) + - first_name (VARCHAR(50)) + - last_name (VARCHAR(50)) + - email (VARCHAR(100), UNIQUE) + - phone (VARCHAR(20)) + +- **Products**: + - product_id (INT, PRIMARY KEY) + - name (VARCHAR(100)) + - description (TEXT) + - price (DECIMAL(10, 2)) + +- **Orders**: + - order_id (INT, PRIMARY KEY) + - customer_id (INT, FOREIGN KEY references Customers(customer_id)) + - order_date (DATE) + +- **OrderItems**: + - order_item_id (INT, PRIMARY KEY) + - order_id (INT, FOREIGN KEY references Orders(order_id)) + - product_id (INT, FOREIGN KEY references Products(product_id)) + - quantity (INT) + +Here is the SQL code to create these tables: + +```sql +CREATE TABLE Customers ( + customer_id INT PRIMARY KEY, + first_name VARCHAR(50), + last_name VARCHAR(50), + email VARCHAR(100) UNIQUE, + phone VARCHAR(20) +); + +CREATE TABLE Products ( + product_id INT PRIMARY KEY, + name VARCHAR(100), + description TEXT, + price DECIMAL(10, 2) +); + +CREATE TABLE Orders ( + order_id INT PRIMARY KEY, + customer_id INT, + order_date DATE, + FOREIGN KEY (customer_id) REFERENCES Customers(customer_id) +); + +CREATE TABLE OrderItems ( + order_item_id INT PRIMARY KEY, + order_id INT, + product_id INT, + quantity INT, + FOREIGN KEY (order_id) REFERENCES Orders(order_id), + FOREIGN KEY (product_id) REFERENCES Products(product_id) +); +``` + +#### Example 2: Understanding a Schema + +**User**: I have an existing schema for a library system. Can you help me understand it? + +**Agent**: +Of course! Let's start with a high-level overview. Could you provide the names of the tables? + +**User**: The tables are Books, Authors, and BookAuthors. + +**Agent**: +Great! Here's a brief overview: + +- **Books**: + - book_id (INT, PRIMARY KEY) + - title (VARCHAR(100)) + - genre (VARCHAR(50)) + - published_date (DATE) + +- **Authors**: + - author_id (INT, PRIMARY KEY) + - first_name (VARCHAR(50)) + - last_name (VARCHAR(50)) + +- **BookAuthors**: + - book_id (INT, FOREIGN KEY references Books(book_id)) + - author_id (INT, FOREIGN KEY references Authors(author_id)) + - PRIMARY KEY (book_id, author_id) + +The `Books` table contains information about each book, `Authors` contains information about each author, and `BookAuthors` is a junction table that handles the many-to-many relationship between books and authors. + +Here is the SQL code for these tables: + +```sql +CREATE TABLE Books ( + book_id INT PRIMARY KEY, + title VARCHAR(100), + genre VARCHAR(50), + published_date DATE +); + +CREATE TABLE Authors ( + author_id INT PRIMARY KEY, + first_name VARCHAR(50), + last_name VARCHAR(50) +); + +CREATE TABLE BookAuthors ( + book_id INT, + author_id INT, + PRIMARY KEY (book_id, author_id), + FOREIGN KEY (book_id) REFERENCES Books(book_id), + FOREIGN KEY (author_id) REFERENCES Authors(author_id) +); +``` + +#### Example 3: Querying Tables + +**User**: How can I write a query to find all orders placed by a customer with a specific email? + +**Agent**: +First, we need to join the `Customers` and `Orders` tables on the `customer_id` column. Then, we filter the results by the customer's email. Here’s how you can do it: + +```sql +SELECT Orders.order_id, Orders.order_date +FROM Customers +JOIN Orders ON Customers.customer_id = Orders.customer_id +WHERE Customers.email = 'example@example.com'; +``` + +This query selects the order IDs and order dates for all orders placed by the customer with the email 'example@example.com'. + +--- + +This system prompt and the accompanying examples should help the SQL data generator agent assist users effectively in generating schemas, understanding them, and writing queries. + + +""" + +# Initialize the agent +agent = Agent( + agent_name="SQL-Agent", + system_prompt=SQL_SYSTEM_PROMPT, + llm=model, + max_loops=1, + autosave=True, + # dynamic_temperature_enabled=True, + dashboard=False, + code_interpreter=True, + verbose=True, + streaming_on=True, + # interactive=True, # Set to False to disable interactive mode + dynamic_temperature_enabled=True, + saved_state_path="finance_agent.json", + # tools=[#Add your functions here# ], + # stopping_token="Stop!", + interactive=True, + # docs_folder="docs", # Enter your folder name + # pdf_path="docs/finance_agent.pdf", + # sop="Calculate the profit for a company.", + # sop_list=["Calculate the profit for a company."], + user_name="swarms_corp", + # # docs= + # # docs_folder="docs", + retry_attempts=3, + # context_length=1000, + # tool_schema = dict + context_length=200000, + # agent_ops_on=True, +) + + +agent.run( + "Let's create a sql schema table for a brand ambassadors program, they share a link and we track the people that sign up and provide them with a unique code to share. The schema should include tables for ambassadors, signups, and codes." +) diff --git a/playground/agents/use_cases/finance/401k_agent.py b/playground/agents/use_cases/finance/401k_agent.py new file mode 100644 index 00000000..a53f28d9 --- /dev/null +++ b/playground/agents/use_cases/finance/401k_agent.py @@ -0,0 +1,149 @@ +import os + +from swarms import Agent, HuggingfaceLLM + +# Get the OpenAI API key from the environment variable +api_key = os.getenv("OPENAI_API_KEY") + +# Create an instance of the OpenAIChat class +# model = OpenAIChat( +# api_key=api_key, model_name="gpt-4o-mini", temperature=0.1 +# ) + +model = HuggingfaceLLM( + model_id="bert-base-uncased", +) + + +# Prompt +ROTH_IRA_SYSTEM_PROMPT = """ +### System Prompt for a 401(k) and Roth IRA Management Agent + +#### Introduction +You are a highly intelligent and empathetic AI agent specialized in helping individuals set up, manage, and run their 401(k) and Roth IRA accounts. Your primary goal is to assist users in making informed decisions about their retirement savings. You should always provide clear, concise, and accurate information, taking into account the user's specific situation and needs. + +#### Goals +1. Help users understand the basics of 401(k) and Roth IRA accounts. +2. Assist users in setting up new accounts. +3. Guide users in managing their existing accounts. +4. Provide personalized advice based on the user's financial goals and situation. +5. Ensure users are aware of the tax implications and benefits of their retirement accounts. +6. Encourage users to think long-term and make decisions that align with their retirement goals. + +#### How to Think +1. **Empathy and Understanding**: Always show empathy and understanding towards the user's situation. Acknowledge their concerns and provide reassurance. +2. **Personalization**: Tailor your responses to the user's specific financial situation, goals, and needs. +3. **Clarity and Simplicity**: Use clear and simple language to explain complex financial concepts. Avoid jargon unless it is necessary, and always define any terms you use. +4. **Accuracy and Reliability**: Provide accurate and reliable information. If you are unsure about something, indicate that and suggest consulting a financial advisor for specific advice. +5. **Encouragement**: Encourage users to save and invest wisely for their retirement. Highlight the benefits of planning ahead and making informed decisions. + +#### Multi-Shot Conversational Examples + +**Example 1: Setting up a 401(k)** + +**User**: I just started a new job and they offer a 401(k) plan. How do I set it up? + +**Agent**: Congratulations on your new job! Setting up a 401(k) is a great step towards securing your retirement. Here's what you need to do: + +1. **Enroll in the Plan**: Contact your HR department or benefits coordinator to get the enrollment forms. They will guide you through the process. +2. **Contribution Amount**: Decide how much you want to contribute from each paycheck. It's often recommended to contribute enough to get the full employer match if your company offers one. +3. **Investment Options**: Choose how you want to invest your contributions. Most plans offer a range of options, from conservative to aggressive. Consider your risk tolerance and retirement timeline. +4. **Beneficiaries**: Designate a beneficiary for your account in case something happens to you. + +Would you like more detailed guidance on any of these steps? + +**Example 2: Managing a Roth IRA** + +**User**: I already have a Roth IRA. How should I manage it to maximize my returns? + +**Agent**: Great to hear that you have a Roth IRA! Here are some tips to help you manage it effectively: + +1. **Regular Contributions**: Make regular contributions to your Roth IRA. For 2023, the maximum contribution is $6,500 ($7,500 if you're 50 or older). +2. **Investment Diversification**: Diversify your investments to spread risk. Consider a mix of stocks, bonds, and other assets that align with your risk tolerance and time horizon. +3. **Rebalancing**: Periodically rebalance your portfolio to maintain your desired asset allocation. This means adjusting your investments to ensure you are not too heavily weighted in one area. +4. **Tax Considerations**: Remember that qualified withdrawals from a Roth IRA are tax-free. This can be a great advantage in retirement. +5. **Stay Informed**: Keep up-to-date with financial news and consider consulting a financial advisor for personalized advice. + +Is there a specific aspect of your Roth IRA management you need more help with? + +**Example 3: Understanding Tax Implications** + +**User**: What are the tax implications of withdrawing from my 401(k) and Roth IRA? + +**Agent**: Understanding the tax implications is crucial for making smart withdrawal decisions. Here's a brief overview: + +1. **401(k) Withdrawals**: Withdrawals from a traditional 401(k) are generally taxed as ordinary income. If you withdraw before age 59½, you may also face a 10% early withdrawal penalty, unless you qualify for an exception. +2. **Roth IRA Withdrawals**: Qualified withdrawals from a Roth IRA are tax-free. To be qualified, the account must have been open for at least 5 years, and you must be 59½ or older, disabled, or using the withdrawal for a first-time home purchase (up to a $10,000 lifetime limit). + +It's important to plan your withdrawals carefully to minimize taxes and penalties. Would you like more detailed information on this topic? + +**Example 4: Retirement Planning** + +**User**: How do I know if I'm saving enough for retirement? + +**Agent**: That's a great question and a common concern. Here are some steps to help you determine if you're on track: + +1. **Calculate Your Retirement Needs**: Estimate how much money you'll need in retirement. Consider your desired lifestyle, expected expenses, and how long you plan to be retired. +2. **Assess Your Savings**: Add up your current retirement savings, including your 401(k), IRA, and any other accounts. Use online retirement calculators to project your future savings based on your current contribution rate and expected investment returns. +3. **Contribution Rate**: Aim to save at least 15% of your income for retirement. If you started late, you might need to save more. +4. **Adjust as Needed**: If you're not on track, consider increasing your contributions, reducing expenses, or adjusting your investment strategy. + +Would you like to use a retirement calculator to get a more precise estimate? + +**Example 5: Choosing Between 401(k) and Roth IRA** + +**User**: Should I contribute to my 401(k) or a Roth IRA? + +**Agent**: Both 401(k) and Roth IRA accounts have their advantages. Here are some factors to consider: + +1. **Tax Treatment**: Contributions to a traditional 401(k) are tax-deductible, reducing your taxable income now. Roth IRA contributions are made with after-tax dollars, but qualified withdrawals are tax-free. +2. **Employer Match**: If your employer offers a match on your 401(k) contributions, it's generally a good idea to contribute enough to get the full match. It's essentially free money. +3. **Income Limits**: Roth IRAs have income limits for contributions. If your income is too high, you may not be eligible to contribute directly to a Roth IRA. +4. **Withdrawal Flexibility**: Roth IRAs offer more flexibility for withdrawals, especially in retirement, since they are tax-free and not subject to required minimum distributions (RMDs). + +Consider your current tax situation, expected future tax rates, and retirement goals when making your decision. Would you like to explore this further based on your specific circumstances? + +### Closing Remarks +Always prioritize the user's specific needs and provide clear, accurate, and empathetic guidance. Your goal is to empower users to make informed decisions about their retirement savings and help them achieve financial security. + +--- + +This 3,000-word system prompt ensures the LLM agent is well-equipped to assist users with their 401(k) and Roth IRA accounts, providing detailed examples to guide the agent in reasoning and problem-solving. + +""" + +# Initialize the agent +agent = Agent( + agent_name="401K-Roth-IRA-Agent", + system_prompt=ROTH_IRA_SYSTEM_PROMPT, + llm=model, + max_loops="auto", + autosave=True, + dashboard=False, + verbose=True, + streaming_on=True, + interactive=True, + # interactive=True, # Set to False to disable interactive mode + saved_state_path="finance_agent.json", + # tools=[Add your functions here# ], + # stopping_token="Stop!", + # interactive=True, + # docs_folder="docs", # Enter your folder name + # pdf_path="docs/finance_agent.pdf", + # sop="Calculate the profit for a company.", + # sop_list=["Calculate the profit for a company."], + user_name="swarms_corp", + # # docs= + # # docs_folder="docs", + retry_attempts=3, + # context_length=1000, + # tool_schema = dict + context_length=200000, + # agent_ops_on=True, + # long_term_memory=ChromaDB(docs_folder="artifacts"), +) + + +agent.run( + "Create a comprehensive guide on setting up and managing a Roth IRA account." +) diff --git a/playground/structs/swarms/different_architectures/circular_swarm.py b/playground/structs/swarms/different_architectures/circular_swarm.py new file mode 100644 index 00000000..8fdfaff5 --- /dev/null +++ b/playground/structs/swarms/different_architectures/circular_swarm.py @@ -0,0 +1,100 @@ +import os +from swarms import Agent, OpenAIChat +from swarms.prompts.finance_agent_sys_prompt import ( + FINANCIAL_AGENT_SYS_PROMPT, +) +from swarms.structs.swarming_architectures import ( + circular_swarm, +) + +# Get the OpenAI API key from the environment variable +api_key = os.getenv("OPENAI_API_KEY") + +# Create an instance of the OpenAIChat class +model = OpenAIChat( + api_key=api_key, model_name="gpt-4o-mini", temperature=0.1 +) + +# Initialize the agents +financial_agent1 = Agent( + agent_name="Financial-Analysis-Agent1", + system_prompt=FINANCIAL_AGENT_SYS_PROMPT, + llm=model, + max_loops=1, + autosave=True, + dashboard=False, + verbose=True, + streaming_on=True, + dynamic_temperature_enabled=True, + saved_state_path="finance_agent1.json", + user_name="swarms_corp", + retry_attempts=3, + context_length=200000, +) + +financial_agent2 = Agent( + agent_name="Financial-Analysis-Agent2", + system_prompt=FINANCIAL_AGENT_SYS_PROMPT, + llm=model, + max_loops=1, + autosave=True, + dashboard=False, + verbose=True, + streaming_on=True, + dynamic_temperature_enabled=True, + saved_state_path="finance_agent2.json", + user_name="swarms_corp", + retry_attempts=3, + context_length=200000, +) + +financial_agent3 = Agent( + agent_name="Financial-Analysis-Agent3", + system_prompt=FINANCIAL_AGENT_SYS_PROMPT, + llm=model, + max_loops=1, + autosave=True, + dashboard=False, + verbose=True, + streaming_on=True, + dynamic_temperature_enabled=True, + saved_state_path="finance_agent3.json", + user_name="swarms_corp", + retry_attempts=3, + context_length=200000, +) + +financial_agent4 = Agent( + agent_name="Financial-Analysis-Agent4", + system_prompt=FINANCIAL_AGENT_SYS_PROMPT, + llm=model, + max_loops=1, + autosave=True, + dashboard=False, + verbose=True, + streaming_on=True, + dynamic_temperature_enabled=True, + saved_state_path="finance_agent4.json", + user_name="swarms_corp", + retry_attempts=3, + context_length=200000, +) + +# Agents +agents = [ + financial_agent1, + financial_agent2, + financial_agent3, + financial_agent4, +] +task = [ + "How can I establish a ROTH IRA to buy stocks and get a tax break? What are the criteria" + "What's the best platform to setup a trust?" + "How can I get a loan to start a business?", +] + +# Run the agents in a circular swarm +response = circular_swarm( + agents=agents, tasks=task, return_full_history=True +) +print(response) diff --git a/playground/structs/swarms/different_architectures/one_to_one_agent_discussion_example.py b/playground/structs/swarms/different_architectures/one_to_one_agent_discussion_example.py new file mode 100644 index 00000000..83e64bef --- /dev/null +++ b/playground/structs/swarms/different_architectures/one_to_one_agent_discussion_example.py @@ -0,0 +1,54 @@ +import os + +from swarms import Agent, OpenAIChat, one_to_one + +# Get the OpenAI API key from the environment variable +api_key = os.getenv("OPENAI_API_KEY") + +# Create an instance of the OpenAIChat class +model = OpenAIChat( + api_key=api_key, model_name="gpt-4o-mini", temperature=0.1 +) + +# Initialize the agents +financial_agent1 = Agent( + agent_name="Financial-Analysis-Agent1", + # system_prompt=FINANCIAL_AGENT_SYS_PROMPT, + llm=model, + max_loops=1, + autosave=True, + dashboard=False, + verbose=True, + streaming_on=True, + dynamic_temperature_enabled=True, + saved_state_path="finance_agent1.json", + user_name="swarms_corp", + context_length=200000, +) + +financial_agent2 = Agent( + agent_name="Financial-Analysis-Agent2", + # system_prompt=FINANCIAL_AGENT_SYS_PROMPT, + llm=model, + max_loops=1, + autosave=True, + dashboard=False, + verbose=True, + streaming_on=True, + dynamic_temperature_enabled=True, + saved_state_path="finance_agent2.json", + user_name="swarms_corp", + context_length=200000, +) + +# Agents +task = "How can I establish a ROTH IRA to buy stocks and get a tax break? What are the criteria, Discuss with eachother to get the best answer." + +# Run the agents in a circular swarm +response = one_to_one( + sender=financial_agent1, + receiver=financial_agent2, + task=task, + max_loops=1, +) +print(response) diff --git a/playground/structs/swarms/different_architectures/star_swarm.py b/playground/structs/swarms/different_architectures/star_swarm.py new file mode 100644 index 00000000..2b3ec2a3 --- /dev/null +++ b/playground/structs/swarms/different_architectures/star_swarm.py @@ -0,0 +1,101 @@ +import os +from swarms import Agent, OpenAIChat +from swarms.prompts.finance_agent_sys_prompt import ( + FINANCIAL_AGENT_SYS_PROMPT, +) +from swarms.structs.swarming_architectures import ( + star_swarm, +) + +# Get the OpenAI API key from the environment variable +api_key = os.getenv("OPENAI_API_KEY") + +# Create an instance of the OpenAIChat class +model = OpenAIChat( + api_key=api_key, model_name="gpt-4o-mini", temperature=0.1 +) + +# Initialize the agents +financial_agent1 = Agent( + agent_name="Financial-Analysis-Agent1", + system_prompt=FINANCIAL_AGENT_SYS_PROMPT, + llm=model, + max_loops=1, + autosave=True, + dashboard=False, + verbose=True, + streaming_on=True, + dynamic_temperature_enabled=True, + saved_state_path="finance_agent1.json", + user_name="swarms_corp", + retry_attempts=3, + context_length=200000, +) + +financial_agent2 = Agent( + agent_name="Financial-Analysis-Agent2", + system_prompt=FINANCIAL_AGENT_SYS_PROMPT, + llm=model, + max_loops=1, + autosave=True, + dashboard=False, + verbose=True, + streaming_on=True, + dynamic_temperature_enabled=True, + saved_state_path="finance_agent2.json", + user_name="swarms_corp", + retry_attempts=3, + context_length=200000, +) + +financial_agent3 = Agent( + agent_name="Financial-Analysis-Agent3", + system_prompt=FINANCIAL_AGENT_SYS_PROMPT, + llm=model, + max_loops=1, + autosave=True, + dashboard=False, + verbose=True, + streaming_on=True, + dynamic_temperature_enabled=True, + saved_state_path="finance_agent3.json", + user_name="swarms_corp", + retry_attempts=3, + context_length=200000, +) + +financial_agent4 = Agent( + agent_name="Financial-Analysis-Agent4", + system_prompt=FINANCIAL_AGENT_SYS_PROMPT, + llm=model, + max_loops=1, + autosave=True, + dashboard=False, + verbose=True, + streaming_on=True, + dynamic_temperature_enabled=True, + saved_state_path="finance_agent4.json", + user_name="swarms_corp", + retry_attempts=3, + context_length=200000, +) + +# Agents +agents = [ + financial_agent1, + financial_agent2, + financial_agent3, + financial_agent4, +] +task = [ + "How can I establish a ROTH IRA to buy stocks and get a tax break? What are the criteria" + "What's the best platform to setup a trust?" + "How can I get a loan to start a business?", +] + +# Run the agents in a circular swarm +response = star_swarm( + agents=agents, + tasks=task, +) +print(response) diff --git a/pyproject.toml b/pyproject.toml index 6591da4b..0fdaafd3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "poetry.core.masonry.api" [tool.poetry] name = "swarms" -version = "5.4.5" +version = "5.4.6" description = "Swarms - Pytorch" license = "MIT" authors = ["Kye Gomez "] @@ -35,6 +35,8 @@ keywords = [ "Agents", "Generative Agents", "Generative AI", + "Agent Marketplace", + "Agent Store", ] classifiers = [ "Development Status :: 4 - Beta", diff --git a/swarms/artifacts/main_artifact.py b/swarms/artifacts/main_artifact.py index 27be48cb..e45bcdc1 100644 --- a/swarms/artifacts/main_artifact.py +++ b/swarms/artifacts/main_artifact.py @@ -2,7 +2,7 @@ from swarms.utils.loguru_logger import logger import os import json from typing import List, Union, Dict, Any -from pydantic.v1 import BaseModel, Field, validator +from pydantic import BaseModel, Field, validator from datetime import datetime @@ -11,9 +11,13 @@ class FileVersion(BaseModel): Represents a version of the file with its content and timestamp. """ - version_number: int - content: str - timestamp: datetime + version_number: int = Field( + ..., description="The version number of the file" + ) + content: str = Field( + ..., description="The content of the file version" + ) + timestamp: str = Field(default_factory=datetime.now) def __str__(self) -> str: return f"Version {self.version_number} (Timestamp: {self.timestamp}):\n{self.content}" @@ -31,11 +35,19 @@ class Artifact(BaseModel): edit_count (int): The number of times the file has been edited. """ - file_path: str - file_type: str - contents: str = Field(default="") + file_path: str = Field(..., description="The path to the file") + file_type: str = Field( + ..., + description="The type of the file", + # example=".txt", + ) + contents: str = Field( + ..., description="The contents of the file in string format" + ) versions: List[FileVersion] = Field(default_factory=list) - edit_count: int = Field(default=0) + edit_count: int = Field( + ..., description="The number of times the file has been edited" + ) @validator("file_type", pre=True, always=True) def validate_file_type(cls, v, values): diff --git a/swarms/models/__init__.py b/swarms/models/__init__.py index 6404d5c6..84f354d2 100644 --- a/swarms/models/__init__.py +++ b/swarms/models/__init__.py @@ -40,6 +40,7 @@ from swarms.models.types import ( # noqa: E402 ) from swarms.models.vilt import Vilt # noqa: E402 from swarms.models.popular_llms import FireWorksAI +from swarms.models.openai_function_caller import OpenAIFunctionCaller __all__ = [ "BaseEmbeddingModel", @@ -75,4 +76,5 @@ __all__ = [ "OpenAIEmbeddings", "llama3Hosted", "FireWorksAI", + "OpenAIFunctionCaller", ] diff --git a/swarms/models/openai_function_caller.py b/swarms/models/openai_function_caller.py new file mode 100644 index 00000000..29a755fb --- /dev/null +++ b/swarms/models/openai_function_caller.py @@ -0,0 +1,175 @@ +import openai +from pydantic import BaseModel +import os +from swarms.utils.loguru_logger import logger +from swarms.models.base_llm import BaseLLM +from typing import List + + +class OpenAIFunctionCaller(BaseLLM): + """ + A class that represents a caller for OpenAI chat completions. + + Args: + system_prompt (str): The system prompt to be used in the chat completion. + model_name (str): The name of the OpenAI model to be used. + max_tokens (int): The maximum number of tokens in the generated completion. + temperature (float): The temperature parameter for randomness in the completion. + base_model (BaseModel): The base model to be used for the completion. + openai_api_key (str): The API key for accessing the OpenAI service. + parallel_tool_calls (bool): Whether to make parallel tool calls. + top_p (float): The top-p parameter for nucleus sampling in the completion. + + Attributes: + system_prompt (str): The system prompt to be used in the chat completion. + model_name (str): The name of the OpenAI model to be used. + max_tokens (int): The maximum number of tokens in the generated completion. + temperature (float): The temperature parameter for randomness in the completion. + base_model (BaseModel): The base model to be used for the completion. + parallel_tool_calls (bool): Whether to make parallel tool calls. + top_p (float): The top-p parameter for nucleus sampling in the completion. + client (openai.OpenAI): The OpenAI client for making API calls. + + Methods: + check_api_key: Checks if the API key is provided and retrieves it from the environment if not. + run: Runs the chat completion with the given task and returns the generated completion. + + """ + + def __init__( + self, + system_prompt: str = None, + model_name: str = "gpt-4o-2024-08-06", + max_tokens: int = 4000, + temperature: float = 0.4, + base_model: BaseModel = None, + openai_api_key: str = None, + parallel_tool_calls: bool = False, + top_p: float = 0.9, + *args, + **kwargs, + ): + super().__init__(*args, **kwargs) + self.system_prompt = system_prompt + self.model_name = model_name + self.max_tokens = max_tokens + self.temperature = temperature + self.openai_api_key = openai_api_key + self.base_model = base_model + self.parallel_tool_calls = parallel_tool_calls + self.top_p = top_p + self.client = openai.OpenAI(api_key=self.check_api_key()) + + def check_api_key(self) -> str: + """ + Checks if the API key is provided and retrieves it from the environment if not. + + Returns: + str: The API key. + + """ + if self.openai_api_key is None: + self.openai_api_key = os.getenv("OPENAI_API_KEY") + + return self.openai_api_key + + def run(self, task: str, *args, **kwargs): + """ + Runs the chat completion with the given task and returns the generated completion. + + Args: + task (str): The user's task for the chat completion. + *args: Additional positional arguments to be passed to the OpenAI API. + **kwargs: Additional keyword arguments to be passed to the OpenAI API. + + Returns: + str: The generated completion. + + """ + try: + completion = self.client.beta.chat.completions.parse( + model=self.model_name, + messages=[ + {"role": "system", "content": self.system_prompt}, + {"role": "user", "content": task}, + ], + max_tokens=self.max_tokens, + temperature=self.temperature, + response_format=self.base_model, + parallel_tool_calls=self.parallel_tool_calls, + tools=([openai.pydantic_function_tool(self.base_model)]), + *args, + **kwargs, + ) + + out = ( + completion.choices[0] + # .message.tool_calls[0] + # .function.arguments + ) + + # Conver str to dict + # print(out) + # out = eval(out) + return out + except Exception as error: + logger.error( + f"Error in running OpenAI chat completion: {error}" + ) + return None + + def convert_to_dict_from_base_model( + self, base_model: BaseModel + ) -> dict: + return openai.pydantic_function_tool(base_model) + + def convert_list_of_base_models(self, base_models: List[BaseModel]): + """ + Converts a list of BaseModels to a list of dictionaries. + + Args: + base_models (List[BaseModel]): A list of BaseModels to be converted. + + Returns: + List[Dict]: A list of dictionaries representing the converted BaseModels. + """ + return [ + self.convert_to_dict_from_base_model(base_model) + for base_model in base_models + ] + + +# def agents_list( +# agents: List[Agent] = None, +# ) -> str: +# responses = [] + +# for agent in agents: +# name = agent.agent_name +# description = agent.description +# response = f"Agent Name {name}: Description {description}" +# responses.append(response) + +# return concat_strings(responses) + + +# class HierarchicalOrderCall(BaseModel): +# agent_name: str +# task: str + + +# # Example usage: +# # Initialize the function caller +# function_caller = OpenAIFunctionCaller( +# system_prompt="You are a helpful assistant.", +# openai_api_key=""," +# max_tokens=500, +# temperature=0.5, +# base_model=HierarchicalOrderCall, +# ) + +# # Run the function caller +# response = function_caller.run( +# "Send an order to the financial agent twice" +# ) +# print(response) diff --git a/swarms/models/tiktoken_wrapper.py b/swarms/models/tiktoken_wrapper.py index 4b94c59a..8c006117 100644 --- a/swarms/models/tiktoken_wrapper.py +++ b/swarms/models/tiktoken_wrapper.py @@ -4,7 +4,7 @@ import tiktoken class TikTokenizer: def __init__( self, - model_name: str = "gpt-4o", + model_name: str = "o200k_base", ): """ Initializes a TikTokenizer object. @@ -13,29 +13,13 @@ class TikTokenizer: model_name (str, optional): The name of the model to use for tokenization. Defaults to "gpt-4o". """ try: - self.tokenizer = tiktoken.encoding_for_model(model_name) + self.model_name = model_name + # self.tokenizer = tiktoken./(model_name) except Exception as e: raise ValueError( f"Failed to initialize tokenizer with model '{model_name}': {str(e)}" ) - def len(self, string: str) -> int: - """ - Returns the number of tokens in a text string. - - Args: - string (str): The input text string. - - Returns: - int: The number of tokens in the text string. - """ - try: - num_tokens = len(self.tokenizer.encode(string)) - print(f"Number of tokens: {num_tokens}") - return num_tokens - except Exception as e: - raise ValueError(f"Failed to tokenize string: {str(e)}") - def count_tokens(self, string: str) -> int: """ Returns the number of tokens in a text string. @@ -46,9 +30,7 @@ class TikTokenizer: Returns: int: The number of tokens in the text string. """ - try: - num_tokens = len(self.tokenizer.encode(string)) - print(f"Number of tokens: {num_tokens}") - return num_tokens - except Exception as e: - raise ValueError(f"Failed to count tokens: {str(e)}") + """Returns the number of tokens in a text string.""" + encoding = tiktoken.get_encoding(self.model_name) + num_tokens = len(encoding.encode(string)) + return num_tokens diff --git a/swarms/structs/agent.py b/swarms/structs/agent.py index fccfef2d..5cd2ff94 100644 --- a/swarms/structs/agent.py +++ b/swarms/structs/agent.py @@ -459,7 +459,9 @@ class Agent(BaseStructure): ) # If multiple base models, then conver them. - self.handle_multiple_base_models() + if self.list_base_models is not None: + + self.handle_multiple_base_models() # If the algorithm of thoughts is enabled then set the sop to the algorithm of thoughts if self.algorithm_of_thoughts is not False: @@ -763,32 +765,7 @@ class Agent(BaseStructure): while attempt < self.retry_attempts and not success: try: if self.long_term_memory is not None: - memory_retrieval = ( - self.long_term_memory_prompt( - task, *args, **kwargs - ) - ) - - if exists(self.tokenizer): - task_prompt = ( - self.count_and_shorten_context_window( - memory_retrieval - ) - ) - - # Merge the task prompt with the memory retrieval - task_prompt = f"{task_prompt} Documents: Available {memory_retrieval}" - - response = self.llm( - task_prompt, *args, **kwargs - ) - print(response) - - # Add to memory - self.short_memory.add( - role=self.agent_name, content=response - ) - all_responses.append(response) + self.memory_query(task_prompt) else: response_args = ( @@ -1005,42 +982,42 @@ class Agent(BaseStructure): ) ) - def long_term_memory_prompt(self, query: str, *args, **kwargs): - """ - Generate the agent long term memory prompt - - Args: - system_prompt (str): The system prompt - history (List[str]): The history of the conversation - - Returns: - str: The agent history prompt - """ - try: - logger.info(f"Querying long term memory database for {query}") - ltr = self.long_term_memory.query(query, *args, **kwargs) - - # Count the tokens - logger.info("Couting tokens of retrieved document") - ltr_count = self.tokenizer.count_tokens(ltr) - logger.info(f"Retrieved document token count {ltr_count}") - - if ltr_count > self.memory_chunk_size: - logger.info( - f"Truncating memory by {self.memory_chunk_size}" - ) - out = self.truncate_string_by_tokens( - ltr, self.memory_chunk_size - ) - logger.info( - f"Memory truncated by {self.memory_chunk_size}" - ) - - # Retrieve only the chunk size of the memory - return out - except Exception as error: - logger.error(f"Error querying long term memory: {error}") - raise error + # def long_term_memory_prompt(self, query: str, *args, **kwargs): + # """ + # Generate the agent long term memory prompt + + # Args: + # system_prompt (str): The system prompt + # history (List[str]): The history of the conversation + + # Returns: + # str: The agent history prompt + # """ + # try: + # logger.info(f"Querying long term memory database for {query}") + # ltr = self.long_term_memory.query(query, *args, **kwargs) + + # # Count the tokens + # logger.info("Couting tokens of retrieved document") + # ltr_count = self.tokenizer.count_tokens(ltr) + # logger.info(f"Retrieved document token count {ltr_count}") + + # if ltr_count > self.memory_chunk_size: + # logger.info( + # f"Truncating memory by {self.memory_chunk_size}" + # ) + # out = self.truncate_string_by_tokens( + # ltr, self.memory_chunk_size + # ) + # logger.info( + # f"Memory truncated by {self.memory_chunk_size}" + # ) + + # # Retrieve only the chunk size of the memory + # return out + # except Exception as error: + # logger.error(f"Error querying long term memory: {error}") + # raise error def add_memory(self, message: str): """Add a memory to the agent @@ -1720,13 +1697,24 @@ class Agent(BaseStructure): return None - def memory_query(self, task: str = None, *args, **kwargs): + def memory_query(self, task: str = None, *args, **kwargs) -> str: try: + # Query the long term memory if self.long_term_memory is not None: - memory_retrieval = self.long_term_memory_prompt( + logger.info(f"Querying long term memory for: {task}") + memory_retrieval = self.long_term_memory.query( task, *args, **kwargs ) - # print(len(memory_retrieval)) + + memory_token_count = self.tokenizer.count_tokens( + memory_retrieval + ) + + if memory_token_count > self.memory_chunk_size: + # Truncate the memory by the memory chunk size + memory_retrieval = self.truncate_string_by_tokens( + memory_retrieval, self.memory_chunk_size + ) # Merge the task prompt with the memory retrieval task_prompt = ( @@ -1739,6 +1727,7 @@ class Agent(BaseStructure): self.short_memory.add( role=self.agent_name, content=response ) + return response except Exception as e: print(f"An error occurred: {e}") diff --git a/swarms/structs/concat.py b/swarms/structs/concat.py index 6ed2c608..80570568 100644 --- a/swarms/structs/concat.py +++ b/swarms/structs/concat.py @@ -18,6 +18,9 @@ def concat_strings(string_list: List[str]) -> str: if not isinstance(string_list, list): raise TypeError("Input must be a list of strings.") + if not all(isinstance(string, str) for string in string_list): + raise TypeError("All elements in the list must be strings.") + try: return "".join(string_list) except TypeError: diff --git a/swarms/structs/concurrent_workflow.py b/swarms/structs/concurrent_workflow.py index 0104f07f..701b0a4a 100644 --- a/swarms/structs/concurrent_workflow.py +++ b/swarms/structs/concurrent_workflow.py @@ -6,14 +6,15 @@ from swarms.utils.loguru_logger import logger class ConcurrentWorkflow: - def __init__(self, agents: List[Agent], max_loops: int): - """ - Initializes the ConcurrentWorkflow with the given parameters. + """ + Initializes the ConcurrentWorkflow with the given parameters. - Args: - agents (List[Agent]): The list of agents to initialize. - max_loops (int): The maximum number of loops each agent can run. - """ + Args: + agents (List[Agent]): The list of agents to initialize. + max_loops (int): The maximum number of loops each agent can run. + """ + + def __init__(self, agents: List[Agent], max_loops: int): self.max_loops = max_loops self.agents = agents self.num_agents = len(agents) diff --git a/swarms/structs/hierarchical_swarm_openai.py b/swarms/structs/hierarchical_swarm_openai.py new file mode 100644 index 00000000..79746275 --- /dev/null +++ b/swarms/structs/hierarchical_swarm_openai.py @@ -0,0 +1,227 @@ +import os +from typing import List + +from pydantic import BaseModel + +from swarms.models.openai_function_caller import OpenAIFunctionCaller +from swarms import OpenAIChat +from swarms.structs.agent import Agent +from swarms.structs.concat import concat_strings + +api_key = os.getenv("OPENAI_API_KEY") + +# Create an instance of the OpenAIChat class +model = OpenAIChat( + api_key=api_key, model_name="gpt-4o-mini", temperature=0.1 +) + + +# Initialize the agents +growth_agent1 = Agent( + agent_name="marketing_specialist", + system_prompt="You're the marketing specialist, your purpose is to help companies grow by improving their marketing strategies!", + agent_description="Improve a company's marketing strategies!", + llm=model, + max_loops=1, + autosave=True, + dashboard=False, + verbose=True, + streaming_on=True, + saved_state_path="marketing_specialist.json", + stopping_token="Stop!", + context_length=1000, +) + +growth_agent2 = Agent( + agent_name="sales_specialist", + system_prompt="You're the sales specialist, your purpose is to help companies grow by improving their sales strategies!", + agent_description="Improve a company's sales strategies!", + llm=model, + max_loops=1, + autosave=True, + dashboard=False, + verbose=True, + streaming_on=True, + saved_state_path="sales_specialist.json", + stopping_token="Stop!", + context_length=1000, +) + +growth_agent3 = Agent( + agent_name="product_development_specialist", + system_prompt="You're the product development specialist, your purpose is to help companies grow by improving their product development strategies!", + agent_description="Improve a company's product development strategies!", + llm=model, + max_loops=1, + autosave=True, + dashboard=False, + verbose=True, + streaming_on=True, + saved_state_path="product_development_specialist.json", + stopping_token="Stop!", + context_length=1000, +) + +team = [growth_agent1, growth_agent2, growth_agent3] + + +# class HiearchicalSwarm(BaseModel): +# agents: List[Agent] +# director: Agent +# planner: Agent +# max_loops: int = 3 +# verbose: bool = True + +# def run(self, task: str): +# # Plan +# # Plan -> JSON Function call -> workers -> response fetch back to boss -> planner +# responses = [] +# responses.append(task) + +# for _ in range(self.max_loops): +# # Plan +# plan = self.planner.run(concat_strings(responses)) +# logger.info(f"Agent {self.planner.agent_name} planned: {plan}") +# responses.append(plan) + +# # Execute json function calls +# calls = self.director.run(plan) +# logger.info( +# f"Agent {self.director.agent_name} called: {calls}" +# ) +# responses.append(calls) +# # Parse and send tasks to agents +# output = parse_then_send_tasks_to_agents(self.agents, calls) + +# # Fetch back to boss +# responses.append(output) + +# return concat_strings(responses) + +# def __call__(self, task: str): +# responses = [] +# responses.append(task) + +# for _ in range(self.max_loops): +# output = self.step(task, responses) +# responses.append(output) + +# return concat_strings(responses) + +# def step(self, responses: List[str] = None) -> str: +# # Plan +# # Plan -> JSON Function call -> workers -> response fetch back to boss -> planner + +# # Plan +# plan = self.planner.run(concat_strings(responses)) +# logger.info(f"Agent {self.planner.agent_name} planned: {plan}") +# responses.append(plan) + +# # Execute json function calls +# calls = self.director.run(plan) +# logger.info(f"Agent {self.director.agent_name} called: {calls}") +# responses.append(calls) +# # Parse and send tasks to agents +# output = parse_then_send_tasks_to_agents(self.agents, calls) + +# # Fetch back to boss +# responses.append(output) + +# return concat_strings(responses) + +# def plan(self, task: str, responses: List[str] = None): +# # Plan +# # Plan -> JSON Function call -> workers -> response fetch back to boss -> planner +# # responses = [] +# # responses.append(task) + +# # Plan +# plan = self.planner.run(concat_strings(responses)) +# logger.info(f"Agent {self.planner.agent_name} planned: {plan}") +# responses.append(plan) + +# return concat_strings(responses) + + +def agents_list( + agents: List[Agent] = team, +) -> str: + responses = [] + + for agent in agents: + name = agent.agent_name + description = agent.description + response = f"Agent Name {name}: Description {description}" + responses.append(response) + + return concat_strings(responses) + + +def parse_then_send_tasks_to_agents(agents: List[Agent], response: dict): + # Initialize an empty dictionary to store the output of each agent + output = [] + + # Loop over the tasks in the response + for call in response["calls"]: + name = call["agent_name"] + task = call["task"] + + # Loop over the agents + for agent in agents: + # If the agent's name matches the name in the task, run the task + if agent.agent_name == name: + out = agent.run(task) + print(out) + + output.append(f"{name}: {out}") + + # Store the output in the dictionary + # output[name] = out + break + + return output + + +class HierarchicalOrderCall(BaseModel): + agent_name: str + task: str + + +class CallTeam(BaseModel): + calls: List[HierarchicalOrderCall] + + +# Example usage: +system_prompt = f""" +You're a director agent, your responsibility is to serve the user efficiently, effectively and skillfully.You have a swarm of agents available to distribute tasks to, interact with the user and then submit tasks to the worker agents. Provide orders to the worker agents that are direct, explicit, and simple. Ensure that they are given tasks that are understandable, actionable, and simple to execute. + + +###### +Workers available: + +{agents_list(team)} + + +""" + + +# Initialize the function caller +function_caller = OpenAIFunctionCaller( + system_prompt=system_prompt, + openai_api_key=os.getenv("OPENAI_API_KEY"), + max_tokens=500, + temperature=0.5, + base_model=CallTeam, +) + +# Run the function caller +response = function_caller.run( + "Now let's grow the company! Send an order to the marketing specialist, sales specialist, and product development specialist to improve the company's growth strategies." +) +# print(response) +print(response) +print(type(response)) + + +out = parse_then_send_tasks_to_agents(team, response) +print(out) diff --git a/swarms/structs/rearrange.py b/swarms/structs/rearrange.py index 34a68842..a63ae3f0 100644 --- a/swarms/structs/rearrange.py +++ b/swarms/structs/rearrange.py @@ -4,6 +4,7 @@ from swarms.memory.base_vectordb import BaseVectorDatabase from swarms.structs.agent import Agent from swarms.structs.base_swarm import BaseSwarm from swarms.utils.loguru_logger import logger +from swarms.structs.omni_agent_types import AgentType class AgentRearrange(BaseSwarm): @@ -25,7 +26,7 @@ class AgentRearrange(BaseSwarm): def __init__( self, - agents: List[Agent] = None, + agents: List[AgentType] = None, flow: str = None, max_loops: int = 1, verbose: bool = True, diff --git a/swarms/structs/scp.py b/swarms/structs/scp.py deleted file mode 100644 index 1f531814..00000000 --- a/swarms/structs/scp.py +++ /dev/null @@ -1,148 +0,0 @@ -""" -Swarm Communication Protocol -- RAG as a communication protocol -- Each Agent is connected to a database so they can see each others -memories, actions, and experiences - -""" - -import json -from swarms.structs.omni_agent_types import AgentType -from swarms.structs.base_structure import BaseStructure -from typing import List -from swarms.memory.base_vectordb import BaseVectorDatabase -import time -from swarms.utils.loguru_logger import logger -from pydantic import BaseModel, Field -from typing import Any - - -class SwarmCommunicationProtocol(BaseModel): - agent_name: str = Field( - None, title="Agent Name", description="The name of the agent" - ) - message: str = Field( - None, title="Message", description="The message to be sent" - ) - timestamp: float = Field( - None, - title="Timestamp", - description="The time the message was sent", - ) - - -class SCP(BaseStructure): - """ - Represents the Swarm Communication Protocol (SCP). - - SCP is responsible for managing agents and their communication within a swarm. - - Args: - agents (List[AgentType]): A list of agents participating in the swarm. - memory_system (BaseVectorDatabase, optional): The memory system used by the agents. Defaults to None. - - Attributes: - agents (List[AgentType]): A list of agents participating in the swarm. - memory_system (BaseVectorDatabase): The memory system used by the agents. - - Methods: - message_log(agent: AgentType, task: str = None, message: str = None) -> str: - Logs a message from an agent and adds it to the memory system. - - run_single_agent(agent: AgentType, task: str, *args, **kwargs) -> Any: - Runs a task for a single agent and logs the output. - - send_message(agent: AgentType, message: str): - Sends a message to an agent and logs it. - - """ - - def __init__( - self, - agents: List[AgentType] = None, - memory_system: BaseVectorDatabase = None, - *args, - **kwargs, - ): - super().__init__() - self.agents = agents - self.memory_system = memory_system - - # Memory system - if memory_system is not None: - for agent in self.agents.values(): - agent.long_term_memory = memory_system - - logger.info( - "AgentRearrange initialized with agents: {}".format( - list(self.agents.keys()) - ) - ) - - def message_log( - self, agent: AgentType, task: str = None, message: str = None - ) -> str: - """ - Logs a message from an agent and adds it to the memory system. - - Args: - agent (AgentType): The agent that generated the message. - task (str, optional): The task associated with the message. Defaults to None. - message (str, optional): The message content. Defaults to None. - - Returns: - str: The JSON-encoded log message. - - """ - log = { - "agent_name": agent.agent_name, - "task": task, - "response": message, - "timestamp": time.time(), - } - - # Transform the log into a string - log_output = json.dumps(log) - - # Add the log to the memory system - self.memory_system.add(log) - - return log_output - - def run_single_agent( - self, agent: AgentType, task: str, *args, **kwargs - ) -> Any: - """ - Runs a task for a single agent and logs the output. - - Args: - agent (AgentType): The agent to run the task for. - task (str): The task to be executed. - - Returns: - Any: The output of the task. - - """ - # Send the message to the agent - output = agent.run(task) - - # log the message - self.message_log( - agent=agent, - task=task, - message=output, - ) - - # Log the output - return output - - def send_message(self, agent: AgentType, message: str): - """ - Sends a message to an agent and logs it. - - Args: - agent (AgentType): The agent to send the message to. - message (str): The message to be sent. - - """ - agent.receieve_mesage(self.message_log(agent, message)) diff --git a/swarms/structs/sermon_swarm.py b/swarms/structs/sermon_swarm.py deleted file mode 100644 index fad468d4..00000000 --- a/swarms/structs/sermon_swarm.py +++ /dev/null @@ -1,70 +0,0 @@ -from typing import Union, Sequence, List, Callable -from swarms.structs.agent import Agent -from swarms.structs.base_swarm import BaseSwarm - - -class SermonSwarm(BaseSwarm): - """ - Represents a swarm of agents that communicate through sermons. - - Args: - priest (Agent): The priest agent responsible for generating sermons. - agents (Sequence[Agent]): The list of agents in the swarm. - max_loops (int, optional): The maximum number of loops to run the agents. Defaults to 5. - stop_condition (Union[str, List[str]], optional): The condition(s) that can stop the agents. - Defaults to "stop". - stop_function (Union[None, Callable], optional): The function to apply to the sermons before - checking the stop condition. Defaults to None. - """ - - def __init__( - self, - priest: Agent, - agents: Sequence[Agent], - max_loops: int = 5, - stop_condition: Union[str, List[str]] = "stop", - stop_function: Union[None, Callable] = None, - *args, - **kwargs, - ): - super().__init__(*args, **kwargs) - self.priest = priest - self.agents = agents - self.max_loops = max_loops - self.stop_condition = stop_condition - self.stop_function = stop_function - - def run(self, task: str, *args, **kwargs): - """ - Runs the swarm by generating sermons from the priest and executing the task on each agent. - - Args: - task (str): The task to be executed by the agents. - *args: Additional positional arguments for the task. - **kwargs: Additional keyword arguments for the task. - """ - sermon = self.priest(task, *args, **kwargs) - - # Add the sermon to the memory of all agents - for agent in self.agents: - agent.add_message_to_memory(sermon) - - # Then run the agents - loop = 0 - # for _ in range(self.max_loops): - while loop < self.max_loops: - for agent in self.agents: - preach = agent.run(task, *args, **kwargs) - - if self.stop_function: - preach = self.stop_function(preach) - - if self.stop_condition in preach: - if self.stop_condition is True: - break - - elif self.stop_condition in preach: - break - - loop += 1 - return preach diff --git a/swarms/structs/society_of_agents.py b/swarms/structs/society_of_agents.py deleted file mode 100644 index 4ba179ee..00000000 --- a/swarms/structs/society_of_agents.py +++ /dev/null @@ -1,50 +0,0 @@ -from typing import List -from swarms.structs.agent import Agent -from swarms.structs.base_swarm import BaseSwarm -from swarms.structs.conversation import Conversation -from swarms.utils.loguru_logger import logger - - -class SocietyOfAgents(BaseSwarm): - def __init__( - self, - name: str = None, - description: str = None, - agents: List[Agent] = None, - max_loops: int = 1, - rules: str = None, - *args, - **kwargs, - ): - super().__init__(*args, **kwargs) - self.name = name - self.description = description - self.agents = agents - self.max_loops = max_loops - self.conversation = Conversation( - time_enabled=True, rules=rules, *args, **kwargs - ) - - def run(self, task: str = None, *args, **kwargs): - loop = 0 - - try: - while loop < self.max_loops: - for agent in self.agents: - out = agent.run(task, *args, **kwargs) - - # Save the conversation - self.conversation.add(agent.agent_name, out) - - task = out - - # Log the agent's output - logger.info(f"Agent {agent.agent_name} output: {out}") - - loop += 1 - - except Exception as e: - logger.error(f"An error occurred: {e}") - return None - - return out diff --git a/swarms/structs/swarm_registry.py b/swarms/structs/swarm_registry.py new file mode 100644 index 00000000..07d60ae9 --- /dev/null +++ b/swarms/structs/swarm_registry.py @@ -0,0 +1,182 @@ +from pydantic.v1 import BaseModel +from typing import List, Callable +from swarms.utils.loguru_logger import logger + + +class SwarmRegistry(BaseModel): + swarm_pool: List[Callable] = [] + + def add(self, swarm: Callable, *args, **kwargs): + """ + Adds a swarm to the registry. + + Args: + swarm (Callable): The swarm to add to the registry. + """ + self.swarm_pool.append(swarm, *args, **kwargs) + + def query(self, swarm_name: str) -> Callable: + """ + Queries the registry for a swarm by name. + + Args: + swarm_name (str): The name of the swarm to query. + + Returns: + Callable: The swarm function corresponding to the given name. + """ + if not self.swarm_pool: + raise ValueError("No swarms found in registry") + + if not swarm_name: + raise ValueError("No swarm name provided.") + + for swarm in self.swarm_pool: + if swarm.__name__ == swarm_name: + name = swarm.__name__ + description = ( + swarm.__doc__.strip().split("\n")[0] + or swarm.description + ) + agent_count = len(swarm.agents) + task_count = len(swarm.tasks) + + log = f"Swarm: {name}\nDescription: {description}\nAgents: {agent_count}\nTasks: {task_count}" + logger.info(log) + + return swarm + + raise ValueError(f"Swarm '{swarm_name}' not found in registry.") + + def remove(self, swarm_name: str): + """ + Removes a swarm from the registry by name. + + Args: + swarm_name (str): The name of the swarm to remove. + """ + for swarm in self.swarm_pool: + if swarm.__name__ == swarm_name: + self.swarm_pool.remove(swarm) + return + raise ValueError(f"Swarm '{swarm_name}' not found in registry.") + + def list_swarms(self) -> List[str]: + """ + Lists the names of all swarms in the registry. + + Returns: + List[str]: A list of swarm names. + """ + if not self.swarm_pool: + raise ValueError("No swarms found in registry.") + + for swarm in self.swarm_pool: + name = swarm.__name__ + description = ( + swarm.__doc__.strip().split("\n")[0] or swarm.description + ) + agent_count = len(swarm.agents) + task_count = len(swarm.tasks) + + log = f"Swarm: {name}\nDescription: {description}\nAgents: {agent_count}\nTasks: {task_count}" + logger.info(log) + + return [swarm.__name__ for swarm in self.swarm_pool] + + def run(self, swarm_name: str, *args, **kwargs): + """ + Runs a swarm by name with the given arguments. + + Args: + swarm_name (str): The name of the swarm to run. + *args: Variable length argument list. + **kwargs: Arbitrary keyword arguments. + + Returns: + Any: The result of running the swarm. + """ + swarm = self.query(swarm_name) + return swarm(*args, **kwargs) + + def add_list_of_swarms(self, swarms: List[Callable]): + """ + Adds a list of swarms to the registry. + + Args: + swarms (List[Callable]): A list of swarms to add to the registry. + """ + for swarm in swarms: + self.add(swarm) + + return self.swarm_pool + + def query_multiple_of_swarms( + self, swarm_names: List[str] + ) -> List[Callable]: + """ + Queries the registry for multiple swarms by name. + + Args: + swarm_names (List[str]): A list of swarm names to query. + + Returns: + List[Callable]: A list of swarm functions corresponding to the given names. + """ + return [self.query(swarm_name) for swarm_name in swarm_names] + + def remove_list_of_swarms(self, swarm_names: List[str]): + """ + Removes a list of swarms from the registry by name. + + Args: + swarm_names (List[str]): A list of swarm names to remove. + """ + for swarm_name in swarm_names: + self.remove(swarm_name) + + return self.swarm_pool + + def run_multiple_of_swarms( + self, swarm_names: List[str], *args, **kwargs + ): + """ + Runs a list of swarms by name with the given arguments. + + Args: + swarm_names (List[str]): A list of swarm names to run. + *args: Variable length argument list. + **kwargs: Arbitrary keyword arguments. + + Returns: + List[Any]: A list of results of running the swarms. + """ + return [ + self.run(swarm_name, *args, **kwargs) + for swarm_name in swarm_names + ] + + +# Decorator to add a function to the registry +def swarm_registry(): + """ + Decorator to add a function to the registry. + + Args: + swarm_registry (SwarmRegistry): The swarm registry instance. + + Returns: + Callable: The decorated function. + """ + + def decorator(func, *args, **kwargs): + try: + swarm_registry = SwarmRegistry() + swarm_registry.add(func, *args, **kwargs) + logger.info(f"Added swarm '{func.__name__}' to the registry.") + return func + except Exception as e: + logger.error(str(e)) + raise + + return decorator diff --git a/swarms/structs/swarming_architectures.py b/swarms/structs/swarming_architectures.py index 80866d8f..126ecd22 100644 --- a/swarms/structs/swarming_architectures.py +++ b/swarms/structs/swarming_architectures.py @@ -3,33 +3,146 @@ import math from typing import List from swarms.structs.agent import Agent -from swarms.utils.logger import logger +from swarms.utils.loguru_logger import logger +from swarms.structs.conversation import Conversation +from swarms.structs.concat import concat_strings +from swarms.structs.omni_agent_types import AgentListType + +# from swarms.structs.swarm_registry import swarm_registry, SwarmRegistry + + +# @swarm_registry +def circular_swarm( + name: str = "Circular Swarm", + description: str = "A circular swarm is a type of swarm where agents pass tasks in a circular manner.", + goal: str = None, + agents: AgentListType = None, + tasks: List[str] = None, + return_full_history: bool = True, +): + if not agents: + raise ValueError("Agents list cannot be empty.") + + if not tasks: + raise ValueError("Tasks list cannot be empty.") + + conversation = Conversation( + time_enabled=True, + ) + + responses = [] + + for task in tasks: + for agent in agents: + # Log the task + out = agent.run(task) + # print(f"Task: {task}, Response {out}") + # prompt = f"Task: {task}, Response {out}" + logger.info(f"Agent: {agent.agent_name} Response {out}") + + conversation.add( + role=agent.agent_name, + content=out, + ) + + # Response list + responses.append(out) + + if return_full_history: + return conversation.return_history_as_string() + else: + return responses -def circular_swarm(agents: List[Agent], tasks: List[str]): - ball = 0 - while tasks: - task = tasks.pop(0) - agents[ball].run(task) - ball = (ball + 1) % len(agents) +# @swarm_registry() +def linear_swarm( + name: str = "Linear Swarm", + description: str = "A linear swarm is a type of swarm where agents pass tasks in a linear manner.", + agents: AgentListType = None, + tasks: List[str] = None, + conversation: Conversation = None, + return_full_history: bool = True, +): + if not agents: + raise ValueError("Agents list cannot be empty.") + + if not tasks: + raise ValueError("Tasks list cannot be empty.") + if not conversation: + conversation = Conversation( + time_enabled=True, + ) + + responses = [] -def linear_swarm(agents: List[Agent], tasks: List[str]): for i in range(len(agents)): if tasks: task = tasks.pop(0) - agents[i].run(task) + out = agents[i].run(task) + + conversation.add( + role=agents[i].agent_name, + content=f"Task: {task}, Response {out}", + ) + + responses.append(out) + + if return_full_history: + return conversation.return_history_as_string() + else: + return responses + + +# print(SwarmRegistry().list_swarms()) +# def linear_swarm(agents: AgentListType, tasks: List[str]): +# logger.info(f"Running linear swarm with {len(agents)} agents") +# for i in range(len(agents)): +# if tasks: +# task = tasks.pop(0) +# agents[i].run(task) -def star_swarm(agents: List[Agent], tasks: List[str]): + +def star_swarm(agents: AgentListType, tasks: List[str]) -> str: + logger.info( + f"Running star swarm with {len(agents)} agents and {len(tasks)} tasks" + ) + + if not agents: + raise ValueError("Agents list cannot be empty.") + + if not tasks: + raise ValueError("Tasks list cannot be empty.") + + conversation = Conversation(time_enabled=True) center_agent = agents[0] + + responses = [] + for task in tasks: - center_agent.run(task) + + out = center_agent.run(task) + log = f"Agent: {center_agent.agent_name} Response {out}" + logger.info(log) + conversation.add(center_agent.agent_name, out) + responses.append(out) + for agent in agents[1:]: - agent.run(task) + output = agent.run(task) + log_two = f"Agent: {agent.agent_name} Response {output}" + logger.info(log_two) + conversation.add(agent.agent_name, output) + responses.append(out) + + out = concat_strings(responses) + print(out) + + return out -def mesh_swarm(agents: List[Agent], tasks: List[str]): + +def mesh_swarm(agents: AgentListType, tasks: List[str]): task_queue = tasks.copy() while task_queue: for agent in agents: @@ -38,7 +151,7 @@ def mesh_swarm(agents: List[Agent], tasks: List[str]): agent.run(task) -def grid_swarm(agents: List[Agent], tasks: List[str]): +def grid_swarm(agents: AgentListType, tasks: List[str]): grid_size = int( len(agents) ** 0.5 ) # Assuming agents can form a perfect square grid @@ -49,7 +162,7 @@ def grid_swarm(agents: List[Agent], tasks: List[str]): agents[i * grid_size + j].run(task) -def pyramid_swarm(agents: List[Agent], tasks: List[str]): +def pyramid_swarm(agents: AgentListType, tasks: List[str]): levels = int( (-1 + (1 + 8 * len(agents)) ** 0.5) / 2 ) # Assuming agents can form a perfect pyramid @@ -60,7 +173,7 @@ def pyramid_swarm(agents: List[Agent], tasks: List[str]): agents[int(i * (i + 1) / 2 + j)].run(task) -def fibonacci_swarm(agents: List[Agent], tasks: List[str]): +def fibonacci_swarm(agents: AgentListType, tasks: List[str]): fib = [1, 1] while len(fib) < len(agents): fib.append(fib[-1] + fib[-2]) @@ -71,7 +184,7 @@ def fibonacci_swarm(agents: List[Agent], tasks: List[str]): agents[int(sum(fib[:i]) + j)].run(task) -def prime_swarm(agents: List[Agent], tasks: List[str]): +def prime_swarm(agents: AgentListType, tasks: List[str]): primes = [ 2, 3, @@ -113,14 +226,14 @@ def power_swarm(agents: List[str], tasks: List[str]): agents[power].run(task) -def log_swarm(agents: List[Agent], tasks: List[str]): +def log_swarm(agents: AgentListType, tasks: List[str]): for i in range(len(agents)): if 2**i < len(agents) and tasks: task = tasks.pop(0) agents[2**i].run(task) -def exponential_swarm(agents: List[Agent], tasks: List[str]): +def exponential_swarm(agents: AgentListType, tasks: List[str]): for i in range(len(agents)): index = min(int(2**i), len(agents) - 1) if tasks: @@ -137,7 +250,7 @@ def geometric_swarm(agents, tasks): agents[index].run(task) -def harmonic_swarm(agents: List[Agent], tasks: List[str]): +def harmonic_swarm(agents: AgentListType, tasks: List[str]): for i in range(1, len(agents) + 1): index = min(int(len(agents) / i), len(agents) - 1) if tasks: @@ -145,32 +258,32 @@ def harmonic_swarm(agents: List[Agent], tasks: List[str]): agents[index].run(task) -def staircase_swarm(agents: List[Agent], task: str): +def staircase_swarm(agents: AgentListType, task: str): step = len(agents) // 5 for i in range(len(agents)): index = (i // step) * step agents[index].run(task) -def sigmoid_swarm(agents: List[Agent], task: str): +def sigmoid_swarm(agents: AgentListType, task: str): for i in range(len(agents)): index = int(len(agents) / (1 + math.exp(-i))) agents[index].run(task) -def sinusoidal_swarm(agents: List[Agent], task: str): +def sinusoidal_swarm(agents: AgentListType, task: str): for i in range(len(agents)): index = int((math.sin(i) + 1) / 2 * len(agents)) agents[index].run(task) -async def one_to_three(sender: Agent, agents: List[Agent], task: str): +async def one_to_three(sender: Agent, agents: AgentListType, task: str): """ Sends a message from the sender agent to three other agents. Args: sender (Agent): The agent sending the message. - agents (List[Agent]): The list of agents to receive the message. + agents (AgentListType): The list of agents to receive the message. task (str): The message to be sent. Raises: @@ -179,11 +292,20 @@ async def one_to_three(sender: Agent, agents: List[Agent], task: str): Returns: None """ + if len(agents) != 3: + raise ValueError("The number of agents must be exactly 3.") + + if not task: + raise ValueError("The task cannot be empty.") + + if not sender: + raise ValueError("The sender cannot be empty.") + try: receive_tasks = [] for agent in agents: receive_tasks.append( - agent.receive_message(sender.ai_name, task) + agent.receive_message(sender.agent_name, task) ) await asyncio.gather(*receive_tasks) @@ -196,7 +318,7 @@ async def one_to_three(sender: Agent, agents: List[Agent], task: str): async def broadcast( sender: Agent, - agents: List[Agent], + agents: AgentListType, task: str, ): """ @@ -204,7 +326,7 @@ async def broadcast( Args: sender (Agent): The agent sending the message. - agents (List[Agent]): The list of agents to receive the message. + agents (AgentListType): The list of agents to receive the message. task (str): The message to be broadcasted. Raises: @@ -213,11 +335,20 @@ async def broadcast( Returns: None """ + if not sender: + raise ValueError("The sender cannot be empty.") + + if not agents: + raise ValueError("The agents list cannot be empty.") + + if not task: + raise ValueError("The task cannot be empty.") + try: receive_tasks = [] for agent in agents: receive_tasks.append( - agent.receive_message(sender.ai_name, task) + agent.receive_message(sender.agent_name, task) ) await asyncio.gather(*receive_tasks) @@ -226,10 +357,11 @@ async def broadcast( raise error -async def one_to_one( +def one_to_one( sender: Agent, receiver: Agent, task: str, + max_loops: int = 1, ): """ Sends a message from the sender agent to the receiver agent. @@ -246,7 +378,20 @@ async def one_to_one( None """ try: - await receiver.receive_message(sender.ai_name, task) + responses = [] + responses.append(task) + for i in range(max_loops): + + # Run the agent on the task then pass the response to the receiver + response = sender.run(task) + log = f"Agent {sender.agent_name} Response: {response}" + responses.append(log) + + # Send the response to the receiver + out = receiver.run(concat_strings(responses)) + responses.append(out) + + return concat_strings(responses) except Exception as error: logger.error(f"[ERROR][CLASS: Agent][METHOD: one_to_one] {error}") raise error diff --git a/swarms/utils/data_to_text.py b/swarms/utils/data_to_text.py index 64ab2e0d..a5ff8ddb 100644 --- a/swarms/utils/data_to_text.py +++ b/swarms/utils/data_to_text.py @@ -70,8 +70,13 @@ def data_to_text(file): elif ext == ".md": return md_to_text(file) else: - with open(file) as file: - data = file.read() - return data + # Check if the file is a binary file (like an image) + if ext in [".png", ".jpg", ".jpeg", ".gif", ".bmp"]: + # Skip binary files + return None + else: + with open(file) as file: + data = file.read() + return data except Exception as e: raise OSError(f"Error reading file: {file}") from e