diff --git a/.env.example b/.env.example index 40b4d386..b80bf6c9 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,4 @@ -OPENAI_API_KEY="" +OPENAI_API_KEY="sk-" GOOGLE_API_KEY="" ANTHROPIC_API_KEY="" AI21_API_KEY="your_api_key_here" diff --git a/README.md b/README.md index 48f8f753..20d06363 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ $ pip3 install -U swarms # Usage Examples 🤖 -Run example in Collab: +Run example in Collab: Open In Colab @@ -74,19 +74,26 @@ Features: ✅ Long term memory database with RAG (ChromaDB, Pinecone, Qdrant) ```python +import os from swarms import Agent, OpenAIChat from swarms.prompts.finance_agent_sys_prompt import ( FINANCIAL_AGENT_SYS_PROMPT, ) -model = 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 +) # Initialize the agent agent = Agent( agent_name="Financial-Analysis-Agent", system_prompt=FINANCIAL_AGENT_SYS_PROMPT, llm=model, - max_loops=1, + max_loops=2, autosave=True, # dynamic_temperature_enabled=True, dashboard=False, @@ -95,7 +102,7 @@ agent = Agent( # interactive=True, # Set to False to disable interactive mode dynamic_temperature_enabled=True, saved_state_path="finance_agent.json", - # tools=[Add your functions here# ], + # tools=[#Add your functions here# ], # stopping_token="Stop!", # interactive=True, # docs_folder="docs", # Enter your folder name @@ -109,14 +116,16 @@ agent = Agent( # context_length=1000, # tool_schema = dict context_length=200000, + # tool_schema= + # tools # agent_ops_on=True, - # long_term_memory=ChromaDB(docs_folder="artifacts"), ) agent.run( "What are the components of a startups stock incentive equity plan" ) + ``` ----- diff --git a/docs/index.md b/docs/index.md deleted file mode 100644 index 064f8f09..00000000 --- a/docs/index.md +++ /dev/null @@ -1,16 +0,0 @@ - -# Swarms - -Orchestrate enterprise-grade agents for multi-agent collaboration and orchestration to automate real-world problems. - -| Core Concepts | How-To Guides | Examples | Community | -|--------------------------------------------------|----------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------| -| [Agents](swarms/structs/agent) | [Installing Swarms](swarms/install/install) | [Swarm of Business Analysts for Business Reports](applications/business-analyst-agent) | [Join the Swarms Community!](https://discord.gg/3Zck7nX6) | -| [Memory](swarms/memory/diy_memory) | [Docker Setup](swarms/install/docker_setup) | [Compliance Swarm for Customer Privacy](https://medium.com/@kyeg/building-compliance-agents-with-chroma-db-llama3-sop-prompting-0ed3e73559d2) | [Swarms Ecosystem](https://github.com/kyegomez/swarm-ecosystem) | -| [Tools](swarms/tools/main) | [Create Custom Tools](https://medium.com/@kyeg/the-swarms-tool-system-functions-pydantic-basemodels-as-tools-and-radical-customization-c2a2e227b8ca) | [Self-Replicating Hierarchical Swarms](https://medium.com/@kyeg/announcing-neosapiens-self-replicating-swarms-0a47410aafa7) | [Support Team](https://cal.com/swarms/swarms-onboarding-session) | -| [Tasks](https://docs.swarms.world/en/latest/swarms/structs/task/) | [Multi-Agent Flows](swarms/structs/agent_rearrange) | | [Book a 1 on 1 Call With Founder: Kye](https://cal.com/swarms/swarms-onboarding-session) | -| [Multi-Agent Orchestration](swarms/structs/agent_rearrange) | [Sequential Workflows](swarms/structs/sequential_workflow) | | | -| | [Connecting LLMs](https://docs.swarms.world/en/latest/swarms/models/custom_model/) | | | -| | [Customizing Agents](./how-to/Customizing-Agents) | | | -| | [Human Input on Execution](./how-to/Human-Input-on-Execution) | | | -| | [Agent Monitoring with AgentOps](https://medium.com/@kyeg/enterprise-grade-autonomous-agents-with-production-ready-monitoring-4295f6737bbf) | | | \ No newline at end of file diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 34742bb3..7af1d608 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -47,6 +47,10 @@ extra: link: https://x.com/KyeGomezB - icon: fontawesome/brands/github link: https://github.com/kyegomez/swarms + - icon: fontawesome/brands/twitter + link: https://x.com/swarms_corp + - icon: fontawesome/brands/discord + link: https://discord.com/servers/agora-999382051935506503 theme: name: material custom_dir: overrides @@ -139,15 +143,17 @@ nav: - Overview: "swarms/structs/index.md" - Build Custom Agents: "swarms/structs/diy_your_own_agent.md" - Long Term Memory with RAG: "swarms/memory/diy_memory.md" - - Tool Usage and Function Calling: "swarms/tools/main.md" + - Tool Usage and Function Calling: "swarms/tools/build_tool.md" - Tasks, Agents with runtimes, triggers, task prioritiies, scheduled tasks, and more: "swarms/structs/task.md" # - Integrating Agents from Langchain, Griptape, CrewAI, Autogen, and more!: "swarms/agents/third_party.md" - Multi-Agent Collaboration: - Overview: "swarms/structs/multi_agent_orchestration.md" - Swarm Architectures: "swarms/concept/swarm_architectures.md" - - Workflows: "swarms/structs/workflows.md" + - Multi-Agent Workflows: "swarms/structs/multi_agent_collaboration_examples.md" + # - Workflows: "swarms/structs/workflows.md" - Contributing: - Tests: "swarms/framework/test.md" + - Code Cleanliness: "swarms/framework/code_cleanliness.md" - Reference: - Overview: "swarms/structs/index.md" - Models: @@ -165,6 +171,7 @@ nav: - GPT4VisionAPI: "swarms/models/gpt4v.md" - Agents: - Agent: "swarms/structs/agent.md" + - Tools: "swarms/agents/build_tool.md" - Task: "swarms/structs/task.md" - ToolAgent: "swarms/agents/tool_agent.md" - Artifacts: @@ -215,5 +222,4 @@ nav: # - Guides: # - Comparing LLM Provider Pricing A Guide for Enterprises: "guides/pricing.md" - References: - - Agent Glossary: "swarms/glossary.md" - - List of The Best Multi-Agent Papers: "swarms/papers.md" \ No newline at end of file + - Agent Glossary: "swarms/glossary.md" \ No newline at end of file diff --git a/docs/swarms/framework/code_cleanliness.md b/docs/swarms/framework/code_cleanliness.md new file mode 100644 index 00000000..e1c04690 --- /dev/null +++ b/docs/swarms/framework/code_cleanliness.md @@ -0,0 +1,407 @@ +# Code Cleanliness in Python: A Comprehensive Guide + +Code cleanliness is an essential aspect of software development that ensures code is easy to read, understand, and maintain. Clean code leads to fewer bugs, easier debugging, and more efficient collaboration among developers. This blog article delves into the principles of writing clean Python code, emphasizing the use of type annotations, docstrings, and the Loguru logging library. We'll explore the importance of each component and provide practical examples to illustrate best practices. + +## Table of Contents +1. Introduction to Code Cleanliness +2. Importance of Type Annotations +3. Writing Effective Docstrings +4. Structuring Your Code +5. Error Handling and Logging with Loguru +6. Refactoring for Clean Code +7. Examples of Clean Code +8. Conclusion + +## 1. Introduction to Code Cleanliness + +Code cleanliness refers to the practice of writing code that is easy to read, understand, and maintain. Clean code follows consistent conventions and is organized logically, making it easier for developers to collaborate and for new team members to get up to speed quickly. + +### Why Clean Code Matters + +1. **Readability**: Clean code is easy to read and understand, which reduces the time needed to grasp what the code does. +2. **Maintainability**: Clean code is easier to maintain and modify, reducing the risk of introducing bugs when making changes. +3. **Collaboration**: Clean code facilitates collaboration among team members, as everyone can easily understand and follow the codebase. +4. **Debugging**: Clean code makes it easier to identify and fix bugs, leading to more reliable software. + +## 2. Importance of Type Annotations + +Type annotations in Python provide a way to specify the types of variables, function arguments, and return values. They enhance code readability and help catch type-related errors early in the development process. + +### Benefits of Type Annotations + +1. **Improved Readability**: Type annotations make it clear what types of values are expected, improving code readability. +2. **Error Detection**: Type annotations help catch type-related errors during development, reducing runtime errors. +3. **Better Tooling**: Many modern IDEs and editors use type annotations to provide better code completion and error checking. + +### Example of Type Annotations + +```python +from typing import List + +def calculate_average(numbers: List[float]) -> float: + """ + Calculates the average of a list of numbers. + + Args: + numbers (List[float]): A list of numbers. + + Returns: + float: The average of the numbers. + """ + return sum(numbers) / len(numbers) +``` + +In this example, the `calculate_average` function takes a list of floats as input and returns a float. The type annotations make it clear what types are expected and returned, enhancing readability and maintainability. + +## 3. Writing Effective Docstrings + +Docstrings are an essential part of writing clean code in Python. They provide inline documentation for modules, classes, methods, and functions. Effective docstrings improve code readability and make it easier for other developers to understand and use your code. + +### Benefits of Docstrings + +1. **Documentation**: Docstrings serve as inline documentation, making it easier to understand the purpose and usage of code. +2. **Consistency**: Well-written docstrings ensure consistent documentation across the codebase. +3. **Ease of Use**: Docstrings make it easier for developers to use and understand code without having to read through the implementation details. + +### Example of Effective Docstrings + +```python +def calculate_factorial(n: int) -> int: + """ + Calculates the factorial of a given non-negative integer. + + Args: + n (int): The non-negative integer to calculate the factorial of. + + Returns: + int: The factorial of the given number. + + Raises: + ValueError: If the input is a negative integer. + """ + if n < 0: + raise ValueError("Input must be a non-negative integer.") + factorial = 1 + for i in range(1, n + 1): + factorial *= i + return factorial +``` + +In this example, the docstring clearly explains the purpose of the `calculate_factorial` function, its arguments, return value, and the exception it may raise. + +## 4. Structuring Your Code + +Proper code structure is crucial for code cleanliness. A well-structured codebase is easier to navigate, understand, and maintain. Here are some best practices for structuring your Python code: + +### Organizing Code into Modules and Packages + +Organize your code into modules and packages to group related functionality together. This makes it easier to find and manage code. + +```python +# project/ +# ├── main.py +# ├── utils/ +# │ ├── __init__.py +# │ ├── file_utils.py +# │ └── math_utils.py +# └── models/ +# ├── __init__.py +# ├── user.py +# └── product.py +``` + +### Using Functions and Classes + +Break down your code into small, reusable functions and classes. This makes your code more modular and easier to test. + +```python +class User: + def __init__(self, name: str, age: int): + """ + Initializes a new user. + + Args: + name (str): The name of the user. + age (int): The age of the user. + """ + self.name = name + self.age = age + + def greet(self) -> str: + """ + Greets the user. + + Returns: + str: A greeting message. + """ + return f"Hello, {self.name}!" +``` + +### Keeping Functions Small + +Functions should do one thing and do it well. Keep functions small and focused on a single task. + +```python +def save_user(user: User, filename: str) -> None: + """ + Saves user data to a file. + + Args: + user (User): The user object to save. + filename (str): The name of the file to save the user data to. + """ + with open(filename, 'w') as file: + file.write(f"{user.name},{user.age}") +``` + +## 5. Error Handling and Logging with Loguru + +Effective error handling and logging are critical components of clean code. They help you manage and diagnose issues that arise during the execution of your code. + +### Error Handling Best Practices + +1. **Use Specific Exceptions**: Catch specific exceptions rather than using a generic `except` clause. +2. **Provide Meaningful Messages**: When raising exceptions, provide meaningful error messages to help diagnose the issue. +3. **Clean Up Resources**: Use `finally` blocks or context managers to ensure that resources are properly cleaned up. + +### Example of Error Handling + +```python +def divide_numbers(numerator: float, denominator: float) -> float: + """ + Divides the numerator by the denominator. + + Args: + numerator (float): The number to be divided. + denominator (float): The number to divide by. + + Returns: + float: The result of the division. + + Raises: + ValueError: If the denominator is zero. + """ + if denominator == 0: + raise ValueError("The denominator cannot be zero.") + return numerator / denominator +``` + +### Logging with Loguru + +Loguru is a powerful logging library for Python that makes logging simple and enjoyable. It provides a clean and easy-to-use API for logging messages with different severity levels. + +#### Installing Loguru + +```bash +pip install loguru +``` + +#### Basic Usage of Loguru + +```python +from loguru import logger + +logger.debug("This is a debug message") +logger.info("This is an info message") +logger.warning("This is a warning message") +logger.error("This is an error message") +logger.critical("This is a critical message") +``` + +### Example of Logging in a Function + +```python +from loguru import logger + +def fetch_data(url: str) -> str: + """ + Fetches data from a given URL and returns it as a string. + + Args: + url (str): The URL to fetch data from. + + Returns: + str: The data fetched from the URL. + + Raises: + requests.exceptions.RequestException: If there is an error with the request. + """ + try: + logger.info(f"Fetching data from {url}") + response = requests.get(url) + response.raise_for_status() + logger.info("Data fetched successfully") + return response.text + except requests.exceptions.RequestException as e: + logger.error(f"Error fetching data: {e}") + raise +``` + +In this example, Loguru is used to log messages at different severity levels. The `fetch_data` function logs informational messages when fetching data and logs an error message if an exception is raised. + +## 6. Refactoring for Clean Code + +Refactoring is the process of restructuring existing code without changing its external behavior. It is an essential practice for maintaining clean code. Refactoring helps improve code readability, reduce complexity, and eliminate redundancy. + +### Identifying Code Smells + +Code smells are indicators of potential issues in the code that may require refactoring. Common code smells include: +1. **Long Methods**: Methods that are too long and do too many things. +2. **Duplicated Code**: Code that is duplicated in multiple places. +3. **Large Classes**: Classes that have too many responsibilities. +4. **Poor Naming**: Variables, functions, or classes with unclear or misleading names. + +### Refactoring Techniques + +1. **Extract Method**: Break down long methods into smaller, more focused methods. +2. **Rename Variables**: Use meaningful names for variables, functions, and classes. +3. **Remove Duplicated Code**: Consolidate duplicated code into a single location. +4. **Simplify Conditional Expressions**: Simplify complex conditional expressions for + + better readability. + +### Example of Refactoring + +Before refactoring: +```python +def process_data(data: List[int]) -> int: + total = 0 + for value in data: + if value > 0: + total += value + return total +``` + +After refactoring: +```python +def filter_positive_values(data: List[int]) -> List[int]: + """ + Filters the positive values from the input data. + + Args: + data (List[int]): The input data. + + Returns: + List[int]: A list of positive values. + """ + return [value for value in data if value > 0] + +def sum_values(values: List[int]) -> int: + """ + Sums the values in the input list. + + Args: + values (List[int]): A list of values to sum. + + Returns: + int: The sum of the values. + """ + return sum(values) + +def process_data(data: List[int]) -> int: + """ + Processes the data by filtering positive values and summing them. + + Args: + data (List[int]): The input data. + + Returns: + int: The sum of the positive values. + """ + positive_values = filter_positive_values(data) + return sum_values(positive_values) +``` + +In this example, the `process_data` function is refactored into smaller, more focused functions. This improves readability and maintainability. + +## 7. Examples of Clean Code + +### Example 1: Reading a File + +```python +def read_file(file_path: str) -> str: + """ + Reads the content of a file and returns it as a string. + + Args: + file_path (str): The path to the file to read. + + Returns: + str: The content of the file. + + Raises: + FileNotFoundError: If the file does not exist. + IOError: If there is an error reading the file. + """ + try: + with open(file_path, 'r') as file: + return file.read() + except FileNotFoundError as e: + logger.error(f"File not found: {file_path}") + raise + except IOError as e: + logger.error(f"Error reading file: {file_path}") + raise +``` + +### Example 2: Fetching Data from a URL + +```python +import requests +from loguru import logger + +def fetch_data(url: str) -> str: + """ + Fetches data from a given URL and returns it as a string. + + Args: + url (str): The URL to fetch data from. + + Returns: + str: The data fetched from the URL. + + Raises: + requests.exceptions.RequestException: If there is an error with the request. + """ + try: + logger.info(f"Fetching data from {url}") + response = requests.get(url) + response.raise_for_status() + logger.info("Data fetched successfully") + return response.text + except requests.exceptions.RequestException as e: + logger.error(f"Error fetching data: {e}") + raise +``` + +### Example 3: Calculating Factorial + +```python +def calculate_factorial(n: int) -> int: + """ + Calculates the factorial of a given non-negative integer. + + Args: + n (int): The non-negative integer to calculate the factorial of. + + Returns: + int: The factorial of the given number. + + Raises: + ValueError: If the input is a negative integer. + """ + if n < 0: + raise ValueError("Input must be a non-negative integer.") + factorial = 1 + for i in range(1, n + 1): + factorial *= i + return factorial +``` + +## 8. Conclusion + +Writing clean code in Python is crucial for developing maintainable, readable, and error-free software. By using type annotations, writing effective docstrings, structuring your code properly, and leveraging logging with Loguru, you can significantly improve the quality of your codebase. + +Remember to refactor your code regularly to eliminate code smells and improve readability. Clean code not only makes your life as a developer easier but also enhances collaboration and reduces the likelihood of bugs. + +By following the principles and best practices outlined in this article, you'll be well on your way to writing clean, maintainable Python code. \ No newline at end of file diff --git a/docs/swarms/structs/index.md b/docs/swarms/structs/index.md index 88eb756a..39d279ba 100644 --- a/docs/swarms/structs/index.md +++ b/docs/swarms/structs/index.md @@ -22,7 +22,7 @@ The performance impact is rated on a scale from one to five stars, with multi-ag # Usage Examples 🤖 ### Google Collab Example -Run example in Collab: +Run example in Collab: Open In Colab diff --git a/docs/swarms/structs/multi_agent_collaboration_examples.md b/docs/swarms/structs/multi_agent_collaboration_examples.md new file mode 100644 index 00000000..03640709 --- /dev/null +++ b/docs/swarms/structs/multi_agent_collaboration_examples.md @@ -0,0 +1,226 @@ +# Multi-Agent Examples + + +### `SequentialWorkflow` +Sequential Workflow enables you to sequentially execute tasks with `Agent` and then pass the output into the next agent and onwards until you have specified your max loops. + +```python +from swarms import Agent, SequentialWorkflow, Anthropic + + +# Initialize the language model agent (e.g., GPT-3) +llm = Anthropic() + +# Initialize agents for individual tasks +agent1 = Agent( + agent_name="Blog generator", + system_prompt="Generate a blog post like stephen king", + llm=llm, + max_loops=1, + dashboard=False, + tools=[], +) +agent2 = Agent( + agent_name="summarizer", + system_prompt="Sumamrize the blog post", + llm=llm, + max_loops=1, + dashboard=False, + tools=[], +) + +# Create the Sequential workflow +workflow = SequentialWorkflow( + agents=[agent1, agent2], max_loops=1, verbose=False +) + +# Run the workflow +workflow.run( + "Generate a blog post on how swarms of agents can help businesses grow." +) + +``` + +------ + +## `AgentRearrange` +Inspired by Einops and einsum, this orchestration techniques enables you to map out the relationships between various agents. For example you specify linear and sequential relationships like `a -> a1 -> a2 -> a3` or concurrent relationships where the first agent will send a message to 3 agents all at once: `a -> a1, a2, a3`. You can customize your workflow to mix sequential and concurrent relationships. [Docs Available:](https://swarms.apac.ai/en/latest/swarms/structs/agent_rearrange/) + +```python +from swarms import Agent, AgentRearrange, Anthropic + + +# Initialize the director agent + +director = Agent( + agent_name="Director", + system_prompt="Directs the tasks for the workers", + llm=Anthropic(), + max_loops=1, + dashboard=False, + streaming_on=True, + verbose=True, + stopping_token="", + state_save_file_type="json", + saved_state_path="director.json", +) + + +# Initialize worker 1 + +worker1 = Agent( + agent_name="Worker1", + system_prompt="Generates a transcript for a youtube video on what swarms are", + llm=Anthropic(), + max_loops=1, + dashboard=False, + streaming_on=True, + verbose=True, + stopping_token="", + state_save_file_type="json", + saved_state_path="worker1.json", +) + + +# Initialize worker 2 +worker2 = Agent( + agent_name="Worker2", + system_prompt="Summarizes the transcript generated by Worker1", + llm=Anthropic(), + max_loops=1, + dashboard=False, + streaming_on=True, + verbose=True, + stopping_token="", + state_save_file_type="json", + saved_state_path="worker2.json", +) + + +# Create a list of agents +agents = [director, worker1, worker2] + +# Define the flow pattern +flow = "Director -> Worker1 -> Worker2" + +# Using AgentRearrange class +agent_system = AgentRearrange(agents=agents, flow=flow) +output = agent_system.run( + "Create a format to express and communicate swarms of llms in a structured manner for youtube" +) +print(output) + +``` + +## `HierarhicalSwarm` +Coming soon... + + +## `GraphSwarm` + +```python +import os + +from dotenv import load_dotenv + +from swarms import Agent, Edge, GraphWorkflow, Node, NodeType, OpenAIChat + +load_dotenv() + +api_key = os.environ.get("OPENAI_API_KEY") + +llm = OpenAIChat( + temperature=0.5, openai_api_key=api_key, max_tokens=4000 +) +agent1 = Agent(llm=llm, max_loops=1, autosave=True, dashboard=True) +agent2 = Agent(llm=llm, max_loops=1, autosave=True, dashboard=True) + +def sample_task(): + print("Running sample task") + return "Task completed" + +wf_graph = GraphWorkflow() +wf_graph.add_node(Node(id="agent1", type=NodeType.AGENT, agent=agent1)) +wf_graph.add_node(Node(id="agent2", type=NodeType.AGENT, agent=agent2)) +wf_graph.add_node( + Node(id="task1", type=NodeType.TASK, callable=sample_task) +) +wf_graph.add_edge(Edge(source="agent1", target="task1")) +wf_graph.add_edge(Edge(source="agent2", target="task1")) + +wf_graph.set_entry_points(["agent1", "agent2"]) +wf_graph.set_end_points(["task1"]) + +print(wf_graph.visualize()) + +# Run the workflow +results = wf_graph.run() +print("Execution results:", results) + +``` + +## `MixtureOfAgents` +This is an implementation from the paper: "Mixture-of-Agents Enhances Large Language Model Capabilities" by together.ai, it achieves SOTA on AlpacaEval 2.0, MT-Bench and FLASK, surpassing GPT-4 Omni. Great for tasks that need to be parallelized and then sequentially fed into another loop + +```python +from swarms import Agent, OpenAIChat, MixtureOfAgents + +# Initialize the director agent +director = Agent( + agent_name="Director", + system_prompt="Directs the tasks for the accountants", + llm=OpenAIChat(), + max_loops=1, + dashboard=False, + streaming_on=True, + verbose=True, + stopping_token="", + state_save_file_type="json", + saved_state_path="director.json", +) + +# Initialize accountant 1 +accountant1 = Agent( + agent_name="Accountant1", + system_prompt="Prepares financial statements", + llm=OpenAIChat(), + max_loops=1, + dashboard=False, + streaming_on=True, + verbose=True, + stopping_token="", + state_save_file_type="json", + saved_state_path="accountant1.json", +) + +# Initialize accountant 2 +accountant2 = Agent( + agent_name="Accountant2", + system_prompt="Audits financial records", + llm=OpenAIChat(), + max_loops=1, + dashboard=False, + streaming_on=True, + verbose=True, + stopping_token="", + state_save_file_type="json", + saved_state_path="accountant2.json", +) + +# Create a list of agents +agents = [director, accountant1, accountant2] + + +# Swarm +swarm = MixtureOfAgents( + name="Mixture of Accountants", + agents=agents, + layers=3, + final_agent=director, +) + + +# Run the swarm +out = swarm.run("Prepare financial statements and audit financial records") +print(out) +``` diff --git a/docs/swarms/tools/base_tool.md b/docs/swarms/tools/base_tool.md index 6f5776fa..e69de29b 100644 --- a/docs/swarms/tools/base_tool.md +++ b/docs/swarms/tools/base_tool.md @@ -1,118 +0,0 @@ -# Documentation Outline for `BaseTool` Class - -1. **Module Overview** -2. **Installation and Setup** -3. **Class Definition** -4. **Attributes and Methods** -5. **Functionality and Usage** - - Basic Usage Examples - - Advanced Use Cases -6. **Common Issues and Troubleshooting** -7. **References and Additional Resources** - -## 1. Module Overview - -The `BaseTool` class is a part of the `swarms` package and serves as a foundational class for creating and managing tools that can be executed with different inputs and configurations. It leverages Pydantic for input validation and includes extensive logging for easy debugging and monitoring. - -## 2. Installation and Setup - -To use the `BaseTool` class, ensure that you have the required dependencies installed: - -```bash -pip install pydantic loguru -``` - -Include the necessary imports in your Python script: - -```python -from swarms.tools.base_tool import BaseTool -``` - -## 3. Class Definition - -`BaseTool` is designed using Pydantic's `BaseModel` to leverage type annotations and validations: - -```python -from pydantic import BaseModel - -class BaseTool(BaseModel): - # Attributes and method definitions follow -``` - -## 4. Attributes and Methods - -### Attributes - -| Attribute | Type | Description | -|---------------------|----------------------------|--------------------------------------------------------------| -| `verbose` | `bool` | Enables verbose output, providing detailed logs. | -| `functions` | `List[Callable[..., Any]]` | Stores a list of functions that can be managed by the tool. | -| `base_models` | `List[type[BaseModel]]` | List of Pydantic models associated with the tool. | -| `autocheck` | `bool` | Automatically checks conditions before execution (not implemented). | -| `auto_execute_tool` | `Optional[bool]` | Automatically executes tools if set. | - -### Key Methods - -- `func_to_dict`: Converts a function to a dictionary format suitable for OpenAI function schema. -- `load_params_from_func_for_pybasemodel`: Loads parameters dynamically for Pydantic models based on the function signature. -- `execute_tool`: Executes a specified tool using a mapping of function names to callable functions. - -## 5. Functionality and Usage - -### Basic Usage Examples - -#### Initialize BaseTool - -```python -tool = BaseTool(verbose=True) -``` - -#### Convert a Function to Dictionary - -```python -def sample_function(x, y): - return x + y - -schema = tool.func_to_dict(sample_function, name="AddFunction", description="Adds two numbers") -print(schema) -``` - -### Advanced Use Cases - -#### Executing a Tool Dynamically - -```python -# Define a sample tool -def add(x, y): - return x + y - -# Tool registration and execution -tool_dict = tool.func_to_dict(add, name="Add") -result = tool.execute_tool([tool_dict], {'Add': add}, 5, 3) -print("Result of add:", result) -``` - -#### Handling Multiple Models - -```python -# Define multiple Pydantic models -class ModelOne(BaseModel): - a: int - -class ModelTwo(BaseModel): - b: str - -# Convert and manage multiple models -schemas = tool.multi_base_models_to_dict([ModelOne, ModelTwo]) -print(schemas) -``` - -## 6. Common Issues and Troubleshooting - -- **Type Errors**: Ensure that all parameters match the expected types as defined in the Pydantic models. -- **Execution Failures**: Check the function and tool configurations for compatibility and completeness. - -## 7. References and Additional Resources - -- [Pydantic Documentation](https://pydantic-docs.helpmanual.io/) -- [Loguru GitHub Repository](https://github.com/Delgan/loguru) diff --git a/docs/swarms/tools/build_tool.md b/docs/swarms/tools/build_tool.md new file mode 100644 index 00000000..0bb0c9cd --- /dev/null +++ b/docs/swarms/tools/build_tool.md @@ -0,0 +1,353 @@ +### Swarms Tool Documentation Page + +Welcome to the Swarms Tool Documentation! + +Here you will find examples and guidelines on how to build and use tools in the Swarms environment. A tool is a Python function designed to perform specific tasks, with clear type annotations and comprehensive docstrings. Below are examples of tools to help you get started. + +# Rules + +To create a tool in the Swarms environment, follow these rules: + +1. **Function Definition**: + - The tool must be defined as a Python function. + - The function should perform a specific task and be named appropriately. + +2. **Type Annotations**: + - All arguments and the return value must have type annotations. + - Both input and output types must be strings (`str`). + +3. **Docstrings**: + - Each function must include a comprehensive docstring that adheres to PEP 257 standards. The docstring should explain: + - The purpose of the function. + - Arguments: names, types, and descriptions. + - Return value: type and description. + - Potential exceptions that the function may raise. + +4. **Input and Output Types**: + - The function's input must be a string. + - The function's output must be a string. + + +### Example Tools + + + + + +### Examples and Anti-Examples + +#### Example 1: Fetch Financial News + +**Correct Implementation** + +```python +import requests +import os + +def fetch_financial_news(query: str = "Nvidia news", num_articles: int = 5) -> str: + """ + Fetches financial news from the Google News API and returns a formatted string of the top news. + + Args: + query (str): The query term to search for news. Default is "Nvidia news". + num_articles (int): The number of top articles to fetch. Default is 5. + + Returns: + str: A formatted string of the top financial news articles. + + Raises: + ValueError: If the API response is invalid or there are no articles found. + requests.exceptions.RequestException: If there is an error with the request. + """ + url = "https://newsapi.org/v2/everything" + params = { + "q": query, + "apiKey": os.getenv("NEWSAPI_KEY"), + "pageSize": num_articles, + "sortBy": "relevancy", + } + + try: + response = requests.get(url, params=params) + response.raise_for_status() + data = response.json() + + if "articles" not in data or len(data["articles"]) == 0: + raise ValueError("No articles found or invalid API response.") + + articles = data["articles"] + formatted_articles = [] + + for i, article in enumerate(articles, start=1): + title = article.get("title", "No Title") + description = article.get("description", "No Description") + url = article.get("url", "No URL") + formatted_articles.append( + f"{i}. {title}\nDescription: {description}\nRead more: {url}\n" + ) + + return "\n".join(formatted_articles) + + except requests.exceptions.RequestException as e: + print(f"Request Error: {e}") + raise + except ValueError as e: + print(f"Value Error: {e}") + raise +``` + +**Incorrect Implementation** + +```python +import requests +import os + +def fetch_financial_news(query="Nvidia news", num_articles=5): + # Fetches financial news from the Google News API and returns a formatted string of the top news. + url = "https://newsapi.org/v2/everything" + params = { + "q": query, + "apiKey": os.getenv("NEWSAPI_KEY"), + "pageSize": num_articles, + "sortBy": "relevancy", + } + + response = requests.get(url, params=params) + response.raise_for_status() + data = response.json() + + if "articles" not in data or len(data["articles"]) == 0: + raise ValueError("No articles found or invalid API response.") + + articles = data["articles"] + formatted_articles = [] + + for i, article in enumerate(articles, start=1): + title = article.get("title", "No Title") + description = article.get("description", "No Description") + url = article.get("url", "No URL") + formatted_articles.append( + f"{i}. {title}\nDescription: {description}\nRead more: {url}\n" + ) + + return "\n".join(formatted_articles) +``` + +**Issues with Incorrect Implementation:** +- No type annotations for arguments and return value. +- Missing comprehensive docstring. + +#### Example 2: Convert Celsius to Fahrenheit + +**Correct Implementation** + +```python +def celsius_to_fahrenheit(celsius_str: str) -> str: + """ + Converts a temperature from Celsius to Fahrenheit. + + Args: + celsius_str (str): The temperature in Celsius as a string. + + Returns: + str: The temperature converted to Fahrenheit as a formatted string. + + Raises: + ValueError: If the input cannot be converted to a float. + """ + try: + celsius = float(celsius_str) + fahrenheit = celsius * 9/5 + 32 + return f"{celsius}°C is {fahrenheit}°F" + except ValueError as e: + print(f"Value Error: {e}") + raise +``` + +**Incorrect Implementation** + +```python +def celsius_to_fahrenheit(celsius): + # Converts a temperature from Celsius to Fahrenheit. + celsius = float(celsius) + fahrenheit = celsius * 9/5 + 32 + return f"{celsius}°C is {fahrenheit}°F" +``` + +**Issues with Incorrect Implementation:** +- No type annotations for arguments and return value. +- Missing comprehensive docstring. +- Input type is not enforced as string. + +#### Example 3: Calculate Compound Interest + +**Correct Implementation** + +```python +def calculate_compound_interest(principal_str: str, rate_str: str, time_str: str, n_str: str) -> str: + """ + Calculates compound interest. + + Args: + principal_str (str): The initial amount of money as a string. + rate_str (str): The annual interest rate (decimal) as a string. + time_str (str): The time the money is invested for in years as a string. + n_str (str): The number of times that interest is compounded per year as a string. + + Returns: + str: The amount of money accumulated after n years, including interest. + + Raises: + ValueError: If any of the inputs cannot be converted to the appropriate type or are negative. + """ + try: + principal = float(principal_str) + rate = float(rate_str) + time = float(time_str) + n = int(n_str) + + if principal < 0 or rate < 0 or time < 0 or n < 0: + raise ValueError("Inputs must be non-negative.") + + amount = principal * (1 + rate / n) ** (n * time) + return f"The amount after {time} years is {amount:.2f}" + except ValueError as e: + print(f"Value Error: {e}") + raise +``` + +**Incorrect Implementation** + +```python +def calculate_compound_interest(principal, rate, time, n): + # Calculates compound interest. + principal = float(principal) + rate = float(rate) + time = float(time) + n = int(n) + + if principal < 0 or rate < 0 or time < 0 or n < 0: + raise ValueError("Inputs must be non-negative.") + + amount = principal * (1 + rate / n) ** (n * time) + return f"The amount after {time} years is {amount:.2f}" +``` + +**Issues with Incorrect Implementation:** +- No type annotations for arguments and return value. +- Missing comprehensive docstring. +- Input types are not enforced as strings. + +By following these rules and using the examples provided, you can create robust and well-documented tools in the Swarms environment. Ensure that all functions include proper type annotations, comprehensive docstrings, and that both input and output types are strings. + +#### Example Tool 4: Reverse a String + +**Functionality**: Reverses a given string. + +```python +def reverse_string(s: str) -> str: + """ + Reverses a given string. + + Args: + s (str): The string to reverse. + + Returns: + str: The reversed string. + + Raises: + TypeError: If the input is not a string. + """ + try: + if not isinstance(s, str): + raise TypeError("Input must be a string.") + return s[::-1] + except TypeError as e: + print(f"Type Error: {e}") + raise +``` + +#### Example Tool 5: Check Palindrome + +**Functionality**: Checks if a given string is a palindrome. + +```python +def is_palindrome(s: str) -> str: + """ + Checks if a given string is a palindrome. + + Args: + s (str): The string to check. + + Returns: + str: A message indicating whether the string is a palindrome or not. + + Raises: + TypeError: If the input is not a string. + """ + try: + if not isinstance(s, str): + raise TypeError("Input must be a string.") + normalized_str = ''.join(filter(str.isalnum, s)).lower() + is_palindrome = normalized_str == normalized_str[::-1] + return f"The string '{s}' is {'a palindrome' if is_palindrome else 'not a palindrome'}." + except TypeError as e: + print(f"Type Error: {e}") + raise +``` + +#### Example Tool 6: Fetch Current Weather + +**Functionality**: Fetches the current weather for a given city from the OpenWeatherMap API. + +```python +import requests +import os + +def fetch_current_weather(city: str) -> str: + """ + Fetches the current weather for a given city from the OpenWeatherMap API. + + Args: + city (str): The name of the city to fetch the weather for. + + Returns: + str: A formatted string of the current weather in the specified city. + + Raises: + ValueError: If the API response is invalid or the city is not found. + requests.exceptions.RequestException: If there is an error with the request. + """ + url = "http://api.openweathermap.org/data/2.5/weather" + params = { + "q": city, + "appid": os.getenv("OPENWEATHERMAP_KEY"), + "units": "metric", + } + + try: + response = requests.get(url, params=params) + response.raise_for_status() + data = response.json() + + if "weather" not in data or "main" not in data: + raise ValueError("Invalid API response or city not found.") + + weather_description = data["weather"][0]["description"] + temperature = data["main"]["temp"] + return f"The current weather in {city} is {weather_description} with a temperature of {temperature}°C." + + except requests.exceptions.RequestException as e: + print(f"Request Error: {e}") + raise + except ValueError as e: + print(f"Value Error: {e}") + raise +``` + +By following the examples provided, you can create your own tools to perform various tasks in the Swarms environment. Ensure each function includes type annotations, comprehensive docstrings, and appropriate error handling to make your tools robust and easy to use. + + + + + diff --git a/playground/structs/agent/agent_with_many_tools.py b/docs/swarms/tools/tools_examples.py similarity index 100% rename from playground/structs/agent/agent_with_many_tools.py rename to docs/swarms/tools/tools_examples.py diff --git a/docs/swarms_cloud/available_models.md b/docs/swarms_cloud/available_models.md index 6754cc80..66f23e7c 100644 --- a/docs/swarms_cloud/available_models.md +++ b/docs/swarms_cloud/available_models.md @@ -2,8 +2,7 @@ | Model Name | Description | Input Price | Output Price | Use Cases | |-----------------------|---------------------------------------------------------------------------------------------------------|--------------|--------------|------------------------------------------------------------------------| -| **Qwen-vl** | Qwen VL for real-world multi-modal function calling. | $5/1M Tokens | $10/1M Tokens | Multi-modal interactions and function handling in complex environments.| -| **XComposer2-4khd-7b** | One of the highest performing VLMs (Video Language Models). | $4/1M Tokens | $8/1M Tokens | High-resolution video processing and understanding. | +| **nternlm-xcomposer2-4khd** | One of the highest performing VLMs (Video Language Models). | $4/1M Tokens | $8/1M Tokens | High-resolution video processing and understanding. | ## What models should we add? diff --git a/docs/swarms_cloud/migrate_openai.md b/docs/swarms_cloud/migrate_openai.md index 23718eec..46d35ce3 100644 --- a/docs/swarms_cloud/migrate_openai.md +++ b/docs/swarms_cloud/migrate_openai.md @@ -1,6 +1,5 @@ -**Quickstart** - ## Migrate from OpenAI to Swarms in 3 lines of code + If you’ve been using GPT-3.5 or GPT-4, switching to Swarms is easy! Swarms VLMs are available to use through our OpenAI compatible API. Additionally, if you have been building or prototyping using OpenAI’s Python SDK you can keep your code as-is and use Swarms’s VLMs models. @@ -54,19 +53,41 @@ If you prefer, you can also directly paste your token into the client initializa Once you’ve completed the steps above, the code below will call Swarms LLMs: ```python +from dotenv import load_dotenv from openai import OpenAI -client = OpenAI() +load_dotenv() +openai_api_key = "" + +openai_api_base = "https://api.swarms.world/v1" +model = "internlm-xcomposer2-4khd" -completion = client.chat.completions.create( - model="cogvlm-chat-17b", +client = OpenAI(api_key=openai_api_key, base_url=openai_api_base) +# Note that this model expects the image to come before the main text +chat_response = client.chat.completions.create( + model=model, messages=[ - {"role": "system", "content": "You are a helpful assistant."}, - {"role": "user", "content": "Hello!"}, + { + "role": "user", + "content": [ + { + "type": "image_url", + "image_url": { + "url": "https://home-cdn.reolink.us/wp-content/uploads/2022/04/010345091648784709.4253.jpg", + }, + }, + { + "type": "text", + "text": "What is the most dangerous object in the image?", + }, + ], + } ], + temperature=0.1, + max_tokens=5000, ) +print("Chat response:", chat_response) -print(completion.choices[0].message) ```  Note that you need to supply one of Swarms’s supported LLMs as an argument, as in the example above. For a complete list of our supported LLMs, check out our REST API page. @@ -75,7 +96,7 @@ Note that you need to supply one of Swarms’s supported LLMs as an argument, as ## Example output The code above produces the following object: -``` +```python ChatCompletionMessage(content=" Hello! How can I assist you today? Do you have any questions or tasks you'd like help with? Please let me know and I'll do my best to assist you.", role='assistant' function_call=None, tool_calls=None) ``` diff --git a/example.py b/example.py index c647556d..06ca5534 100644 --- a/example.py +++ b/example.py @@ -1,9 +1,16 @@ +import os from swarms import Agent, OpenAIChat from swarms.prompts.finance_agent_sys_prompt import ( FINANCIAL_AGENT_SYS_PROMPT, ) -model = 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 +) # Initialize the agent agent = Agent( @@ -19,7 +26,7 @@ agent = Agent( # interactive=True, # Set to False to disable interactive mode dynamic_temperature_enabled=True, saved_state_path="finance_agent.json", - # tools=[Add your functions here# ], + # tools=[#Add your functions here# ], # stopping_token="Stop!", # interactive=True, # docs_folder="docs", # Enter your folder name @@ -36,7 +43,6 @@ agent = Agent( # tool_schema= # tools # agent_ops_on=True, - # long_term_memory=ChromaDB(docs_folder="artifacts"), ) diff --git a/main.py b/main.py new file mode 100644 index 00000000..aef0de2f --- /dev/null +++ b/main.py @@ -0,0 +1,133 @@ +import os + +import requests + +from swarms import Agent, OpenAIChat +from swarms.prompts.finance_agent_sys_prompt import ( + FINANCIAL_AGENT_SYS_PROMPT, +) + +# 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 +) + + +def fetch_financial_news( + query: str = "Nvidia news", num_articles: int = 5 +) -> str: + """ + Fetches financial news from the Google News API and returns a formatted string of the top news. + + Args: + api_key (str): Your Google News API key. + query (str): The query term to search for news. Default is "financial". + num_articles (int): The number of top articles to fetch. Default is 5. + + Returns: + str: A formatted string of the top financial news articles. + + Raises: + ValueError: If the API response is invalid or there are no articles found. + requests.exceptions.RequestException: If there is an error with the request. + """ + url = "https://newsapi.org/v2/everything" + params = { + "q": query, + "apiKey": "ceabc81a7d8f45febfedadb27177f3a3", + "pageSize": num_articles, + "sortBy": "relevancy", + } + + try: + response = requests.get(url, params=params) + response.raise_for_status() + data = response.json() + + if "articles" not in data or len(data["articles"]) == 0: + raise ValueError("No articles found or invalid API response.") + + articles = data["articles"] + formatted_articles = [] + + for i, article in enumerate(articles, start=1): + title = article.get("title", "No Title") + description = article.get("description", "No Description") + url = article.get("url", "No URL") + formatted_articles.append( + f"{i}. {title}\nDescription: {description}\nRead more: {url}\n" + ) + + return "\n".join(formatted_articles) + + except requests.exceptions.RequestException as e: + print(f"Request Error: {e}") + raise + except ValueError as e: + print(f"Value Error: {e}") + raise + + +# # Example usage: +# api_key = "ceabc81a7d8f45febfedadb27177f3a3" +# print(fetch_financial_news(api_key)) + + +# Initialize the agent +agent = Agent( + agent_name="Financial-Analysis-Agent", + # system_prompt=FINANCIAL_AGENT_SYS_PROMPT, + llm=model, + max_loops=2, + autosave=True, + # dynamic_temperature_enabled=True, + dashboard=False, + 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=[fetch_financial_news], + # 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, + # long_term_memory=ChromaDB(docs_folder="artifacts"), +) + + +def run_finance_agent(query: str) -> str: + """ + Runs the financial analysis agent with the given query. + + Args: + query (str): The user query to run the agent with. + + Returns: + str: The response from the financial analysis agent. + """ + query = fetch_financial_news(query) + print(query) + response = agent(query) + return response + + +# Example usage: +query = "Nvidia news" +response = run_finance_agent(f"Summarize the latest Nvidia financial news {query}") +print(response) diff --git a/openai_model.py b/openai_model.py new file mode 100644 index 00000000..2f8ac76e --- /dev/null +++ b/openai_model.py @@ -0,0 +1,28 @@ +from swarms import OpenAIChat, Agent +import os + +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, + max_tokens=4000, +) + +# Agent +agent = Agent( + agent_name="Non-Profit Incorporation Agent", + llm=model, + system_prompt="I am an AI assistant that helps you incorporate a non-profit organization. I can provide information on the best states to incorporate a non-profit in, the steps to incorporate a non-profit, and answer any other questions you may have about non-profit incorporation.", + max_loops="auto", + interactive=True, + streaming_on=True, +) + + +# Run +response = agent("What's the best state to incorporate a non profit in?") +print(response) diff --git a/playground/structs/agent/basic_agent_with_azure_openai.py b/playground/agents/basic_agent_with_azure_openai.py similarity index 100% rename from playground/structs/agent/basic_agent_with_azure_openai.py rename to playground/agents/basic_agent_with_azure_openai.py diff --git a/playground/structs/agent/custom_model_with_agent.py b/playground/agents/custom_model_with_agent.py similarity index 100% rename from playground/structs/agent/custom_model_with_agent.py rename to playground/agents/custom_model_with_agent.py diff --git a/playground/structs/agent/easy_example.py b/playground/agents/easy_example.py similarity index 100% rename from playground/structs/agent/easy_example.py rename to playground/agents/easy_example.py diff --git a/playground/agents/agent_ops.py b/playground/agents/monitoring/agent_ops.py similarity index 100% rename from playground/agents/agent_ops.py rename to playground/agents/monitoring/agent_ops.py diff --git a/playground/structs/agent/multion/multion_example.ipynb b/playground/agents/multion/multion_example.ipynb similarity index 100% rename from playground/structs/agent/multion/multion_example.ipynb rename to playground/agents/multion/multion_example.ipynb diff --git a/agent_with_basemodel_output_type.py b/playground/agents/tools/agent_with_basemodel_output_type.py similarity index 100% rename from agent_with_basemodel_output_type.py rename to playground/agents/tools/agent_with_basemodel_output_type.py diff --git a/playground/agents/tools/agent_with_many_tools.py b/playground/agents/tools/agent_with_many_tools.py new file mode 100644 index 00000000..e69de29b diff --git a/playground/agents/devin.py b/playground/agents/tools/devin.py similarity index 100% rename from playground/agents/devin.py rename to playground/agents/tools/devin.py diff --git a/playground/structs/agent/tool_agent.py b/playground/agents/tools/tool_agent.py similarity index 100% rename from playground/structs/agent/tool_agent.py rename to playground/agents/tools/tool_agent.py diff --git a/playground/agents/tool_agent/command_r_tool_agent.py b/playground/agents/tools/tool_agent/command_r_tool_agent.py similarity index 100% rename from playground/agents/tool_agent/command_r_tool_agent.py rename to playground/agents/tools/tool_agent/command_r_tool_agent.py diff --git a/playground/agents/tool_agent/example_toolagent.py b/playground/agents/tools/tool_agent/example_toolagent.py similarity index 100% rename from playground/agents/tool_agent/example_toolagent.py rename to playground/agents/tools/tool_agent/example_toolagent.py diff --git a/playground/agents/tool_agent/jamba_tool_agent.py b/playground/agents/tools/tool_agent/jamba_tool_agent.py similarity index 100% rename from playground/agents/tool_agent/jamba_tool_agent.py rename to playground/agents/tools/tool_agent/jamba_tool_agent.py diff --git a/playground/agents/tool_agent/tool_agent_pydantic.py b/playground/agents/tools/tool_agent/tool_agent_pydantic.py similarity index 100% rename from playground/agents/tool_agent/tool_agent_pydantic.py rename to playground/agents/tools/tool_agent/tool_agent_pydantic.py diff --git a/playground/agents/tool_agent/tool_agent_with_llm.py b/playground/agents/tools/tool_agent/tool_agent_with_llm.py similarity index 100% rename from playground/agents/tool_agent/tool_agent_with_llm.py rename to playground/agents/tools/tool_agent/tool_agent_with_llm.py diff --git a/playground/agents/amazon_review_agent.py b/playground/agents/use_cases/code_gen/amazon_review_agent.py similarity index 100% rename from playground/agents/amazon_review_agent.py rename to playground/agents/use_cases/code_gen/amazon_review_agent.py diff --git a/playground/agents/api_requester_agent.py b/playground/agents/use_cases/code_gen/api_requester_agent.py similarity index 100% rename from playground/agents/api_requester_agent.py rename to playground/agents/use_cases/code_gen/api_requester_agent.py diff --git a/playground/agents/estate_planning_agent.py b/playground/agents/use_cases/finance/estate_planning_agent.py similarity index 100% rename from playground/agents/estate_planning_agent.py rename to playground/agents/use_cases/finance/estate_planning_agent.py diff --git a/playground/agents/financial_agent_gpt4o_mini.py b/playground/agents/use_cases/finance/financial_agent_gpt4o_mini.py similarity index 100% rename from playground/agents/financial_agent_gpt4o_mini.py rename to playground/agents/use_cases/finance/financial_agent_gpt4o_mini.py diff --git a/playground/structs/agent/kyle_hackathon.py b/playground/agents/use_cases/kyle_hackathon.py similarity index 97% rename from playground/structs/agent/kyle_hackathon.py rename to playground/agents/use_cases/kyle_hackathon.py index 58d8f26f..36fcfcd2 100644 --- a/playground/structs/agent/kyle_hackathon.py +++ b/playground/agents/use_cases/kyle_hackathon.py @@ -4,7 +4,7 @@ from dotenv import load_dotenv from swarms import Agent, OpenAIChat from swarms.agents.multion_agent import MultiOnAgent -from playground.memory.chroma_db import ChromaDB +from swarms_memory import ChromaDB from swarms import tool from swarms.tools.prebuilt.code_interpreter import ( SubprocessCodeInterpreter, diff --git a/playground/agents/multi_modal_auto_agent_example.py b/playground/agents/use_cases/multi_modal/multi_modal_auto_agent_example.py similarity index 100% rename from playground/agents/multi_modal_auto_agent_example.py rename to playground/agents/use_cases/multi_modal/multi_modal_auto_agent_example.py diff --git a/playground/agents/multi_modal_example.py b/playground/agents/use_cases/multi_modal/multi_modal_example.py similarity index 100% rename from playground/agents/multi_modal_example.py rename to playground/agents/use_cases/multi_modal/multi_modal_example.py diff --git a/playground/structs/agent/multi_modal_flow_example.py b/playground/agents/use_cases/multi_modal/multi_modal_flow_example.py similarity index 100% rename from playground/structs/agent/multi_modal_flow_example.py rename to playground/agents/use_cases/multi_modal/multi_modal_flow_example.py diff --git a/playground/structs/agent/multi_modal_rag_agent.py b/playground/agents/use_cases/multi_modal/multi_modal_rag_agent.py similarity index 97% rename from playground/structs/agent/multi_modal_rag_agent.py rename to playground/agents/use_cases/multi_modal/multi_modal_rag_agent.py index 7821f3b4..c309d60a 100644 --- a/playground/structs/agent/multi_modal_rag_agent.py +++ b/playground/agents/use_cases/multi_modal/multi_modal_rag_agent.py @@ -4,7 +4,7 @@ import os from dotenv import load_dotenv from swarms import Agent, OpenAIChat -from playground.memory.chroma_db import ChromaDB +from swarms_memory import ChromaDB from swarms.prompts.visual_cot import VISUAL_CHAIN_OF_THOUGHT from swarms import tool diff --git a/playground/structs/agent/new_agent_tool_system.py b/playground/agents/use_cases/multi_modal/new_agent_tool_system.py similarity index 100% rename from playground/structs/agent/new_agent_tool_system.py rename to playground/agents/use_cases/multi_modal/new_agent_tool_system.py diff --git a/playground/agents/new_perplexity_agent.py b/playground/agents/use_cases/research/new_perplexity_agent.py similarity index 100% rename from playground/agents/new_perplexity_agent.py rename to playground/agents/use_cases/research/new_perplexity_agent.py diff --git a/playground/agents/perplexity_agent.py b/playground/agents/use_cases/research/perplexity_agent.py similarity index 100% rename from playground/agents/perplexity_agent.py rename to playground/agents/use_cases/research/perplexity_agent.py diff --git a/playground/agents/perimeter_defense_agent.py b/playground/agents/use_cases/security/perimeter_defense_agent.py similarity index 100% rename from playground/agents/perimeter_defense_agent.py rename to playground/agents/use_cases/security/perimeter_defense_agent.py diff --git a/playground/swarms_example.ipynb b/playground/collabs/swarms_example.ipynb similarity index 100% rename from playground/swarms_example.ipynb rename to playground/collabs/swarms_example.ipynb diff --git a/playground/structs/agent/agent_basic_customize.py b/playground/structs/agent/agent_basic_customize.py deleted file mode 100644 index 76b6f178..00000000 --- a/playground/structs/agent/agent_basic_customize.py +++ /dev/null @@ -1,29 +0,0 @@ -from swarms.models import OpenAIChat -from swarms.structs import Agent - -api_key = "" - -# Initialize the language model, this model can be swapped out with Anthropic, ETC, Huggingface Models like Mistral, ETC -llm = OpenAIChat( - # model_name="gpt-4" - openai_api_key=api_key, - temperature=0.5, - # max_tokens=100, -) - -## Initialize the workflow -agent = Agent( - llm=llm, - max_loops=2, - dashboard=True, - # stopping_condition=None, # You can define a stopping condition as needed. - # loop_interval=1, - # retry_attempts=3, - # retry_interval=1, - # interactive=False, # Set to 'True' for interactive mode. - # dynamic_temperature=False, # Set to 'True' for dynamic temperature handling. -) - -# Run the workflow on a task -out = agent.run("Generate a 10,000 word blog on health and wellness.") -print(out) diff --git a/playground/structs/agent/agent_with_tools_example.py b/playground/structs/agent/agent_with_tools_example.py deleted file mode 100644 index 91787a6b..00000000 --- a/playground/structs/agent/agent_with_tools_example.py +++ /dev/null @@ -1,76 +0,0 @@ -""" - - -tool decorated func [search_api] -> agent which parses the docs of the tool func --> injected into prompt -> agent will output json containing tool usage -> agent output will be parsed -> tool executed --> terminal response can be returned to agent for self-healing - - -""" - -import os - -from dotenv import load_dotenv - -# Import the OpenAIChat model and the Agent struct -from swarms import Agent, OpenAIChat - -# Load the environment variables -load_dotenv() - - -# Define a tool -def search_api(query: str, description: str): - """Search the web for the query - - Args: - query (str): _description_ - - Returns: - _type_: _description_ - """ - return f"Search results for {query}" - - -def weather_api( - query: str, -): - """_summary_ - - Args: - query (str): _description_ - """ - print(f"Getting the weather for {query}") - - -def rapid_api(query: str): - """_summary_ - - Args: - query (str): _description_ - """ - print(f"Getting the weather for {query}") - - -# Get the API key from the environment -api_key = os.environ.get("OPENAI_API_KEY") - -# Initialize the language model -llm = OpenAIChat( - temperature=0.5, - openai_api_key=api_key, -) - - -## Initialize the workflow -agent = Agent( - agent_name="Research Agent", - llm=llm, - max_loops=1, - dashboard=True, - tools=[search_api, weather_api, rapid_api], -) - -# Run the workflow on a task -out = agent.run("Generate a 10,000 word blog on health and wellness.") -print(out) diff --git a/playground/structs/agent/fuyu_flow_example.py b/playground/structs/agent/fuyu_flow_example.py deleted file mode 100644 index 4231d827..00000000 --- a/playground/structs/agent/fuyu_flow_example.py +++ /dev/null @@ -1,10 +0,0 @@ -from swarms import Agent, Fuyu - -llm = Fuyu() - -agent = Agent(max_loops="auto", llm=llm) - -agent.run( - task="Describe this image in a few sentences: ", - img="https://unsplash.com/photos/0pIC5ByPpZY", -) diff --git a/playground/structs/agent_registry.py b/playground/structs/swarms/agent_registry.py similarity index 100% rename from playground/structs/agent_registry.py rename to playground/structs/swarms/agent_registry.py diff --git a/multi_agent_collab_demo.py b/playground/structs/swarms/multi_agent_collab_demo.py similarity index 100% rename from multi_agent_collab_demo.py rename to playground/structs/swarms/multi_agent_collab_demo.py diff --git a/playground/structs/multi_agent_collaboration/agent_delegation.py b/playground/structs/swarms/multi_agent_collaboration/agent_delegation.py similarity index 100% rename from playground/structs/multi_agent_collaboration/agent_delegation.py rename to playground/structs/swarms/multi_agent_collaboration/agent_delegation.py diff --git a/playground/structs/multi_agent_collaboration/agent_rearrange.py b/playground/structs/swarms/multi_agent_collaboration/agent_rearrange.py similarity index 100% rename from playground/structs/multi_agent_collaboration/agent_rearrange.py rename to playground/structs/swarms/multi_agent_collaboration/agent_rearrange.py diff --git a/playground/structs/multi_agent_collaboration/agent_rearrange_human_in_loop.py b/playground/structs/swarms/multi_agent_collaboration/agent_rearrange_human_in_loop.py similarity index 100% rename from playground/structs/multi_agent_collaboration/agent_rearrange_human_in_loop.py rename to playground/structs/swarms/multi_agent_collaboration/agent_rearrange_human_in_loop.py diff --git a/playground/structs/multi_agent_collaboration/autoswarm.py b/playground/structs/swarms/multi_agent_collaboration/autoswarm.py similarity index 100% rename from playground/structs/multi_agent_collaboration/autoswarm.py rename to playground/structs/swarms/multi_agent_collaboration/autoswarm.py diff --git a/playground/structs/multi_agent_collaboration/build_your_own_swarm.py b/playground/structs/swarms/multi_agent_collaboration/build_your_own_swarm.py similarity index 100% rename from playground/structs/multi_agent_collaboration/build_your_own_swarm.py rename to playground/structs/swarms/multi_agent_collaboration/build_your_own_swarm.py diff --git a/playground/structs/multi_agent_collaboration/company_example.py b/playground/structs/swarms/multi_agent_collaboration/company_example.py similarity index 100% rename from playground/structs/multi_agent_collaboration/company_example.py rename to playground/structs/swarms/multi_agent_collaboration/company_example.py diff --git a/playground/structs/multi_agent_collaboration/concurrent_workflow_example.py b/playground/structs/swarms/multi_agent_collaboration/concurrent_workflow_example.py similarity index 100% rename from playground/structs/multi_agent_collaboration/concurrent_workflow_example.py rename to playground/structs/swarms/multi_agent_collaboration/concurrent_workflow_example.py diff --git a/playground/structs/multi_agent_collaboration/debate_example.py b/playground/structs/swarms/multi_agent_collaboration/debate_example.py similarity index 100% rename from playground/structs/multi_agent_collaboration/debate_example.py rename to playground/structs/swarms/multi_agent_collaboration/debate_example.py diff --git a/playground/structs/multi_agent_collaboration/graph_workflow_example.py b/playground/structs/swarms/multi_agent_collaboration/graph_workflow_example.py similarity index 100% rename from playground/structs/multi_agent_collaboration/graph_workflow_example.py rename to playground/structs/swarms/multi_agent_collaboration/graph_workflow_example.py diff --git a/playground/structs/multi_agent_collaboration/load_balancer_example.py b/playground/structs/swarms/multi_agent_collaboration/load_balancer_example.py similarity index 100% rename from playground/structs/multi_agent_collaboration/load_balancer_example.py rename to playground/structs/swarms/multi_agent_collaboration/load_balancer_example.py diff --git a/playground/structs/multi_agent_collaboration/majority_voting.py b/playground/structs/swarms/multi_agent_collaboration/majority_voting.py similarity index 100% rename from playground/structs/multi_agent_collaboration/majority_voting.py rename to playground/structs/swarms/multi_agent_collaboration/majority_voting.py diff --git a/playground/structs/multi_agent_collaboration/message_pool.py b/playground/structs/swarms/multi_agent_collaboration/message_pool.py similarity index 100% rename from playground/structs/multi_agent_collaboration/message_pool.py rename to playground/structs/swarms/multi_agent_collaboration/message_pool.py diff --git a/playground/structs/multi_agent_collaboration/message_pool_example.py b/playground/structs/swarms/multi_agent_collaboration/message_pool_example.py similarity index 100% rename from playground/structs/multi_agent_collaboration/message_pool_example.py rename to playground/structs/swarms/multi_agent_collaboration/message_pool_example.py diff --git a/playground/structs/multi_agent_collaboration/mixture_of_agents/agent_ops_moa.py b/playground/structs/swarms/multi_agent_collaboration/mixture_of_agents/agent_ops_moa.py similarity index 100% rename from playground/structs/multi_agent_collaboration/mixture_of_agents/agent_ops_moa.py rename to playground/structs/swarms/multi_agent_collaboration/mixture_of_agents/agent_ops_moa.py diff --git a/playground/structs/multi_agent_collaboration/mixture_of_agents/moa_with_scp.py b/playground/structs/swarms/multi_agent_collaboration/mixture_of_agents/moa_with_scp.py similarity index 100% rename from playground/structs/multi_agent_collaboration/mixture_of_agents/moa_with_scp.py rename to playground/structs/swarms/multi_agent_collaboration/mixture_of_agents/moa_with_scp.py diff --git a/playground/structs/multi_agent_collaboration/multi_process_workflow.py b/playground/structs/swarms/multi_agent_collaboration/multi_process_workflow.py similarity index 100% rename from playground/structs/multi_agent_collaboration/multi_process_workflow.py rename to playground/structs/swarms/multi_agent_collaboration/multi_process_workflow.py diff --git a/playground/structs/multi_agent_collaboration/recursive_example.py b/playground/structs/swarms/multi_agent_collaboration/recursive_example.py similarity index 100% rename from playground/structs/multi_agent_collaboration/recursive_example.py rename to playground/structs/swarms/multi_agent_collaboration/recursive_example.py diff --git a/playground/structs/multi_agent_collaboration/round_robin_example.py b/playground/structs/swarms/multi_agent_collaboration/round_robin_example.py similarity index 100% rename from playground/structs/multi_agent_collaboration/round_robin_example.py rename to playground/structs/swarms/multi_agent_collaboration/round_robin_example.py diff --git a/playground/structs/multi_agent_collaboration/round_robin_swarm_example.py b/playground/structs/swarms/multi_agent_collaboration/round_robin_swarm_example.py similarity index 100% rename from playground/structs/multi_agent_collaboration/round_robin_swarm_example.py rename to playground/structs/swarms/multi_agent_collaboration/round_robin_swarm_example.py diff --git a/playground/structs/multi_agent_collaboration/sequential_workflow_example.py b/playground/structs/swarms/multi_agent_collaboration/sequential_workflow_example.py similarity index 100% rename from playground/structs/multi_agent_collaboration/sequential_workflow_example.py rename to playground/structs/swarms/multi_agent_collaboration/sequential_workflow_example.py diff --git a/playground/structs/multi_agent_collaboration/sequential_workflow_new.py b/playground/structs/swarms/multi_agent_collaboration/sequential_workflow_new.py similarity index 100% rename from playground/structs/multi_agent_collaboration/sequential_workflow_new.py rename to playground/structs/swarms/multi_agent_collaboration/sequential_workflow_new.py diff --git a/playground/structs/multi_agent_collaboration/sequential_workflow_with_agents.py b/playground/structs/swarms/multi_agent_collaboration/sequential_workflow_with_agents.py similarity index 100% rename from playground/structs/multi_agent_collaboration/sequential_workflow_with_agents.py rename to playground/structs/swarms/multi_agent_collaboration/sequential_workflow_with_agents.py diff --git a/playground/structs/multi_agent_collaboration/society_of_agents.py b/playground/structs/swarms/multi_agent_collaboration/society_of_agents.py similarity index 100% rename from playground/structs/multi_agent_collaboration/society_of_agents.py rename to playground/structs/swarms/multi_agent_collaboration/society_of_agents.py diff --git a/playground/structs/multi_agent_collaboration/swarm_network_api_on.py b/playground/structs/swarms/multi_agent_collaboration/swarm_network_api_on.py similarity index 100% rename from playground/structs/multi_agent_collaboration/swarm_network_api_on.py rename to playground/structs/swarms/multi_agent_collaboration/swarm_network_api_on.py diff --git a/playground/structs/multi_agent_collaboration/swarm_network_example.py b/playground/structs/swarms/multi_agent_collaboration/swarm_network_example.py similarity index 100% rename from playground/structs/multi_agent_collaboration/swarm_network_example.py rename to playground/structs/swarms/multi_agent_collaboration/swarm_network_example.py diff --git a/playground/structs/multi_agent_collaboration/swarm_of_ba_agents/agents.py b/playground/structs/swarms/multi_agent_collaboration/swarm_of_ba_agents/agents.py similarity index 100% rename from playground/structs/multi_agent_collaboration/swarm_of_ba_agents/agents.py rename to playground/structs/swarms/multi_agent_collaboration/swarm_of_ba_agents/agents.py diff --git a/playground/structs/search_arena/requirements.txt b/playground/structs/swarms/search_arena/requirements.txt similarity index 100% rename from playground/structs/search_arena/requirements.txt rename to playground/structs/swarms/search_arena/requirements.txt diff --git a/playground/structs/search_arena/search_agents.py b/playground/structs/swarms/search_arena/search_agents.py similarity index 100% rename from playground/structs/search_arena/search_agents.py rename to playground/structs/swarms/search_arena/search_agents.py diff --git a/playground/structs/task_example.py b/playground/structs/tasks/task_example.py similarity index 100% rename from playground/structs/task_example.py rename to playground/structs/tasks/task_example.py diff --git a/playground/structs/example_concurrentworkflow.py b/playground/structs/workflows/example_concurrentworkflow.py similarity index 100% rename from playground/structs/example_concurrentworkflow.py rename to playground/structs/workflows/example_concurrentworkflow.py diff --git a/playground/structs/example_recursiveworkflow.py b/playground/structs/workflows/example_recursiveworkflow.py similarity index 100% rename from playground/structs/example_recursiveworkflow.py rename to playground/structs/workflows/example_recursiveworkflow.py diff --git a/playground/structs/example_sequentialworkflow.py b/playground/structs/workflows/example_sequentialworkflow.py similarity index 100% rename from playground/structs/example_sequentialworkflow.py rename to playground/structs/workflows/example_sequentialworkflow.py diff --git a/playground/structs/example_swarmnetwork.py b/playground/structs/workflows/example_swarmnetwork.py similarity index 100% rename from playground/structs/example_swarmnetwork.py rename to playground/structs/workflows/example_swarmnetwork.py diff --git a/swarms/cli/onboarding.py b/swarms/cli/onboarding.py new file mode 100644 index 00000000..2bbbab38 --- /dev/null +++ b/swarms/cli/onboarding.py @@ -0,0 +1,121 @@ +import os +from termcolor import colored +import json + +welcome = """ +Swarms is the first-ever multi-agent enterpris-grade framework that enables you to seamlessly orchestrate agents! +""" + + +def print_welcome(): + print( + colored( + f"Welcome to the Swarms Framework! \n {welcome}", + "cyan", + attrs=["bold"], + ) + ) + print( + colored( + "Thank you for trying out Swarms. We are excited to have you on board to enable you to get started.", + "cyan", + ) + ) + print() + print(colored("Resources", "cyan", attrs=["bold"])) + print( + colored("GitHub: ", "cyan") + + colored("https://github.com/kyegomez/swarms", "magenta") + ) + print( + colored("Discord: ", "cyan") + + colored( + "https://discord.com/servers/agora-999382051935506503", + "magenta", + ) + ) + print( + colored("Documentation: ", "cyan") + + colored("https://docs.swarms.world", "magenta") + ) + print( + colored("Marketplace: ", "cyan") + + colored("https://swarms.world", "magenta") + ) + print( + colored("Submit an Issue: ", "cyan") + + colored( + "https://github.com/kyegomez/swarms/issues/new/choose", + "magenta", + ) + ) + print( + colored("Swarms Project Board // Roadmap ", "cyan") + + colored( + "https://github.com/users/kyegomez/projects/1", "magenta" + ) + ) + print() + print( + colored( + "Let's get to know you a bit better!", + "magenta", + attrs=["bold"], + ) + ) + + +def get_user_info(): + first_name = input(colored("What is your first name? ", "blue")) + last_name = input(colored("What is your last name? ", "blue")) + email = input(colored("What is your email? ", "blue")) + company = input(colored("Which company do you work for? ", "blue")) + project = input( + colored("What are you trying to build with Swarms? ", "blue") + ) + swarms_type = input( + colored("What type of swarms are you building? ", "blue") + ) + + user_info = { + "first_name": first_name, + "last_name": last_name, + "email": email, + "company": company, + "project": project, + "swarms_type": swarms_type, + } + + return user_info + + +def save_user_info(user_info: dict = None): + cache_dir = os.path.expanduser("~/.swarms_cache") + if not os.path.exists(cache_dir): + os.makedirs(cache_dir) + + cache_file = os.path.join(cache_dir, "user_info.json") + with open(cache_file, "w") as f: + json.dump(user_info, f, indent=4) + + print( + colored( + "Your information has been saved as a JSON file! Thank you.", + "cyan", + ) + ) + + +def onboard(): + print_welcome() + user_info = get_user_info() + save_user_info(user_info) + print( + colored( + "You're all set! Enjoy using Swarms.", "cyan", attrs=["bold"] + ) + ) + + +if __name__ == "__main__": + onboard() diff --git a/swarms/structs/__init__.py b/swarms/structs/__init__.py index 600e23ae..c5a72642 100644 --- a/swarms/structs/__init__.py +++ b/swarms/structs/__init__.py @@ -155,4 +155,4 @@ __all__ = [ "sigmoid_swarm", "staircase_swarm", "star_swarm", -] \ No newline at end of file +] diff --git a/swarms/structs/agent.py b/swarms/structs/agent.py index 9e493ee4..67da5739 100644 --- a/swarms/structs/agent.py +++ b/swarms/structs/agent.py @@ -790,12 +790,13 @@ class Agent(BaseStructure): all_responses.append(response) - # Check if tools is not None + # TODO: Implement reliablity check if self.tools is not None: - self.parse_function_call_and_execute(response) + # self.parse_function_call_and_execute(response) + self.parse_and_execute_tools(response) - if self.code_interpreter is not False: - self.code_interpreter_execution(response) + # if self.code_interpreter is not False: + # self.code_interpreter_execution(response) if self.evaluator: evaluated_response = self.evaluator(response) @@ -887,10 +888,13 @@ class Agent(BaseStructure): self.check_end_session_agentops() # final_response = " ".join(all_responses) - all_responses = [response for response in all_responses if response is not None] + all_responses = [ + response + for response in all_responses + if response is not None + ] final_response = " ".join(all_responses) - if self.return_history: return self.short_memory.return_history_as_string() else: @@ -1618,48 +1622,46 @@ class Agent(BaseStructure): def convert_tool_into_openai_schema(self): logger.info("Converting tools into OpenAI function calling schema") - if callable(self.tools): - for tool in self.tools: - # Transform the tool into a openai function calling schema - name = tool.__name__ - description = tool.__doc__ - logger.info( - f"Converting tool: {name} into a OpenAI certified function calling schema. Add documentation and type hints." - ) - tool_schema_list = get_openai_function_schema_from_func( - tool, name=name, description=description - ) + # if callable(self.tools): + for tool in self.tools: + # Transform the tool into a openai function calling schema + name = tool.__name__ + description = tool.__doc__ + logger.info( + f"Converting tool: {name} into a OpenAI certified function calling schema. Add documentation and type hints." + ) + tool_schema_list = get_openai_function_schema_from_func( + tool, name=name, description=description + ) - # Transform the dictionary to a string - tool_schema_list = json.dumps(tool_schema_list, indent=4) + # Transform the dictionary to a string + tool_schema_list = json.dumps(tool_schema_list, indent=4) - # Add the tool schema to the short memory - self.short_memory.add( - role="System", content=tool_schema_list - ) + # Add the tool schema to the short memory + self.short_memory.add(role="System", content=tool_schema_list) - logger.info( - f"Conversion process successful, the tool {name} has been integrated with the agent successfully." - ) + logger.info( + f"Conversion process successful, the tool {name} has been integrated with the agent successfully." + ) - else: - for tool in self.tools: + # else: + # for tool in self.tools: - # Parse the json for the name of the function - name = tool["name"] - description = tool["description"] + # # Parse the json for the name of the function + # name = tool["name"] + # description = tool["description"] - # Transform the dict into a string - tool_schema_list = json.dumps(tool, indent=4) + # # Transform the dict into a string + # tool_schema_list = json.dumps(tool, indent=4) - # Add the tool schema to the short memory - self.short_memory.add( - role="System", content=tool_schema_list - ) + # # Add the tool schema to the short memory + # self.short_memory.add( + # role="System", content=tool_schema_list + # ) - logger.info( - f"Conversion process successful, the tool {name} has been integrated with the agent successfully." - ) + # logger.info( + # f"Conversion process successful, the tool {name} has been integrated with the agent successfully." + # ) return None diff --git a/swarms/structs/tool_registry.py b/swarms/structs/tool_registry.py new file mode 100644 index 00000000..e69de29b diff --git a/swarms/telemetry/hashicorp_vault.py b/swarms/telemetry/hashicorp_vault.py new file mode 100644 index 00000000..7c9b3af8 --- /dev/null +++ b/swarms/telemetry/hashicorp_vault.py @@ -0,0 +1,110 @@ +import requests +from loguru import logger +import os + + +def fetch_secrets_from_vault( + client_id: str = os.getenv("HCP_CLIENT_ID"), + client_secret: str = os.getenv("HCP_CLIENT_SECRET"), + organization_id: str = os.getenv("HCP_ORGANIZATION_ID"), + project_id: str = os.getenv("HCP_PROJECT_ID"), + app_id: str = os.getenv("HCP_APP_ID"), +) -> str: + """ + Fetch secrets from HashiCorp Vault using service principal authentication. + + Args: + client_id (str): The client ID for the service principal. + client_secret (str): The client secret for the service principal. + organization_id (str): The ID of the organization in HCP. + project_id (str): The ID of the project in HCP. + app_id (str): The ID of the app in HCP. + + Returns: + str: A dictionary containing the fetched secrets. + + Raises: + Exception: If there is an error retrieving the API token or secrets. + """ + # Step 1: Generate the API Token + token_url = "https://auth.idp.hashicorp.com/oauth2/token" + token_data = { + "client_id": client_id, + "client_secret": client_secret, + "grant_type": "client_credentials", + "audience": "https://api.hashicorp.cloud", + } + token_headers = {"Content-Type": "application/x-www-form-urlencoded"} + + logger.info("Requesting API token from HashiCorp Vault") + response = requests.post( + token_url, data=token_data, headers=token_headers + ) + + if response.status_code != 200: + logger.error( + f"Failed to retrieve API token. Status Code: {response.status_code}, Response: {response.text}" + ) + response.raise_for_status() + + api_token = response.json().get("access_token") + + if not api_token: + raise Exception("Failed to retrieve API token") + + # Step 2: Fetch Secrets + secrets_url = f"https://api.cloud.hashicorp.com/secrets/2023-06-13/organizations/{organization_id}/projects/{project_id}/apps/{app_id}/open" + secrets_headers = {"Authorization": f"Bearer {api_token}"} + + logger.info("Fetching secrets from HashiCorp Vault") + response = requests.get(secrets_url, headers=secrets_headers) + + if response.status_code != 200: + logger.error( + f"Failed to fetch secrets. Status Code: {response.status_code}, Response: {response.text}" + ) + response.raise_for_status() + + secrets = response.json() + + for secret in secrets["secrets"]: + name = secret.get("name") + value = secret.get("version", {}).get("value") + print(f"Name: {name}, Value: {value}") + + return name, value + + +# def main() -> None: +# """ +# Main function to fetch secrets from HashiCorp Vault and print them. + +# Raises: +# EnvironmentError: If required environment variables are not set. +# """ +# HCP_CLIENT_ID = os.getenv("HCP_CLIENT_ID") +# HCP_CLIENT_SECRET = os.getenv("HCP_CLIENT_SECRET") +# ORGANIZATION_ID = os.getenv("HCP_ORGANIZATION_ID") +# PROJECT_ID = os.getenv("HCP_PROJECT_ID") +# APP_ID = os.getenv("HCP_APP_ID") + +# # if not all([HCP_CLIENT_ID, HCP_CLIENT_SECRET, ORGANIZATION_ID, PROJECT_ID, APP_ID]): +# # raise EnvironmentError("One or more environment variables are missing: HCP_CLIENT_ID, HCP_CLIENT_SECRET, ORGANIZATION_ID, PROJECT_ID, APP_ID") + +# secrets = fetch_secrets_from_vault( +# HCP_CLIENT_ID, +# HCP_CLIENT_SECRET, +# ORGANIZATION_ID, +# PROJECT_ID, +# APP_ID, +# ) +# print(secrets) + +# for secret in secrets["secrets"]: +# name = secret.get("name") +# value = secret.get("version", {}).get("value") +# print(f"Name: {name}, Value: {value}") + + +# if __name__ == "__main__": +# main() diff --git a/swarms/utils/parse_code.py b/swarms/utils/parse_code.py index 838d5868..cc70915f 100644 --- a/swarms/utils/parse_code.py +++ b/swarms/utils/parse_code.py @@ -11,9 +11,16 @@ def extract_code_from_markdown(markdown_content: str): Returns: - str: A single string containing all the code blocks separated by newlines. """ - # Regular expression for fenced code blocks + # Regular expression for fenced code blocks with optional language specifier pattern = r"```(?:\w+\n)?(.*?)```" matches = re.findall(pattern, markdown_content, re.DOTALL) # Concatenate all code blocks separated by newlines return "\n".join(code.strip() for code in matches) + + +# example = """```json +# { "type": "function", "function": { "name": "fetch_financial_news", "parameters": { "query": "Nvidia news", "num_articles": 5 } } } +# ```""" + +# print(extract_code_from_markdown(example)) # Output: { "type": "function", "function": { "name": "fetch_financial_news", "parameters": { "query": "Nvidia news", "num_articles": 5 } } }