parent
55e7f186a8
commit
3b4a510833
@ -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) | | |
|
@ -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.
|
@ -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="<DONE>",
|
||||
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="<DONE>",
|
||||
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="<DONE>",
|
||||
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="<DONE>",
|
||||
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="<DONE>",
|
||||
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="<DONE>",
|
||||
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)
|
||||
```
|
@ -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)
|
@ -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.
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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)
|
@ -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)
|
@ -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)
|
@ -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)
|
@ -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",
|
||||
)
|
@ -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()
|
@ -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()
|
Loading…
Reference in new issue