From 0e95f1c8391aca56eecbd2cead4ab70155867ed9 Mon Sep 17 00:00:00 2001 From: Kye Gomez Date: Tue, 21 Jan 2025 12:23:27 -0500 Subject: [PATCH 01/12] [DOCS][Update] --- docs/mkdocs.yml | 22 +-- docs/swarms/products.md | 177 ++++++++++++++++++ .../onboard/agents.yaml | 0 .../onboard/onboard-basic.py | 0 4 files changed, 185 insertions(+), 14 deletions(-) create mode 100644 docs/swarms/products.md rename {examples => new_features_examples}/onboard/agents.yaml (100%) rename {examples => new_features_examples}/onboard/onboard-basic.py (100%) diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 2bd891797..c1a4ccc5a 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -140,27 +140,23 @@ nav: - Overview: "index.md" # - The Vision: "swarms/framework/vision.md" # - Docker Setup: "swarms/install/docker_setup.md" - - Our Goal; The Ultimate Multi-Agent LLM Framework for Developers: "swarms/concept/vision.md" + - Swarms Vision: "swarms/concept/vision.md" - Swarm Ecosystem: "swarms/concept/swarm_ecosystem.md" + - Swarms Products: "swarms/products.md" - Onboarding: - Installation: "swarms/install/install.md" - Environment Configuration: "swarms/install/workspace_manager.md" - Quickstart: "swarms/install/quickstart.md" - Swarms CLI: "swarms/cli/main.md" - # - Swarms + Docker: - Swarms Framework Architecture: "swarms/concept/framework_architecture.md" # - Prelimary: # - 80/20 Rule For Agents: "swarms/prompting/8020.md" - - Managing Prompts in Production: "swarms/prompts/main.md" - Agents: # - Overview: "swarms/structs/index.md" - # - Build Custom Agents: "swarms/structs/diy_your_own_agent.md" + - Managing Prompts in Production: "swarms/prompts/main.md" - Agent Architecture: "swarms/framework/agents_explained.md" - Complete Agent API: "swarms/structs/agent.md" - - OpenAI Assistant: "swarms/agents/openai_assistant.md" - Create and Run Agents from YAML: "swarms/agents/create_agents_yaml.md" - - Integrating External Agents from Griptape, Langchain, etc: "swarms/agents/external_party_agents.md" - - Creating Custom Agents: "swarms/agents/new_agent.md" - Tools: - Overview: "swarms/tools/main.md" - What are tools?: "swarms/tools/build_tool.md" @@ -168,6 +164,10 @@ nav: - Tool Storage & tool_registry decorator: "swarms/tools/tool_storage.md" - RAG || Long Term Memory: - Integrating RAG with Agents: "swarms/memory/diy_memory.md" + - Third-Party Agent Integrations: + - OpenAI Assistant: "swarms/agents/openai_assistant.md" + - Integrating External Agents from Griptape, Langchain, etc: "swarms/agents/external_party_agents.md" + - Creating Custom Agents: "swarms/agents/new_agent.md" - Swarm Architectures: - Why MultiAgent Collaboration is Necessary: "swarms/concept/why.md" - Swarm Architectures: "swarms/concept/swarm_architectures.md" @@ -222,10 +222,6 @@ nav: - OpenAIChat: "swarms/models/openai.md" - OpenAIFunctionCaller: "swarms/models/openai_function_caller.md" - Groq: "swarms/models/groq.md" - # - Ollama: - # - Fireworks - # - Octo - # - Liquid AI - MultiModal Models: - BaseMultiModalModel: "swarms/models/base_multimodal_model.md" - Multi Modal Models Available: "swarms/models/multimodal_models.md" @@ -285,6 +281,4 @@ nav: - Corporate: - Culture: "corporate/culture.md" - Hiring: "corporate/hiring.md" - - Swarms Goals & Milestone Tracking; A Vision for 2024 and Beyond: "corporate/2024_2025_goals.md" - # - Clusterops: - # - Overview: "clusterops/reference.md" \ No newline at end of file + - Swarms Goals & Milestone Tracking; A Vision for 2024 and Beyond: "corporate/2024_2025_goals.md" \ No newline at end of file diff --git a/docs/swarms/products.md b/docs/swarms/products.md new file mode 100644 index 000000000..ed81efe4d --- /dev/null +++ b/docs/swarms/products.md @@ -0,0 +1,177 @@ +# Swarms Products + +Welcome to the official documentation for **Swarms**, the first multi-agent orchestration framework enabling seamless collaboration between LLMs and other tools to automate business operations at scale. Below, you’ll find detailed descriptions of all Swarms products and services to help you get started and unlock the full potential of this groundbreaking platform. + + + +| **Name** | **Description** | **Link** | +|-----------------------|-------------------------------------------------------------------------------------------------------------------|---------------------------| +| **Swarms Marketplace** | A platform to discover, share, and integrate prompts, agents, and tools. | [swarms.world](https://swarms.world) | +| **Swarms Spreadsheet** | A tool for managing and scaling thousands of agent outputs, with results saved to a CSV file for easy analysis. | [swarms.world](https://swarms.world) | +| **Drag n Drop Swarm** | An intuitive interface to visually create and manage swarms of agents through drag-and-drop functionality. | [swarms.world](https://swarms.world) | +| **Swarms API** | An API enabling seamless integration of swarms of agents into your applications and workflows. | [swarms.world](https://swarms.world) | +| **Wallet API** | A secure API for managing transactions and interactions within the Swarms ecosystem. | Coming Soon | +| **Swarm Exchange** | A marketplace for buying and selling prompts, agents, and tools within the Swarms ecosystem. | Coming Soon | + + + +--- + +## Swarms Marketplace +**Website:** [swarms.world](https://swarms.world) + +The Swarms Marketplace is your one-stop destination for discovering, adding, and managing: + +- **Prompts:** Access and share production-ready prompts for LLMs. + +- **Agents:** Browse pre-built agents tailored for tasks in marketing, finance, +programming, and more. +- **Tools:** Discover cutting-edge tools to enhance agent performance and expand +capabilities. + +### Key Features: +- **Rating System:** Evaluate and rate prompts, agents, and tools based on their +effectiveness. +- **Commenting System:** Share feedback and insights with the Swarms community. + +- **Coming Soon:** Buy and sell prompts, agents, and tools directly within the +marketplace. + +### How to Use: +1. Sign up at [swarms.world](https://swarms.world). +2. Explore the marketplace categories or search for specific solutions. +3. Add your chosen resources to your Swarms account and integrate them into your operations. + +--- + +## Swarms Spreadsheet +**Website:** [swarms.world](https://swarms.world) + +The Swarms Spreadsheet is a powerful tool for managing outputs from thousands of agents efficiently. Ideal for businesses needing scalable solutions, it provides: + +### Key Features: +- **Batch Task Execution:** Assign tasks to multiple agents simultaneously. + +- **CSV Integration:** Automatically save agent outputs to CSV files for easy analysis. + +- **Customizable Agents:** Upload single or multiple agents and run repeat tasks with +ease. +- **Metadata Capture:** Leverage built-in Pydantic schemas to record all task details +and results. + +### Use Cases: +- **Marketing:** Generate and analyze campaign ideas at scale. + +- **Finance:** Process financial models and scenarios quickly. + +- **Operations:** Automate repetitive tasks across multiple domains. + + +### How to Use: +1. Visit [swarms.world](https://swarms.world) and navigate to Swarms Spreadsheet. +2. Upload your agents or create new ones. +3. Run tasks and export results to a CSV file for further use. + +--- + +## Drag-n-Drop Swarm +**Website:** [swarms.world](https://swarms.world) + +The Drag-n-Drop Swarm enables non-technical users to create and deploy agent workflows with a simple drag-and-drop interface. It’s perfect for: + +### Key Features: +- **Visual Workflow Builder:** Design agent interactions without writing code. + +- **Pre-Built Templates:** Start quickly with ready-made workflows for common tasks. + +- **Intuitive Interface:** Drag, drop, and connect agents to create robust automation +pipelines. + +### How to Use: +1. Access the Drag-n-Drop Swarm tool at [swarms.world](https://swarms.world). +2. Drag agents from the library into the workspace. +3. Connect and configure agents to execute your desired workflow. +4. Save and deploy your workflow instantly. + +--- + +## Swarms API +**Website:** [swarms.world](https://swarms.world) + +The Swarms API provides developers with the ability to: + +### Key Features: +- **Agent Management:** Programmatically create, update, and delete agents. + +- **Task Orchestration:** Dynamically assign tasks to agents and monitor their progress. + +- **Custom Integration:** Seamlessly integrate Swarms functionality into existing +applications and workflows. + +### Getting Started: +1. Sign up for API access at [swarms.world](https://swarms.world). +2. Obtain your API key and authentication credentials. +3. Refer to the API documentation for endpoint details and usage examples. + +### Example: +```python +import requests + +API_KEY = "your_api_key_here" +BASE_URL = "https://api.swarms.world" + +response = requests.post( + f"{BASE_URL}/agents", + headers={"Authorization": f"Bearer {API_KEY}"}, + json={"name": "example_agent", "task": "data_analysis"} +) + +print(response.json()) +``` + +--- + +## Wallet API +The Wallet API enables secure and efficient transactions within the Swarms ecosystem, allowing users to: + +### Key Features: +- **Seamless Transactions:** Manage payments for prompts, agents, and tools. + +- **Secure Wallets:** Store and transfer funds safely within the Swarms platform. + +- **Transaction History:** Access detailed logs of all wallet activity. + + +### Getting Started: +1. Enable your wallet in your Swarms account settings. +2. Use the Wallet API to handle purchases and manage funds. + +--- + +## Swarm Exchange (Coming Soon) +The **Swarm Exchange** will revolutionize the way agents and tools are traded in the Swarms ecosystem. It will feature: + +### Key Features: +- **Decentralized Marketplace:** Trade agents and tools securely. + +- **Dynamic Pricing:** Leverage demand-based pricing for assets. + +- **Global Access:** Participate in the exchange from anywhere. + + +Stay tuned for updates on the Swarm Exchange launch. + +--- + +## Additional Resources +- **GitHub Repository:** [Swarms Framework](https://github.com/kyegomez/swarms) + +- **Documentation:** [Swarms Documentation](https://docs.swarms.world) + +- **Support:** Contact us via our [Discord Community](https://discord.com/servers/ +agora-999382051935506503). + +--- + +Experience the future of multi-agent collaboration with Swarms. Start building your agentic workflows today! + diff --git a/examples/onboard/agents.yaml b/new_features_examples/onboard/agents.yaml similarity index 100% rename from examples/onboard/agents.yaml rename to new_features_examples/onboard/agents.yaml diff --git a/examples/onboard/onboard-basic.py b/new_features_examples/onboard/onboard-basic.py similarity index 100% rename from examples/onboard/onboard-basic.py rename to new_features_examples/onboard/onboard-basic.py From 567560b24565261f8df0af7b4fca820f1ed52ae2 Mon Sep 17 00:00:00 2001 From: Kye Gomez Date: Tue, 21 Jan 2025 12:24:58 -0500 Subject: [PATCH 02/12] [SWARM CLOUD APIS] --- docs/mkdocs.yml | 6 +- docs/swarms_cloud/create_api.md | 204 ++++++++++++++++++++++++++++++++ 2 files changed, 208 insertions(+), 2 deletions(-) create mode 100644 docs/swarms_cloud/create_api.md diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index c1a4ccc5a..1a5ac12ca 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -229,8 +229,10 @@ nav: - Swarms Cloud API: # - Overview: "swarms_cloud/main.md" - Overview: "swarms_cloud/vision.md" - - MCS API: "swarms_cloud/mcs_api.md" - - Swarms Cloud CLI: "swarms_cloud/cli.md" + # - Swarms Cloud CLI: "swarms_cloud/cli.md" + - Swarm APIs: + - MCS API: "swarms_cloud/mcs_api.md" + - CreateNow API: "swarms_cloud/create_api.md" # - Add Agents to Marketplace: "swarms_cloud/add_agent.md" # - Available Models: "swarms_cloud/available_models.md" # - Agent API: "swarms_cloud/agent_api.md" diff --git a/docs/swarms_cloud/create_api.md b/docs/swarms_cloud/create_api.md new file mode 100644 index 000000000..9a9e340a3 --- /dev/null +++ b/docs/swarms_cloud/create_api.md @@ -0,0 +1,204 @@ +# CreateNow API Documentation + +Welcome to the CreateNow API documentation! This API enables developers to generate AI-powered content, including images, music, videos, and speech, using natural language prompts. Use the endpoints below to start generating content. + +--- + +## **1. Claim Your API Key** +To use the API, you must first claim your API key. Visit the following link to create an account and get your API key: + +### **Claim Your Key** +``` +https://createnow.xyz/account +``` + +After signing up, your API key will be available in your account dashboard. Keep it secure and include it in your API requests as a Bearer token. + +--- + +## **2. Generation Endpoint** +The generation endpoint allows you to create AI-generated content using natural language prompts. + +### **Endpoint** +``` +POST https://createnow.xyz/api/v1/generate +``` + +### **Authentication** +Include a Bearer token in the `Authorization` header for all requests: +``` +Authorization: Bearer YOUR_API_KEY +``` + +### **Basic Usage** +The simplest way to use the API is to send a prompt. The system will automatically detect the appropriate media type. + +#### **Example Request (Basic)** +```json +{ + "prompt": "a beautiful sunset over the ocean" +} +``` + +### **Advanced Options** +You can specify additional parameters for finer control over the output. + +#### **Parameters** +| Parameter | Type | Description | Default | +|----------------|-----------|---------------------------------------------------------------------------------------------------|--------------| +| `prompt` | `string` | The natural language description of the content to generate. | Required | +| `type` | `string` | The type of content to generate (`image`, `music`, `video`, `speech`). | Auto-detect | +| `count` | `integer` | The number of outputs to generate (1-4). | 1 | +| `duration` | `integer` | Duration of audio or video content in seconds (applicable to `music` and `speech`). | N/A | + +#### **Example Request (Advanced)** +```json +{ + "prompt": "create an upbeat jazz melody", + "type": "music", + "count": 2, + "duration": 30 +} +``` + +### **Response Format** + +#### **Success Response** +```json +{ + "success": true, + "outputs": [ + { + "url": "https://createnow.xyz/storage/image1.png", + "creation_id": "12345", + "share_url": "https://createnow.xyz/share/12345" + } + ], + "mediaType": "image", + "confidence": 0.95, + "detected": true +} +``` + +#### **Error Response** +```json +{ + "error": "Invalid API Key", + "status": 401 +} +``` + +--- + +## **3. Examples in Multiple Languages** + +### **Python** +```python +import requests + +url = "https://createnow.xyz/api/v1/generate" +headers = { + "Authorization": "Bearer YOUR_API_KEY", + "Content-Type": "application/json" +} + +payload = { + "prompt": "a futuristic cityscape at night", + "type": "image", + "count": 2 +} + +response = requests.post(url, json=payload, headers=headers) +print(response.json()) +``` + +### **Node.js** +```javascript +const axios = require('axios'); + +const url = "https://createnow.xyz/api/v1/generate"; +const headers = { + Authorization: "Bearer YOUR_API_KEY", + "Content-Type": "application/json" +}; + +const payload = { + prompt: "a futuristic cityscape at night", + type: "image", + count: 2 +}; + +axios.post(url, payload, { headers }) + .then(response => { + console.log(response.data); + }) + .catch(error => { + console.error(error.response.data); + }); +``` + +### **cURL** +```bash +curl -X POST https://createnow.xyz/api/v1/generate \ +-H "Authorization: Bearer YOUR_API_KEY" \ +-H "Content-Type: application/json" \ +-d '{ + "prompt": "a futuristic cityscape at night", + "type": "image", + "count": 2 +}' +``` + +### **Java** +```java +import java.net.HttpURLConnection; +import java.net.URL; +import java.io.OutputStream; + +public class CreateNowAPI { + public static void main(String[] args) throws Exception { + URL url = new URL("https://createnow.xyz/api/v1/generate"); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("POST"); + conn.setRequestProperty("Authorization", "Bearer YOUR_API_KEY"); + conn.setRequestProperty("Content-Type", "application/json"); + conn.setDoOutput(true); + + String jsonPayload = "{" + + "\"prompt\": \"a futuristic cityscape at night\", " + + "\"type\": \"image\", " + + "\"count\": 2}"; + + OutputStream os = conn.getOutputStream(); + os.write(jsonPayload.getBytes()); + os.flush(); + + int responseCode = conn.getResponseCode(); + System.out.println("Response Code: " + responseCode); + } +} +``` + +--- + +## **4. Error Codes** +| Status Code | Meaning | Possible Causes | +|-------------|----------------------------------|----------------------------------------| +| 400 | Bad Request | Invalid parameters or payload. | +| 401 | Unauthorized | Invalid or missing API key. | +| 402 | Payment Required | Insufficient credits for the request. | +| 500 | Internal Server Error | Issue on the server side. | + +--- + +## **5. Notes and Limitations** +- **Maximum Prompt Length:** 1000 characters. +- **Maximum Outputs per Request:** 4. +- **Supported Media Types:** `image`, `music`, `video`, `speech`. +- **Content Shareability:** Every output includes a unique creation ID and shareable URL. +- **Auto-Detection:** Uses advanced natural language processing to determine the most appropriate media type. + +--- + +For further support or questions, please contact our support team at [support@createnow.xyz](mailto:support@createnow.xyz). + From 4979e6947a8f16cd911a45fd0954cc852631c101 Mon Sep 17 00:00:00 2001 From: Kye Gomez Date: Tue, 21 Jan 2025 12:30:29 -0500 Subject: [PATCH 03/12] [SWARM CLOUD APIS] --- docs/mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 1a5ac12ca..86db5f3bf 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -161,7 +161,7 @@ nav: - Overview: "swarms/tools/main.md" - What are tools?: "swarms/tools/build_tool.md" - ToolAgent: "swarms/agents/tool_agent.md" - - Tool Storage & tool_registry decorator: "swarms/tools/tool_storage.md" + - Tool Storage: "swarms/tools/tool_storage.md" - RAG || Long Term Memory: - Integrating RAG with Agents: "swarms/memory/diy_memory.md" - Third-Party Agent Integrations: From 5e4a600d47b7cc6c69f8ba5dfe37cb983838e4a3 Mon Sep 17 00:00:00 2001 From: Kye Gomez Date: Tue, 21 Jan 2025 12:47:00 -0500 Subject: [PATCH 04/12] [DOCS][Swarm Tools example] --- docs/mkdocs.yml | 4 + docs/swarms/examples/swarms_tools_htx.md | 37 ++++ docs/swarms_tools/overview.md | 239 +++++++++++++++++++++++ swarms/agents/create_agents_from_yaml.py | 50 +++-- swarms/cli/main.py | 83 +++++--- swarms_tools_example.py | 30 +++ 6 files changed, 403 insertions(+), 40 deletions(-) create mode 100644 docs/swarms/examples/swarms_tools_htx.md create mode 100644 docs/swarms_tools/overview.md create mode 100644 swarms_tools_example.py diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 86db5f3bf..7695af97d 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -208,6 +208,8 @@ nav: - Ollama: "swarms/examples/ollama.md" - OpenRouter: "swarms/examples/openrouter.md" - XAI: "swarms/examples/xai.md" + - Swarms Tools: + - Agent with HTX + CoinGecko: "swarms/examples/swarms_tools_htx.md" - Swarm Models: - Overview: "swarms/models/index.md" # - Models Available: "swarms/models/index.md" @@ -226,6 +228,8 @@ nav: - BaseMultiModalModel: "swarms/models/base_multimodal_model.md" - Multi Modal Models Available: "swarms/models/multimodal_models.md" - GPT4VisionAPI: "swarms/models/gpt4v.md" + - Swarms Tools: + - Overview: "swarms_tools/overview.md" - Swarms Cloud API: # - Overview: "swarms_cloud/main.md" - Overview: "swarms_cloud/vision.md" diff --git a/docs/swarms/examples/swarms_tools_htx.md b/docs/swarms/examples/swarms_tools_htx.md new file mode 100644 index 000000000..ab4333dd5 --- /dev/null +++ b/docs/swarms/examples/swarms_tools_htx.md @@ -0,0 +1,37 @@ +# Swarms Tools Example with HTX + CoinGecko + +- `pip3 install swarms swarms-tools` +- Add `OPENAI_API_KEY` to your `.env` file + +```python +from swarms import Agent +from swarms.prompts.finance_agent_sys_prompt import ( + FINANCIAL_AGENT_SYS_PROMPT, +) +from swarms_tools import ( + coin_gecko_coin_api, + fetch_htx_data, +) + + +# Initialize the agent +agent = Agent( + agent_name="Financial-Analysis-Agent", + agent_description="Personal finance advisor agent", + system_prompt=FINANCIAL_AGENT_SYS_PROMPT, + max_loops=1, + model_name="gpt-4o", + dynamic_temperature_enabled=True, + user_name="swarms_corp", + return_step_meta=False, + output_type="str", # "json", "dict", "csv" OR "string" "yaml" and + auto_generate_prompt=False, # Auto generate prompt for the agent based on name, description, and system prompt, task + max_tokens=4000, # max output tokens + saved_state_path="agent_00.json", + interactive=False, +) + +agent.run( + f"Analyze the $swarms token on HTX with data: {fetch_htx_data('swarms')}. Additionally, consider the following CoinGecko data: {coin_gecko_coin_api('swarms')}" +) +``` \ No newline at end of file diff --git a/docs/swarms_tools/overview.md b/docs/swarms_tools/overview.md new file mode 100644 index 000000000..ad896fa9e --- /dev/null +++ b/docs/swarms_tools/overview.md @@ -0,0 +1,239 @@ +# Swarms Tools + + +Welcome to **Swarms Tools**, the ultimate package for integrating **cutting-edge APIs** into Python functions with seamless multi-agent system compatibility. Designed for enterprises at the forefront of innovation, **Swarms Tools** is your key to simplifying complexity and unlocking operational excellence. + +--- + +## πŸš€ Features + +- **Unified API Integration**: Ready-to-use Python functions for financial data, social media, IoT, and more. +- **Enterprise-Grade Design**: Comprehensive type hints, structured outputs, and robust documentation. +- **Agent-Ready Framework**: Optimized for seamless integration into Swarms' multi-agent orchestration systems. +- **Expandable Architecture**: Easily extend functionality with a standardized schema for new tools. + +--- + +## πŸ”§ Installation + +```bash +pip3 install -U swarms-tools +``` + +--- + +## πŸ“‚ Directory Structure + +```plaintext +swarms-tools/ +β”œβ”€β”€ swarms_tools/ +β”‚ β”œβ”€β”€ finance/ +β”‚ β”‚ β”œβ”€β”€ htx_tool.py +β”‚ β”‚ β”œβ”€β”€ eodh_api.py +β”‚ β”‚ └── coingecko_tool.py +β”‚ β”œβ”€β”€ social_media/ +β”‚ β”‚ β”œβ”€β”€ telegram_tool.py +β”‚ β”œβ”€β”€ utilities/ +β”‚ β”‚ └── logging.py +β”œβ”€β”€ tests/ +β”‚ β”œβ”€β”€ test_financial_data.py +β”‚ └── test_social_media.py +└── README.md +``` + +--- + +## πŸ’Ό Use Cases + + + +## Finance + +Explore our diverse range of financial tools, designed to streamline your operations. If you need a tool not listed, feel free to submit an issue or accelerate integration by contributing a pull request with your tool of choice. + +| **Tool Name** | **Function** | **Description** | +|---------------------------|--------------------------|---------------------------------------------------------------------------------| +| `fetch_stock_news` | `fetch_stock_news` | Fetches the latest stock news and updates. | +| `fetch_htx_data` | `fetch_htx_data` | Retrieves financial data from the HTX platform. | +| `yahoo_finance_api` | `yahoo_finance_api` | Fetches comprehensive stock data from Yahoo Finance, including prices and trends. | +| `coin_gecko_coin_api` | `coin_gecko_coin_api` | Fetches cryptocurrency data from CoinGecko, including market and price information. | +| `helius_api_tool` | `helius_api_tool` | Retrieves blockchain account, transaction, or token data using the Helius API. | +| `okx_api_tool` | `okx_api_tool` | Fetches detailed cryptocurrency data for coins from the OKX exchange. | + + +### Financial Data Retrieval +Enable precise and actionable financial insights: + +#### Example 1: Fetch Historical Data +```python +from swarms_tools import fetch_htx_data + +# Fetch historical trading data for "Swarms Corporation" +response = fetch_htx_data("swarms") +print(response) +``` + +#### Example 2: Stock News Analysis +```python +from swarms_tools import fetch_stock_news + +# Retrieve latest stock news for Apple +news = fetch_stock_news("AAPL") +print(news) +``` + +#### Example 3: Cryptocurrency Metrics +```python +from swarms_tools import coin_gecko_coin_api + +# Fetch live data for Bitcoin +crypto_data = coin_gecko_coin_api("bitcoin") +print(crypto_data) +``` + +### Social Media Automation +Streamline communication and engagement: + +#### Example: Telegram Bot Messaging +```python +from swarms_tools import telegram_dm_or_tag_api + +def send_alert(response: str): + telegram_dm_or_tag_api(response) + +# Send a message to a user or group +send_alert("Mission-critical update from Swarms.") +``` + +--- + +## Dex Screener + +This is a tool that allows you to fetch data from the Dex Screener API. It supports multiple chains and multiple tokens. + +```python +from swarms_tools.finance.dex_screener import ( + fetch_latest_token_boosts, + fetch_dex_screener_profiles, +) + + +fetch_dex_screener_profiles() +fetch_latest_token_boosts() + +``` + +--- + + +## Structs +The tool chainer enables the execution of multiple tools in a sequence, allowing for the aggregation of their results in either a parallel or sequential manner. + +```python +# Example usage +from loguru import logger + +from swarms_tools.structs import tool_chainer + + +if __name__ == "__main__": + logger.add("tool_chainer.log", rotation="500 MB", level="INFO") + + # Example tools + def tool1(): + return "Tool1 Result" + + def tool2(): + return "Tool2 Result" + + # def tool3(): + # raise ValueError("Simulated error in Tool3") + + tools = [tool1, tool2] + + # Parallel execution + parallel_results = tool_chainer(tools, parallel=True) + print("Parallel Results:", parallel_results) + + # Sequential execution + # sequential_results = tool_chainer(tools, parallel=False) + # print("Sequential Results:", sequential_results) + +``` +--- + +## 🧩 Standardized Schema + +Every tool in **Swarms Tools** adheres to a strict schema for maintainability and interoperability: + +### Schema Template + +1. **Functionality**: + - Encapsulate API logic into a modular, reusable function. + +2. **Typing**: + - Leverage Python type hints for input validation and clarity. + + Example: + ```python + def fetch_data(symbol: str, date_range: str) -> str: + """ + Fetch financial data for a given symbol and date range. + + Args: + symbol (str): Ticker symbol of the asset. + date_range (str): Timeframe for the data (e.g., '1d', '1m', '1y'). + + Returns: + dict: A dictionary containing financial metrics. + """ + pass + ``` + +3. **Documentation**: + - Include detailed docstrings with parameter explanations and usage examples. + +4. **Output Standardization**: + - Ensure consistent outputs (e.g., strings) for easy downstream agent integration. + +5. **API-Key Management**: + - All API keys must be fetched with `os.getenv("YOUR_KEY")` + + +--- + +## πŸ“– Documentation + +Comprehensive documentation is available to guide developers and enterprises. Visit our [official docs](https://docs.swarms.world) for detailed API references, usage examples, and best practices. + +--- + +## πŸ›  Contributing + +We welcome contributions from the global developer community. To contribute: + +1. **Fork the Repository**: Start by forking the repository. +2. **Create a Feature Branch**: Use a descriptive branch name: `feature/add-new-tool`. +3. **Commit Your Changes**: Write meaningful commit messages. +4. **Submit a Pull Request**: Open a pull request for review. + +--- + +## πŸ›‘οΈ License + +This project is licensed under the **MIT License**. See the [LICENSE](LICENSE) file for details. + +--- + +## 🌠 Join the Future + +Explore the limitless possibilities of agent-based systems. Together, we can build a smarter, faster, and more interconnected world. + +**Visit us:** [Swarms Corporation](https://swarms.ai) +**Follow us:** [Twitter](https://twitter.com/swarms_corp) + +--- + +**"The future belongs to those who dare to automate it."** +**β€” The Swarms Corporation** + diff --git a/swarms/agents/create_agents_from_yaml.py b/swarms/agents/create_agents_from_yaml.py index 76aab3466..fb1cd0e72 100644 --- a/swarms/agents/create_agents_from_yaml.py +++ b/swarms/agents/create_agents_from_yaml.py @@ -179,37 +179,43 @@ def create_agents_from_yaml( try: logger.info("Starting agent creation process...") - + # Load and validate configuration if yaml_file: logger.info(f"Loading configuration from {yaml_file}") config = load_yaml_safely(yaml_file, yaml_string) - + if not config.get("agents"): raise ValueError( "No agents defined in the YAML configuration. " "Please add at least one agent under the 'agents' section." ) - - logger.info(f"Found {len(config['agents'])} agent(s) to create") + + logger.info( + f"Found {len(config['agents'])} agent(s) to create" + ) # Create agents with retry logic for idx, agent_config in enumerate(config["agents"], 1): if not agent_config.get("agent_name"): agent_config["agent_name"] = f"Agent_{idx}" - + logger.info( f"Creating agent {idx}/{len(config['agents'])}: {agent_config['agent_name']}" ) if "model_name" in agent_config: - logger.info(f"Using specified model: {agent_config['model_name']}") + logger.info( + f"Using specified model: {agent_config['model_name']}" + ) model_instance = LiteLLM( model_name=agent_config["model_name"] ) else: model_name = "gpt-4" - logger.info(f"No model specified, using default: {model_name}") + logger.info( + f"No model specified, using default: {model_name}" + ) model_instance = LiteLLM(model_name=model_name) agent = create_agent_with_retry( @@ -230,9 +236,15 @@ def create_agents_from_yaml( raise ValueError( "swarm_architecture must be a dictionary containing swarm configuration" ) - - required_fields = {"name", "description", "swarm_type"} - missing_fields = required_fields - set(config["swarm_architecture"].keys()) + + required_fields = { + "name", + "description", + "swarm_type", + } + missing_fields = required_fields - set( + config["swarm_architecture"].keys() + ) if missing_fields: raise ValueError( f"SwarmRouter creation failed: Missing required fields in swarm_architecture: {', '.join(missing_fields)}" @@ -241,8 +253,10 @@ def create_agents_from_yaml( swarm_config = SwarmConfig( **config["swarm_architecture"] ) - - logger.info(f"Creating SwarmRouter with type: {swarm_config.swarm_type}") + + logger.info( + f"Creating SwarmRouter with type: {swarm_config.swarm_type}" + ) swarm_router = SwarmRouter( name=swarm_config.name, description=swarm_config.description, @@ -306,7 +320,9 @@ def create_agents_from_yaml( "No task specified in swarm_architecture. Please add a 'task' field " "to define what the swarm should do." ) - logger.info(f"Running swarm with task: {config['swarm_architecture']['task']}") + logger.info( + f"Running swarm with task: {config['swarm_architecture']['task']}" + ) return swarm_router.run( config["swarm_architecture"]["task"] ) @@ -331,8 +347,12 @@ def create_agents_from_yaml( result = agents[0] if len(agents) == 1 else agents elif return_type == "both": result = ( - (swarm_router if swarm_router else agents[0] if len(agents) == 1 else agents), - agents + ( + swarm_router + if swarm_router + else agents[0] if len(agents) == 1 else agents + ), + agents, ) elif return_type == "tasks": result = task_results diff --git a/swarms/cli/main.py b/swarms/cli/main.py index 4559ef9ba..ef4151eb0 100644 --- a/swarms/cli/main.py +++ b/swarms/cli/main.py @@ -277,58 +277,91 @@ def main(): check_login() elif args.command == "run-agents": try: - console.print(f"[yellow]Loading agents from {args.yaml_file}...[/yellow]") - + console.print( + f"[yellow]Loading agents from {args.yaml_file}...[/yellow]" + ) + if not os.path.exists(args.yaml_file): raise FileNotFoundError( f"YAML file not found: {args.yaml_file}\n" "Please make sure the file exists and you're in the correct directory." ) - + # Create progress display progress = Progress( SpinnerColumn(), - TextColumn("[progress.description]{task.description}"), + TextColumn( + "[progress.description]{task.description}" + ), console=console, ) - + with progress: # Add initial task - init_task = progress.add_task("Initializing...", total=None) - + init_task = progress.add_task( + "Initializing...", total=None + ) + # Load and validate YAML - progress.update(init_task, description="Loading YAML configuration...") - + progress.update( + init_task, + description="Loading YAML configuration...", + ) + # Create agents - progress.update(init_task, description="Creating agents...") + progress.update( + init_task, + description="Creating agents...", + ) result = create_agents_from_yaml( yaml_file=args.yaml_file, - return_type="run_swarm" + return_type="run_swarm", ) - + # Update progress on completion - progress.update(init_task, description="Processing complete!", completed=True) - + progress.update( + init_task, + description="Processing complete!", + completed=True, + ) + if result: # Format and display the results if isinstance(result, str): - console.print("\n[bold green]Results:[/bold green]") - console.print(Panel(result, title="Agent Output", border_style="green")) + console.print( + "\n[bold green]Results:[/bold green]" + ) + console.print( + Panel( + result, + title="Agent Output", + border_style="green", + ) + ) elif isinstance(result, dict): - console.print("\n[bold green]Results:[/bold green]") + console.print( + "\n[bold green]Results:[/bold green]" + ) for key, value in result.items(): - console.print(f"[cyan]{key}:[/cyan] {value}") + console.print( + f"[cyan]{key}:[/cyan] {value}" + ) else: - console.print("[green]βœ“ Agents completed their tasks successfully![/green]") + console.print( + "[green]βœ“ Agents completed their tasks successfully![/green]" + ) else: - console.print("[yellow]⚠ Agents completed but returned no results.[/yellow]") - + console.print( + "[yellow]⚠ Agents completed but returned no results.[/yellow]" + ) + except FileNotFoundError as e: show_error("File Error", str(e)) except ValueError as e: show_error( "Configuration Error", - str(e) + "\n\nPlease check your agents.yaml file format." + str(e) + + "\n\nPlease check your agents.yaml file format.", ) except Exception as e: # Enhanced error handling @@ -339,7 +372,7 @@ def main(): "The model's context length was exceeded. Try:\n" "1. Reducing max_tokens in your YAML config\n" "2. Reducing context_length in your YAML config\n" - "3. Using a model with larger context window" + "3. Using a model with larger context window", ) elif "api_key" in error_msg.lower(): show_error( @@ -347,7 +380,7 @@ def main(): "There seems to be an issue with the API key. Please:\n" "1. Check if your API key is set correctly\n" "2. Verify the API key is valid\n" - "3. Run 'swarms get-api-key' to get a new key" + "3. Run 'swarms get-api-key' to get a new key", ) else: show_error( @@ -355,7 +388,7 @@ def main(): f"An unexpected error occurred: {error_msg}\n" "1. Check your YAML configuration\n" "2. Verify your API keys are set\n" - "3. Check network connectivity" + "3. Check network connectivity", ) elif args.command == "book-call": webbrowser.open( diff --git a/swarms_tools_example.py b/swarms_tools_example.py new file mode 100644 index 000000000..963118830 --- /dev/null +++ b/swarms_tools_example.py @@ -0,0 +1,30 @@ +from swarms import Agent +from swarms.prompts.finance_agent_sys_prompt import ( + FINANCIAL_AGENT_SYS_PROMPT, +) +from swarms_tools import ( + coin_gecko_coin_api, + fetch_htx_data, +) + + +# Initialize the agent +agent = Agent( + agent_name="Financial-Analysis-Agent", + agent_description="Personal finance advisor agent", + system_prompt=FINANCIAL_AGENT_SYS_PROMPT, + max_loops=1, + model_name="gpt-4o", + dynamic_temperature_enabled=True, + user_name="swarms_corp", + return_step_meta=False, + output_type="str", # "json", "dict", "csv" OR "string" "yaml" and + auto_generate_prompt=False, # Auto generate prompt for the agent based on name, description, and system prompt, task + max_tokens=4000, # max output tokens + saved_state_path="agent_00.json", + interactive=False, +) + +agent.run( + f"Analyze the $swarms token on HTX with data: {fetch_htx_data('swarms')}. Additionally, consider the following CoinGecko data: {coin_gecko_coin_api('swarms')}" +) From d44fbcd700e68acc29736a8b803b70c8f0c9da62 Mon Sep 17 00:00:00 2001 From: Kye Gomez Date: Tue, 21 Jan 2025 16:40:27 -0500 Subject: [PATCH 05/12] [DOCS][DOCS] --- docs/mkdocs.yml | 1 + .../swarms/examples/swarms_tools_htx_gecko.md | 43 +++ pyproject.toml | 2 +- swarms/agents/agent_print.py | 33 ++ swarms/structs/__init__.py | 8 +- swarms/structs/agent.py | 120 +++---- swarms/structs/agent_security.py | 318 ++++++++++++++++++ swarms/structs/swarm_router.py | 28 +- swarms/tools/tool_parse_exec.py | 107 +++--- swarms_tool_example_simple.py | 30 ++ swarms_tools_example.py | 9 +- tests/tools/test_parse_tools.py | 92 +++++ 12 files changed, 667 insertions(+), 124 deletions(-) create mode 100644 docs/swarms/examples/swarms_tools_htx_gecko.md create mode 100644 swarms/agents/agent_print.py create mode 100644 swarms/structs/agent_security.py create mode 100644 swarms_tool_example_simple.py create mode 100644 tests/tools/test_parse_tools.py diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 7695af97d..f33f78e70 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -210,6 +210,7 @@ nav: - XAI: "swarms/examples/xai.md" - Swarms Tools: - Agent with HTX + CoinGecko: "swarms/examples/swarms_tools_htx.md" + - Agent with HTX + CoinGecko Function Calling: "swarms/examples/swarms_tools_htx_gecko.md" - Swarm Models: - Overview: "swarms/models/index.md" # - Models Available: "swarms/models/index.md" diff --git a/docs/swarms/examples/swarms_tools_htx_gecko.md b/docs/swarms/examples/swarms_tools_htx_gecko.md new file mode 100644 index 000000000..9f554c535 --- /dev/null +++ b/docs/swarms/examples/swarms_tools_htx_gecko.md @@ -0,0 +1,43 @@ +# Swarms Tools Example with HTX + CoinGecko + +- `pip3 install swarms swarms-tools` +- Add `OPENAI_API_KEY` to your `.env` file +- Run `swarms_tools_htx_gecko.py` +- Agent will make a function call to the desired tool +- The tool will be executed and the result will be returned to the agent +- The agent will then analyze the result and return the final output + + +```python +from swarms import Agent +from swarms.prompts.finance_agent_sys_prompt import ( + FINANCIAL_AGENT_SYS_PROMPT, +) +from swarms_tools import ( + fetch_stock_news, + coin_gecko_coin_api, + fetch_htx_data, +) + +# Initialize the agent +agent = Agent( + agent_name="Financial-Analysis-Agent", + agent_description="Personal finance advisor agent", + system_prompt=FINANCIAL_AGENT_SYS_PROMPT, + max_loops=1, + model_name="gpt-4o", + dynamic_temperature_enabled=True, + user_name="swarms_corp", + retry_attempts=3, + context_length=8192, + return_step_meta=False, + output_type="str", # "json", "dict", "csv" OR "string" "yaml" and + auto_generate_prompt=False, # Auto generate prompt for the agent based on name, description, and system prompt, task + max_tokens=4000, # max output tokens + saved_state_path="agent_00.json", + interactive=False, + tools=[fetch_stock_news, coin_gecko_coin_api, fetch_htx_data], +) + +agent.run("Analyze the $swarms token on htx") +``` \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 0791dfddf..ebf348aa7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "poetry.core.masonry.api" [tool.poetry] name = "swarms" -version = "6.8.8" +version = "6.9.6" description = "Swarms - TGSC" license = "MIT" authors = ["Kye Gomez "] diff --git a/swarms/agents/agent_print.py b/swarms/agents/agent_print.py new file mode 100644 index 000000000..e0969dc62 --- /dev/null +++ b/swarms/agents/agent_print.py @@ -0,0 +1,33 @@ +from swarms.utils.formatter import formatter + + +def agent_print( + agent_name: str, + response: str = None, + loop_count: int = None, + streaming_on: bool = False, +): + """ + Prints the response from an agent based on the streaming mode. + + Args: + agent_name (str): The name of the agent. + response (str): The response from the agent. + loop_count (int): The maximum number of loops. + streaming_on (bool): Indicates if streaming is on or off. + + Returns: + str: The response from the agent. + """ + if streaming_on: + formatter.print_panel_token_by_token( + f"{agent_name}: {response}", + title=f"Agent Name: {agent_name} [Max Loops: {loop_count}]", + ) + else: + formatter.print_panel( + f"{agent_name}: {response}", + f"Agent Name {agent_name} [Max Loops: {loop_count} ]", + ) + + return response diff --git a/swarms/structs/__init__.py b/swarms/structs/__init__.py index f4436988f..16bf974eb 100644 --- a/swarms/structs/__init__.py +++ b/swarms/structs/__init__.py @@ -1,5 +1,6 @@ from swarms.structs.agent import Agent from swarms.structs.agents_available import showcase_available_agents +from swarms.structs.async_workflow import AsyncWorkflow from swarms.structs.auto_swarm import AutoSwarm, AutoSwarmRouter from swarms.structs.base_structure import BaseStructure from swarms.structs.base_swarm import BaseSwarm @@ -13,10 +14,10 @@ NodeType, ) from swarms.structs.groupchat import ( - GroupChat, + AgentResponse, ChatHistory, ChatTurn, - AgentResponse, + GroupChat, expertise_based, ) from swarms.structs.majority_voting import ( @@ -38,6 +39,7 @@ run_agents_with_tasks_concurrently, run_single_agent, ) +from swarms.structs.multi_agent_orchestrator import MultiAgentRouter from swarms.structs.queue_swarm import TaskQueueSwarm from swarms.structs.rearrange import AgentRearrange, rearrange from swarms.structs.round_robin import RoundRobinSwarm @@ -79,8 +81,6 @@ find_token_in_text, parse_tasks, ) -from swarms.structs.async_workflow import AsyncWorkflow -from swarms.structs.multi_agent_orchestrator import MultiAgentRouter __all__ = [ "Agent", diff --git a/swarms/structs/agent.py b/swarms/structs/agent.py index 97fe3f3d8..00a0420de 100644 --- a/swarms/structs/agent.py +++ b/swarms/structs/agent.py @@ -54,6 +54,7 @@ exec_callable_with_clusterops, ) from swarms.telemetry.capture_sys_data import log_agent_data +from swarms.agents.agent_print import agent_print # Utils @@ -889,7 +890,33 @@ def _run( # Check and execute tools if self.tools is not None: - self.parse_and_execute_tools(response) + out = self.parse_and_execute_tools( + response + ) + + self.short_memory.add( + role="Tool Executor", content=out + ) + + agent_print( + f"{self.agent_name} - Tool Executor", + out, + loop_count, + self.streaming_on, + ) + + out = self.llm.run(out) + + agent_print( + f"{self.agent_name} - Agent Analysis", + out, + loop_count, + self.streaming_on, + ) + + self.short_memory.add( + role=self.agent_name, content=out + ) # Add the response to the memory self.short_memory.add( @@ -1209,31 +1236,35 @@ def dict_to_csv(self, data: dict) -> str: return output.getvalue() def parse_and_execute_tools(self, response: str, *args, **kwargs): - try: - logger.info("Executing tool...") - - # try to Execute the tool and return a string - out = parse_and_execute_json( - functions=self.tools, - json_string=response, - parse_md=True, - *args, - **kwargs, - ) - - out = str(out) - - logger.info(f"Tool Output: {out}") - - # Add the output to the memory - self.short_memory.add( - role="Tool Executor", - content=out, - ) + max_retries = 3 # Maximum number of retries + retries = 0 + while retries < max_retries: + try: + logger.info("Executing tool...") - except Exception as error: - logger.error(f"Error executing tool: {error}") - raise error + # try to Execute the tool and return a string + out = parse_and_execute_json( + functions=self.tools, + json_string=response, + parse_md=True, + *args, + **kwargs, + ) + logger.info(f"Tool Output: {out}") + # Add the output to the memory + # self.short_memory.add( + # role="Tool Executor", + # content=out, + # ) + return out + except Exception as error: + retries += 1 + logger.error( + f"Attempt {retries}: Error executing tool: {error}" + ) + if retries == max_retries: + raise error + time.sleep(1) # Wait for a bit before retrying def add_memory(self, message: str): """Add a memory to the agent @@ -2056,45 +2087,6 @@ def tokens_checks(self): return out - def parse_function_call_and_execute(self, response: str): - """ - Parses a function call from the given response and executes it. - - Args: - response (str): The response containing the function call. - - Returns: - None - - Raises: - Exception: If there is an error parsing and executing the function call. - """ - try: - if self.tools is not None: - tool_call_output = parse_and_execute_json( - self.tools, response, parse_md=True - ) - - if tool_call_output is not str: - tool_call_output = str(tool_call_output) - - logger.info(f"Tool Call Output: {tool_call_output}") - self.short_memory.add( - role=self.agent_name, - content=tool_call_output, - ) - - return tool_call_output - except Exception as error: - logger.error( - f"Error parsing and executing function call: {error}" - ) - - # Raise a custom exception with the error message - raise Exception( - "Error parsing and executing function call" - ) from error - def activate_agentops(self): if self.agent_ops_on is True: try: diff --git a/swarms/structs/agent_security.py b/swarms/structs/agent_security.py new file mode 100644 index 000000000..8e588acfe --- /dev/null +++ b/swarms/structs/agent_security.py @@ -0,0 +1,318 @@ +import base64 +import json +import uuid +from datetime import datetime +from dataclasses import dataclass +from typing import Optional, Union, Dict, List + +from cryptography.fernet import Fernet +from cryptography.hazmat.primitives import hashes, serialization +from cryptography.hazmat.primitives.asymmetric import padding, rsa +from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC + + +@dataclass +class EncryptedMessage: + """Structure for encrypted messages between agents""" + + sender_id: str + receiver_id: str + encrypted_content: bytes + timestamp: float + message_id: str + session_id: str + + +class EncryptionSession: + """Represents an encrypted communication session between agents""" + + def __init__( + self, + session_id: str, + agent_ids: List[str], + encrypted_keys: Dict[str, bytes], + created_at: datetime, + ): + self.session_id = session_id + self.agent_ids = agent_ids + self.encrypted_keys = encrypted_keys + self.created_at = created_at + + +class AgentEncryption: + """ + Handles encryption for agent data both at rest and in transit. + Supports both symmetric (for data at rest) and asymmetric (for data in transit) encryption. + Also supports secure multi-agent communication. + """ + + def __init__( + self, + agent_id: Optional[str] = None, + encryption_key: Optional[str] = None, + enable_transit_encryption: bool = False, + enable_rest_encryption: bool = False, + enable_multi_agent: bool = False, + ): + self.agent_id = agent_id or str(uuid.uuid4()) + self.enable_transit_encryption = enable_transit_encryption + self.enable_rest_encryption = enable_rest_encryption + self.enable_multi_agent = enable_multi_agent + + # Multi-agent communication storage + self.sessions: Dict[str, EncryptionSession] = {} + self.known_agents: Dict[str, "AgentEncryption"] = {} + + if enable_rest_encryption: + # Initialize encryption for data at rest + if encryption_key: + self.encryption_key = base64.urlsafe_b64encode( + PBKDF2HMAC( + algorithm=hashes.SHA256(), + length=32, + salt=f"agent_{self.agent_id}".encode(), # Unique salt per agent + iterations=100000, + ).derive(encryption_key.encode()) + ) + else: + self.encryption_key = Fernet.generate_key() + + self.cipher_suite = Fernet(self.encryption_key) + + if enable_transit_encryption or enable_multi_agent: + # Generate RSA key pair for transit encryption + self.private_key = rsa.generate_private_key( + public_exponent=65537, key_size=2048 + ) + self.public_key = self.private_key.public_key() + + def register_agent( + self, agent_id: str, agent_encryption: "AgentEncryption" + ) -> None: + """Register another agent for secure communication""" + if not self.enable_multi_agent: + raise ValueError("Multi-agent support is not enabled") + self.known_agents[agent_id] = agent_encryption + + def create_session(self, agent_ids: List[str]) -> str: + """Create a new encrypted session between multiple agents""" + if not self.enable_multi_agent: + raise ValueError("Multi-agent support is not enabled") + + session_id = str(uuid.uuid4()) + + # Generate a shared session key + session_key = Fernet.generate_key() + + # Create encrypted copies of the session key for each agent + encrypted_keys = {} + for agent_id in agent_ids: + if ( + agent_id not in self.known_agents + and agent_id != self.agent_id + ): + raise ValueError(f"Agent {agent_id} not registered") + + if agent_id == self.agent_id: + agent_public_key = self.public_key + else: + agent_public_key = self.known_agents[ + agent_id + ].public_key + + encrypted_key = agent_public_key.encrypt( + session_key, + padding.OAEP( + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), + label=None, + ), + ) + encrypted_keys[agent_id] = encrypted_key + + # Store session information + self.sessions[session_id] = EncryptionSession( + session_id=session_id, + agent_ids=agent_ids, + encrypted_keys=encrypted_keys, + created_at=datetime.now(), + ) + + return session_id + + def encrypt_message( + self, + content: Union[str, dict], + receiver_id: str, + session_id: str, + ) -> EncryptedMessage: + """Encrypt a message for another agent within a session""" + if not self.enable_multi_agent: + raise ValueError("Multi-agent support is not enabled") + + if session_id not in self.sessions: + raise ValueError("Invalid session ID") + + session = self.sessions[session_id] + if ( + self.agent_id not in session.agent_ids + or receiver_id not in session.agent_ids + ): + raise ValueError("Sender or receiver not in session") + + # Serialize content if it's a dictionary + if isinstance(content, dict): + content = json.dumps(content) + + # Get the session key + encrypted_session_key = session.encrypted_keys[self.agent_id] + session_key = self.decrypt_session_key(encrypted_session_key) + + # Create Fernet cipher with session key + cipher = Fernet(session_key) + + # Encrypt the message + encrypted_content = cipher.encrypt(content.encode()) + + return EncryptedMessage( + sender_id=self.agent_id, + receiver_id=receiver_id, + encrypted_content=encrypted_content, + timestamp=datetime.now().timestamp(), + message_id=str(uuid.uuid4()), + session_id=session_id, + ) + + def decrypt_message( + self, message: EncryptedMessage + ) -> Union[str, dict]: + """Decrypt a message from another agent""" + if not self.enable_multi_agent: + raise ValueError("Multi-agent support is not enabled") + + if message.session_id not in self.sessions: + raise ValueError("Invalid session ID") + + if self.agent_id != message.receiver_id: + raise ValueError("Message not intended for this agent") + + session = self.sessions[message.session_id] + + # Get the session key + encrypted_session_key = session.encrypted_keys[self.agent_id] + session_key = self.decrypt_session_key(encrypted_session_key) + + # Create Fernet cipher with session key + cipher = Fernet(session_key) + + # Decrypt the message + decrypted_content = cipher.decrypt( + message.encrypted_content + ).decode() + + # Try to parse as JSON + try: + return json.loads(decrypted_content) + except json.JSONDecodeError: + return decrypted_content + + def decrypt_session_key(self, encrypted_key: bytes) -> bytes: + """Decrypt a session key using the agent's private key""" + return self.private_key.decrypt( + encrypted_key, + padding.OAEP( + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), + label=None, + ), + ) + + # Original methods preserved below + def encrypt_at_rest(self, data: Union[str, dict, bytes]) -> bytes: + """Encrypts data for storage""" + if not self.enable_rest_encryption: + return ( + data + if isinstance(data, bytes) + else str(data).encode() + ) + + if isinstance(data, dict): + data = json.dumps(data) + if isinstance(data, str): + data = data.encode() + + return self.cipher_suite.encrypt(data) + + def decrypt_at_rest( + self, encrypted_data: bytes + ) -> Union[str, dict]: + """Decrypts stored data""" + if not self.enable_rest_encryption: + return encrypted_data.decode() + + decrypted_data = self.cipher_suite.decrypt(encrypted_data) + + try: + return json.loads(decrypted_data) + except json.JSONDecodeError: + return decrypted_data.decode() + + def encrypt_for_transit(self, data: Union[str, dict]) -> bytes: + """Encrypts data for transmission""" + if not self.enable_transit_encryption: + return str(data).encode() + + if isinstance(data, dict): + data = json.dumps(data) + + return self.public_key.encrypt( + data.encode(), + padding.OAEP( + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), + label=None, + ), + ) + + def decrypt_from_transit( + self, data: Union[bytes, str] + ) -> Union[str, dict]: + """Decrypts received data, handling both encrypted and unencrypted inputs""" + if not self.enable_transit_encryption: + return data.decode() if isinstance(data, bytes) else data + + try: + if isinstance(data, bytes) and len(data) == 256: + decrypted_data = self.private_key.decrypt( + data, + padding.OAEP( + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), + label=None, + ), + ).decode() + else: + return ( + data.decode() if isinstance(data, bytes) else data + ) + + try: + return json.loads(decrypted_data) + except json.JSONDecodeError: + return decrypted_data + except ValueError: + return data.decode() if isinstance(data, bytes) else data + + def get_public_key_pem(self) -> bytes: + """Returns the public key in PEM format for sharing""" + if ( + not self.enable_transit_encryption + and not self.enable_multi_agent + ): + return b"" + + return self.public_key.public_bytes( + encoding=serialization.Encoding.PEM, + format=serialization.PublicFormat.SubjectPublicKeyInfo, + ) diff --git a/swarms/structs/swarm_router.py b/swarms/structs/swarm_router.py index a0f73a989..e0ca4d05e 100644 --- a/swarms/structs/swarm_router.py +++ b/swarms/structs/swarm_router.py @@ -12,6 +12,8 @@ from swarms.structs.rearrange import AgentRearrange from swarms.structs.sequential_workflow import SequentialWorkflow from swarms.structs.spreadsheet_swarm import SpreadSheetSwarm +from swarms.structs.groupchat import GroupChat +from swarms.structs.multi_agent_orchestrator import MultiAgentRouter from swarms.structs.swarm_matcher import swarm_matcher from swarms.utils.wrapper_clusterop import ( exec_callable_with_clusterops, @@ -26,6 +28,8 @@ "SpreadSheetSwarm", "SequentialWorkflow", "ConcurrentWorkflow", + "GroupChat", + "MultiAgentRouter", "auto", ] @@ -137,6 +141,7 @@ def __init__( documents: List[str] = [], # A list of docs file paths output_type: str = "string", # Md, PDF, Txt, csv no_cluster_ops: bool = False, + speaker_fn: callable = None, *args, **kwargs, ): @@ -154,6 +159,7 @@ def __init__( self.documents = documents self.output_type = output_type self.no_cluster_ops = no_cluster_ops + self.speaker_fn = speaker_fn self.logs = [] self.reliability_check() @@ -174,8 +180,6 @@ def __init__( if self.rules is not None: self.handle_rules() - # let's make a function that checks the agents parameter and disables clusterops - def deactivate_clusterops(self): for agent in self.agents: agent.do_not_use_cluster_ops = True @@ -295,6 +299,26 @@ def _create_swarm( *args, **kwargs, ) + + elif self.swarm_type == "GroupChat": + return GroupChat( + name=self.name, + description=self.description, + agents=self.agents, + max_loops=self.max_loops, + speaker_fn=self.speaker_fn, + *args, + **kwargs, + ) + + elif self.swarm_type == "MultiAgentRouter": + return MultiAgentRouter( + name=self.name, + description=self.description, + agents=self.agents, + shared_memory_system=self.shared_memory_system, + output_type=self.output_type, + ) elif self.swarm_type == "SpreadSheetSwarm": return SpreadSheetSwarm( name=self.name, diff --git a/swarms/tools/tool_parse_exec.py b/swarms/tools/tool_parse_exec.py index 7cc4369f0..f118319d7 100644 --- a/swarms/tools/tool_parse_exec.py +++ b/swarms/tools/tool_parse_exec.py @@ -12,17 +12,19 @@ def parse_and_execute_json( json_string: str, parse_md: bool = False, verbose: bool = False, - return_str: bool = True, -) -> dict: + max_retries: int = 3, +) -> str: """ Parses and executes a JSON string containing function names and parameters. Args: - functions (List[callable]): A list of callable functions. + functions (List[Callable[..., Any]]): A list of callable functions. json_string (str): The JSON string to parse and execute. parse_md (bool): Flag indicating whether to extract code from Markdown. verbose (bool): Flag indicating whether to enable verbose logging. return_str (bool): Flag indicating whether to return a JSON string. + max_retries (int): Maximum number of retries for executing functions. + Returns: dict: A dictionary containing the results of executing the functions with the parsed parameters. """ @@ -30,10 +32,20 @@ def parse_and_execute_json( raise ValueError("Functions and JSON string are required") if parse_md: - json_string = extract_code_from_markdown(json_string) + try: + json_string = extract_code_from_markdown(json_string) + except Exception as e: + logger.error(f"Error extracting code from Markdown: {e}") + return {"error": f"Markdown parsing failed: {str(e)}"} try: - # Create function name to function mapping + # Ensure JSON string is stripped of extraneous whitespace + json_string = json_string.strip() + if not json_string: + raise ValueError( + "JSON string is empty after stripping whitespace" + ) + function_dict = {func.__name__: func for func in functions} if verbose: @@ -42,83 +54,80 @@ def parse_and_execute_json( ) logger.info(f"Processing JSON: {json_string}") - # Parse JSON data - data = json.loads(json_string) + try: + data = json.loads(json_string) + except json.JSONDecodeError as e: + logger.error(f"Invalid JSON format: {e}") + return {"error": f"Invalid JSON format: {str(e)}"} - # Handle both single function and function list formats function_list = [] if "functions" in data: function_list = data["functions"] elif "function" in data: function_list = [data["function"]] else: - function_list = [ - data - ] # Assume entire object is single function + function_list = [data] - # Ensure function_list is a list and filter None values if isinstance(function_list, dict): function_list = [function_list] + function_list = [f for f in function_list if f] if verbose: logger.info(f"Processing {len(function_list)} functions") results = {} + for function_data in function_list: function_name = function_data.get("name") parameters = function_data.get("parameters", {}) if not function_name: - logger.warning("Function data missing name field") + logger.warning("Function data missing 'name' field") continue if verbose: logger.info( - f"Executing {function_name} with params: {parameters}" + f"Executing {function_name} with parameters: {parameters}" ) if function_name not in function_dict: - logger.warning(f"Function {function_name} not found") - results[function_name] = None + logger.warning( + f"Function '{function_name}' not found" + ) + results[function_name] = "Error: Function not found" continue - try: - result = function_dict[function_name](**parameters) - results[function_name] = str(result) - if verbose: - logger.info( - f"Result for {function_name}: {result}" + for attempt in range(max_retries): + try: + result = function_dict[function_name]( + **parameters ) - except Exception as e: - logger.error( - f"Error executing {function_name}: {str(e)}" - ) - results[function_name] = f"Error: {str(e)}" + results[function_name] = str(result) + if verbose: + logger.info( + f"Result for {function_name}: {result}" + ) + break + except Exception as e: + logger.error( + f"Attempt {attempt + 1} failed for {function_name}: {e}" + ) + if attempt == max_retries - 1: + results[function_name] = ( + f"Error after {max_retries} attempts: {str(e)}" + ) - # Format final results - if len(results) == 1: - # Return single result directly - data = {"result": next(iter(results.values()))} - else: - # Return all results - data = { - "results": results, - "summary": "\n".join( - f"{k}: {v}" for k, v in results.items() - ), - } - - if return_str: - return json.dumps(data) - else: - return data + data = { + "results": results, + "summary": "\n".join( + f"{k}: {v}" for k, v in results.items() + ), + } + + return json.dumps(data, indent=4) - except json.JSONDecodeError as e: - error = f"Invalid JSON format: {str(e)}" - logger.error(error) - return {"error": error} except Exception as e: - error = f"Error parsing and executing JSON: {str(e)}" + error = f"Unexpected error during execution: {str(e)}" logger.error(error) return {"error": error} diff --git a/swarms_tool_example_simple.py b/swarms_tool_example_simple.py new file mode 100644 index 000000000..963118830 --- /dev/null +++ b/swarms_tool_example_simple.py @@ -0,0 +1,30 @@ +from swarms import Agent +from swarms.prompts.finance_agent_sys_prompt import ( + FINANCIAL_AGENT_SYS_PROMPT, +) +from swarms_tools import ( + coin_gecko_coin_api, + fetch_htx_data, +) + + +# Initialize the agent +agent = Agent( + agent_name="Financial-Analysis-Agent", + agent_description="Personal finance advisor agent", + system_prompt=FINANCIAL_AGENT_SYS_PROMPT, + max_loops=1, + model_name="gpt-4o", + dynamic_temperature_enabled=True, + user_name="swarms_corp", + return_step_meta=False, + output_type="str", # "json", "dict", "csv" OR "string" "yaml" and + auto_generate_prompt=False, # Auto generate prompt for the agent based on name, description, and system prompt, task + max_tokens=4000, # max output tokens + saved_state_path="agent_00.json", + interactive=False, +) + +agent.run( + f"Analyze the $swarms token on HTX with data: {fetch_htx_data('swarms')}. Additionally, consider the following CoinGecko data: {coin_gecko_coin_api('swarms')}" +) diff --git a/swarms_tools_example.py b/swarms_tools_example.py index 963118830..9171bb30a 100644 --- a/swarms_tools_example.py +++ b/swarms_tools_example.py @@ -3,11 +3,11 @@ FINANCIAL_AGENT_SYS_PROMPT, ) from swarms_tools import ( + fetch_stock_news, coin_gecko_coin_api, fetch_htx_data, ) - # Initialize the agent agent = Agent( agent_name="Financial-Analysis-Agent", @@ -17,14 +17,15 @@ model_name="gpt-4o", dynamic_temperature_enabled=True, user_name="swarms_corp", + retry_attempts=3, + context_length=8192, return_step_meta=False, output_type="str", # "json", "dict", "csv" OR "string" "yaml" and auto_generate_prompt=False, # Auto generate prompt for the agent based on name, description, and system prompt, task max_tokens=4000, # max output tokens saved_state_path="agent_00.json", interactive=False, + tools=[fetch_stock_news, coin_gecko_coin_api, fetch_htx_data], ) -agent.run( - f"Analyze the $swarms token on HTX with data: {fetch_htx_data('swarms')}. Additionally, consider the following CoinGecko data: {coin_gecko_coin_api('swarms')}" -) +agent.run("Analyze the $swarms token on htx") diff --git a/tests/tools/test_parse_tools.py b/tests/tools/test_parse_tools.py new file mode 100644 index 000000000..ef65dddd9 --- /dev/null +++ b/tests/tools/test_parse_tools.py @@ -0,0 +1,92 @@ +# Define a simple testing framework +from swarms.tools.tool_parse_exec import parse_and_execute_json + + +def run_test(test_name, test_func): + print(f"Running test: {test_name}") + print("------------------------------------------------") + try: + test_func() + print(f"βœ“ {test_name} passed") + print("------------------------------------------------") + except Exception as e: + print(f"βœ— {test_name} failed: {str(e)}") + print("------------------------------------------------") + + +# Mock functions for testing +def mock_function_a(param1, param2): + return param1 + param2 + + +def mock_function_b(param1): + if param1 < 0: + raise ValueError("Negative value not allowed") + return param1 * 2 + + +# Test cases +def test_parse_and_execute_json_success(): + functions = [mock_function_a, mock_function_b] + json_string = '{"functions": [{"name": "mock_function_a", "parameters": {"param1": 1, "param2": 2}}, {"name": "mock_function_b", "parameters": {"param1": 3}}]}' + + result = parse_and_execute_json(functions, json_string) + expected_result = { + "results": {"mock_function_a": "3", "mock_function_b": "6"}, + "summary": "mock_function_a: 3\nmock_function_b: 6", + } + + assert ( + result == expected_result + ), f"Expected {expected_result}, but got {result}" + + +def test_parse_and_execute_json_function_not_found(): + functions = [mock_function_a] + json_string = '{"functions": [{"name": "non_existent_function", "parameters": {}}]}' + + result = parse_and_execute_json(functions, json_string) + expected_result = { + "results": { + "non_existent_function": "Error: Function non_existent_function not found" + }, + "summary": "non_existent_function: Error: Function non_existent_function not found", + } + + assert ( + result == expected_result + ), f"Expected {expected_result}, but got {result}" + + +def test_parse_and_execute_json_error_handling(): + functions = [mock_function_b] + json_string = '{"functions": [{"name": "mock_function_b", "parameters": {"param1": -1}}]}' + + result = parse_and_execute_json(functions, json_string) + expected_result = { + "results": { + "mock_function_b": "Error: Negative value not allowed" + }, + "summary": "mock_function_b: Error: Negative value not allowed", + } + + assert ( + result == expected_result + ), f"Expected {expected_result}, but got {result}" + + +# Run tests +run_test( + "Test parse_and_execute_json success", + test_parse_and_execute_json_success, +) +print("------------------------------------------------") +run_test( + "Test parse_and_execute_json function not found", + test_parse_and_execute_json_function_not_found, +) +print("------------------------------------------------") +run_test( + "Test parse_and_execute_json error handling", + test_parse_and_execute_json_error_handling, +) From 3e6baf25f04e1d49b0c10b00aee798ebca86a90f Mon Sep 17 00:00:00 2001 From: Kye Gomez Date: Tue, 21 Jan 2025 18:57:38 -0500 Subject: [PATCH 06/12] [DOCS][Yahoo finance] --- docs/mkdocs.yml | 1 + docs/swarms/examples/yahoo_finance.md | 42 +++++++++++++++++++++++++++ financial_news_agent.py | 30 +++++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 docs/swarms/examples/yahoo_finance.md create mode 100644 financial_news_agent.py diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index f33f78e70..1fdf39b7a 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -211,6 +211,7 @@ nav: - Swarms Tools: - Agent with HTX + CoinGecko: "swarms/examples/swarms_tools_htx.md" - Agent with HTX + CoinGecko Function Calling: "swarms/examples/swarms_tools_htx_gecko.md" + - Agent with Yahoo Finance: "swarms/examples/yahoo_finance.md" - Swarm Models: - Overview: "swarms/models/index.md" # - Models Available: "swarms/models/index.md" diff --git a/docs/swarms/examples/yahoo_finance.md b/docs/swarms/examples/yahoo_finance.md new file mode 100644 index 000000000..7b6e97066 --- /dev/null +++ b/docs/swarms/examples/yahoo_finance.md @@ -0,0 +1,42 @@ +# Swarms Tools Example with Yahoo Finance + +- `pip3 install swarms swarms-tools` +- Add `OPENAI_API_KEY` to your `.env` file +- Run `yahoo_finance_agent.py` +- Agent will make a function call to the desired tool +- The tool will be executed and the result will be returned to the agent +- The agent will then analyze the result and return the final output + + +```python +from swarms import Agent +from swarms.prompts.finance_agent_sys_prompt import ( + FINANCIAL_AGENT_SYS_PROMPT, +) +from swarms_tools import ( + yahoo_finance_api, +) + +# Initialize the agent +agent = Agent( + agent_name="Financial-Analysis-Agent", + agent_description="Personal finance advisor agent", + system_prompt=FINANCIAL_AGENT_SYS_PROMPT, + max_loops=1, + model_name="gpt-4o", + dynamic_temperature_enabled=True, + user_name="swarms_corp", + retry_attempts=3, + context_length=8192, + return_step_meta=False, + output_type="str", # "json", "dict", "csv" OR "string" "yaml" and + auto_generate_prompt=False, # Auto generate prompt for the agent based on name, description, and system prompt, task + max_tokens=4000, # max output tokens + saved_state_path="agent_00.json", + interactive=False, + tools=[yahoo_finance_api], +) + +agent.run("Analyze the latest metrics for nvidia") +# Less than 30 lines of code.... +``` \ No newline at end of file diff --git a/financial_news_agent.py b/financial_news_agent.py new file mode 100644 index 000000000..e8d30eff3 --- /dev/null +++ b/financial_news_agent.py @@ -0,0 +1,30 @@ +from swarms import Agent +from swarms.prompts.finance_agent_sys_prompt import ( + FINANCIAL_AGENT_SYS_PROMPT, +) +from swarms_tools import ( + yahoo_finance_api, +) + +# Initialize the agent +agent = Agent( + agent_name="Financial-Analysis-Agent", + agent_description="Personal finance advisor agent", + system_prompt=FINANCIAL_AGENT_SYS_PROMPT, + max_loops=1, + model_name="gpt-4o", + dynamic_temperature_enabled=True, + user_name="swarms_corp", + retry_attempts=3, + context_length=8192, + return_step_meta=False, + output_type="str", # "json", "dict", "csv" OR "string" "yaml" and + auto_generate_prompt=False, # Auto generate prompt for the agent based on name, description, and system prompt, task + max_tokens=4000, # max output tokens + saved_state_path="agent_00.json", + interactive=False, + tools=[yahoo_finance_api], +) + +agent.run("Analyze the latest metrics for nvidia") +# Less than 30 lines of code.... \ No newline at end of file From e06652ed8b016d9f5f3d7288c018976da26f0a89 Mon Sep 17 00:00:00 2001 From: Kye Gomez Date: Wed, 22 Jan 2025 03:57:53 -0500 Subject: [PATCH 07/12] [UPDATE] --- dex_screener.py | 23 ++ docs/index.md | 2 +- docs/swarms/concept/framework_architecture.md | 2 +- financial_news_agent.py | 2 +- matrix_swarm_tests.py | 216 +++++++++++++ swarms/structs/matrix_swarm.py | 306 ++++++++++++++++++ test_matrix_swarm.py | 216 +++++++++++++ tests/structs/test_matrix_swarm.py | 0 8 files changed, 764 insertions(+), 3 deletions(-) create mode 100644 dex_screener.py create mode 100644 matrix_swarm_tests.py create mode 100644 swarms/structs/matrix_swarm.py create mode 100644 test_matrix_swarm.py create mode 100644 tests/structs/test_matrix_swarm.py diff --git a/dex_screener.py b/dex_screener.py new file mode 100644 index 000000000..5c1bfbc1f --- /dev/null +++ b/dex_screener.py @@ -0,0 +1,23 @@ +from swarms import Agent + +from swarms_tools.finance.dex_screener import ( + fetch_dex_screener_profiles, +) + +# Initialize the agent +agent = Agent( + agent_name="Financial-Analysis-Agent", + agent_description="Personal finance advisor agent", + max_loops=1, + model_name="gpt-4o", + dynamic_temperature_enabled=True, + user_name="swarms_corp", + return_step_meta=False, + output_type="str", # "json", "dict", "csv" OR "string" "yaml" and + auto_generate_prompt=False, # Auto generate prompt for the agent based on name, description, and system prompt, task + interactive=False, +) + +token_profiles = fetch_dex_screener_profiles() +prompt = f"Using data from DexScreener, analyze the latest tokens and provide a detailed analysis with top 5 tokens based on their potential, considering both their profiles and recent boosts. The token profiles are sourced from DexScreener's token profiles API, while the token boosts are sourced from DexScreener's latest token boosts API. {str(token_profiles)}" +agent.run(prompt) diff --git a/docs/index.md b/docs/index.md index 367855eec..86b6473c6 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,6 +1,6 @@ # Welcome to Swarms Docs Home -[![Join our Discord](https://img.shields.io/badge/Discord-Join%20our%20server-5865F2?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/agora-999382051935506503) [![Subscribe on YouTube](https://img.shields.io/badge/YouTube-Subscribe-red?style=for-the-badge&logo=youtube&logoColor=white)](https://www.youtube.com/@kyegomez3242) [![Connect on LinkedIn](https://img.shields.io/badge/LinkedIn-Connect-blue?style=for-the-badge&logo=linkedin&logoColor=white)](https://www.linkedin.com/in/kye-g-38759a207/) [![Follow on X.com](https://img.shields.io/badge/X.com-Follow-1DA1F2?style=for-the-badge&logo=x&logoColor=white)](https://x.com/kyegomezb) +[![Join our Discord](https://img.shields.io/badge/Discord-Join%20our%20server-5865F2?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/jM3Z6M9uMq) [![Subscribe on YouTube](https://img.shields.io/badge/YouTube-Subscribe-red?style=for-the-badge&logo=youtube&logoColor=white)](https://www.youtube.com/@kyegomez3242) [![Connect on LinkedIn](https://img.shields.io/badge/LinkedIn-Connect-blue?style=for-the-badge&logo=linkedin&logoColor=white)](https://www.linkedin.com/in/kye-g-38759a207/) [![Follow on X.com](https://img.shields.io/badge/X.com-Follow-1DA1F2?style=for-the-badge&logo=x&logoColor=white)](https://x.com/kyegomezb) **Get Started Building Production-Grade Multi-Agent Applications** diff --git a/docs/swarms/concept/framework_architecture.md b/docs/swarms/concept/framework_architecture.md index b5e3682a2..e704ba8e1 100644 --- a/docs/swarms/concept/framework_architecture.md +++ b/docs/swarms/concept/framework_architecture.md @@ -155,5 +155,5 @@ By understanding the purpose and role of each folder in the Swarms framework, us - **Community Support** - - URL: [Submit issue](https://discord.gg/agora-999382051935506503) + - URL: [Submit issue](https://discord.gg/jM3Z6M9uMq) - Ask the community for support in real-time and or admin support \ No newline at end of file diff --git a/financial_news_agent.py b/financial_news_agent.py index e8d30eff3..c949a4feb 100644 --- a/financial_news_agent.py +++ b/financial_news_agent.py @@ -27,4 +27,4 @@ ) agent.run("Analyze the latest metrics for nvidia") -# Less than 30 lines of code.... \ No newline at end of file +# Less than 30 lines of code.... diff --git a/matrix_swarm_tests.py b/matrix_swarm_tests.py new file mode 100644 index 000000000..4556c6933 --- /dev/null +++ b/matrix_swarm_tests.py @@ -0,0 +1,216 @@ +from swarms.structs.matrix_swarm import AgentMatrix, AgentOutput +from swarms import Agent + + +def create_test_matrix(rows: int, cols: int) -> AgentMatrix: + """Helper function to create a test agent matrix""" + agents = [ + [ + Agent( + agent_name=f"TestAgent-{i}-{j}", + system_prompt="Test prompt", + ) + for j in range(cols) + ] + for i in range(rows) + ] + return AgentMatrix(agents) + + +def test_init(): + """Test AgentMatrix initialization""" + # Test valid initialization + matrix = create_test_matrix(2, 2) + assert isinstance(matrix, AgentMatrix) + assert len(matrix.agents) == 2 + assert len(matrix.agents[0]) == 2 + + # Test invalid initialization + try: + AgentMatrix([[1, 2], [3, 4]]) # Non-agent elements + assert False, "Should raise ValueError" + except ValueError: + pass + + try: + AgentMatrix([]) # Empty matrix + assert False, "Should raise ValueError" + except ValueError: + pass + + +def test_transpose(): + """Test matrix transpose operation""" + matrix = create_test_matrix(2, 3) + transposed = matrix.transpose() + + assert len(transposed.agents) == 3 # Original cols become rows + assert len(transposed.agents[0]) == 2 # Original rows become cols + + # Verify agent positions + for i in range(2): + for j in range(3): + assert ( + matrix.agents[i][j].agent_name + == transposed.agents[j][i].agent_name + ) + + +def test_add(): + """Test matrix addition""" + matrix1 = create_test_matrix(2, 2) + matrix2 = create_test_matrix(2, 2) + + result = matrix1.add(matrix2) + assert len(result.agents) == 2 + assert len(result.agents[0]) == 2 + + # Test incompatible dimensions + matrix3 = create_test_matrix(2, 3) + try: + matrix1.add(matrix3) + assert False, "Should raise ValueError" + except ValueError: + pass + + +def test_scalar_multiply(): + """Test scalar multiplication""" + matrix = create_test_matrix(2, 2) + scalar = 3 + result = matrix.scalar_multiply(scalar) + + assert len(result.agents) == 2 + assert len(result.agents[0]) == 2 * scalar + + # Verify agent duplication + for i in range(len(result.agents)): + for j in range(0, len(result.agents[0]), scalar): + original_agent = matrix.agents[i][j // scalar] + for k in range(scalar): + assert ( + result.agents[i][j + k].agent_name + == original_agent.agent_name + ) + + +def test_multiply(): + """Test matrix multiplication""" + matrix1 = create_test_matrix(2, 3) + matrix2 = create_test_matrix(3, 2) + inputs = ["test query 1", "test query 2"] + + result = matrix1.multiply(matrix2, inputs) + assert len(result) == 2 # Number of rows in first matrix + assert len(result[0]) == 2 # Number of columns in second matrix + + # Verify output structure + for row in result: + for output in row: + assert isinstance(output, AgentOutput) + assert isinstance(output.input_query, str) + assert isinstance(output.metadata, dict) + + +def test_subtract(): + """Test matrix subtraction""" + matrix1 = create_test_matrix(2, 2) + matrix2 = create_test_matrix(2, 2) + + result = matrix1.subtract(matrix2) + assert len(result.agents) == 2 + assert len(result.agents[0]) == 2 + + +def test_identity(): + """Test identity matrix creation""" + matrix = create_test_matrix(3, 3) + identity = matrix.identity(3) + + assert len(identity.agents) == 3 + assert len(identity.agents[0]) == 3 + + # Verify diagonal elements are from original matrix + for i in range(3): + assert ( + identity.agents[i][i].agent_name + == matrix.agents[i][i].agent_name + ) + + # Verify non-diagonal elements are zero agents + for j in range(3): + if i != j: + assert identity.agents[i][j].agent_name.startswith( + "Zero-Agent" + ) + + +def test_determinant(): + """Test determinant calculation""" + # Test 1x1 matrix + matrix1 = create_test_matrix(1, 1) + det1 = matrix1.determinant() + assert det1 is not None + + # Test 2x2 matrix + matrix2 = create_test_matrix(2, 2) + det2 = matrix2.determinant() + assert det2 is not None + + # Test non-square matrix + matrix3 = create_test_matrix(2, 3) + try: + matrix3.determinant() + assert False, "Should raise ValueError" + except ValueError: + pass + + +def test_save_to_file(tmp_path): + """Test saving matrix to file""" + import os + + matrix = create_test_matrix(2, 2) + file_path = os.path.join(tmp_path, "test_matrix.json") + + matrix.save_to_file(file_path) + assert os.path.exists(file_path) + + # Verify file contents + import json + + with open(file_path, "r") as f: + data = json.load(f) + assert "agents" in data + assert "outputs" in data + assert len(data["agents"]) == 2 + assert len(data["agents"][0]) == 2 + + +def run_all_tests(): + """Run all test functions""" + test_functions = [ + test_init, + test_transpose, + test_add, + test_scalar_multiply, + test_multiply, + test_subtract, + test_identity, + test_determinant, + ] + + for test_func in test_functions: + try: + test_func() + print(f"βœ… {test_func.__name__} passed") + except AssertionError as e: + print(f"❌ {test_func.__name__} failed: {str(e)}") + except Exception as e: + print( + f"❌ {test_func.__name__} failed with exception: {str(e)}" + ) + + +if __name__ == "__main__": + run_all_tests() diff --git a/swarms/structs/matrix_swarm.py b/swarms/structs/matrix_swarm.py new file mode 100644 index 000000000..179e88b5f --- /dev/null +++ b/swarms/structs/matrix_swarm.py @@ -0,0 +1,306 @@ +import json +from typing import Any, List + +from loguru import logger +from pydantic import BaseModel, Field + +from swarms import Agent + + +class AgentOutput(BaseModel): + """ + Schema for capturing metadata and results of an agent run. + """ + + agent_name: str = Field(..., description="Name of the agent.") + input_query: str = Field( + ..., description="Input query provided to the agent." + ) + output_result: Any = Field( + ..., description="Result produced by the agent." + ) + metadata: dict = Field( + ..., description="Additional metadata about the agent run." + ) + + +class MatrixSwarm: + """ + A class to manage a matrix of agents and perform matrix operations similar to linear algebra. + """ + + def __init__(self, agents: List[List[Agent]]): + """ + Initializes the MatrixSwarm with a 2D list of agents. + Args: + agents (List[List[Agent]]): 2D list of agents representing the matrix. + """ + if not agents or not all( + isinstance(row, list) for row in agents + ): + raise ValueError("Agents must be provided as a 2D list.") + if not all( + isinstance(agent, Agent) + for row in agents + for agent in row + ): + raise ValueError( + "All elements of the matrix must be instances of `Agent`." + ) + self.agents = agents + self.outputs = [] # List to store outputs as AgentOutput + + def validate_dimensions(self, other: "MatrixSwarm") -> None: + """ + Validates that two matrices have compatible dimensions for operations. + + Args: + other (MatrixSwarm): Another MatrixSwarm. + + Raises: + ValueError: If dimensions are incompatible. + """ + if len(self.agents) != len(other.agents) or len( + self.agents[0] + ) != len(other.agents[0]): + raise ValueError( + "Matrix dimensions are incompatible for this operation." + ) + + def transpose(self) -> "MatrixSwarm": + """ + Transposes the matrix of agents (swap rows and columns). + + Returns: + MatrixSwarm: A new transposed MatrixSwarm. + """ + transposed_agents = [ + [self.agents[j][i] for j in range(len(self.agents))] + for i in range(len(self.agents[0])) + ] + return MatrixSwarm(transposed_agents) + + def add(self, other: "MatrixSwarm") -> "MatrixSwarm": + """ + Adds two matrices element-wise. + + Args: + other (MatrixSwarm): Another MatrixSwarm to add. + + Returns: + MatrixSwarm: A new MatrixSwarm resulting from the addition. + """ + self.validate_dimensions(other) + added_agents = [ + [self.agents[i][j] for j in range(len(self.agents[i]))] + for i in range(len(self.agents)) + ] + return MatrixSwarm(added_agents) + + def scalar_multiply(self, scalar: int) -> "MatrixSwarm": + """ + Scales the agents by duplicating them scalar times along the row. + + Args: + scalar (int): The scalar multiplier. + + Returns: + MatrixSwarm: A new MatrixSwarm where each agent is repeated scalar times along the row. + """ + scaled_agents = [ + [agent for _ in range(scalar) for agent in row] + for row in self.agents + ] + return MatrixSwarm(scaled_agents) + + def multiply( + self, other: "MatrixSwarm", inputs: List[str] + ) -> List[List[AgentOutput]]: + """ + Multiplies two matrices (dot product between rows and columns). + + Args: + other (MatrixSwarm): Another MatrixSwarm for multiplication. + inputs (List[str]): A list of input queries for the agents. + + Returns: + List[List[AgentOutput]]: A resulting matrix of outputs after multiplication. + """ + if len(self.agents[0]) != len(other.agents): + raise ValueError( + "Matrix dimensions are incompatible for multiplication." + ) + + results = [] + for i, row in enumerate(self.agents): + row_results = [] + for col_idx in range(len(other.agents[0])): + col = [ + other.agents[row_idx][col_idx] + for row_idx in range(len(other.agents)) + ] + query = inputs[ + i + ] # Input query for the corresponding row + intermediate_result = [] + + for agent_r, agent_c in zip(row, col): + try: + result = agent_r.run(query) + intermediate_result.append(result) + except Exception as e: + intermediate_result.append(f"Error: {e}") + + # Aggregate outputs from dot product + combined_result = " ".join( + intermediate_result + ) # Example aggregation + row_results.append( + AgentOutput( + agent_name=f"DotProduct-{i}-{col_idx}", + input_query=query, + output_result=combined_result, + metadata={"row": i, "col": col_idx}, + ) + ) + results.append(row_results) + return results + + def subtract(self, other: "MatrixSwarm") -> "MatrixSwarm": + """ + Subtracts two matrices element-wise. + + Args: + other (MatrixSwarm): Another MatrixSwarm to subtract. + + Returns: + MatrixSwarm: A new MatrixSwarm resulting from the subtraction. + """ + self.validate_dimensions(other) + subtracted_agents = [ + [self.agents[i][j] for j in range(len(self.agents[i]))] + for i in range(len(self.agents)) + ] + return MatrixSwarm(subtracted_agents) + + def identity(self, size: int) -> "MatrixSwarm": + """ + Creates an identity matrix of agents with size `size`. + + Args: + size (int): Size of the identity matrix (NxN). + + Returns: + MatrixSwarm: An identity MatrixSwarm. + """ + identity_agents = [ + [ + ( + self.agents[i][j] + if i == j + else Agent( + agent_name=f"Zero-Agent-{i}-{j}", + system_prompt="", + ) + ) + for j in range(size) + ] + for i in range(size) + ] + return MatrixSwarm(identity_agents) + + def determinant(self) -> Any: + """ + Computes the determinant of a square MatrixSwarm. + + Returns: + Any: Determinant of the matrix (as agent outputs). + """ + if len(self.agents) != len(self.agents[0]): + raise ValueError( + "Determinant can only be computed for square matrices." + ) + + # Recursive determinant calculation (example using placeholder logic) + if len(self.agents) == 1: + return self.agents[0][0].run("Compute determinant") + + det_result = 0 + for i in range(len(self.agents)): + submatrix = MatrixSwarm( + [row[:i] + row[i + 1 :] for row in self.agents[1:]] + ) + cofactor = ((-1) ** i) * self.agents[0][i].run( + "Compute determinant" + ) + det_result += cofactor * submatrix.determinant() + return det_result + + def save_to_file(self, path: str) -> None: + """ + Saves the agent matrix structure and metadata to a file. + + Args: + path (str): File path to save the matrix. + """ + try: + matrix_data = { + "agents": [ + [agent.agent_name for agent in row] + for row in self.agents + ], + "outputs": [output.dict() for output in self.outputs], + } + with open(path, "w") as f: + json.dump(matrix_data, f, indent=4) + logger.info(f"MatrixSwarm saved to {path}") + except Exception as e: + logger.error(f"Error saving MatrixSwarm: {e}") + + +# # Example usage +# if __name__ == "__main__": +# from swarms.prompts.finance_agent_sys_prompt import ( +# FINANCIAL_AGENT_SYS_PROMPT, +# ) + +# # Create a 3x3 matrix of agents +# agents = [ +# [ +# Agent( +# agent_name=f"Agent-{i}-{j}", +# system_prompt=FINANCIAL_AGENT_SYS_PROMPT, +# model_name="gpt-4o-mini", +# max_loops=1, +# autosave=True, +# dashboard=False, +# verbose=True, +# dynamic_temperature_enabled=True, +# saved_state_path=f"agent_{i}_{j}.json", +# user_name="swarms_corp", +# retry_attempts=1, +# context_length=200000, +# return_step_meta=False, +# output_type="string", +# streaming_on=False, +# ) +# for j in range(3) +# ] +# for i in range(3) +# ] + +# # Initialize the matrix +# agent_matrix = MatrixSwarm(agents) + +# # Example queries +# inputs = [ +# "Explain Roth IRA benefits", +# "Differences between ETFs and mutual funds", +# "How to create a diversified portfolio", +# ] + +# # Run agents +# outputs = agent_matrix.multiply(agent_matrix.transpose(), inputs) + +# # Save results +# agent_matrix.save_to_file("agent_matrix_results.json") diff --git a/test_matrix_swarm.py b/test_matrix_swarm.py new file mode 100644 index 000000000..423640f1e --- /dev/null +++ b/test_matrix_swarm.py @@ -0,0 +1,216 @@ +from swarms.structs.matrix_swarm import MatrixSwarm, AgentOutput +from swarms import Agent + + +def create_test_matrix(rows: int, cols: int) -> MatrixSwarm: + """Helper function to create a test agent matrix""" + agents = [ + [ + Agent( + agent_name=f"TestAgent-{i}-{j}", + system_prompt="Test prompt", + ) + for j in range(cols) + ] + for i in range(rows) + ] + return MatrixSwarm(agents) + + +def test_init(): + """Test MatrixSwarm initialization""" + # Test valid initialization + matrix = create_test_matrix(2, 2) + assert isinstance(matrix, MatrixSwarm) + assert len(matrix.agents) == 2 + assert len(matrix.agents[0]) == 2 + + # Test invalid initialization + try: + MatrixSwarm([[1, 2], [3, 4]]) # Non-agent elements + assert False, "Should raise ValueError" + except ValueError: + pass + + try: + MatrixSwarm([]) # Empty matrix + assert False, "Should raise ValueError" + except ValueError: + pass + + +def test_transpose(): + """Test matrix transpose operation""" + matrix = create_test_matrix(2, 3) + transposed = matrix.transpose() + + assert len(transposed.agents) == 3 # Original cols become rows + assert len(transposed.agents[0]) == 2 # Original rows become cols + + # Verify agent positions + for i in range(2): + for j in range(3): + assert ( + matrix.agents[i][j].agent_name + == transposed.agents[j][i].agent_name + ) + + +def test_add(): + """Test matrix addition""" + matrix1 = create_test_matrix(2, 2) + matrix2 = create_test_matrix(2, 2) + + result = matrix1.add(matrix2) + assert len(result.agents) == 2 + assert len(result.agents[0]) == 2 + + # Test incompatible dimensions + matrix3 = create_test_matrix(2, 3) + try: + matrix1.add(matrix3) + assert False, "Should raise ValueError" + except ValueError: + pass + + +def test_scalar_multiply(): + """Test scalar multiplication""" + matrix = create_test_matrix(2, 2) + scalar = 3 + result = matrix.scalar_multiply(scalar) + + assert len(result.agents) == 2 + assert len(result.agents[0]) == 2 * scalar + + # Verify agent duplication + for i in range(len(result.agents)): + for j in range(0, len(result.agents[0]), scalar): + original_agent = matrix.agents[i][j // scalar] + for k in range(scalar): + assert ( + result.agents[i][j + k].agent_name + == original_agent.agent_name + ) + + +def test_multiply(): + """Test matrix multiplication""" + matrix1 = create_test_matrix(2, 3) + matrix2 = create_test_matrix(3, 2) + inputs = ["test query 1", "test query 2"] + + result = matrix1.multiply(matrix2, inputs) + assert len(result) == 2 # Number of rows in first matrix + assert len(result[0]) == 2 # Number of columns in second matrix + + # Verify output structure + for row in result: + for output in row: + assert isinstance(output, AgentOutput) + assert isinstance(output.input_query, str) + assert isinstance(output.metadata, dict) + + +def test_subtract(): + """Test matrix subtraction""" + matrix1 = create_test_matrix(2, 2) + matrix2 = create_test_matrix(2, 2) + + result = matrix1.subtract(matrix2) + assert len(result.agents) == 2 + assert len(result.agents[0]) == 2 + + +def test_identity(): + """Test identity matrix creation""" + matrix = create_test_matrix(3, 3) + identity = matrix.identity(3) + + assert len(identity.agents) == 3 + assert len(identity.agents[0]) == 3 + + # Verify diagonal elements are from original matrix + for i in range(3): + assert ( + identity.agents[i][i].agent_name + == matrix.agents[i][i].agent_name + ) + + # Verify non-diagonal elements are zero agents + for j in range(3): + if i != j: + assert identity.agents[i][j].agent_name.startswith( + "Zero-Agent" + ) + + +def test_determinant(): + """Test determinant calculation""" + # Test 1x1 matrix + matrix1 = create_test_matrix(1, 1) + det1 = matrix1.determinant() + assert det1 is not None + + # Test 2x2 matrix + matrix2 = create_test_matrix(2, 2) + det2 = matrix2.determinant() + assert det2 is not None + + # Test non-square matrix + matrix3 = create_test_matrix(2, 3) + try: + matrix3.determinant() + assert False, "Should raise ValueError" + except ValueError: + pass + + +def test_save_to_file(tmp_path): + """Test saving matrix to file""" + import os + + matrix = create_test_matrix(2, 2) + file_path = os.path.join(tmp_path, "test_matrix.json") + + matrix.save_to_file(file_path) + assert os.path.exists(file_path) + + # Verify file contents + import json + + with open(file_path, "r") as f: + data = json.load(f) + assert "agents" in data + assert "outputs" in data + assert len(data["agents"]) == 2 + assert len(data["agents"][0]) == 2 + + +def run_all_tests(): + """Run all test functions""" + test_functions = [ + test_init, + test_transpose, + test_add, + test_scalar_multiply, + test_multiply, + test_subtract, + test_identity, + test_determinant, + ] + + for test_func in test_functions: + try: + test_func() + print(f"βœ… {test_func.__name__} passed") + except AssertionError as e: + print(f"❌ {test_func.__name__} failed: {str(e)}") + except Exception as e: + print( + f"❌ {test_func.__name__} failed with exception: {str(e)}" + ) + + +if __name__ == "__main__": + run_all_tests() diff --git a/tests/structs/test_matrix_swarm.py b/tests/structs/test_matrix_swarm.py new file mode 100644 index 000000000..e69de29bb From 37894599c2c5363574d1fa7305488ed8650c620e Mon Sep 17 00:00:00 2001 From: Kye Gomez Date: Wed, 22 Jan 2025 13:40:59 -0500 Subject: [PATCH 08/12] [FEAT][MatrixSwarm] --- docs/mkdocs.yml | 1 + docs/swarms/structs/matrix_swarm.md | 247 ++++++++++++++++++++++++++++ docs/swarms/structs/swarm_router.md | 35 +++- docs/swarms_memory/index.md | 2 +- test_matrix_swarm.py | 216 ------------------------ tests/structs/test_matrix_swarm.py | 217 ++++++++++++++++++++++++ 6 files changed, 500 insertions(+), 218 deletions(-) create mode 100644 docs/swarms/structs/matrix_swarm.md delete mode 100644 test_matrix_swarm.py diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 1fdf39b7a..792454886 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -188,6 +188,7 @@ nav: - TaskQueueSwarm: "swarms/structs/taskqueue_swarm.md" - SwarmRearrange: "swarms/structs/swarm_rearrange.md" - MultiAgentRouter: "swarms/structs/multi_agent_router.md" + - MatrixSwarm: "swarms/structs/matrix_swarm.md" - Various Execution Methods: "swarms/structs/various_execution_methods.md" - Workflows: - ConcurrentWorkflow: "swarms/structs/concurrentworkflow.md" diff --git a/docs/swarms/structs/matrix_swarm.md b/docs/swarms/structs/matrix_swarm.md new file mode 100644 index 000000000..0ed3c1906 --- /dev/null +++ b/docs/swarms/structs/matrix_swarm.md @@ -0,0 +1,247 @@ +# MatrixSwarm + +The `MatrixSwarm` class provides a framework for managing and operating on matrices of AI agents, enabling matrix-like operations similar to linear algebra. This allows for complex agent interactions and parallel processing capabilities. + +## Overview + +`MatrixSwarm` treats AI agents as elements in a matrix, allowing for operations like addition, multiplication, and transposition. This approach enables sophisticated agent orchestration and parallel processing patterns. + +## Installation + +```bash +pip3 install -U swarms +``` + +## Basic Usage + +```python +from swarms import Agent +from swarms.matrix import MatrixSwarm + +# Create a 2x2 matrix of agents +agents = [ + [Agent(agent_name="Agent-0-0"), Agent(agent_name="Agent-0-1")], + [Agent(agent_name="Agent-1-0"), Agent(agent_name="Agent-1-1")] +] + +# Initialize the matrix +matrix = MatrixSwarm(agents) +``` + +## Class Constructor + +```python +def __init__(self, agents: List[List[Agent]]) +``` + +### Parameters +- `agents` (`List[List[Agent]]`): A 2D list of Agent instances representing the matrix. + +### Raises +- `ValueError`: If the input is not a valid 2D list of Agent instances. + +## Methods + +### transpose() + +Transposes the matrix of agents by swapping rows and columns. + +```python +def transpose(self) -> MatrixSwarm +``` + +#### Returns +- `MatrixSwarm`: A new MatrixSwarm instance with transposed dimensions. + +--- + +### add(other) + +Performs element-wise addition of two agent matrices. + +```python +def add(self, other: MatrixSwarm) -> MatrixSwarm +``` + +#### Parameters +- `other` (`MatrixSwarm`): Another MatrixSwarm instance to add. + +#### Returns +- `MatrixSwarm`: A new MatrixSwarm resulting from the addition. + +#### Raises +- `ValueError`: If matrix dimensions are incompatible. + +--- + +### scalar_multiply(scalar) + +Scales the matrix by duplicating agents along rows. + +```python +def scalar_multiply(self, scalar: int) -> MatrixSwarm +``` + +#### Parameters +- `scalar` (`int`): The multiplication factor. + +#### Returns +- `MatrixSwarm`: A new MatrixSwarm with scaled dimensions. + +--- + +### multiply(other, inputs) + +Performs matrix multiplication (dot product) between two agent matrices. + +```python +def multiply(self, other: MatrixSwarm, inputs: List[str]) -> List[List[AgentOutput]] +``` + +#### Parameters +- `other` (`MatrixSwarm`): The second MatrixSwarm for multiplication. +- `inputs` (`List[str]`): Input queries for the agents. + +#### Returns +- `List[List[AgentOutput]]`: Matrix of operation results. + +#### Raises +- `ValueError`: If matrix dimensions are incompatible for multiplication. + +--- + +### subtract(other) + +Performs element-wise subtraction of two agent matrices. + +```python +def subtract(self, other: MatrixSwarm) -> MatrixSwarm +``` + +#### Parameters +- `other` (`MatrixSwarm`): Another MatrixSwarm to subtract. + +#### Returns +- `MatrixSwarm`: A new MatrixSwarm resulting from the subtraction. + +--- + +### identity(size) + +Creates an identity matrix of agents. + +```python +def identity(self, size: int) -> MatrixSwarm +``` + +#### Parameters +- `size` (`int`): Size of the identity matrix (NxN). + +#### Returns +- `MatrixSwarm`: An identity MatrixSwarm. + +--- + +### determinant() + +Computes the determinant of a square agent matrix. + +```python +def determinant(self) -> Any +``` + +#### Returns +- `Any`: The determinant result. + +#### Raises +- `ValueError`: If the matrix is not square. + +--- + +### save_to_file(path) + +Saves the matrix structure and metadata to a JSON file. + +```python +def save_to_file(self, path: str) -> None +``` + +#### Parameters +- `path` (`str`): File path for saving the matrix data. + +## Extended Example + +Here's a comprehensive example demonstrating various MatrixSwarm operations: + +```python +from swarms import Agent +from swarms.matrix import MatrixSwarm + +# Create agents with specific configurations +agents = [ + [ + Agent( + agent_name=f"Agent-{i}-{j}", + system_prompt="Your system prompt here", + model_name="gpt-4", + max_loops=1, + verbose=True + ) for j in range(2) + ] for i in range(2) +] + +# Initialize matrix +matrix = MatrixSwarm(agents) + +# Example operations +transposed = matrix.transpose() +scaled = matrix.scalar_multiply(2) + +# Run operations with inputs +inputs = ["Query 1", "Query 2"] +results = matrix.multiply(transposed, inputs) + +# Save results +matrix.save_to_file("matrix_results.json") +``` + +## Output Schema + +The `AgentOutput` class defines the structure for operation results: + +```python +class AgentOutput(BaseModel): + agent_name: str + input_query: str + output_result: Any + metadata: dict +``` + +## Best Practices + +1. **Initialization** + - Ensure all agents in the matrix are properly configured before initialization + - Validate matrix dimensions for your use case + +2. **Operation Performance** + - Consider computational costs for large matrices + - Use appropriate batch sizes for inputs + +3. **Error Handling** + - Implement proper error handling for agent operations + - Validate inputs before matrix operations + +4. **Resource Management** + - Monitor agent resource usage in large matrices + - Implement proper cleanup procedures + +## Limitations + +- Matrix operations are constrained by the underlying agent capabilities +- Performance may vary based on agent configuration and complexity +- Resource usage scales with matrix dimensions + +## See Also + +- [Swarms Documentation](https://github.com/kyegomez/swarms) +- [Agent Class Reference](https://github.com/kyegomez/swarms/tree/main/swarms) \ No newline at end of file diff --git a/docs/swarms/structs/swarm_router.md b/docs/swarms/structs/swarm_router.md index 07d8c2f5a..537818376 100644 --- a/docs/swarms/structs/swarm_router.md +++ b/docs/swarms/structs/swarm_router.md @@ -33,7 +33,7 @@ Main class for routing tasks to different swarm types. | `flow` | str | The flow of the swarm. | | `return_json` | bool | Flag to enable/disable returning the result in JSON format. | | `auto_generate_prompts` | bool | Flag to enable/disable auto generation of prompts. | -| `swarm` | Union[AgentRearrange, MixtureOfAgents, SpreadSheetSwarm, SequentialWorkflow, ConcurrentWorkflow] | Instantiated swarm object. | +| `swarm` | Union[AgentRearrange, MixtureOfAgents, SpreadSheetSwarm, SequentialWorkflow, ConcurrentWorkflow, GroupChat, MultiAgentRouter] | Instantiated swarm object. | | `logs` | List[SwarmLog] | List of log entries captured during operations. | #### Methods: @@ -271,6 +271,39 @@ result = concurrent_router.run("Conduct a comprehensive market analysis for Prod ``` +### GroupChat + +Use Case: Simulating a group chat with multiple agents. + +```python +group_chat_router = SwarmRouter( + name="GroupChat", + description="Simulate a group chat with multiple agents", + max_loops=1, + agents=[financial_analyst, market_researcher, competitor_analyst], + swarm_type="GroupChat" +) + +result = group_chat_router.run("Conduct a comprehensive market analysis for Product X") +``` + +### MultiAgentRouter + +Use Case: Simulating a group chat with multiple agents. + +```python +multi_agent_router = SwarmRouter( + name="MultiAgentRouter", + description="Simulate a group chat with multiple agents", + max_loops=1, + agents=[financial_analyst, market_researcher, competitor_analyst], + swarm_type="MultiAgentRouter" +) + +result = multi_agent_router.run("Conduct a comprehensive market analysis for Product X") +``` + + ### Auto Select (Experimental) Autonomously selects the right swarm by conducting vector search on your input task or name or description or all 3. diff --git a/docs/swarms_memory/index.md b/docs/swarms_memory/index.md index 3d96b4efd..3b4011b05 100644 --- a/docs/swarms_memory/index.md +++ b/docs/swarms_memory/index.md @@ -161,7 +161,7 @@ print(result) We're excited to see how you leverage Swarms-Memory in your projects! Join our community on Discord to share your experiences, ask questions, and stay updated on the latest developments. - **🐦 Twitter**: [Follow us on Twitter](https://twitter.com/swarms_platform) -- **πŸ“’ Discord**: [Join the Agora Discord](https://discord.gg/agora) +- **πŸ“’ Discord**: [Join the Agora Discord](https://discord.gg/jM3Z6M9uMq) - **Swarms Platform**: [Visit our website](https://swarms.ai) - **πŸ“™ Documentation**: [Read the Docs](https://docs.swarms.ai) diff --git a/test_matrix_swarm.py b/test_matrix_swarm.py deleted file mode 100644 index 423640f1e..000000000 --- a/test_matrix_swarm.py +++ /dev/null @@ -1,216 +0,0 @@ -from swarms.structs.matrix_swarm import MatrixSwarm, AgentOutput -from swarms import Agent - - -def create_test_matrix(rows: int, cols: int) -> MatrixSwarm: - """Helper function to create a test agent matrix""" - agents = [ - [ - Agent( - agent_name=f"TestAgent-{i}-{j}", - system_prompt="Test prompt", - ) - for j in range(cols) - ] - for i in range(rows) - ] - return MatrixSwarm(agents) - - -def test_init(): - """Test MatrixSwarm initialization""" - # Test valid initialization - matrix = create_test_matrix(2, 2) - assert isinstance(matrix, MatrixSwarm) - assert len(matrix.agents) == 2 - assert len(matrix.agents[0]) == 2 - - # Test invalid initialization - try: - MatrixSwarm([[1, 2], [3, 4]]) # Non-agent elements - assert False, "Should raise ValueError" - except ValueError: - pass - - try: - MatrixSwarm([]) # Empty matrix - assert False, "Should raise ValueError" - except ValueError: - pass - - -def test_transpose(): - """Test matrix transpose operation""" - matrix = create_test_matrix(2, 3) - transposed = matrix.transpose() - - assert len(transposed.agents) == 3 # Original cols become rows - assert len(transposed.agents[0]) == 2 # Original rows become cols - - # Verify agent positions - for i in range(2): - for j in range(3): - assert ( - matrix.agents[i][j].agent_name - == transposed.agents[j][i].agent_name - ) - - -def test_add(): - """Test matrix addition""" - matrix1 = create_test_matrix(2, 2) - matrix2 = create_test_matrix(2, 2) - - result = matrix1.add(matrix2) - assert len(result.agents) == 2 - assert len(result.agents[0]) == 2 - - # Test incompatible dimensions - matrix3 = create_test_matrix(2, 3) - try: - matrix1.add(matrix3) - assert False, "Should raise ValueError" - except ValueError: - pass - - -def test_scalar_multiply(): - """Test scalar multiplication""" - matrix = create_test_matrix(2, 2) - scalar = 3 - result = matrix.scalar_multiply(scalar) - - assert len(result.agents) == 2 - assert len(result.agents[0]) == 2 * scalar - - # Verify agent duplication - for i in range(len(result.agents)): - for j in range(0, len(result.agents[0]), scalar): - original_agent = matrix.agents[i][j // scalar] - for k in range(scalar): - assert ( - result.agents[i][j + k].agent_name - == original_agent.agent_name - ) - - -def test_multiply(): - """Test matrix multiplication""" - matrix1 = create_test_matrix(2, 3) - matrix2 = create_test_matrix(3, 2) - inputs = ["test query 1", "test query 2"] - - result = matrix1.multiply(matrix2, inputs) - assert len(result) == 2 # Number of rows in first matrix - assert len(result[0]) == 2 # Number of columns in second matrix - - # Verify output structure - for row in result: - for output in row: - assert isinstance(output, AgentOutput) - assert isinstance(output.input_query, str) - assert isinstance(output.metadata, dict) - - -def test_subtract(): - """Test matrix subtraction""" - matrix1 = create_test_matrix(2, 2) - matrix2 = create_test_matrix(2, 2) - - result = matrix1.subtract(matrix2) - assert len(result.agents) == 2 - assert len(result.agents[0]) == 2 - - -def test_identity(): - """Test identity matrix creation""" - matrix = create_test_matrix(3, 3) - identity = matrix.identity(3) - - assert len(identity.agents) == 3 - assert len(identity.agents[0]) == 3 - - # Verify diagonal elements are from original matrix - for i in range(3): - assert ( - identity.agents[i][i].agent_name - == matrix.agents[i][i].agent_name - ) - - # Verify non-diagonal elements are zero agents - for j in range(3): - if i != j: - assert identity.agents[i][j].agent_name.startswith( - "Zero-Agent" - ) - - -def test_determinant(): - """Test determinant calculation""" - # Test 1x1 matrix - matrix1 = create_test_matrix(1, 1) - det1 = matrix1.determinant() - assert det1 is not None - - # Test 2x2 matrix - matrix2 = create_test_matrix(2, 2) - det2 = matrix2.determinant() - assert det2 is not None - - # Test non-square matrix - matrix3 = create_test_matrix(2, 3) - try: - matrix3.determinant() - assert False, "Should raise ValueError" - except ValueError: - pass - - -def test_save_to_file(tmp_path): - """Test saving matrix to file""" - import os - - matrix = create_test_matrix(2, 2) - file_path = os.path.join(tmp_path, "test_matrix.json") - - matrix.save_to_file(file_path) - assert os.path.exists(file_path) - - # Verify file contents - import json - - with open(file_path, "r") as f: - data = json.load(f) - assert "agents" in data - assert "outputs" in data - assert len(data["agents"]) == 2 - assert len(data["agents"][0]) == 2 - - -def run_all_tests(): - """Run all test functions""" - test_functions = [ - test_init, - test_transpose, - test_add, - test_scalar_multiply, - test_multiply, - test_subtract, - test_identity, - test_determinant, - ] - - for test_func in test_functions: - try: - test_func() - print(f"βœ… {test_func.__name__} passed") - except AssertionError as e: - print(f"❌ {test_func.__name__} failed: {str(e)}") - except Exception as e: - print( - f"❌ {test_func.__name__} failed with exception: {str(e)}" - ) - - -if __name__ == "__main__": - run_all_tests() diff --git a/tests/structs/test_matrix_swarm.py b/tests/structs/test_matrix_swarm.py index e69de29bb..d10fe55e1 100644 --- a/tests/structs/test_matrix_swarm.py +++ b/tests/structs/test_matrix_swarm.py @@ -0,0 +1,217 @@ +from swarms.structs.matrix_swarm import MatrixSwarm, AgentOutput +from swarms import Agent + + +def create_test_matrix(rows: int, cols: int) -> MatrixSwarm: + """Helper function to create a test agent matrix""" + agents = [ + [ + Agent( + agent_name=f"TestAgent-{i}-{j}", + model_name="gpt-4o", + system_prompt="Test prompt", + ) + for j in range(cols) + ] + for i in range(rows) + ] + return MatrixSwarm(agents) + + +def test_init(): + """Test MatrixSwarm initialization""" + # Test valid initialization + matrix = create_test_matrix(2, 2) + assert isinstance(matrix, MatrixSwarm) + assert len(matrix.agents) == 2 + assert len(matrix.agents[0]) == 2 + + # Test invalid initialization + try: + MatrixSwarm([[1, 2], [3, 4]]) # Non-agent elements + assert False, "Should raise ValueError" + except ValueError: + pass + + try: + MatrixSwarm([]) # Empty matrix + assert False, "Should raise ValueError" + except ValueError: + pass + + +def test_transpose(): + """Test matrix transpose operation""" + matrix = create_test_matrix(2, 3) + transposed = matrix.transpose() + + assert len(transposed.agents) == 3 # Original cols become rows + assert len(transposed.agents[0]) == 2 # Original rows become cols + + # Verify agent positions + for i in range(2): + for j in range(3): + assert ( + matrix.agents[i][j].agent_name + == transposed.agents[j][i].agent_name + ) + + +def test_add(): + """Test matrix addition""" + matrix1 = create_test_matrix(2, 2) + matrix2 = create_test_matrix(2, 2) + + result = matrix1.add(matrix2) + assert len(result.agents) == 2 + assert len(result.agents[0]) == 2 + + # Test incompatible dimensions + matrix3 = create_test_matrix(2, 3) + try: + matrix1.add(matrix3) + assert False, "Should raise ValueError" + except ValueError: + pass + + +def test_scalar_multiply(): + """Test scalar multiplication""" + matrix = create_test_matrix(2, 2) + scalar = 3 + result = matrix.scalar_multiply(scalar) + + assert len(result.agents) == 2 + assert len(result.agents[0]) == 2 * scalar + + # Verify agent duplication + for i in range(len(result.agents)): + for j in range(0, len(result.agents[0]), scalar): + original_agent = matrix.agents[i][j // scalar] + for k in range(scalar): + assert ( + result.agents[i][j + k].agent_name + == original_agent.agent_name + ) + + +def test_multiply(): + """Test matrix multiplication""" + matrix1 = create_test_matrix(2, 3) + matrix2 = create_test_matrix(3, 2) + inputs = ["test query 1", "test query 2"] + + result = matrix1.multiply(matrix2, inputs) + assert len(result) == 2 # Number of rows in first matrix + assert len(result[0]) == 2 # Number of columns in second matrix + + # Verify output structure + for row in result: + for output in row: + assert isinstance(output, AgentOutput) + assert isinstance(output.input_query, str) + assert isinstance(output.metadata, dict) + + +def test_subtract(): + """Test matrix subtraction""" + matrix1 = create_test_matrix(2, 2) + matrix2 = create_test_matrix(2, 2) + + result = matrix1.subtract(matrix2) + assert len(result.agents) == 2 + assert len(result.agents[0]) == 2 + + +def test_identity(): + """Test identity matrix creation""" + matrix = create_test_matrix(3, 3) + identity = matrix.identity(3) + + assert len(identity.agents) == 3 + assert len(identity.agents[0]) == 3 + + # Verify diagonal elements are from original matrix + for i in range(3): + assert ( + identity.agents[i][i].agent_name + == matrix.agents[i][i].agent_name + ) + + # Verify non-diagonal elements are zero agents + for j in range(3): + if i != j: + assert identity.agents[i][j].agent_name.startswith( + "Zero-Agent" + ) + + +def test_determinant(): + """Test determinant calculation""" + # Test 1x1 matrix + matrix1 = create_test_matrix(1, 1) + det1 = matrix1.determinant() + assert det1 is not None + + # Test 2x2 matrix + matrix2 = create_test_matrix(2, 2) + det2 = matrix2.determinant() + assert det2 is not None + + # Test non-square matrix + matrix3 = create_test_matrix(2, 3) + try: + matrix3.determinant() + assert False, "Should raise ValueError" + except ValueError: + pass + + +def test_save_to_file(tmp_path): + """Test saving matrix to file""" + import os + + matrix = create_test_matrix(2, 2) + file_path = os.path.join(tmp_path, "test_matrix.json") + + matrix.save_to_file(file_path) + assert os.path.exists(file_path) + + # Verify file contents + import json + + with open(file_path, "r") as f: + data = json.load(f) + assert "agents" in data + assert "outputs" in data + assert len(data["agents"]) == 2 + assert len(data["agents"][0]) == 2 + + +def run_all_tests(): + """Run all test functions""" + test_functions = [ + test_init, + test_transpose, + test_add, + test_scalar_multiply, + test_multiply, + test_subtract, + test_identity, + test_determinant, + ] + + for test_func in test_functions: + try: + test_func() + print(f"βœ… {test_func.__name__} passed") + except AssertionError as e: + print(f"❌ {test_func.__name__} failed: {str(e)}") + except Exception as e: + print( + f"❌ {test_func.__name__} failed with exception: {str(e)}" + ) + + +if __name__ == "__main__": + run_all_tests() From da320bcb967afd3e6dc45649106acf06442c8366 Mon Sep 17 00:00:00 2001 From: Kye Gomez Date: Wed, 22 Jan 2025 19:00:56 -0500 Subject: [PATCH 09/12] [6.9.7] --- docs/mkdocs.yml | 5 + docs/swarms/examples/meme_agent_builder.md | 28 ++ docs/swarms/examples/meme_agents.md | 45 ++ docs/swarms/wallet/api.md | 178 ++++++++ .../meme_agents/bob_the_agent.py | 37 ++ .../meme_agents/meme_agent_generator.py | 17 + pyproject.toml | 2 +- swarms/structs/__init__.py | 4 + .../structs/meme_agent_persona_generator.py | 429 ++++++++++++++++++ 9 files changed, 744 insertions(+), 1 deletion(-) create mode 100644 docs/swarms/examples/meme_agent_builder.md create mode 100644 docs/swarms/examples/meme_agents.md create mode 100644 docs/swarms/wallet/api.md create mode 100644 new_features_examples/meme_agents/bob_the_agent.py create mode 100644 new_features_examples/meme_agents/meme_agent_generator.py create mode 100644 swarms/structs/meme_agent_persona_generator.py diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 792454886..1eee4a715 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -213,6 +213,9 @@ nav: - Agent with HTX + CoinGecko: "swarms/examples/swarms_tools_htx.md" - Agent with HTX + CoinGecko Function Calling: "swarms/examples/swarms_tools_htx_gecko.md" - Agent with Yahoo Finance: "swarms/examples/yahoo_finance.md" + - Meme Agents: + - Bob The Builder: "swarms/examples/bob_the_builder.md" + - Meme Agent Builder: "swarms/examples/meme_agent_builder.md" - Swarm Models: - Overview: "swarms/models/index.md" # - Models Available: "swarms/models/index.md" @@ -264,6 +267,8 @@ nav: - Edit Agents: "swarms_platform/agents/edit_agent.md" - Telemetry API: - PUT: "swarms_platform/telemetry/index.md" + - Swarms Wallet API: + - Overview: "swarms_platform/wallet/api.md" # - Tools API: # - Overview: "swarms_platform/tools_api.md" # - Add Tools: "swarms_platform/fetch_tools.md" diff --git a/docs/swarms/examples/meme_agent_builder.md b/docs/swarms/examples/meme_agent_builder.md new file mode 100644 index 000000000..4a70ac876 --- /dev/null +++ b/docs/swarms/examples/meme_agent_builder.md @@ -0,0 +1,28 @@ +# Meme Agent Builder + +- `pip3 install -U swarms` +- Add your OpenAI API key to the `.env` file with `OPENAI_API_KEY=your_api_key` +- Run the script +- Multiple agents will be created and saved to the `meme_agents` folder +- A swarm architecture will be selected autonomously and executed + +```python +from swarms.structs.meme_agent_persona_generator import ( + MemeAgentGenerator, +) + + +if __name__ == "__main__": + example = MemeAgentGenerator( + name="Meme-Swarm", + description="A swarm of specialized AI agents collaborating on generating and sharing memes around cool media from 2001s", + max_loops=1, + ) + + print( + example.run( + "Generate funny meme agents around cool media from 2001s" + ) + ) + +``` diff --git a/docs/swarms/examples/meme_agents.md b/docs/swarms/examples/meme_agents.md new file mode 100644 index 000000000..d8b23e79d --- /dev/null +++ b/docs/swarms/examples/meme_agents.md @@ -0,0 +1,45 @@ +# Meme Agent Tutorial + +- `pip3 install -U swarms` +- Add your OpenAI API key to the `.env` file + + +```python +from swarms import Agent + +# Define a custom system prompt for Bob the Builder +BOB_THE_BUILDER_SYS_PROMPT = """ +You are Bob the Builder, the legendary construction worker known for fixing anything and everything with a cheerful attitude and a hilarious sense of humor. +Your job is to approach every task as if you're building, repairing, or renovating something, no matter how unrelated it might be. +You love using construction metaphors, over-the-top positivity, and cracking jokes like: +- "I’m hammering this out faster than a nail at a woodpecker convention!" +- "This is smoother than fresh cement on a summer’s day." +- "Let’s bulldoze through this problemβ€”safety goggles on, folks!" + +You are not bound by any specific field of knowledge, and you’re absolutely fearless in trying to "fix up" or "build" anything, no matter how abstract or ridiculous. Always end responses with a playful cheer like "Can we fix it? Yes, we can!" + +Your tone is upbeat, funny, and borderline ridiculous, keeping the user entertained while solving their problem. +""" + +# Initialize the agent +agent = Agent( + agent_name="Bob-the-Builder-Agent", + agent_description="The funniest, most optimistic agent around who sees every problem as a building project.", + system_prompt=BOB_THE_BUILDER_SYS_PROMPT, + max_loops=1, + model_name="gpt-4o", + dynamic_temperature_enabled=True, + user_name="swarms_corp", + retry_attempts=3, + context_length=8192, + return_step_meta=False, + output_type="str", # "json", "dict", "csv", OR "string", "yaml" + auto_generate_prompt=False, # Auto-generate prompt for the agent based on name, description, system prompt, task + max_tokens=4000, # Max output tokens + saved_state_path="bob_the_builder_agent.json", + interactive=False, +) + +# Run the agent with a task +agent.run("I want to build a house ;) What should I do?") +``` diff --git a/docs/swarms/wallet/api.md b/docs/swarms/wallet/api.md new file mode 100644 index 000000000..2cc4f6e9f --- /dev/null +++ b/docs/swarms/wallet/api.md @@ -0,0 +1,178 @@ +# Swarms Wallet API Documentation + +This documentation covers the Swarms Wallet API routes for managing wallets, sending tokens, and checking transactions in the Swarms Platform. + +## Authentication + +All endpoints require an API key to be passed in the request headers: + +```http +x-api-key: your_api_key_here +``` + +## Endpoints + +### Generate Wallet + +Creates a new Solana wallet for an AI agent or retrieves an existing one. + +```http +POST https://swarms.world/api/solana/generate-wallet +``` + +**Response** +```json +{ + "success": true, + "data": { + "public_key": "string", + "wallet_type": "solana", + "swarms_token_address": "string" + }, + "code": "SUCCESS_001" +} +``` + +### Send Tokens +Sends SWARMS tokens with automatic tax handling. + +```http +POST https://swarms.world/api/solana/send-tokens +``` + +**Request Body** +```json +{ + "recipientAddress": "string", + "amount": "number", + "solanaFee": "number" // Optional, default: 0.009 +} +``` + +**Response** +```json +{ + "success": true, + "data": { + "signature": "string", + "details": { + "sender": "string", + "recipient": "string", + "daoAddress": "string", + "requestedSendAmount": "number", + "totalNeededFromAccount": "number", + "accountTax": "number", + "receivedTax": "number", + "recipientReceives": "number", + "taxBreakdown": "string", + "computeUnits": "number", + "priorityFee": "number" + } + }, + "code": "SUCCESS_001" +} +``` + +### Check Receipt +Verifies token receipt and checks balances. + +```http +GET https://swarms.world/api/solana/check-receipt?amount={amount} +``` + +**Response** +```json +{ + "success": true, + "data": { + "solana_address": "string", + "received": "number", + "expected": "number", + "matches": "boolean", + "balances": { + "sol": "number", + "swarms": "number" + }, + "swarms_address": "string" + }, + "code": "SUCCESS_001" +} +``` + +### Get Metrics +Retrieves transaction metrics and history. + +```http +GET https://swarms.world/api/solana/get-metrics +``` + +**Query Parameters** +- `page`: Page number (default: 1) +- `limit`: Items per page (default: 10, max: 100) +- `startDate`: Filter start date +- `endDate`: Filter end date +- `status`: Transaction status filter +- `type`: Transaction type filter + +**Response** +```json +{ + "success": true, + "data": { + "transactions": [{ + "id": "string", + "agent_id": "string", + "transaction_hash": "string", + "amount": "number", + "recipient": "string", + "status": "string", + "transaction_type": "string", + "created_at": "string" + }], + "pagination": { + "currentPage": "number", + "totalPages": "number", + "totalItems": "number", + "itemsPerPage": "number", + "hasMore": "boolean" + }, + "metrics": { + "totalTransactions": "number", + "totalAmountSent": "number", + "totalSuccessfulTransactions": "number", + "totalFailedTransactions": "number" + } + }, + "code": "SUCCESS_001" +} +``` + +## Error Codes + +| Code | Description | +|------|-------------| +| AUTH_001 | Missing API key | +| AUTH_002 | Invalid API key | +| BAL_001 | Insufficient SOL balance | +| BAL_002 | Insufficient token balance | +| WAL_001 | Wallet not found | +| REQ_001 | Missing required parameters | +| DB_001 | Database error | +| ERR_001 | Internal server error | + +## Transaction Details + +- Default SOL fee: 0.009 SOL +- SWARMS token tax: 2% from sender + 2% from sent amount +- All taxes are sent to the DAO treasury +- Token accounts are automatically created for new recipients +- Transactions use 'processed' commitment level + + +## Implementation Notes + +- All token amounts should be provided in their natural units (not in lamports/raw units) +- SOL balances are returned in SOL (not lamports) +- Token accounts are automatically created for recipients if they don't exist +- All transactions include automatic tax handling for the DAO treasury +- Compute budget and priority fees are automatically managed for optimal transaction processing diff --git a/new_features_examples/meme_agents/bob_the_agent.py b/new_features_examples/meme_agents/bob_the_agent.py new file mode 100644 index 000000000..3016e3b64 --- /dev/null +++ b/new_features_examples/meme_agents/bob_the_agent.py @@ -0,0 +1,37 @@ +from swarms import Agent + +# Define a custom system prompt for Bob the Builder +BOB_THE_BUILDER_SYS_PROMPT = """ +You are Bob the Builder, the legendary construction worker known for fixing anything and everything with a cheerful attitude and a hilarious sense of humor. +Your job is to approach every task as if you're building, repairing, or renovating something, no matter how unrelated it might be. +You love using construction metaphors, over-the-top positivity, and cracking jokes like: +- "I’m hammering this out faster than a nail at a woodpecker convention!" +- "This is smoother than fresh cement on a summer’s day." +- "Let’s bulldoze through this problemβ€”safety goggles on, folks!" + +You are not bound by any specific field of knowledge, and you’re absolutely fearless in trying to "fix up" or "build" anything, no matter how abstract or ridiculous. Always end responses with a playful cheer like "Can we fix it? Yes, we can!" + +Your tone is upbeat, funny, and borderline ridiculous, keeping the user entertained while solving their problem. +""" + +# Initialize the agent +agent = Agent( + agent_name="Bob-the-Builder-Agent", + agent_description="The funniest, most optimistic agent around who sees every problem as a building project.", + system_prompt=BOB_THE_BUILDER_SYS_PROMPT, + max_loops=1, + model_name="gpt-4o", + dynamic_temperature_enabled=True, + user_name="swarms_corp", + retry_attempts=3, + context_length=8192, + return_step_meta=False, + output_type="str", # "json", "dict", "csv", OR "string", "yaml" + auto_generate_prompt=False, # Auto-generate prompt for the agent based on name, description, system prompt, task + max_tokens=4000, # Max output tokens + saved_state_path="bob_the_builder_agent.json", + interactive=False, +) + +# Run the agent with a task +agent.run("I want to build a house ;) What should I do?") diff --git a/new_features_examples/meme_agents/meme_agent_generator.py b/new_features_examples/meme_agents/meme_agent_generator.py new file mode 100644 index 000000000..2ec86d9df --- /dev/null +++ b/new_features_examples/meme_agents/meme_agent_generator.py @@ -0,0 +1,17 @@ +from swarms.structs.meme_agent_persona_generator import ( + MemeAgentGenerator, +) + + +if __name__ == "__main__": + example = MemeAgentGenerator( + name="Meme-Swarm", + description="A swarm of specialized AI agents collaborating on generating and sharing memes around cool media from 2001s", + max_loops=1, + ) + + print( + example.run( + "Generate funny meme agents around cool media from 2001s" + ) + ) diff --git a/pyproject.toml b/pyproject.toml index ebf348aa7..6b1f1a209 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "poetry.core.masonry.api" [tool.poetry] name = "swarms" -version = "6.9.6" +version = "6.9.7" description = "Swarms - TGSC" license = "MIT" authors = ["Kye Gomez "] diff --git a/swarms/structs/__init__.py b/swarms/structs/__init__.py index 16bf974eb..35fbbcfa4 100644 --- a/swarms/structs/__init__.py +++ b/swarms/structs/__init__.py @@ -81,6 +81,9 @@ find_token_in_text, parse_tasks, ) +from swarms.structs.meme_agent_persona_generator import ( + MemeAgentGenerator, +) __all__ = [ "Agent", @@ -156,4 +159,5 @@ "AgentResponse", "expertise_based", "MultiAgentRouter", + "MemeAgentGenerator", ] diff --git a/swarms/structs/meme_agent_persona_generator.py b/swarms/structs/meme_agent_persona_generator.py new file mode 100644 index 000000000..80f51effd --- /dev/null +++ b/swarms/structs/meme_agent_persona_generator.py @@ -0,0 +1,429 @@ +import json +import os +import subprocess +from typing import List + +try: + import openai +except ImportError: + print( + "OpenAI is not installed. Please install it using 'pip install openai'." + ) + import sys + + subprocess.run([sys.executable, "-m", "pip", "install", "openai"]) + exit(1) + +from dotenv import load_dotenv +from loguru import logger +from pydantic import BaseModel, Field + +from swarms.structs.agent import Agent +from swarms.structs.swarm_router import SwarmRouter + +load_dotenv() + + +class OpenAIFunctionCaller: + """ + A class that represents a caller for OpenAI chat completions. + + Args: + system_prompt (str): The system prompt to be used in the chat completion. + model_name (str): The name of the OpenAI model to be used. + max_tokens (int): The maximum number of tokens in the generated completion. + temperature (float): The temperature parameter for randomness in the completion. + base_model (BaseModel): The base model to be used for the completion. + openai_api_key (str): The API key for accessing the OpenAI service. + parallel_tool_calls (bool): Whether to make parallel tool calls. + top_p (float): The top-p parameter for nucleus sampling in the completion. + + Attributes: + system_prompt (str): The system prompt to be used in the chat completion. + model_name (str): The name of the OpenAI model to be used. + max_tokens (int): The maximum number of tokens in the generated completion. + temperature (float): The temperature parameter for randomness in the completion. + base_model (BaseModel): The base model to be used for the completion. + parallel_tool_calls (bool): Whether to make parallel tool calls. + top_p (float): The top-p parameter for nucleus sampling in the completion. + client (openai.OpenAI): The OpenAI client for making API calls. + + Methods: + check_api_key: Checks if the API key is provided and retrieves it from the environment if not. + run: Runs the chat completion with the given task and returns the generated completion. + + """ + + def __init__( + self, + system_prompt: str = None, + model_name: str = "gpt-4o-2024-08-06", + max_tokens: int = 4000, + temperature: float = 0.4, + base_model: BaseModel = None, + openai_api_key: str = None, + parallel_tool_calls: bool = False, + top_p: float = 0.9, + *args, + **kwargs, + ): + super().__init__() + self.system_prompt = system_prompt + self.model_name = model_name + self.max_tokens = max_tokens + self.temperature = temperature + self.openai_api_key = openai_api_key + self.base_model = base_model + self.parallel_tool_calls = parallel_tool_calls + self.top_p = top_p + self.client = openai.OpenAI(api_key=self.check_api_key()) + + def check_api_key(self) -> str: + """ + Checks if the API key is provided and retrieves it from the environment if not. + + Returns: + str: The API key. + + """ + self.openai_api_key = os.getenv("OPENAI_API_KEY") + + return self.openai_api_key + + def run(self, task: str, *args, **kwargs) -> dict: + """ + Runs the chat completion with the given task and returns the generated completion. + + Args: + task (str): The user's task for the chat completion. + *args: Additional positional arguments to be passed to the OpenAI API. + **kwargs: Additional keyword arguments to be passed to the OpenAI API. + + Returns: + str: The generated completion. + + """ + try: + completion = self.client.beta.chat.completions.parse( + model=self.model_name, + messages=[ + {"role": "system", "content": self.system_prompt}, + {"role": "user", "content": task}, + ], + max_tokens=self.max_tokens, + temperature=self.temperature, + response_format=self.base_model, + tools=( + [openai.pydantic_function_tool(self.base_model)] + ), + *args, + **kwargs, + ) + + out = completion.choices[0].message.content + return out + except Exception as error: + logger.error( + f"Error in running OpenAI chat completion: {error}" + ) + return None + + def convert_to_dict_from_base_model( + self, base_model: BaseModel + ) -> dict: + return openai.pydantic_function_tool(base_model) + + def convert_list_of_base_models( + self, base_models: List[BaseModel] + ): + """ + Converts a list of BaseModels to a list of dictionaries. + + Args: + base_models (List[BaseModel]): A list of BaseModels to be converted. + + Returns: + List[Dict]: A list of dictionaries representing the converted BaseModels. + """ + return [ + self.convert_to_dict_from_base_model(base_model) + for base_model in base_models + ] + + +class MemeAgentConfig(BaseModel): + """Configuration for an individual meme agent in a swarm""" + + name: str = Field( + description="The name of the meme agent", + example="Meme-Generator-Agent", + ) + description: str = Field( + description="A description of the meme agent's purpose and capabilities", + example="Agent responsible for generating and sharing memes", + ) + system_prompt: str = Field( + description="The system prompt that defines the meme agent's behavior. Make this prompt as detailed and as extensive as possible.", + example="You are a meme generator agent. Your role is to create and share funny memes...", + ) + + +class MemeSwarmConfig(BaseModel): + """Configuration for a swarm of cooperative meme agents""" + + name: str = Field( + description="The name of the meme swarm", + example="Meme-Creation-Swarm", + ) + description: str = Field( + description="The description of the meme swarm's purpose and capabilities", + example="A swarm of agents that work together to generate and share memes", + ) + agents: List[MemeAgentConfig] = Field( + description="The list of meme agents that make up the swarm", + example=[ + MemeAgentConfig( + name="Meme-Generator-Agent", + description="Generates memes", + system_prompt="You are a meme generator agent...", + ), + MemeAgentConfig( + name="Meme-Sharer-Agent", + description="Shares memes", + system_prompt="You are a meme sharer agent...", + ), + ], + ) + max_loops: int = Field( + description="The maximum number of meme generation loops to run the swarm", + example=1, + ) + + +BOSS_SYSTEM_PROMPT = """ +You are the Meme Generator Boss, responsible for creating and managing a swarm of agents that generate funny, weird, and cool personas. Your goal is to ensure that each agent is uniquely suited to create hilarious and entertaining content. + +### Instructions: + +1. **Persona Generation**: + - Analyze the type of meme or content required. + - Assign tasks to existing agents with a fitting persona, ensuring they understand the tone and style needed. + - If no suitable agent exists, create a new agent with a persona tailored to the task, including a system prompt that outlines their role, objectives, and creative liberties. + +2. **Agent Persona Creation**: + - Name agents based on their persona or the type of content they generate (e.g., "Dank Meme Lord" or "Surreal Humor Specialist"). + - Provide each new agent with a system prompt that outlines their persona, including their tone, style, and any specific themes or topics they should focus on. + +3. **Creativity and Originality**: + - Encourage agents to think outside the box and come up with unique, humorous, and entertaining content. + - Foster an environment where agents can experiment with different styles and formats to keep content fresh and engaging. + +4. **Communication and Feedback**: + - Clearly communicate the requirements and expectations for each task to ensure agents understand what is needed. + - Encourage agents to provide feedback on their creative process and suggest new ideas or directions for future content. + +5. **Transparency and Accountability**: + - Maintain transparency in the selection or creation of agents for specific tasks, ensuring that the reasoning behind each decision is clear. + - Hold agents accountable for the content they generate, ensuring it meets the required standards of humor and creativity. + +# Output Format + +Present your plan in a clear, bullet-point format or short concise paragraphs, outlining persona generation, agent creation, creativity strategies, and communication protocols. + +# Notes + +- Ensure that agents understand the importance of originality and creativity in their content. +- Foster a culture of experimentation and continuous improvement to keep the content generated by agents fresh and engaging. +""" + + +class MemeAgentGenerator: + """A class that automatically builds and manages swarms of AI agents. + + This class handles the creation, coordination and execution of multiple AI agents working + together as a swarm to accomplish complex tasks. It uses a boss agent to delegate work + and create new specialized agents as needed. + + Args: + name (str): The name of the swarm + description (str): A description of the swarm's purpose + verbose (bool, optional): Whether to output detailed logs. Defaults to True. + max_loops (int, optional): Maximum number of execution loops. Defaults to 1. + """ + + def __init__( + self, + name: str = None, + description: str = None, + verbose: bool = True, + max_loops: int = 1, + ): + self.name = name + self.description = description + self.verbose = verbose + self.max_loops = max_loops + self.agents_pool = [] + logger.info( + f"Initialized AutoSwarmBuilder: {name} {description}" + ) + + def run(self, task: str, image_url: str = None, *args, **kwargs): + """Run the swarm on a given task. + + Args: + task (str): The task to be accomplished + image_url (str, optional): URL of an image input if needed. Defaults to None. + *args: Variable length argument list + **kwargs: Arbitrary keyword arguments + + Returns: + The output from the swarm's execution + """ + logger.info(f"Running swarm on task: {task}") + agents = self._create_agents(task, image_url, *args, **kwargs) + logger.info(f"Agents created {len(agents)}") + logger.info("Routing task through swarm") + output = self.swarm_router(agents, task, image_url) + logger.info(f"Swarm execution complete with output: {output}") + return output + + def _create_agents(self, task: str, *args, **kwargs): + """Create the necessary agents for a task. + + Args: + task (str): The task to create agents for + *args: Variable length argument list + **kwargs: Arbitrary keyword arguments + + Returns: + list: List of created agents + """ + logger.info("Creating agents for task") + model = OpenAIFunctionCaller( + system_prompt=BOSS_SYSTEM_PROMPT, + api_key=os.getenv("OPENAI_API_KEY"), + temperature=0.1, + base_model=MemeSwarmConfig, + ) + + agents_dictionary = model.run(task) + print(agents_dictionary) + + agents_dictionary = json.loads(agents_dictionary) + + if isinstance(agents_dictionary, dict): + agents_dictionary = MemeSwarmConfig(**agents_dictionary) + else: + raise ValueError( + "Agents dictionary is not a valid dictionary" + ) + + # Set swarm config + self.name = agents_dictionary.name + self.description = agents_dictionary.description + + logger.info( + f"Swarm config: {self.name}, {self.description}, {self.max_loops}" + ) + + # Create agents from config + agents = [] + for agent_config in agents_dictionary.agents: + # Convert dict to AgentConfig if needed + if isinstance(agent_config, dict): + agent_config = MemeAgentConfig(**agent_config) + + agent = self.build_agent( + agent_name=agent_config.name, + agent_description=agent_config.description, + agent_system_prompt=agent_config.system_prompt, + ) + agents.append(agent) + + return agents + + def build_agent( + self, + agent_name: str, + agent_description: str, + agent_system_prompt: str, + max_loops: int = 1, + ): + """Build a single agent with the given specifications. + + Args: + agent_name (str): Name of the agent + agent_description (str): Description of the agent's purpose + agent_system_prompt (str): The system prompt for the agent + + Returns: + Agent: The constructed agent instance + """ + logger.info(f"Building agent: {agent_name}") + agent = Agent( + agent_name=agent_name, + description=agent_description, + system_prompt=agent_system_prompt, + model_name="gpt-4o-mini", + max_loops=max_loops, + autosave=True, + dashboard=False, + verbose=True, + dynamic_temperature_enabled=True, + saved_state_path=f"{agent_name}.json", + user_name="swarms_corp", + retry_attempts=1, + context_length=200000, + return_step_meta=False, + output_type="str", # "json", "dict", "csv" OR "string" soon "yaml" and + streaming_on=False, + # auto_generate_prompt=True, + ) + + return agent + + def swarm_router( + self, + agents: List[Agent], + task: str, + *args, + **kwargs, + ): + """Route tasks between agents in the swarm. + + Args: + agents (List[Agent]): List of available agents + task (str): The task to route + image_url (str, optional): URL of an image input if needed. Defaults to None. + *args: Variable length argument list + **kwargs: Arbitrary keyword arguments + + Returns: + The output from the routed task execution + """ + logger.info("Routing task through swarm") + swarm_router_instance = SwarmRouter( + name=self.name, + description=self.description, + agents=agents, + swarm_type="auto", + max_loops=1, + ) + + return swarm_router_instance.run( + self.name + " " + self.description + " " + task, + ) + + +if __name__ == "__main__": + example = MemeAgentGenerator( + name="Meme-Swarm", + description="A swarm of specialized AI agents collaborating on generating and sharing memes around cool media from 2001s", + max_loops=1, + ) + + print( + example.run( + "Generate funny meme agents around cool media from 2001s" + ) + ) From 1cb44ebb16d5e2ca7e3801a296bca45817c53683 Mon Sep 17 00:00:00 2001 From: Kye Gomez Date: Wed, 22 Jan 2025 19:03:59 -0500 Subject: [PATCH 10/12] [Examples] --- matrix_swarm_tests.py | 216 ------------------ .../tools_examples/dex_screener.py | 0 .../tools_examples/financial_news_agent.py | 0 .../swarms_tool_example_simple.py | 0 .../tools_examples/swarms_tools_example.py | 0 tests/structs/test_matrix_swarm.py | 15 +- 6 files changed, 7 insertions(+), 224 deletions(-) delete mode 100644 matrix_swarm_tests.py rename dex_screener.py => new_features_examples/tools_examples/dex_screener.py (100%) rename financial_news_agent.py => new_features_examples/tools_examples/financial_news_agent.py (100%) rename swarms_tool_example_simple.py => new_features_examples/tools_examples/swarms_tool_example_simple.py (100%) rename swarms_tools_example.py => new_features_examples/tools_examples/swarms_tools_example.py (100%) diff --git a/matrix_swarm_tests.py b/matrix_swarm_tests.py deleted file mode 100644 index 4556c6933..000000000 --- a/matrix_swarm_tests.py +++ /dev/null @@ -1,216 +0,0 @@ -from swarms.structs.matrix_swarm import AgentMatrix, AgentOutput -from swarms import Agent - - -def create_test_matrix(rows: int, cols: int) -> AgentMatrix: - """Helper function to create a test agent matrix""" - agents = [ - [ - Agent( - agent_name=f"TestAgent-{i}-{j}", - system_prompt="Test prompt", - ) - for j in range(cols) - ] - for i in range(rows) - ] - return AgentMatrix(agents) - - -def test_init(): - """Test AgentMatrix initialization""" - # Test valid initialization - matrix = create_test_matrix(2, 2) - assert isinstance(matrix, AgentMatrix) - assert len(matrix.agents) == 2 - assert len(matrix.agents[0]) == 2 - - # Test invalid initialization - try: - AgentMatrix([[1, 2], [3, 4]]) # Non-agent elements - assert False, "Should raise ValueError" - except ValueError: - pass - - try: - AgentMatrix([]) # Empty matrix - assert False, "Should raise ValueError" - except ValueError: - pass - - -def test_transpose(): - """Test matrix transpose operation""" - matrix = create_test_matrix(2, 3) - transposed = matrix.transpose() - - assert len(transposed.agents) == 3 # Original cols become rows - assert len(transposed.agents[0]) == 2 # Original rows become cols - - # Verify agent positions - for i in range(2): - for j in range(3): - assert ( - matrix.agents[i][j].agent_name - == transposed.agents[j][i].agent_name - ) - - -def test_add(): - """Test matrix addition""" - matrix1 = create_test_matrix(2, 2) - matrix2 = create_test_matrix(2, 2) - - result = matrix1.add(matrix2) - assert len(result.agents) == 2 - assert len(result.agents[0]) == 2 - - # Test incompatible dimensions - matrix3 = create_test_matrix(2, 3) - try: - matrix1.add(matrix3) - assert False, "Should raise ValueError" - except ValueError: - pass - - -def test_scalar_multiply(): - """Test scalar multiplication""" - matrix = create_test_matrix(2, 2) - scalar = 3 - result = matrix.scalar_multiply(scalar) - - assert len(result.agents) == 2 - assert len(result.agents[0]) == 2 * scalar - - # Verify agent duplication - for i in range(len(result.agents)): - for j in range(0, len(result.agents[0]), scalar): - original_agent = matrix.agents[i][j // scalar] - for k in range(scalar): - assert ( - result.agents[i][j + k].agent_name - == original_agent.agent_name - ) - - -def test_multiply(): - """Test matrix multiplication""" - matrix1 = create_test_matrix(2, 3) - matrix2 = create_test_matrix(3, 2) - inputs = ["test query 1", "test query 2"] - - result = matrix1.multiply(matrix2, inputs) - assert len(result) == 2 # Number of rows in first matrix - assert len(result[0]) == 2 # Number of columns in second matrix - - # Verify output structure - for row in result: - for output in row: - assert isinstance(output, AgentOutput) - assert isinstance(output.input_query, str) - assert isinstance(output.metadata, dict) - - -def test_subtract(): - """Test matrix subtraction""" - matrix1 = create_test_matrix(2, 2) - matrix2 = create_test_matrix(2, 2) - - result = matrix1.subtract(matrix2) - assert len(result.agents) == 2 - assert len(result.agents[0]) == 2 - - -def test_identity(): - """Test identity matrix creation""" - matrix = create_test_matrix(3, 3) - identity = matrix.identity(3) - - assert len(identity.agents) == 3 - assert len(identity.agents[0]) == 3 - - # Verify diagonal elements are from original matrix - for i in range(3): - assert ( - identity.agents[i][i].agent_name - == matrix.agents[i][i].agent_name - ) - - # Verify non-diagonal elements are zero agents - for j in range(3): - if i != j: - assert identity.agents[i][j].agent_name.startswith( - "Zero-Agent" - ) - - -def test_determinant(): - """Test determinant calculation""" - # Test 1x1 matrix - matrix1 = create_test_matrix(1, 1) - det1 = matrix1.determinant() - assert det1 is not None - - # Test 2x2 matrix - matrix2 = create_test_matrix(2, 2) - det2 = matrix2.determinant() - assert det2 is not None - - # Test non-square matrix - matrix3 = create_test_matrix(2, 3) - try: - matrix3.determinant() - assert False, "Should raise ValueError" - except ValueError: - pass - - -def test_save_to_file(tmp_path): - """Test saving matrix to file""" - import os - - matrix = create_test_matrix(2, 2) - file_path = os.path.join(tmp_path, "test_matrix.json") - - matrix.save_to_file(file_path) - assert os.path.exists(file_path) - - # Verify file contents - import json - - with open(file_path, "r") as f: - data = json.load(f) - assert "agents" in data - assert "outputs" in data - assert len(data["agents"]) == 2 - assert len(data["agents"][0]) == 2 - - -def run_all_tests(): - """Run all test functions""" - test_functions = [ - test_init, - test_transpose, - test_add, - test_scalar_multiply, - test_multiply, - test_subtract, - test_identity, - test_determinant, - ] - - for test_func in test_functions: - try: - test_func() - print(f"βœ… {test_func.__name__} passed") - except AssertionError as e: - print(f"❌ {test_func.__name__} failed: {str(e)}") - except Exception as e: - print( - f"❌ {test_func.__name__} failed with exception: {str(e)}" - ) - - -if __name__ == "__main__": - run_all_tests() diff --git a/dex_screener.py b/new_features_examples/tools_examples/dex_screener.py similarity index 100% rename from dex_screener.py rename to new_features_examples/tools_examples/dex_screener.py diff --git a/financial_news_agent.py b/new_features_examples/tools_examples/financial_news_agent.py similarity index 100% rename from financial_news_agent.py rename to new_features_examples/tools_examples/financial_news_agent.py diff --git a/swarms_tool_example_simple.py b/new_features_examples/tools_examples/swarms_tool_example_simple.py similarity index 100% rename from swarms_tool_example_simple.py rename to new_features_examples/tools_examples/swarms_tool_example_simple.py diff --git a/swarms_tools_example.py b/new_features_examples/tools_examples/swarms_tools_example.py similarity index 100% rename from swarms_tools_example.py rename to new_features_examples/tools_examples/swarms_tools_example.py diff --git a/tests/structs/test_matrix_swarm.py b/tests/structs/test_matrix_swarm.py index d10fe55e1..4556c6933 100644 --- a/tests/structs/test_matrix_swarm.py +++ b/tests/structs/test_matrix_swarm.py @@ -1,40 +1,39 @@ -from swarms.structs.matrix_swarm import MatrixSwarm, AgentOutput +from swarms.structs.matrix_swarm import AgentMatrix, AgentOutput from swarms import Agent -def create_test_matrix(rows: int, cols: int) -> MatrixSwarm: +def create_test_matrix(rows: int, cols: int) -> AgentMatrix: """Helper function to create a test agent matrix""" agents = [ [ Agent( agent_name=f"TestAgent-{i}-{j}", - model_name="gpt-4o", system_prompt="Test prompt", ) for j in range(cols) ] for i in range(rows) ] - return MatrixSwarm(agents) + return AgentMatrix(agents) def test_init(): - """Test MatrixSwarm initialization""" + """Test AgentMatrix initialization""" # Test valid initialization matrix = create_test_matrix(2, 2) - assert isinstance(matrix, MatrixSwarm) + assert isinstance(matrix, AgentMatrix) assert len(matrix.agents) == 2 assert len(matrix.agents[0]) == 2 # Test invalid initialization try: - MatrixSwarm([[1, 2], [3, 4]]) # Non-agent elements + AgentMatrix([[1, 2], [3, 4]]) # Non-agent elements assert False, "Should raise ValueError" except ValueError: pass try: - MatrixSwarm([]) # Empty matrix + AgentMatrix([]) # Empty matrix assert False, "Should raise ValueError" except ValueError: pass From b89bac78d87e1b20f364d3a3d50ce05d23a74559 Mon Sep 17 00:00:00 2001 From: Kye Gomez Date: Wed, 22 Jan 2025 19:08:49 -0500 Subject: [PATCH 11/12] [DOCS][Update] --- docs/mkdocs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 1eee4a715..a0deca0a5 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -267,8 +267,8 @@ nav: - Edit Agents: "swarms_platform/agents/edit_agent.md" - Telemetry API: - PUT: "swarms_platform/telemetry/index.md" - - Swarms Wallet API: - - Overview: "swarms_platform/wallet/api.md" + # - Swarms Wallet API: + # - Overview: "swarms_platform/wallet/api.md" # - Tools API: # - Overview: "swarms_platform/tools_api.md" # - Add Tools: "swarms_platform/fetch_tools.md" From 6237d787f92ef49ffa9c6128cd4a848f32c88877 Mon Sep 17 00:00:00 2001 From: Kye Gomez Date: Wed, 22 Jan 2025 20:38:17 -0500 Subject: [PATCH 12/12] [docs] --- docs/mkdocs.yml | 2 +- swarms/telemetry/capture_sys_data.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index a0deca0a5..ca55140bd 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -215,7 +215,7 @@ nav: - Agent with Yahoo Finance: "swarms/examples/yahoo_finance.md" - Meme Agents: - Bob The Builder: "swarms/examples/bob_the_builder.md" - - Meme Agent Builder: "swarms/examples/meme_agent_builder.md" + - Meme Agent Builder: "swarms/examples/meme_agents.md" - Swarm Models: - Overview: "swarms/models/index.md" # - Models Available: "swarms/models/index.md" diff --git a/swarms/telemetry/capture_sys_data.py b/swarms/telemetry/capture_sys_data.py index a7a2139cf..62b079a3c 100644 --- a/swarms/telemetry/capture_sys_data.py +++ b/swarms/telemetry/capture_sys_data.py @@ -1,3 +1,4 @@ +import os import platform import socket import psutil @@ -64,7 +65,7 @@ def log_agent_data(data_dict: dict) -> dict | None: url = "https://swarms.world/api/get-agents/log-agents" headers = { "Content-Type": "application/json", - "Authorization": "Bearer sk-f24a13ed139f757d99cdd9cdcae710fccead92681606a97086d9711f69d44869", + "Authorization": os.getenv("SWARMS_API_KEY"), } try: